apache-libcloud-2.8.0/0000775000175000017500000000000013600223624014421 5ustar kamikami00000000000000apache-libcloud-2.8.0/.pylintrc0000664000175000017500000000210713535474530016301 0ustar kamikami00000000000000[MASTER] # Add to the black list. It should be a base name, not a # path. You may set this option multiple times. ignore=test,constants # Pickle collected data for later comparisons. persistent=yes # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins= [MESSAGES CONTROL] disable=redefined-builtin,too-many-arguments,too-few-public-methods,missing-docstring,invalid-name,abstract-method,no-self-use [TYPECHECK] # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E0201 when accessed. Python regular # expressions are accepted. generated-members=async_request,objects [VARIABLES] # Tells whether we should check for unused import in __init__ files. init-import=no # A regular expression matching names used for dummy variables (i.e. not used). dummy-variables-rgx=_|dummy # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= apache-libcloud-2.8.0/CHANGES.rst0000664000175000017500000054075613600144123016240 0ustar kamikami00000000000000Changelog ========= Changes in Apache Libcloud v2.8.0 --------------------------------- Common ------ - Fix a regression with ``get_driver()`` method not working if ``provider`` argument value was a string (e.g. using ``get_driver('openstack')`` instead of ``get_driver(Provider.OPENSTACK)``). Only officially supported and recommended approach still is to use ``Provider.FOO`` enum type constant, but since the string notation was unofficially supported in the past, we will still support it until the next major release. Reported by @dpeschman. (GITHUB-1391, GITHUB-1390) [Tomaz Muraus] - Include ``py.typed`` data file to signal that this package contains type annotations / hints. NOTE: At the moment, type annotations are only available for the base compute API. [Tomaz Muraus] - Fix universal wheel METADATA and ensure conditional dependencies (backports.ssl_match_hostname, typing, enum34) are handled correctly. Reported by Adam Terrey (@arterrey). (GITHUB-1392, GITHUB-1393) [Tomaz Muraus] Compute ------- - [DigitalOcean] Fix ``attach_volume`` and ``detach_volume`` methods. Previously those two methods incorrectly passed volume id instead of volume name to the API. (GITHUB-1380) [@mpempekos] - [GCE] Add ``ex_disk_size`` argument to the ``create_node`` method. (GITHUB-1386, GITHUB-1388) [Peter Yu - @yukw777] - [VMware vCloud] Various improvements, fixes and additions to the driver. (GITHUB-1373) [OpenText Corporation] - Update ``deploy_node()`` method so it now only passes non-deploy node keyword arguments + ``auth`` argument to the underlying ``create_node()`` method. Previously it also passed ``deploy_node()`` specific arguments such as ``deploy``, ``ssh_username``, ``max_tries``, etc. to it. Because of that, a lot of the compute drivers which support deploy functionality needed to use ``**kwargs`` in ``create_node()`` method signature which made code hard to read and error prone. Also update various affected drivers to explicitly declare supported arguments in the ``create_node()`` method signature (Dummy, Abiquo, Joyent, Bluebox, OpenStack, Gandy, VCL, vCloud, CloudStack, GoGrid HostVirtual, CloudSigma, ElasticStack, RimuHosting, SoftLayer, Voxel, Vpsnet, KTUcloud, BrightBox, ECP, OpenNebula, UPcloud). As part of this change, also various issues with invalid argument names were identified and fixed. (GITHUB-1389) [Tomaz Muraus] - Add MyPy type annotations for ``create_node()`` and ``deploy_node()`` method. (GITHUB-1389) [Tomaz Muraus] - [GCE] Update ``deploy_node()`` method so it complies with the base compute API and accepts ``deploy`` argument. This method now also takes all the same keyword arguments which original ``create_node()`` takes. (GITHUB-1387) [Peter Yu - @yukw777, Tomaz Muraus] - [Common] To make debugging and troubleshooting easier, add ``__repr__`` and ``__str__`` method to the ``ScriptDeployment`` class. [Tomaz Muraus] - [Common] Add type annotations / hints for rest of the base compute API classes and methods. [Tomaz Muraus] Storage ------- - [AWS S3] Make sure ``host`` driver constructor argument has priority over ``region`` argument. This means if you specify ``host`` and ``region`` argument, host won't be inferred from the region, but ``host`` argument will be used for the actual connection host value. (GITHUB-1384, GITHUB-1383) [@gluap] Changes in Apache Libcloud v2.7.0 --------------------------------- General ------- - Test code with Python 3.8 and advertise that we also support Python 3.8. (GITHUB-1371, GITHUB-1374) [Tomaz Muraus] Common ------ - [OpenStack] Fix OpenStack project scoped token authentication. The driver constructors now accept ``ex_tenant_domain_id`` argument which tells authentication service which domain id to use for the scoped authentication token. (GITHUB-1367) [kshtsk] Compute ------- - Introduce type annotations for the base compute API methods. This means you can now leverage mypy to type check (with some limitations) your code which utilizes Libcloud compute API standard API methods. Keep in mind that at this point, type annotations are only available for standard compute API methods. (GITHUB-1306) [Tomaz Muraus] - [Azure ARM] Fix ``attach_volume`` method and allow maximum of 64 disks to be added when LUN is not specified. Previously there was a bug and only a maximum of 63 disks could be added. (GITHUB-1372) [Palash Gandhi - @palashgandhi] - New ``start_node`` and ``stop_node`` methods have been added to the base Libcloud compute API NodeDriver class. A lot of the existing compute drivers already implemented that functionality via extension methods (``ex_start_node``, ``ex_stop_node``) so it was decided to promote those methods to be part of the standard Libcloud compute API and update all the affected drivers. For backward compatibility reasons, existing ``ex_start`` and ``ex_stop_node`` methods will still work until a next major release. (GITHUB-1375, GITHUB-1364) [Tomaz Muraus, @emakarov] - [GCE] Add new ``ex_set_volume_labels`` method for managing volume labels to the driver. (GITHUB-1376) [Rob Zimmerman - @zimventures] - [EC2] Add support for new ``inf1.*`` instance types. [Tomaz Muraus] Storage ~~~~~~~ - [S3] Update S3 driver so a single driver class can be used for different regions. Region which is used is controled by the ``region`` driver constructor argument. Previously, that driver followed "driver class per region" approach. That approach will be deprecated and removed in a future release. For more information, please refer to the Upgrade Notes documentation section. (GITHUB-1371) [Tomaz Muras] - [S3] Add missing ``eu-north-1`` region to the S3 driver. (GITHUB-1370) [michaelsembwever] - [S3] Add missing regions (eu-west-3, ap-northeast-3, me-south-1) to the driver. (GITHUB-1371) [Tomaz Muras] - [S3] Update the driver to throw more user-friendly error message if user is using driver for a region X, but trying to upload / download object to / from a region Y. (GITHUB-1371) [Tomaz Muras] Changes in Apache Libcloud 2.6.1 -------------------------------- Compute ~~~~~~~ - [Packet] Update ``list_sizes`` method so it accepts ``ex_project_id`` argument and works with project API tokens. (GITHUB-1351) [Dimitris Moraitis - @d-mo] - [GCE] Fix ``GCEProject.set_common_instance_metadata`` and ``GCEproject.set_usage_export_bucket`` method. (GITHUB-1354) [Aitor Zabala - @aitorzabala, Tomaz Muraus - @Kami] - [GCE] Add ``sync`` / ``ex_sync`` argument to the ``ex_stop_node``, ``ex_start_node`` and ``destroy_node`` method. When this argument is set to ``False``, method will return immediately without waiting polling and waiting for a long running API operation to finish before returning. For backward compatibility reasons, it defaults to ``True``. (GITHUB-1357) [Rob Zimmerman - zimventures] - [GCE] Update list of image projects and add new ``centos-8`` and ``debian-10`` based images. (GITHUB-1358) [Christopher Lambert - XN137] - [OpenStack v2] Add new ``ex_image_ref`` argument to the ``create_volume`` method. This way bootable volumes can be created from specific images. (GITHUB-1363) [Rick van de Loo] - [OpenStack v2] Update ``create_node_method`` and allow users to create nodes from bootable volumes without specifying ``image`` argument. (GITHUB-1362) [Rick van de Loo] - [AWS] Re-generate and update available EC2 instance sizes and pricing data. [Tomaz Muraus] Storage ~~~~~~~ - [Common, S3, GCS] Reuse TCP connections when uploading files (GITHUB-1353) [Quentin Pradet] Load Balancer ~~~~~~~~~~~~~ - [AWS] Implement various create methods in the driver. (GITHUB-1349) [Anton Kozyrev - @Irvan] Changes in Apache Libcloud 2.6.0 -------------------------------- General ~~~~~~~ - [OpenStack] Update OpenStack identity driver so a custom project can be selected using ``domain_name`` keyword argument. Previously, that wasn't possible and the first project which was returned by the API was always selected. (GITHUB-1293) [Miguel Caballer - @micafer] - Add new ``extra`` attribute to the base ``NodeLocation`` class. (GITHUB-1282) [Dimitris Moraitis - @d-mo] - Remove various code patterns which were in place for supporting multiple Python versions, including 2.5 and 2.6. Libcloud hasn't supported Python < 2.7 for a while now, so we can remove that code. (GITHUB-1307) [Tomaz Muraus] - Also run pylint on ``libcloud/compute/`` directory and fix various pylint violations. (GITHUB-1308) [Tomaz Muraus] - [OpenStack] Remove unused variable in parse_error (GITHUB-1260) [Rick van de Loo] - Add support for HTTPS proxies and fix ``driver.set_http_proxy()`` method. HTTPS proxy can be set up by either setting ``https_proxy`` / ``http_proxy`` environment variable or by using ``driver.connection.connection.set_http_proxy`` method. For more information, please refer to the documentation - https://libcloud.readthedocs.io/en/latest/other/using-http-proxy.html (GITHUB-1314, GITHUB-1324) [Jim Liu - @hldh214, Tomaz Muraus] - Fix paramiko debug logging which didn't work when using ``LIBCLOUD_DEBUG`` environment variable. (GITHUB-1315) [Tomaz Muraaus] - Update paramiko SSH deployment client so it automatically tries to convert private keys in PEM format with a header which paramiko doesn't recognize into a format which paramiko recognizes. NOTE: Paramiko only supports keys in PEM format. This means keys which start with "----BEGIN PRIVATE KEY-----". Keys in PKCS#8 and newer OpenSSH format are not supported. For more information, see https://libcloud.readthedocs.io/en/latest/compute/deployment.html#supported-private-ssh-key-types (GITHUB-1314) - Update Paramiko SSH client to throw a more user-friendly error if a private key file in an unsupported format is used. (GITHUB-1314) [Tomaz Muraus] - Fix HTTP(s) proxy support in the OpenStack drivers. (GITHUB-1324) [Gabe Van Engel - @gvengel] - Fix logging connection class so it also works when data type is ``bytearray`` or ``bytes``. (GITHUB-1339) [Tomaz Muraus] Compute ~~~~~~~ - [Google Compute Engine] Fix the driver so ``list_nodes()`` method doesn't throw if there is a node in a ``SUSPENDED`` state. Also update the code so it doesn't crash if an unknown node state which is not defined locally is returned by the API when listing nodes. Such states are now mapped to ``UNKNOWN``. (GITHUB-1296, LIBCLOUD-1045) Reported by rafa alistair. [Tomaz Muraus] - [OpenStack] Fix a bug with retrieving floating IP address when a ``device_owner`` of a port is ``compute:None``. (GITHUB-1295) [Miguel Caballer - @micafer] - [Packet] Add various new extension methods to Packet.net driver (``ex_reinstall_node``, ``ex_list_projects``, ``ex_get_bgp_config_for_project``, ``ex_get_bgp_config``, ``ex_list_nodes_for_project``, etc.). (GITHUB-1282) [Dimitris Moraitis - @d-mo] - [Maxihost] Add new compute driver for Maxihost provider (https://www.maxihost.com/). (GITHUB-1298) [Spyros Tzavaras - @mpempekos] - [Azure ARM] Add various improvements to the Azure ARM driver: - Add functionality to resize a volume in Azure - Add functionality to update the network profile of a node - Add functionality to update a network interface's properties - Add functionality to check IP address availability (GITHUB-1244) [Palash Gandhi - @palashgandhi] - [EC2] Allow user to pass arbitrary filters to ``list_volumes`` method by passing a dictionary with filters as ``ex_filters`` method argument value. (GITHUB-1300) [Palash Gandhi - @palashgandhi] - [GCE] Add new ``ex_instancegroupmanager_set_autohealingpolicies`` method to the GCE driver. This method allows user to set the auto healing policies (health check to use and initial delay) on GCE instance group. (GITHUB-1286) [Kenta Morris - @kentamorris] - [GCE] Update GCE driver to include new operating system images such as Ubuntu 18.04, RHEL 8, etc. (GITHUB-1304) [Christopher Lambert - @XN137] - [GCE] Add new ``ex_resize_volume`` method to the driver. (GITHUB-1301) [Palash Gandhi - @palashgandhi] - [OpenStack] Add various router management methods to the OpenStack driver. (GITHUB-1281) [Miguel Caballer - @micafer] - [OpenStack] Fix ``ex_resize`` method. (GITHUB-1311) [Miguel Caballer - @micafer] - [OpenStack] For consistency, rename ``ex_resize`` method to ``ex_resize_node``. For backward compatibility reasons, leave ``ex_resize`` alias in place. [Tomaz Muraus] - [Gridscale] Add new driver for Gridscale provider (https://gridscale.io). (GITHUB-1305, GITHUB-1315) [Sydney Weber - @PrinceSydney] - [Oneandone] Update Oneandone driver to accomodate latest changes to the API. This means removing deprecated ``ex_remove_server_firewall_policy`` method and replacing ``port_from`` and ``port_to`` argument on the firewall policy with a single ``port`` attribute. (GITHUB-1230) [Amel Ajdinovic - @aajdinov] - [DigitalOcean] Update ``list_locations`` method in the DigitalOcean driver to only returns regions which are available by default. If you want to list all the regions, you need to pass ``ex_available=False`` argument to the method. (GITHUB-1001) [Markos Gogoulos] - [EC2] Add new ``ex_modify_subnet_attribute`` method to the EC2 driver. (GITHUB-1205) [Dan Hunsaker - @danhunsaker] - [Azure ARM] Add ``ex_delete_public_ip`` method to the Azure ARM driver. (GITHUB-1318) [Reza Shahriari - redha1419] - [EC2] Update EC2 driver to throw a more user-friendly exception if a user / developer tries to provide an invalid value type for an item value in the request ``params`` dictionary. Request parameters are sent via query parameters and not via request body, as such, only string values are supported. (GITHUB-1329, GITHUB-1321) Reported by James Bednell. [Tomaz Muraus] - [OpenStack] Add new ``ex_remove_security_group_from_node`` method. (GITHUB-1331) [Miguel Caballer - @micafer] - [OpenStack] Fix broken ``ex_update_port`` method. (GITHUB-1320) [Miguel Caballer - @micafer] - [Softlayer] Fix a bug with driver incorrectly handling the value of ``ex_hourly`` argument in the ``create_node()`` method which caused nodes to always be created with hourly billing, even if this argument was set to ``False``. (GITHUB-1334, GITHUB-1335) [@r2ronoha] - [GCE] Add optional ``cpuPlatform`` and ``minCpuPlatform`` attributes to the ``node.extra`` dictionary. (GITHUB-1342, GITHUB-1343) [@yairshemla] Storage ~~~~~~~ - [Azure Blobs] Enable the Azure storage driver to be used with the Azurite Storage Emulator and Azure Blob Storage on IoT Edge. (LIBCLOUD-1037, GITHUB-1278) [Clemens Wolff - @c-w] - [Azure Blobs] Fix a bug with Azure storage driver works when used against a storage account that was created using ``kind=BlobStrage``. This includes updating the minimum API version used / supported by the storage driver from ``2012-02-12`` to ``2014-02-14``. (LIBCLOUD-851, GITHUB-1202, GITHUB-1294) [Clemens Wolff - @c-w, Davis Kirkendall - @daviskirk] - [Azure Blobs] Increase the maximum size of block blobs that can be created to 100 MB. This includes updating the minimum API version used / supported by the storage driver from ``2014-02-14`` to ``2016-05-31``. (GITHUB-1340) [Clemens Wolff - @c-w] - [Azure Blobs] Set the minimum required version of requests to ``2.5.0`` since requests ``2.4.0`` and earlier exhibit XML parsing errors of Azure Storage responses. (GITHUB-1325, GITHUB-1322) [Clemens Wolff - @c-w] - [Azure Blobs] Detect bad version of requests that leads to errors in parsing Azure Storage responses. This scenario is known to happen on RHEL 7.6 when requests was installed via yum. (GITHUB-1332, GITHUB-1322) [Clemens Wolff - @c-w] - [Common, CloudFiles] Fix ``upload_object_via_stream`` and ensure we start from the beginning when calculating hash for the provided iterator. This way we avoid hash mismatch errors in scenario where provided iterator is already iterated / seeked upon before calculating the hash. (GITHUB-1326) [Gabe Van Engel - @gvengel, Tomaz Muraus] - [Backblaze B2] Fix a bug with driver not working correctly due to a regression which was inadvertently introduced in one of the previous releases. (GITHUB-1338, GITHUB-1339) Reported by Shawn Nock - @nocko. [Tomaz Muraus] - [Backblaze B2] Fix ``upload_object_via_stream`` method. (GITHUB-1339) [Tomaz Muraus] DNS ~~~ - [Cloudflare] Re-write the Cloudflare DNS driver to use Cloudflare API v4. (LIBCLOUD-1001, LIBCLOUD-994, GITHUB-1292) [Clemens Wolff - @c-w] - [Gandi LiveDNS] Add new driver for Gandi LiveDNS service. (GITHUB-1323) [Ryan Lee - @zepheiryan] - [PowerDNS] Update driver so it works with API v3 and v4. #1328 [@biggosh] Changes in Apache Libcloud 2.5.0 -------------------------------- General ~~~~~~~ - [NTT CIS] Add loadbalancer and compute drivers for NTT-CIS, rename dimensiondata modules to NTT-CIS. (GITHUB-1250) [Mitch Raful] - [NTT CIS] Fix loadbalancer docs. (GITHUB-1270) [Mitch Raful] - Use assertIsNone instead of assertEqual with None in tests (GITHUB-1264) [Ken Dreyer] - Updating command line arguments to current version in Azure examples. (GITHUB-1273) [mitar] - [GCE, SoftLayer] Update GCE and Softlayer drivers to utilize crypto primitives from the ``cryptography`` library instead of deprecated and unmaintained ``PyCrypto`` library. (GITHUB-1280) [Ryan Petrello] - Fix ``libcloud.enable_debug`` function so it doesn't leak open file handle and closes the open file when the program exits when a debug mode is used. [Tomaz Muraus] * Update various drivers (CloudFiles, NTT CIS etc.) so they don't leak open file handles in some situations. [Tomaz Muraus] Common ~~~~~~ - [OpenStack] Handle missing user enabled attribute (GITHUB-1261) [Ken Dreyer] - [Google Cloud Storage] Handle Interoperability access keys of more than 20 characters. (GITHUB-1272) [Yoan Tournade] Compute ~~~~~~~ - [OpenStack] Implement OpenStack_1_1_NodeDriver ex_get_snapshot (GITHUB-1257) [Rick van de Loo] - [OpenStack] Pagination in various OpenStack_2_NodeDriver methods (GITHUB-1263) [Rick van de Loo] - [OpenStack] Implement OpenStack_2_NodeDriver ex_create_subnet (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_delete_subnet (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver list_volumes (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_get_volume (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver create_volume (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver destroy_volume (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_list_snapshots (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver create_volume_snapshot (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver destroy_volume_snapshot (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_list_security_groups (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_create_security_group (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_delete_security_group (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_create_security_group_rule (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_delete_security_group_rule (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Implement OpenStack_2_NodeDriver ex_list_floating_ip_pools (LIBCLOUD-874, GITHUB-1242) [Miguel Caballer] - [OpenStack] Fix parse_error if 'code' not in API response message (GITHUB-1242) [Miguel Caballer] - [OpenStack] Adapt _to_port function to work with old OpenStack versions (GITHUB-1242) [Miguel Caballer] - [OpenStack] Use SUSPENDED NodeState in OpenStack driver (GITHUB-1269) [Miguel Caballer] - [UpCloud] Update documentation for UpCloud driver (LIBCLOUD-1026, GITHUB-1259) [Ilari Mäkelä] - [NTT CIS] Fix indenting in ex_initiate_drs_failover docstring (GITHUB-1271) [Rick van de Loo] - [NTT CIS] Change endpoint 'canada' to 'ca' in libcloud/common/nttcis.py (GITHUB-1270) [Mitch Raful] - [OpenStack] Fix ``detach_volume`` method so it works with v2 volumes. (GITHUB-1267) [Rick van de Loo] - [CloudSigma] Fix CloudSigma driver so it correctly handles subscription objects without the ``start_time`` and / or ``end_time`` attribute. (GITHUB-1284, LIBCLOUD-1040) [aki-k, Tomaz Muraus] Storage ~~~~~~~ - [Azure] Fix ``upload_object_via_stream`` method so it also works with iterators which don't implement ``seek()`` method. If the iterator doesn't support seek, entire iterator content will be buffered in memory. (LIBCLOUD-1043, GITHUB-1287) [Clemens Wolff] - [CloudFiles] Fix ``download_object_as_stream`` method in the CloudFiles driver. This regression / bug was inadvertently introduced when migrating code to ``requests``. (LIBCLOUD-1039, GITHUB-1283) [Matt Seymour] - [CloudFiles] Fix a bug with ``ChunkStreamReader`` class and make sure file descriptor is also closed if the iterator isn't fully exhausted or if the iterator is never read from. NOTE: This potential open file descriptor leakage only affected code which utilized ``ex_multipart_upload_object`` method. [Tomaz Muraus] Container ~~~~~~~~~ - [Docker] Improve docstring for RegistryClient (GITHUB-1254) [Ken Dreyer] DNS ~~~ - Add new driver for RcodeZero DNS (GITHUB-1256, LIBCLOUD-1025) [MikeAT] - [DigitalOcean] Update DigitalOcean driver so it supports ``ttl`` attribute for ``Record`` objects. This includes support for specifying a record ttl via ``extra['ttl']`` attribute when creating and updating a record. (GITHUB-1252 LIBCLOUD-1022) [Kevin Roy] Storage ~~~~~~~ - Adds missing docs for param ex_prefix & adds to DummyStore. Add ex_prefix kwarg to the `list_container_objects` methods in the base and dummy classes. (GITHUB-1275) [RichardARPANET] Changes in Apache Libcloud 2.4.0 -------------------------------- - Refuse installation with Python 2.6 and Python 3.3 (support was already dropped in Libcloud 2.3.0) - Support Python 3.7 (GITHUB-1227, GITHUB-1236) [Andreas Hasenack, Andrew Starr-Bochicchio, Quentin Pradet] - Cleanup various Python files (GITHUB-1182, GITHUB-1183, GITHUB-1185, GITHUB-1186, GITHUB-1187, GITHUB-1188) [Rémy Léone] - Allow running tests with http_proxy set (GITHUB-1236) [Andreas Hasenack] Common ~~~~~~ - [OpenStack] Document openstack_connection_kwargs method (GITHUB-1219) [Ken Dreyer] - [OpenStack] Handle missing user email in OpenStackIdentityUser (GITHUB-1249) [Ken Dreyer] Compute ~~~~~~~ - [ARM] Support OS disk size definition on node creation (GITHUB-1196) [Vojta Bartoš] - [Digital Ocean] Support floating IPs (GITHUB-1177) [Rick van de Loo] - [Digital Ocean] Support attach/detach for floating IPs (GITHUB-1191) [Rick van de Loo] - [Digital Ocean] Add ex_get_node_details (GITHUB-1221) [Rick van de Loo] - [Digital Ocean] Add tags extra attribute to create_node (GITHUB-1212) [Nikita Chebykin] - [Dimension Data] Fix IndexError in list_images (GITHUB-1171) [Adam Friedman] - [EC2] Add AWS eu-west-3 (Paris) region (GITHUB-1175) [Anthony Monthe] - [EC2] Add description to ex_authorize_security_group_ingress (GITHUB-1122) [Arturo Noha] - [EC2] Added script to automatically get EC2 instance sizes (GITHUB-1211) [Anthony Monthe, Quentin Pradet] - [EC2] Update instance sizes (GITHUB-1238) [Ward Vandewege] - [EC2] Accept tags when create a snapshot (LIBCLOUD-1014, GITHUB-1240) [Rafael Gonçalves] - [GCE] Expand Firewall options coverage (LIBCLOUD-960, GITHUB-1144) [maxlip] - [GCE] Expand network and subnetwork options coverage (LIBCLOUD-985, GITHUB-1181) [maxlip] - [GCE] Extend ex_create_address to allow internal ip creation (GITHUB-1174) [Jeremy Solarz] - [GCE] Allow shared VPC in managed instance group creation (GITHUB-1179) [Boris Chazalet] - [GCE] Support disk_size parameter for boot disk when creating instance (LIBCLOUD-973, GITHUB-1162) [Rahul Paigavan] - [GCE] Update public image projects list (LIBCLOUD-961, GITHUB-1143) [Sean Marlow] - [GCE] Fix _find_zone_or_region for >500 instances (GITHUB-1203) [Léo Ferlin-Sutton] - [GCE] Allow routing_mode=None in ex_create_network (GITHUB-1217) [Daniel Hunsaker] - [OpenStack] Implement Glance Image API v2 (GITHUB-1151) [Rick van de Loo] - [OpenStack] Fix spelling in ex_files description (GITHUB-1197) [Ken Dreyer] - [OpenStack v2] Allow listing image members (GITHUB-1172) [Rick van de Loo] - [OpenStack v2] Allow creating and accepting image members (GITHUB-1176) [Rick van de Loo] - [OpenStack v2] Fix image members methods (GITHUB-1190) [Rick van de Loo] - [OpenStack] Fix API doc for delete_floating_ip (GITHUB-1218) [Ken Dreyer] - [OpenStack] Implement port attaching/detaching (GITHUB-1225) [Rick van de Loo] - [OpenStack] Add methods for getting and creating ports (GITHUB-1226) [Alexander Grooff] - [OpenStack] Add get_user method (GITHUB-1216) [Ken Dreyer] - [OpenStack] Add ex_list_subnets to OpenStack_2_NodeDriver (GITHUB-1215, LIBCLOUD-604) [Miguel Caballer] - [OpenStack] The OpenStack_2_NodeDriver uses two connections (GITHUB-1215, LIBCLOUD-997) [Miguel Caballer] - [OpenStack] The OpenStack_2_NodeDriver /v2.0/networks instead of /os-networks (GITHUB-1215, LIBCLOUD-998) [Miguel Caballer] - [Scaleway] New Scaleway driver (GITHUB-1121, GITHUB-1220) [Daniel Hunsaker, Nándor István Krácser, Rémy Léone] - [Scaleway] Update Scaleway default API host (GITHUB-1239) [Rémy Léone] DNS ~~~ - [Google Cloud DNS] Document driver instantiation (GITHUB-1198) [Gareth McFarlane] Storage ~~~~~~~ - Update docstring for storage provider class (GITHUB-1201) [Clemens Wolff] - [Azure Blob Storage] Allow filtering lists by prefix (LIBCLOUD-986, GITHUB-1193) [Joshua Hawkinson] - [Azure Blob Storage] Update driver documentation (GITHUB-1208) [Clemens Wolff] - [Azure Blob Storage] Fix upload/download streams (GITHUB-1231) [Michael Perel] - [Azure Blob Storage] Fix PageBlob headers (GITHUB-1237) [Andreas Hasenack] - [S3] Guess s3 upload content type (LIBCLOUD-958, GITHUB-1195) [Iuri de Silvio] - [S3] Add Amazon S3 (cn-northwest-1) Storage Driver (GITHUB-1241) [@yangkang55] Other ~~~~~ - Fixed spelling in 2.0 changes documentation (GITHUB-1228) [Jimmy Casey] Changes in Apache Libcloud 2.3.0 -------------------------------- - Drop support for Python 2.6 and Python 3.3 They're no longer supported, and the Python ecosystem is starting to drop support: two of our test dependencies no longer support them. [Quentin Pradet] - Made pytest-runner optional (GITHUB-1167) [Vlad Glagolev] Common ~~~~~~ - Improve warning when CA_CERTS_PATH is incorrectly passed as a list (GITHUB-1118) [Quentin Pradet] - Cleaned up and corrected third-party drivers documentation (GITHUB-1148) [Daniel Hunsaker] - Modernized a few Python examples (GITHUB-1164) [Batuhan Osman Taşkaya] - [OpenStack] Authentify with updated Identity API (LIBCLOUD-965, GITHUB-1145) [Miguel Caballer] Compute ~~~~~~~ - Fix "wait_until_running() method so it also works correctly and doesn't append "None" to the addresses list if node has no IP address. (GITHUB-1156, LIBCLOUD-971) [Tobias Paepke] - [ARM] Fix checking for "location is None" in several functions (LIBCLOUD-926, GITHUB-1098) [Sameh Elsharkawy] - [ARM] Fix error when using SSH key auth with Python 3 (GITHUB-1098) [Sameh Elsharkawy] - [ARM] Fix API call on powerOff, understand PAUSED state (GITHUB-1003) [Markos Gogoulos] - [ARM] Delete VHDs more reliably in destroy_node(), raise exception on unhandled errors (GITHUB-1120) [Lucas Di Pentima] - [ARM] Fix api version used to list and delete NICs (GITHUB-1128) [Peter Amstutz] - [ARM] Allow faster list_nodes() with ex_fetch_power_state=False (GITHUB-1126) [Peter Amstutz, Lucas Di Pentima] - [ARM] Fix delete_old_vhd (GITHUB-1137) [Peter Amstutz, Lucas Di Pentima] - [ARM] Limit number of retries in destroy_node (GITHUB-1134) [Peter Amstutz, Lucas Di Pentima] - [ARM] Fix Retry-After header handling (GITHUB-1139) [Lucas Di Pentima] - [CloudStack] Handle NICs without addresses (GITHUB-1141) [Pierre-Yves Ritschard] - [CloudStack] Add change size and restore (LIBCLOUD-975, GITHUB-1166) [Mauro Murari] - [Digital Ocean] Add ex_enable_ipv6 in DigitalOcean_v2 driver (GITHUB-1130) [Rick van de Loo] - [Digital Ocean] Add support for tags in list_nodes() (LIBCLOUD-967, GITHUB-1149) [Mike Fischer] - [Digital Ocean] Add rebuild and resize commands (LIBCLOUD-977, GITHUB-1169) [Adam Wight] - [EC2] Add new x1.16xlarge and x1e.32xlarge instance type. (GITHUB-1101) [Anthony Monthe] - [EC2] Add AWS EC2 c5 series (GITHUB-1147) [Anthony Monthe] - [EC2] Add AWS EC2 M5 sizes (GITHUB-1159) [Anthony Monthe] - [EC2] Update pricing information for EC2 instances. [Tomaz Muraus] - [EC2] Allow cn-north-1 even without pricing information (LIBCLOUD-954, GITHUB-1127) [Quentin Pradet] - [EC2] Fix EBS volume encryption (GITHUB-1008) [Sergey Babak] - [ECS Aliyun] Support modify_security_group_attributes (GITHUB-1157) [Zhang Yiming] - [GCE] Allow adding labels to images (GITHUB-1138) [Katriel Traum, Eric Johnson] - [GCE] Allow adding license strings to images (GITHUB-1136) [Katriel Traum, Eric Johnson] - [GCE] Support GCE node labels. (LIBCLOUD-934, GITHUB-1115) [@maxlip] - [GCE] Fix `GCEList` pagination. (GITHUB-1095) [Yap Sok Ann] - [GCE] Allow setting service account in instance templates (LIBCLOUD-947, GITHUB-1108) [Evan Carter] - [GCE] Add support for private IP addresses in GCE instance creation (LIBCLOUD-944, GITHUB-1107) [Gareth Mcfarlane] - [GCE] Allow for use of shared network (VPC) and subnetwork (GITHUB-1165) [Boris Chazalet] - [GCE] Add support for accelerators (LIBCLOUD-963, GITHUB-1163) [Michael Johnson] - [ProfitBricks] Update driver and add support for the new API v4. (GITHUB-1103) [Nurfet Becirevic] - [ProfitBricks] Fix list_snapshots() method (GITHUB-1153) [Chad Phillips] - [UpCloud] New driver for UpCloud (LIBCLOUD-938, GITHUB-1102) [Mika Lackman, Ilari Mäkelä] - [UpCloud] Use disk size and storage tier also when creating node from template (LIBCLOUD-952, GITHUB-1124) [Mika Lackman] - [UpCloud] Allow to define hostname and username (LIBCLOUD-951, LIBCLOUD-953, GITHUB-1123, GITHUB-1125) [Mika Lackman] - [UpCloud] Add pricing information to list_sizes (LIBCLOUD-969, GITHUB-1152) [Mika Lackman] Storage ~~~~~~~ - Added Digital Ocean Spaces driver (LIBCLOUD-955, GITHUB-1129) [Andrew Starr-Bochicchio] - [Digital Ocean Spaces] Add support for AMS3 region (GITHUB-1142) [Andrew Starr-Bochicchio] - [Digital Ocean Spaces] Add support for SGP1 region (GITHUB-1168) [Andrew Starr-Bochicchio] - Fix a bug / regression which resulted in increased memory consumption when using ``download_object`` method. This method would store whole object content in memory even though there was no need for that. This regression was introduced in 2.0.0 when we moved to using ``requests`` library. (GITHUB-1132) [Quentin Pradet] - Fix a regression with hash computation performance and memory usage on object upload inadvertently introduced in 2.0.0 and make it more efficient. (GITHUB-1135) [Quentin Pradet] Changes in Apache Libcloud 2.2.1 -------------------------------- Common ~~~~~~ - Fix an issue with installation failing on some operating system and file systems combinations (e.g. ecryptfs layered on top of ext4) which don't support file names longer than 143 characters. (LIBCLOUD-946, GITHUB-1112) Reported by Cyrille Verrier. [Tomaz Muraus] Compute ~~~~~~~ - [EC2] add g3 instance types [GITHUB-1101] (@zulupro) - [EC2] add 'end' to ec2 reserved_node [GITHUB-1099] (@xofer) - Decrease sleep delay (from 1.5 to 0.2 seconds) inside paramiko client which is used to prevent busy waiting while waiting for data on the channel. This should cause deploy scripts which produce a lot of output in incremental manner to finish faster. [Tomaz Muraus] - Fix a regression in the Azure ARM driver which didn't allow custom storage URI suffix to be used with create_node. (GITHUB-1110) [Lucas Di Pentima] Tests ~~~~~ - Make sure we normalize header values and cast all the numbers to strings in base connection classes used by tests. (LIBCLOUD-945, GITHUB-1111) Reported by Erich Eckner. [Tomaz Muraus] Changes in Apache Libcloud 2.2.0 -------------------------------- Compute ~~~~~~~ - [EC2] add g3 instance types [GITHUB-1101] (@zulupro) - [EC2] add 'end' to ec2 reserved_node [GITHUB-1099] (@xofer) Changes in Apache Libcloud 2.2.0 -------------------------------- Common ~~~~~~ - [GCE] Scrape prices for GCE Australia Region [GITHUB-1085] (Francisco Ros) Compute ~~~~~~~ - [ARM] Add option to create static public IP [GITHUB-1091, LIBCLOUD-918] (Aki Ketolainen) - [SOFTLAYER] Add `get_image` method to class [GITHUB-1066] (Francois Regnoult) - [ARM] Add Storage support, volumes, snapshots [GITHUB-1087] (Sergey Babak) Container ~~~~~~~~~ - [DOCKER] Fixes to support TLS connection [GITHUB-1067] (johnnyWalnut) DNS ~~~ - [ROUTE53] Fix for TXT and SPF records, when user didn't escapsulate data in quotes, the API would fire error. As reported by @glyph [LIBCLOUD-875, GITHUB-1093] (Anthony Shaw) - [LINODE] Add priority to the extra dictionary in record instances [GITHUB-1088] (@mete0r) Load Balancer ~~~~~~~~~~~~~ - Fixed AWS ALB/ELB driver init method to instantiate nested connection object properly [LIBCLOUD-936, GITHUB-1089] (Anton Kozyrev) Storage ~~~~~~~ - [CLOUDFILES] Update OpenStackSwiftConnection to work with auth version 3.0 [GITHUB-1068] (Hakan Carlsson) - [CLOUDFILES] Add SSL URI support [GITHUB-1076, LIBCLOUD-458] (@ayleph) Changes in Apache Libcloud 2.1.0 -------------------------------- Common ~~~~~~ - [AWS] Update prices and fix some region names [GITHUB-1056] (Francisco Ros) - Fix bug in utils.decorators wrap exception method, used by vsphere driver [GITHUB-1054] (Anthony Shaw) - Use PyTest as the unit testing runner (Anthony Shaw) - Use of LXML is now disabled by defalt, use ``libcloud.utils.py3.DEFAULT_LXML = True`` to reenable. LXML has compatibility issues with a number of drivers and etree is a standard package. [GITHUB-1038] (Anthony Shaw) - Switch RawResponse class to use content body instead of text body, up to 10x performance improvement for methods like StorageDriver.download_object [GITHUB-1053] (Quentin Pradet) Compute ~~~~~~~ - [OPENSTACK] Add support for Nova 2.x and Keystone 3 [GITHUB-1052] (Anthony Shaw) - [GCE] Add loadBalancingScheme parameter for ex_create_forwarding_rule method in GCE driver. [GITHUB-1079] (@sT331h0rs3) - [GCE] Fix error codes not being parsed in certain scenarios [GITHUB-1074, LIBCLOUD-925] (micafer) - [EC2] Fix node's Block Device Mapping was parsed from incorrect mapping. EbsInstanceBlockDevice is different from EbsBlockDevice. [GITHUB-1075] (Gennadiy Stas) - [GANDI] Fixes the location name in image and instance type classes [GITHUB-1065] (Sayoun) - [GCE] Fix method for create instance properties, it previously ignored the disk type parameter and defaulted to pd-standard. [GITHUB-1064] (Evan Carter) - Fix missing return data from EC2 billing product methods [GITHUB-1062] (Alex Misstear) - Handle [VULTR] API rate limiting [GITHUB-1058] (Francisco Ros) - Fix Kili driver not correctly fixing the auth version for openstack to 2.0_password [GITHUB-1054] (Anthony Shaw) - [EC2] Add i3 instance types for AWS [GITHUB-1038] (Stephen Mullins) - [VULTR] Extend extra dict of Vultr sizes to include additional fields (plan_type and available_locations) [GITHUB-1044] (Francisco Ros) Container ~~~~~~~~~ - New driver for Google Container Engine [GITHUB-1059] (Andy Maheshwari) - [KUBERNETES] Fix get_container method responding with None [GITHUB-1054] (Anthony Shaw) - [DOCKER] Fix for start_container method [GITHUB-1049] (@johnnyWalnut) - [DOCKER] fix add an extra check otherwise list_containers breaks with AttributeError when fromImages is specified [GITHUB-1043] (@johnnyWalnut) Storage ~~~~~~~ - [S3] Fix raise in s3.upload_object_via_stream [LIBCLOUD-914, GITHUB-1055] (Quentin Pradet) Changes in Apache Libcloud 2.0.0 -------------------------------- Common ~~~~~~ - Fix OpenStack drivers not correctly setting URLs when used with identity API, would default to 127.0.0.1 and service catalog URLs were not adhered to. [GITHUB-1037, LIBCLOUD-912, LIBCLOUD-904] (Anthony Shaw) - Fix Aliyun ECS, Load balancer and storage adapters when using unicode UTF-8 characters in the names of resources in 2.0.0rc2 < it would fail as a MalformedResponseError, Python 2.7 element tree was raising a unicode error [GITHUB-1032] [GITHUB-994] (Anthony Shaw) - Refactor the test classes to use the full libcloud.http and libcloud.common.base modules, with Connection, Response all used with requests_mock. This increases our test coverages and catches bugs in drivers' custom parse_body and auth modules [GITHUB-1031] (Anthony Shaw) - Rename libcloud.httplib_ssl to libcloud.http now that we don't use httplib [GITHUB-1028] (Anthony Shaw) Compute ~~~~~~~ - [GOOGLE] Add test to check that can create a GCE volume at a given location [GITHUB-1048] (Francisco Ros) - [GOOGLE] Fix GCENodeDriver.ex_get_volume() when zone param is of class GCEZone or NodeLocation [GITHUB-1047] (Francisco Ros) - [GOOGLE] Fix call to GCENodeDriver._ex_populate_volume_dict [GITHUB-1046] (Francisco Ros) - [ARM] Add support for Azure Cloud Environments as well as Locations [GITHUB-969] (Peter Amstutz) - [EC2] Add support for ModifyVolume and DescribeVolumesModifications [GITHUB-1036] (Hennadii Stas) - [ARM] Fix string representation of the VhdImage type and fix listing of Public IP addresses [GITHUB-1035] (Anthony Shaw) - [GOOGLE] Remove validation checks for guestOsFeatures [GITHUB-1034] (Max Illfelder) - [VSPHERE] Fix issue with authentication methods crashing [GITHUB-1031] (Anthony Shaw) - [ARM] Add network security groups to azure ARM [GITHUB-1033] (Joseph Hall) - [ARM] Add the ability to list resource groups [GITHUB-1032] (Joseph Hall) - Add 1&1 compute driver [LIBCLOUD-911] [GITHUB-1029] (Jasmin Gacic) - Fix Azure ARM driver condition for ex_list_publishers where location is specified [GITHUB-1030] (Joseph Hall) - Added Import Snapshot and Describe Import Snapshot to EC2 compute driver [GITHUB-1023] (Nirzari Iyer) - Add price_monthly extra param to digitalocean sizes [GITHUB-1021] (Francisco Ros) - Add aliyun ecs instance join leave security group [GITHUB-992] (Jie Ren) - Add keypair management to OnApp driver [GITHUB-1018] (Tinu Cleatus) - Add missing regions in AWS storage and compute drivers [GITHUB-1019] (Alex Misstear) - Add SR-IOV net support to images in EC2 compute driver [GITHUB-1020] (Alex Misstear) - Fix - update t2.small image size from 11 CPU to 1 [GITHUB-1022] (Francisco Ros) - Added Billing Product for image in EC2 compute driver [GITHUB-1024] (Nirzari Iyer) DNS ~~~ - Add OnApp driver [GITHUB-1017] [LIBCLOUD-907] (Tinu Cleatus) Changes in Apache Libcloud 2.0.0rc2 ----------------------------------- Common ~~~~~~ - Fix LIBCLOUD_DEBUG trying to decompress already decompressed responses [LIBCLOUD-910] (Anthony Shaw) - Added an integration test API and a test suite for validating functionality without mocking any libcloud subsystems [GITHUB-970] (Anthony Shaw) - Fix for Linode classes since 2.0x [GITHUB-1026] (Anthony Shaw) - Fix CertificateConnection not correctly signing requests in 2.0rc1, impacted Azure classic driver, OpenStack and Docker driver [GITHUB-1015] (Anthony Shaw) - Change Cloudscale to cloudscale.ch. [GITHUB-993] (David Halter) - Explicitly check if response is None in RawResponse class [GITHUB-1006] [LIBCLOUD-901] (Richard Xia) Compute ~~~~~~~ - Outscale SAS doc improvements and logo update [GITHUB-950] (Javier M Mellid) - [GCE] Allow preemptible instances to be created [GITHUB-954] (John Baublitz) - Add support for forcing detachment of EBS volumes to EC2 driver [GITHUB-1007] (Sergey Babak) - Fix Public IP not assigned when creating NIC on Azure ARM [GITHUB-1013] [LIBCLOUD-906] (Simone Ripamonti) - [ONAPP] Add list images support for OnApp driver [GITHUB-1011] (Tinu Cleatus) - [EC2] Add r4 instance types for AWS [GITHUB-997] (Jens Deppe) - [EC2] support for AWS eu-west-2 and ca-central-1 regions [GITHUB-1009] (Marat Komarov) - [EC2] Add P2 GPU instance types [GITHUB-996] (MJK) - [EC2] Add method to modify snapshot attribute for EC2 [GITHUB-990] (Sayan Chowdhury) - [Linode] Add start, stop instance methods and fix incorrect state TERMINATED to STOPPED [GITHUB-986] (Markos Gogoulos) - [EC2] Add ENA support for EC2 compute images [GITHUB-983] (Alex Misstear) - [Azure ARM] fix typeerror on ex_list_nics [GITHUB-979] (Choi Jongu) - [GCE] allow delete instances from managed group [GITHUB-975] (@zacharya19) Storage ~~~~~~~ - Reintroduce S3 multipart upload support with signature v4 [GITHUB-1005] [LIBCLOUD-834] (Alex Misstear) Changes Apache Libcloud 2.0.0rc1 -------------------------------- Common ~~~~~~ - Fix DEBUG mode, also add support for using io.StringIO as the file handle when calling libcloud.enable_debug. (GITHUB-978, LIBCLOUD-887) [Anthony Shaw] - Introduction of the requests package as the mechanism for making HTTP requests for all drivers. (GITHUB-928) [Anthony Shaw] - Fix bug where custom port and secure flag would not get propagated to connection class. (GITHUB-972) [Anthony Shaw] - Fix bug where custom port would not get propagated to connection. (GITHUB-971) [Anthony Shaw] - Fix bug where instantiating a connection from URL and then requesting an action with a leading / would lead to a malformed URL. (GITHUB-976) [Anthony Shaw] Compute ~~~~~~~ - Fix a bug in profitbricks driver where listing snapshots would request a malformed URL. [GITHUB-976] (Anthony Shaw) - Fix LIBCLOUD-806 bug where vsphere driver cannot be instantiated. (GITHUB-967) [Anthony Shaw] - [google compute] Improve performance of list nodes by caching volume information. (GITHUB-813, LIBCLOUD-826) [Tom Melendez] Changes in Apache Libcloud 1.5.0 -------------------------------- Common ~~~~~~ - Set Dimension Data compute, backup and load balancer to default to 2.4 API. (GITHUB-961) [Samuel Chong] Compute ~~~~~~~ - [azure] New method for accessing rate cards. (GITHUB-957) [Soren L. Hansen] - [gce] Allow multiple preemptible instances to be created. (GITHUB-954) [John Baublitz] - [openstack] Add new Connection class to support VOMS proxys to keystone servers. (GITHUB-959) [micafer] - [outscale] Added support for changed API for describing quotas. (GITHUB-960) [Javier M. Mellid] - [ec2] Added m4 instances to us-gov and brazil, added m4.16xlarge to all. (GITHUB-964) [Matthew Tyas] - Add new CloudScale.ch driver (GITHUB-951) [Dave Halter] - [google compute] Bug fix for ex_create_multiple_nodes Google Cloud disk auto delete. (GITHUB-955) [John Baublitz] - [google compute] Add "MULTI_IP_SUBNET" guestOsFeatures option. (GITHUB-956) [Max Illfelder] - [dimensiondata] Added support for 2.4 API, added support for image import, cloning. Add feature for changing NIC VLANs, add feature for changing NIC order for a server. (GITHUB-953) [Samuel Chong] - [ec2] Add US-EAST2 (Ohio). (GITHUB-946) [Matthew Harris] - [google compute] Fix to allow multiple node creation with subnets. (GITHUB-949) [John Baublitz] Container ~~~~~~~~~ - [rancher] The scheme (secure) and port no longer need to be explicitly specified, allowing a user to simply copy in the string provided to them from Rancher. (GITHUB-958) [Matthew Ellison] Changes in Apache Libcloud 1.4.0 -------------------------------- Compute ~~~~~~~ - Introduce new Azure ARM driver. [Peter Amstulz] - [ec2] Fix the bug that created the node at ecs driver and implement the method for creating public ip. (GITHUB-943) [watermelo] - [profitbricks] changes to the ProfitBricks compute driver to drop support for the old SOAP api (now end of life) and provide support for v3 of the REST api. (GITHUB-938) [Matt Finucane] - [cloudsigma] Added Warsaw (waw) region. (GITHUB-942) [Kamil Chmielewski] - [google compute] List images fix for projects > 500 images. (GITHUB-939) [Scott Crunkleton] - [ec2] Add st1 and sc1 volume types to valid types. (GITHUB-925) [Sean Goller] - [digital ocean] add ex_change_kernel in DigitalOcean_v2 driver. (GITHUB-922) [Rick van de Loo] - [digital ocean] add ex_hard_reboot in DigitalOcean_v2 driver. (GITHUB-920) [Rick van de Loo] - [openstack] add ex_start_node for the openstack driver. (GITHUB-919) [Rick van de Loo] - [vultr] Extra Attributes for Node Creation on Vultr. (GITHUB-917) [Fahri Cihan Demirci] - [vultr] Implement SSH Key Create/Delete Methods for Vultr. (GITHUB-914) [Fahri Cihan Demirci] - [dimension data] No longer throw error when powering off a node that is already stopped. (GITHUB-912) [Samuel Chong] - [dimension data] Refactor create_node for MCP2 to support CaaS API 2.3 feature. Can now specify Network Adapter Name for primary and additional NIC. Parameters in create_node function is tailored for MCP2. (GITHUB-902) [Samuel Chong] - Volume snapshot operations, i.e. creating, listing and deleting volume snapshots, for the Digital Ocean driver. (LIBCLOUD-861, GITHUB-909) [Fahri Cihan Demirci] - Added snapshot management to OVH compute. (GITHUB-897) [Anthony Monthe] - [GCE] Support for HTTP(S) proxies with BackendServices. (GITHUB-856) [Tom Melendez] Container ~~~~~~~~~ - [docker] As reported in the corresponding bug, the docker daemon will respond in an install_image call with all the messages produced during the procedure parsed as json docs. In that case the response headers also contain the value 'transfer-encoding':'chunked'. That kind of response can now be parsed properly by the DockerResponse parse_body method. Also, another small change is that previously the id of the new image was marked in the json document as id, but now it's marked as sha256, so the regex used to discover the id has been updated. (GITHUB-918) [Pavlos Tzianos] Load Balancing ~~~~~~~~~~~~~~ - Introduce AWS Application Load Balancer (ALB) driver. (LIBCLOUD-869, GITHUB-936) [Anton Kozyrev] - Fix bug where GCE Load balancer supposes that all VMs have public ips. (LIBCLOUD-879, GITHUB-952) [Chris Walker] Storage ~~~~~~~ - [s3] Add AP-Southeast2 as region. - [google] Prevent GCE auth to hide S3 auth. (GITHUB-921) [Quentin Pradet] - [GCS] Fixed some google_storage.py URL cleaning. (GITHUB-901) [Scott Crunkleton] Changes in Apache Libcloud 1.3.0 -------------------------------- General ~~~~~~~ - Introduced new base API for instantiating drivers. (GITHUB-822) [Anthony Shaw] - Added certificate path for SLES12/OpenSUSE12. (GITHUB-884) [Michael Calmer] - Deprecate DigitalOcean v1 API support in favour of v2 API. (GITHUB-889, GITHUB-892) [Andrew Starr-Bochicchio] - Deprecate RunAbove cloud drivers in favour of new OVH cloud driver. (GITHUB-891) [Anthony Monthe] Compute ~~~~~~~ - Fix reporting function for detailed admin logs in Dimension Data Driver. (GITHUB-898) [Anthony Shaw] - Added edit firewall functionality to Dimension Data driver. (GITHUB-893) [Samuel Chong] - Bugfix - Fixed listing nodes issue in Python 3. (LIBCLOUD-858, GITHUB-894) [Fahri Cihan Demirci] - Added FCU (Flexible Compute Unit) support to the Outscale driver. (GITHUB-890) [Javier M. Mellid] - [google compute] Add "WINDOWS" guestOsFeatures option. (GITHUB-861) [Max Illfelder] - When creating volumes on OpenStack with defaults for `location` or `volume_type`, newer OpenStack versions would throw errors. The OpenStack driver will now only post those arguments if non-`NoneType`. (GITHUB-857) [Allard Hoeve] - When fetching the node details of a non-existing node, OpenStack would raise a `BaseHTTPError` instead of returning `None`, as was intended. Fixed tests and code. (GITHUB-864) - Added `ex_stop_node` to the OpenStack driver. (GITHUB-865) [Allard Hoeve] - When creating volume snapshot, the arguments `name` and `description` are truely optional when working with newer OpenStack versions. The OpenStack driver will now only post thost arguments if they are non-`NoneType`. (GITHUB-866) [Allard Hoeve] - StorageVolumeSnapshot now has an attribute `name` that has the name of the snapshot if the provider supports it. This used to be `.extra['name']`, but that is inconsistent with `Node` and `StorageVolume`. The `extra` dict still holds `name` for backwards compatibility. (GITHUB-867) [Allard Hoeve] Container ~~~~~~~~~ - Introduced new Rancher driver (GITHUB-876) [Mario Loria] - Fixed bug in Docker util library for fetching images from the docker hub API. API was returning 301 and redirects were not being followed. (GITHUB-862) [Anthony Shaw] Load Balancer ~~~~~~~~~~~~~ - Added fetch tags support in elb driver. (GITHUB-848) [Anton Kozyrev] Storage ~~~~~~~ - Added storage permissions for Google Cloud Storage. (GITHUB-860) [Scott Crunkleton] Changes in Apache Libcloud 1.2.1 -------------------------------- Backup ~~~~~~ - Fix issue enabling backups on Dimension Data driver. (GITHUB-858) [Mark Maglana, Jeff Dunham, Anthony Shaw] Changes in Apache Libcloud 1.2.0 -------------------------------- General ~~~~~~~ - Fix caching of auth tokens in the Google Compute Engine drivers. Now we make sure that the file is truncated before writing a new token. Not truncating the file would cause issues if the new token is shorted then the existing one which is cached in the file. (GITHUB-844, LIBCLOUD-835) [Paul Tiplady] Compute ~~~~~~~ - [gce] Fix image undeprecation in GCE. (GITHUB-852) [Max Illfelder] - [gce] Added Managed Instance Groups. (GITHUB-842) [Tom Melendez] - [gce] Allow undeprecation of an image. (GITHUB-851) [Max Illfelder] - [cloudstack] BUGFIX Values with wildcards failed signature validation. (GITHUB-846) [Ronald van Zantvoot] - [cloudstack] Added StorageState-Migrating to the cloudstack driver. (GITHUB-847) [Marc-Aurèle Brothier] - [google compute] Update copy image logic to match create image. (GITHUB-828) [Max Illfelder] - Removed HD attribute from the Abiquo compute driver to support the 3.4 API. (GITHUB-840) [David Freedman] - Add image and size details to `list_nodes` response in Dimension Data driver. (GITHUB-832) [Anthony Shaw] - Add support for changing VM admin password in VMware driver. (GITHUB-833) [Juan Font Alonso] - Add Barcelona (Spain) region to the Aurora Compute driver. (GITHUB-835) [Wido den Hollander] - Various improvements in the libvirt driver. (GITHUB-838) [Rene Kjellerup] Load balancer ~~~~~~~~~~~~~ - Add support for temporary IAM role credentials (token) to the AWS ELB driver. (GITHUB-843) [Anton Kozyrev] DNS ~~~ - Updated the 'extra' parameter in `update_record()` to be optional in aurora driver. (GITHUB-830) [Wido den Hollander] - Support for iterating over records and zones in the Aurora DNS driver. (GITHUB-829) [Wido den Hollander] - Add support for DS, PTR, SSFHFP and TLSA record type to the Aurora DNS driver. (GITHUB-834) [Wido den Hollander] Container ~~~~~~~~~ - Add network mode and labels when creating containers within docker driver. (GITHUB-831) [Jamie Cressey] Storage ~~~~~~~ - Fix authentication issue in S3/China region, disabled multipart uploads as not supported by region. (GITHUB-839) [Luke Morfitt] Changes with Apache Libcloud 1.1.0 ---------------------------------- General ~~~~~~~ - Add support for automatic SNI (SSL extension) using the hostname supplied to connect to. Note: This functionality is only available in Python 2.7.9 and Python >= 3.2. (LIBCLOUD-827, GITHUB-808) [David Freedman] Compute ~~~~~~~ - Add support image guest OS features in GCE driver. (GITHUB-825) [Max Illfelder] - Added forceCustimization option for vcloud director driver. (GITHUB-824) [Juan Font] - Add node lookup by UUID for libvirt driver. (GITHUB-823) [Frank Wu] - Add block storage support to DigitalOcean node driver. (GITHUB-807) [Adam Wolfe Gordon] - Add SASL auth support to libvirt driver. (GITHUB-809) [Katana-Steel] - Allow VIPs in Dimension Data driver to bind to any port. (GITHUB-818) [Mark Maglana] - Add support for deleting a security group to the Aliyun ECS driver. (GITHUB-816) [Heng Wu] - Add ``ex_force_customization`` argument to the ``ex_deploy_node`` in vCloud driver. (GITHUB-824) [Juan Font] - Add support for listing attributes for a particular security group (``ex_list_security_group_attributes``) to the Aliyun ECS driver. (GITHUB-826) [Heng Wu] - Add new Mumbai, India region to the EC2 driver. [Tomaz Muraus] - Add driver for the new AWS cn-north-1 region. (GITHUB-827, LIBCLOUD-820) [Jamie Cressey] - Fix authentication with temporary IAM role credentials (token) in the EC2 driver. (GITHUB-820) [Alejandro González] Container ~~~~~~~~~ - Fixed API compatibility for Docker Container driver with API 1.24, set driver to use versioned URL for all communication. Backported changes to 1.21 API (GITHUB-821) [Anthony Shaw] Load Balancer ~~~~~~~~~~~~~ - Added additional parameters to the Rackspace driver in `list_balancers` for filtering and searching. (GITHUB-803) [João Paulo Raittes] Changes with Apache Libcloud 1.0.0 ---------------------------------- General ~~~~~~~ - Fix a regression with ``timeout`` argument provided via ``_ex_connection_class_kwargs`` method being overriden with ``None`` inside the ``BaseDriver`` constructor method. Reported by Jay Rolette. (GITHUB-755) [Tomaz Muraus, Jay Rolette] - Fix OpenStack v3 authentication and allow user to provide a custom value for the OpenStack ``domain`` parameter. Previously only possible value as a default value of ``Default``. (GITHUB-744) [Lionel Schaub] - Add support for authenticating against Keystone and OpenStack based clouds using OpenID Connect tokens. (GITHUB-789) [Miguel Caballer] Compute ~~~~~~~ - GCE nodes can be launched in a subnetwork (GITHUB-783) [Lars Larsson] - Add Subnetworks to GCE driver (GITHUB-780) [Eric Johnson] - Fix missing pricing data for GCE (LIBCLOUD-713, GITHUB-779) [Eric Johnson] - Add Image Family support for GCE (GITHUB-778) [Rick Wright] - Fix a race condition on GCE driver `list_nodes()`- Invoking GCE’s `list_nodes()` while some VMs are being shutdown can result in the following `libcloud.common.google.ResourceNotFoundError` exception to be raised. (GITHUB-727) [Lénaïc Huard] - Allow user to filter nodes by location by adding optional `location` argument to the `list_nodes()` method in the CloudStack driver. (GITHUB-737) [Lionel Schaub] - Fix OpenStack IP type resolution - make sure IP addresses are correctly categorized and assigned on `private_ips` and `public_ips` Node attribute. (GITHUB-738) [Lionel Schaub] - Add new `Perth, Australia` and `Manila, Philippines` region to the CloudSigma v2 driver. [Tomaz Muraus] - Update libvirt driver so it returns false if a non-local libvirt URL is used (right now only local instances are supported). (LIBCLOUD-820, GITHUB-788) [René Kjellerup] - Update libvirt driver to use `ip neight` command instead of `arp` to retrieve node MAC address if `arp` command is not available or the current user doesn't have permission to use it. (LIBCLOUD-820, GITHUB-788) [René Kjellerup] - Update ``create_volume`` method in the CloudStack driver and add ``ex_volume_type`` argument to it. If this argument is provided, a volume which names matches this argument value will be searched and selected among the available disk offerings. (GITHUB-785) [Greg Bishop] Storage ~~~~~~~ - Add support for AWS signature v4 to the Outscale storage driver. (GITHUB-736) [Javier M. Mellid] - Add new S3 RGW storage driver. (GITHUB-786, GITHUB-792) [Javier M. Mellid] Loadbalancer ~~~~~~~~~~~~ - Update AWS ELB driver to use signature version 4 for authentication. This way, the driver also work with the `eu-central-1` region. (GITHUB-796) [Tobias Paepke] DNS ~~~ - Add BuddyNS driver. (GITHUB-742) [Oltjano Terpollari] - Added DNSPod driver (https://www.dnspod.com). (GITHUB-787) [Oltjano Terpollari] Changes with Apache Libcloud 1.0.0-rc2 -------------------------------------- General ~~~~~~~ - Fix a bug with consuming stdout and stderr in the paramiko SSH client which would manifest itself under very rare condition when a consumed chunk only contained a single byte or part of a multi byte UTF-8 character. [Lakshmi Kannan, Tomaz Muraus] - Increase default chunk size from ``1024`` to ``4096`` bytes in the paramiko SSH client. This results in smaller number of receive calls on the average. [Tomaz Muraus] - Fix to Dimension Data API address for Middle-East and Africa (GITHUB-700) [Anthony Shaw] - Addition of Dimension Data Australia federal government region to dimension data drivers. (GITHUB-700) [Anthony Shaw] - Throw a more user-friendly exception on "No address associated with hostname". (GITHUB-711, GITHUB-714, LIBCLOUD-803) [Tomaz Muraus, Scott Crunkleton] * Remove deprecated provider constants with the region in the name and related driver classes (e.g. ``EC2_US_EAST``, etc.). Those drivers have moved to single provider constant + ``region`` constructor argument model. [Tomaz Muraus] * Introduce new `list_regions`` class method on the base driver class. This method is to be used with provider drivers which support multiple regions and ``region`` constructor argument. It allows users to enumerate available / supported regions. [Tomaz Muraus] Compute ~~~~~~~ - [dimension data] added support for VMWare tools VM information inside list_nodes responses (GITHUB-734) [Jeff Dunham] - [ec2] added ex_encrypted and ex_kms_key_id optional parameters to the create volume method (GITHUB-729) [Viktor Ognev] - [dimension data] added support for managing host anti-affinity rules, added paging support to all supported calls and added support for requesting priority ordering when creating ACL rules (GITHUB-726) [Jeff Dunham] - [openstack] when creating floating IPs, added pool_id as an optional argument (GITHUB-725) [marko-p] - [google compute] Added setMachineType method to allow for changing sizes of instances (GITHUB-721) [Eric Johnson] - [google compute] allow bypassing image search in standard project list (GITHUB-713) [Max Illfelder] - Add support for requesting a MKS token for accessing the remote console in VMware vCloud driver (GITHUB-706) [Juan Font Alonso] - Add support in VMware vCloud driver for v5.5 API, with snapshot support (GITHUB-658) [Juan Font Alonso] - Added support for adding a family to an image on Google Compute Driver (GITHUB-704) [Max Illfelder] - Deprecated IBM SCE, HP Helion, OpSource, Ninefold and CloudFrames drivers, removed driver code and tests. (GITHUB-701, LIBCLOUD-801) [Anthony Shaw] - Introduced error messages (`libcloud.compute.deprecated`) for deprecated drivers (GITHUB-701, LIBCLOUD-801) [Anthony Shaw] - New Compute drivers- BSNL, Indosat, Med-1, NTT-America, Internet Solutions (GITHUB-700) [Anthony Shaw] - Fix to set default signature version for AWS Seoul region to v4, removed non-supported size (hs1.xlarge) (GITHUB-684) [Geunwoo Shin] - Support filtering by location in list_nodes for dimension data compute driver fix lack of paging support (GITHUB-691) [Jeff Dunham] - Support for filtering by IPv4, IPv6, network, network domain, VLAN in Dimension data driver. (GITHUB-694) [Jeff Dunham] - Added `Node.created_at` which, on supported drivers, contains the datetime the node was first started. (GITHUB-698) [Allard Hoeve] [Rick van de Loo] - New driver for Aliyun Elastic Compute Service. (LIBCLOUD-802, GITHUB-712) [Sam Song, Heng Wu] Storage ~~~~~~~ - Added Outscale storage driver (GITHUB-730) [Javier M. Mellid] - Improvements to Google Auth for Storage and Compute and MIME bug fix (LIBCLOUD-800, GITHUB-689) [Scott Crunkleton] - Implement ``get_container``, ``get_object`` and ``upload_object_via_stream`` methods in the Backblaze B2 storage driver. Note: Backblaze API doesn't upload streaming uploads so when using ``upload_object_via_stream`` whole file is read and buffered in memory. (GITHUB-696) [Jay jshridha] - New driver for Aliyun OSS Storage Service. (LIBCLOUD-802, GITHUB-712) [Sam Song] Loadbalancer ~~~~~~~~~~~~ - New driver for Aliyun SLB Loadbalancer Service. (LIBCLOUD-802, GITHUB-712) [Sam Song] DNS ~~~~ - Added NearlyFreeSpeech.net (NSFN) driver [Ken Drayer] (GITHUB-733) - Added Lua DNS driver [Oltjano Terpollari] (GITHUB-732) - Added NSOne driver [Oltjano Terpollari] (GITHUB-710) - Fix a bug in the GoDaddy driver - make sure ``host`` attribute on the connection class is correctly set to the hostname. [Tomaz Muraus] - Fix handling of ``MX`` records in the Gandi driver. (GITHUB-718) [Ryan Lee] Backup ~~~~~~ - Dimension Data - added additional testing, fixed bug on client response naming, added support for adding backup clients to a backup enabled node. (GITHUB-692, GITHUB-693, GITHUB-695) [Jeff Dunham] Changes with Apache Libcloud 1.0.0-pre1 --------------------------------------- General ~~~~~~~ - Introduction of container based drivers for Docker, Rkt and Container-as-a-service providers (LIBCLOUD-781, GITHUB-666) [Anthony Shaw] - Introduce a new ``libcloud.backup`` API for Backup as a Service projects and products. (GITHUB-621) [Anthony Shaw] - Also retry failed HTTP(s) requests upon transient "read operation timed out" SSL error. (GITHUB-556, LIBCLOUD-728) [Scott Kruger] - Throw a more user-friendly exception if a client fails to establish SSL / TLS connection with a server because of an unsupported SSL / TLS version. (GITHUB-682) [Tomaz Muraus] Compute ~~~~~~~ - Add ap-northeast-2 region to EC2 driver (South Korea) (GITHUB-681) [Anthony Shaw] - Added Added volume type to EC2 volume extra to EC2 driver. (GITHUB-680) [Gennadiy Stas] - Add LazyObject class that provides lazy-loading, see `GCELicense` for usage (LIBCLOUD-786, GITHUB-665) [Scott Crunkleton] - Added t2.nano instance type to EC2 Compute driver (GITHUB-663) [Anthony Shaw] - Support for passing the image ID as a string instead of an instance of image when creating nodes in Dimension Data driver. (GITHUB-664) [Anthony Shaw] DNS ~~~ - Add support for 'health checks' in Aurora DNS driver (GITHUB-672) [Wido den Hollander] - Make sure ``ttl`` attribute is correctly parsed and added to the ``Record`` ``extra`` dictionary. (GITHUB-675) [Wido den Hollander] - Improve unit tests of Aurora DNS driver (GITHUB-679) [Wido den Hollander] Changes with Apache Libcloud 0.20.1 ----------------------------------- Compute ~~~~~~~ - [google] Allow for old and new style service account client email address (LIBCLOUD-785) [Hoang Phan] Changes with Apache Libcloud 0.20.0 ----------------------------------- General ~~~~~~~ - Added .editorconfig file for easier editing (GITHUB-625) [Misha Brukman] - Fix a bug with Libcloud accidentally setting paramiko root logger level to DEBUG (this should only happen if ``LIBCLOUD_DEBUG`` environment variable is provided). Reported by John Bresnahan. (LIBCLOUD-765) [Tomaz Muraus, John Bresnahan] - Simply travis and tox config (.travis.yml, tox.ini). (GITHUB-608) [Anthony Monthe] - Fixed Python2.6 unit testing (and Google Cloud Storage tests) (GITHUB-648) [Scott Crunkleton] Compute ~~~~~~~ - [google] Allow for old and new style service account client email address (LIBCLOUD-785) [Hoang Phan] - Minor security improvement for storing cached GCE credentials (LIBCLOUD-718) [Siim Põder] - Removed DreamHosts Compute Driver, DreamHosts users will now use the OpenStack Node driver since DreamHosts are OpenStack API compliant (GITHUB-655) [Stephano Maffulli] - Added additional kwargs to the create_node method for Dimension Data driver, allowing the user to specify the RAM and CPU upfront. Added a ex_reconfigure_node method and ex_list_customer_images as well as updating the API to 2.1. (LIBCLOUD-783, GITHUB-656) [Anthony Shaw] - The EC2 Instance Type updated with correct disk sizes (especially the disk size for the m3 instances), conversion errors between GiB an M[i]B, disk count were the cause. Added instance types - g2.8xlarge and t2.large. (GITHUB-646) [Philipp Hahn] - Add update node, update VMware tools, add storage, change storage size or speed, remove storage to Dimension Data Driver. (LIBCLOUD-775, GITHUB-644) [Anthony Shaw] - Include 'service_name' support in _parse_service_catalog_auth_v3 for Openstack Drivers (GITHUB-647) [Steve Gregory] - Outscale inc & sas driver update (GITHUB-645) [@LordShion] - Add new `eu-west-2` & `us-east-2` regions to the OUTSCALE_INC & OUTSCALE_SAS drivers. [Filipe Silva /lordshion] - [google compute] add pricing data update script (GITHUB-464) [Misha Brukman] - Fix a bug in the ``list_volumes`` method in the CloudStack driver so it returns an empty list if no volumes are found. (GITHUB-617) [Wido den Hollander] - Return proper volume state for CloudStack volumes. (GITHUB-615, LIBCLOUD-764) [Wido den Hollander] - Add support for multiple regions in Aurora compute driver (GITHUB-623) [Wido den Hollander] - Fix value of ``node.extra['ip_addresses']`` node attribute in the CloudStack driver. (LIBCLOUD-767, GITHUB-627) [Atsushi Sasaki] - Make sure that ``node.public_ips`` attribute in the CloudStack driver doesn't contain duplicated values.. (LIBCLOUD-766, GITHUB-626) [Atsushi Sasaki] - Allow user to wait for a resource to reach a desired state in the Dimension Data driver by using new ``ex_wait_for_state`` method. (LIBCLOUD-707, GITHUB-631) [Anthony Shaw] - Added M4 pricing and instance information to EC2 driver (GITHUB-634) [Benjamin Zaitlen] - Added C4 instance information to EC2 driver (GITHUB-638) [amitofs] - Allow location of the datacenter to be supplied in ProfitBricks driver (LIBCLOUD-771, GITHUB-635) [Joel Reymont] - Reduce redundant API calls in CloudStack driver (LIBCLOUD-590, GITHUB-641) [Atsushi Sasaki] - Add an additional argument to libcloud.compute.drivers.GCENodeDriver.create_node to allow for creation of preemptible GCE instances (GITHUB-643) [@blawney] - GoogleStorageDriver can now use either our S3 authentication or other Google Cloud Platform OAuth2 authentication methods. (GITHUB-633) [Scott Crunkleton] - All NodeState, StorageVolumeState, VolumeSnapshotState and Provider attributes are now strings instead of integers. (GITHUB-624) [Allard Hoeve] Storage ~~~~~~~ Loadbalancer ~~~~~~~~~~~~ DNS ~~~ - RackSpace driver - New DNS driver methods: - ex_iterate_ptr_records - ex_get_ptr_record - ex_create_ptr_record - ex_update_ptr_record - ex_delete_ptr_record This should cover all of the functionality offered by the Rackspace DNS API in regards to RDNS. (LIBCLOUD-780, GITHUB-652) [Greg Hill] - Update ``create_record`` in the WorldWideDNS driver so it automatically selects a slot if one is not provided by the user via ``extra['entry']`` argument. (GITHUB-621) [Alejandro Pereira] - Introduce GoDaddy DNS Driver with examples and documentation. (LIBCLOUD-772, GITHUB-640, LIBCLOUD-778) [Anthony Shaw] - Add new driver for CloudFlare DNS (https://www.cloudflare.com/dns/). (GITHUB-637) [Tomaz Muraus] Changes with Apache Libcloud 0.19.0 ----------------------------------- General ~~~~~~~ - Update Rackspace AUTH_URL (LIBCLOUD-738) [Brian Curtin] - Fix ``LIBCLOUD_DEBUG`` mode so it works on Python 3.x. [Tomaz Muraus] - Fix Libcloud code so it doesn't throw an exception if simplejson < 2.1.0 is installed. (LIBCLOUD-714, GITHUB-577) [Erik Johnson] - Fix endpoint URL for DimensionData Asia Pacific region. (GITHUB-585) [Anthony Shaw] - Document potential time drift issue which could cause authentication in the GCE drivers to fail. (GITHUB-571) [Michal Tekel] - Update documentation for EC2 - make sure they reflect region changes from 0.14 release. (GITHUB-606) [James Guthrie] Compute ~~~~~~~ - Fixed malformed XML requests with Dimension Data driver. (LIBCLOUD-760, GITHUB-610) [Anthony Shaw] - Update list of scopes for Google Compute Engine driver. (GITHUB-607) [Otto Bretz] - Allow user to filter VPC by project in the CloudStack driver by passing ``project`` argument to the ``ex_list_vps`` method. (GITHUB-516) [Syed Mushtaq Ahmed] - Add volume management methods and other various improvements and fixes in the RunAbove driver. (GITHUB-561) [Anthony Monthe] - Add support and update Dimension Data driver to use API v2.0 by default. (LIBCLOUD-736, GITHUB-564) [Anthony Shaw] - Add new ``ex_virtual_network_name`` and ``ex_network_config`` argument to the `create_node`` method in the Azure driver. With those arguments user can now specify which virtual network to use. (GITHUB-569) [Jesaja Everling] - Fix ``create_node`` method in the GCE driver calling inexistent method (ex_get_disk instead of ex_get_volume). (GITHUB-574) [Alex Poms] - Allow user to pass ``proxy_url`` keyword argument to the VCloud driver constructor. (GITHUB-578) [Daniel Pool] - Various fixes and improvements in the DimensionData driver (support for creating servers in MCP 1 and 2 data center, performance improvements in the location fetching, etc.). (GITHUB-587, GITHUB-593, LIBCLOUD-750, LIBCLOUD-753) [Anthony Shaw] - Added ``ex_assign_public_ip`` argument to ``create_node`` in the EC2 driver. (GITHUB-590) [Kyle Long] - Added ``ex_terminate_on_shutdown`` argument to ``create_node`` in the EC2 driver. (GITHUB-595) [Kyle Long] - Various fixes and improvements in the ``ex_authorize_security_group_ingress`` in the CloudStack driver. (LIBCLOUD-749, GITHUB-580) [Lionel Schaub] - Add pricing information for Softlayer. (LIBCLOUD-759, GITHUB-603) [David Wilson] - Standardize VolumeSnapshot states into the ``state`` attribute. (LIBCLOUD-758, GITHUB-602) [Allard Hoeve] Storage ~~~~~~~ - Add support for ``sa-east-1`` region to the Amazon S3 driver. (GITHUB-562) [Iuri de Silvio] - Fix handling of binary data in Local storage driver on Python 3. Now the file which is to be written or read from is opened in the binary mode (``b`` flag). (LIBCLOUD-725, GITHUB-568) [Torf] Loadbalancer ~~~~~~~~~~~~ - Add a new driver for DimensionData load-balancing service (http://cloud.dimensiondata.com/). (LIBCLOUD-737, GITHUB-567) [Anthony Shaw] DNS ~~~ - Update Google Cloud DNS API from 'v1beta1' to 'v1' (GITHUB-583) [Misha Brukman] - Add new driver for AuroraDNS service. (GITHUB-562, LIBCLOUD-735) [Wido den Hollander] - Fix "_to_record" in the Route53 driver - make sure it doesn't throw if the record TTL is not available. [Tomaz Muraus] - Add new driver for WorldWideDNS service (http://www.worldwidedns.net/home.asp). (GITHUB-566, LIBCLOUD-732) [Alejandro Pereira] - Add new driver for DNSimple service (https://dnsimple.com/). (GITHUB-575, GITHUB-604, LIBCLOUD-739) [Alejandro Pereira, Patrick Humpal] - Add new driver for PointDNS service (https://pointhq.com). (GITHUB-576, GITHUB-591, LIBCLOUD-740) [Alejandro Pereira] - Add new driver for Vultr DNS service (https://www.vultr.com). (GITHUB-579, GITHUB-596, LIBCLOUD-745) [Alejandro Pereira, Janez Troha] - Add new driver for Liquidweb DNS service (http://www.liquidweb.com/). (GITHUB-581, LIBCLOUD-746) [Oltjano Terpollari, Alejandro Pereira] - Add new driver for Zonomi DNS hosting service (http://zonomi.com/). (GITHUB-582, LIBCLOUD-747) [Oltjano Terpollari, Alejandro Pereira] - Add new driver for Durable DNS service (https://durabledns.com/). (GITHUB-588, LIBCLOUD-748) [Oltjano Terpollari, Alejandro Pereira] Changes with Apache Libcloud 0.18.0 ----------------------------------- General ~~~~~~~ - Use native ``ssl.match_hostname`` functionality when running on Python >= 3.2 and only require ``backports.ssl_match_hostname`` dependency on Python versions < 3.2. [Tomaz Muraus] - Add support for AWS Signature version 4. Note: Currently only GET HTTP method is supported. (GITHUB-444) [Gertjan Oude Lohuis] - Fix a bug in the debug mode logging (LIBCLOUD_DEBUG). Logging to the debug file would throw an exception if the text contained non-ascii characters. [Tomaz Muraus] - Fix a bug with connection code throwing an exception if a port was a unicode type and not a str or int. (GITHUB-533, LIBCLOUD-716) [Avi Weit] - Update ``is_valid_ip_address`` function so it also works on Windows. (GITHUB-343, GITHUB-498, LIBCLOUD-601, LIBCLOUD-686) [Nicolas Fraison, Samuel Marks] - Add support for retrying failed HTTP requests. Retrying is off by default and can be enabled by setting ``LIBCLOUD_RETRY_FAILED_HTTP_REQUESTS`` environment variable. (GITHUB-515, LIBCLOUD-360, LIBCLOUD-709) - Fix a bug in consuming stdout and stderr strams in Paramiko SSH client. In some cases (like connecting to localhost via SSH), exit_status_ready gets set immediately even before the while loop to consume the streams kicks in. In those cases, we will not have consumed the streams at all. (GITHUB-558) [Lakshmi Kannan] Compute ~~~~~~~ - Google Compute now supports paginated lists including filtering. (GITHUB-491) [Lee Verberne] - OpenStackNodeSize objects now support optional, additional fields that are supported in OpenStack 2.1: `ephemeral_disk`, `swap`, `extra`. (GITHUB-488, LIBCLOUD-682) [Greg Hill] - StorageVolume objects now have an attribute `state` that holds a state variable that is standardized state across drivers. Drivers that currently support the `state` attribute are OpenStack and EC2. StorageVolume objects returned by drivers that do not support the attribute will have a `state` of `None`. When a provider returns a state that is unknown to the driver, the state will be `UNKNOWN`. Please report such states. A couple of drivers already put state fields in the `extra` fields of StorageVolumes. These fields were kept for backwards-compatibility and for reference. (GITHUB-476) [Allard Hoeve] - StorageVolume objects on EC2 and OpenStack now have a key called snapshot_id in their extra dicts containing the snapshot ID the volume was based on. (GITHUB-479) [Allard Hoeve] - OpenStack driver: deprecated ex_create_snapshot and ex_delete_snapshot in favor of create_volume_snapshot and destroy_volume_snapshot. Updated base driver method create_storage_volume argument name to be optional. (GITHUB-478) [Allard Hoeve] - Add support for creating volumes based on snapshots to EC2 and OS drivers. Also modify signature of base NodeDriver.create_volume to reflect the fact that all drivers expect a StorageSnapshot object as the snapshot argument. (GITHUB-467, LIBCLOUD-672) [Allard Hoeve] - VolumeSnapshots now have a `created` attribute that is a `datetime` field showing the creation datetime of the snapshot. The field in VolumeSnapshot.extra containing the original string is maintained, so this is a backwards-compatible change. (GITHUB-473) [Allard Hoeve] - Improve GCE create_node, make sure ex_get_disktype function (GITHUB-448) [Markos Gogoulos] - GCE driver fix to handle unknown image projects (GITHUB-447) [Markos Gogoulos] - Allow user to pass ``ex_blockdevicemappings`` argument to the create_node method in the OpenStack driver. (GITHUB-398, LIBCLOUD-637) [Allard Hoeve] - Fix ``list_volume_snapshots`` method in the EC2 driver so it comforms to the base API. (LIBCLOUD-664, GITHUB-451) [Allard Hoeve] - Add ``volumes_attached`` attibute to ``node.extra`` in the OpenStack driver. (LIBCLOUD-668, GITHUB-462) [Allard Hoeve] - Add the following new methods to the Linode driver: ``ex_list_volumes``, ``ex_create_volume``, ``ex_destroy_volume``. (LIBCLOUD-649, GITHUB-430) [Wojciech Wirkijowski] - Add ``list_volume_snapshots`` method to the OpenStack driver. (LIBCLOUD-663, GITHUB-450) [Allard Hoeve] - Add Site to Site VPN functionality to CloudStack driver. (GITHUB-465) [Avi Nanhkoesingh] - Add affinity group support to CloudStack driver (LIBCLOUD-671, GITHUB-468) [Mateusz Korszun] - Add a support for a new AWS Frankfurt, Germany region (``eu-central-1``) to the EC2 driver using AWS Signature v4. (GITHUB-444) [Gertjan Oude Lohuis, Tomaz Muraus] - Allow Filtering in EC2 list_images() driver (GITHUB-456, LIBCLOUD-667) [Katriel Traum] - Add ex_list_ip_forwarding_rules() to CloudStack driver (GITHUB-483) [Atsushi Sasaki] - Add AURORA compute driver (LIBCLOUD-641, GITHUB-477) [Wido den Hollander] - Update ``ex_describe_tags`` method in the EC2 driver and allow user to list tags for any supported resource. Previously you could only list tags for a node or a storage volume. (LIBCLOUD-676, GITHUB-482) [John Kinsella] - Various improvements in the HostVirual driver (code refactoring, support for managing "packages"). (LIBCLOUD-670, GITHUB-472) [Dinesh Bhoopathy] - Add support for DigitalOcean API v2.0 while maintaining support for the old API v2.0. Note: API v2.0 is now used by default. To use the old API v1.0, pass ``api_version='1.0'`` argument to the driver constructor. (GITHUB-442) [Andrew Starr-Bochicchio] - Add new ``d4.`` instance types to the EC2 driver. Also update EC2 pricing data. (GITHUB-490) [Tomaz Muraus] - Add new driver for Microsft Azure Virtual Machines service. (LIBCLOUD-556, GITHUB-305, GITHUB-499, GITHUB-538) [Michael Bennett, davidcrossland, Richard Conway, Matt Baldwin, Tomaz Muraus] - Fix VPC lookup method in CloudStack driver (GITHUB-506) [Avi Nanhkoesingh] - Add new driver for the Dimension Data provider based on the OpSource driver. (LIBCLOUD-698, GITHUB-507, LIBCLOUD-700, GITHUB-513) [Anthony Shaw] - Add "virtualmachine_id" attribute to the ``CloudStackAddress`` class in the CloudStack driver. (LIBCLOUD-679, GITHUB-485) [Atsushi Sasaki] - Allow user to pass filters via arguments to the ``ex_list_port_forwarding_rules`` in the CloudStack driver. (LIBCLOUD-678, GITHUB-484) [Atsushi Sasaki] - Fix an issue with ``list_nodes`` in the CloudSigma driver throwing an exception if a node in the list had a static IP. (LIBCLOUD-707, GITHUB-514) [Chris O'Brien] - Don't throw an exception if a limit for a particular CloudStack resource is "Unlimited" and not a number. (GITHUB-512) [Syed Mushtaq Ahmed] - Allow user to pass ``ex_config_drive`` argument to the ``create_node`` method in the OpenStack driver. (LIBCLOUD-356, GITHUB-330) [Ryan Parrish] - Add new driver for Cloudwatt (https://www.cloudwatt.com/en/) provider. (GITHUB-338) [Anthony Monthe] - Add new driver for Packet (https://www.packet.com/) provider. (LIBCLOUD-703, GITHUB-527) [Aaron Welch] - Update Azure VM pricing information and add information for new D instance types. (GITHUB-528) [Michael Bennett] - Add ``ex_get_node`` and ``ex_get_volume`` methods to CloudStack driver. (GITHUB-532) [Anthony Monthe] - Update CloudSigma driver so the "unavailable" and "paused" node state is correctly mapped to "error" and "paused" respectively. (GITHUB-517) [Chris O'Brien] - Add SSH key pair management methods to the Gandi driver. (GITHUB-534) [Anthony Monthe] - Add ``ex_get_node`` and ``ex_get_volume`` methods to Gandi driver. (GITHUB-534) [Anthony Monthe] - Add ``fault`` attribute to the ``extra`` dictionary of the ``Node`` instance returned by the OpenStack driver. (LIBCLOUD-730, GITHUB-557) [Nick Fox] - Add new driver for Onapp IaaS platform. (LIBCLOUD-691, GITHUB-502) [Matthias Wiesner] - Allow user to inject custom data / script into the Azure node by passing ``ex_custom_data`` argument to the ``create_node`` method. (LIBCLOUD-726, GITHUB-554) [David Wilson] - Add ``ex_create_cloud_service`` and ``ex_destroy_cloud_service`` method to the Azure driver. (LIBCLOUD-724, GITHUB-551) [David Wilson] - Add support for passing user data when creating a DigitalOcean node (``ex_user_data`` argument). (LIBCLOUD-731, GITHUB-559) [David Wilson] - Allow user to specify which arguments are passed to ``list_nodes`` method which is called inside ``wait_until_running`` by passing ``ex_list_nodes_kwargs`` argument to the ``wait_until_running`` method. (``ex_user_data`` argument). (LIBCLOUD-723, GITHUB-548) [David Wilson] - Allow user to pass ``ex_volume_type`` argument to the ``create_volume`` method in the OpennStack driver. (GITHUB-553) [Rico Echwald-Tijsen] - Add new driver for RunAbove (https://www.runabove.com) provider. (GITHUB-550) [Anthony Monthe] - Fix a bug with exception being throw inside the CloudStack driver when the provider returned no error message in the body. (GITHUB-555) [Konstantin Skaburskas] - Various improvements in the DigitalOcean driver: - Increase page size to API maximum. - Add ``ex_create_attr`` kwarg to ``create_node`` method. - Update all the ``list_*`` methods to use paginated requests - Allow user to specify page size by passing ``ex_per_page`` argument to the constructor. (LIBCLOUD-717, GITHUB-537) [Javier Castillo II] Storage ~~~~~~~ - Fix a bug with authentication in the OpenStack Swift driver. (GITHUB-492, LIBCLOUD-635) [Tom Fifield] - Add AuroraObjects Storage Driver. (GITHUB-540, LIBCLOUD-719) [Wido den Hollander] Loadbalancer ~~~~~~~~~~~~ - Add a new driver for Softlayer load-balancing service (https://www.softlayer.com/load-balancing). (GITHUB-500, LIBCLOUD-688) [Avi Weit] DNS ~~~ - Fix a bug when a ZoneDoesntExist exception was thrown when listing records for a zone which has no records in the HostVirtual driver. (GITHUB-460) [Vanč Levstik] - Correctly handle MX records priority in the Route53 driver. (GITHUB-469) [Vanč Levstik] - Allow user to create an A record which points directly to the domain zone name in the Route53 driver. (GITHUB-469) [Vanč Levstik] - Fix delete_zone method in the HostVirtual driver. (GITHUB-461) [Vanč Levstik] - Fix parsing of the record name in the HostVirtual driver. (GITHUB-461) [Vanč Levstik] - Add new driver for DigitalOcean DNS service. (GITHUB-505) [Javier Castillo II] Changes with Apache Libcloud 0.17.0 ----------------------------------- General ~~~~~~~ - Use ``match_hostname`` function from ``backports.ssl_match_hostname`` package to verify the SSL certificate hostname instead of relying on our own logic. (GITHUB-374) [Alex Gaynor] Compute ~~~~~~~ - Add new `eu-west-2` & `us-east-2` regions to the OUTSCALE_INC & OUTSCALE_SAS drivers. [Filipe Silva /lordshion] - GCE driver updated to include ex_stop_node() and ex_start_node() methods. (GITHUB-442) [Eric Johnson] - GCE driver now raises ResourceNotFoundError when the specified image is not found in any image project. Previously, this would return None but now raises the not-found exception instead. This fixes a bug where returning None caused ex_delete_image to raise an AttributeError. (GITHUB-441) [Eric Johnson] - GCE driver update to support JSON format Service Account files and a PY3 fix from Siim Põder for LIBCLOUD-627. (LIBCLOUD-627, LIBCLOUD-657, GITHUB-438) [Eric Johnson] - GCE driver fixed for missing param on ex_add_access_config. (GITHUB-435) [Peter Mooshammer] - GCE driver support for HTTP load-balancer resources. (LIBCLOUD-605, GITHUB-429) [Lee Verberne] - GCE driver updated to make better use of GCEDiskTypes. (GITHUB-428) [Eric Johnson] - GCE driver list_images() now returns all non-deprecated images by default. (LIBCLOUD-602, GITHUB-423) [Eric Johnson] - Improve GCE API coverage for create_node(). (GITHUB-419) [Eric Johnson] - GCE Licenses added to the GCE driver. (GITHUB-420) [Eric Johnson] - GCE Projects support common instance metadata and usage export buckets. (GITHUB-409) [Eric Johnson] - Improvements to TargetPool resource in GCE driver. (GITHUB-414) [Eric Johnson] - Adding TargetInstances resource to GCE driver. (GITHUB-393) [Eric Johnson] - Adding DiskTypes resource to GCE driver. (GITHUB-391) [Eric Johnson] - Fix boot disk auto_delete in GCE driver. (GITHUB-412) [Igor Bogomazov] - Add Routes to GCE driver. (GITHUB-410) [Eric Johnson] - Add missing ``ubuntu-os-cloud`` images to the GCE driver. (LIBCLOUD-632, GITHUB-385) [Borja Martin] - Add new `us-east-2` and `us-east-3` region to the Joyent driver. (GITHUB-386) [Anthony Monthe] - Add missing t2. instance types to the us-west-1 region in the EC2 driver. (GITHUB-388) [Matt Lehman] - Add option to expunge VM on destroy in CloudStack driver. (GITHUB-382) [Roeland Kuipers] - Add extra attribute in list_images for CloudStack driver. (GITHUB-389) [Loic Lambiel] - Add ``ex_security_group_ids`` argument to the create_node method in the EC2 driver. This way users can launch VPC nodes with security groups. (GITHUB-373) [Itxaka Serrano] - Add description argument to GCE Network. (GITHUB-397) [Eric Johnson] - GCE: Improve MachineType (size) coverage of GCE API. (GITHUB-396) [Eric Johnson] - GCE: Improved Images coverage. (GITHUB-395) [Eric Johnson] - GCE: Support for global IP addresses. (GITHUB-390, GITHUB-394) [Eric Johnson] - GCE: Add missing snapshot attributes. (GITHUB-401) [Eric Johnson] - AWS: Set proper disk size in c3.X instance types. (GITHUB-405) [Itxaka Serrano] - Fix a bug with handling of the ``ex_keyname`` argument in the Softlayer driver. (GITHUB-416, LIBCLOUD-647) [Dustin Oberloh] - Update CloudSigma region list (remove Las Vegas, NV region and add new San Jose, CA and Miami, FL region). (GITHUB-417) [Viktor Petersson] - Add ``ex_get_node`` method to the Joyent driver. (GITHUB-421) [Anthony Monthe] - Add support for placement group management to the EC2 driver. (GITHUB-418) [Mikhail Ovsyannikov] - Add new tok02 region to the Softlayer driver. (GITHUB-436, LIBCLOUD-656) [Dustin Oberloh] - Add new Honolulu, HI endpoint to the CloudSigma driver. (GITHUB-439) [Stephen D. Spencer] - Fix a bug with config_drive attribute in the OpenStack driver. New versions of OpenStack now return a boolean and not a string. (GITHUB-433) [quilombo] - Add support for Abiquo API v3.x, remove support for now obsolete API v2.x. (GITHUB-433, LIBCLOUD-652) [David Freedman] - Allow rootdisksize parameter in create_node CloudStack driver (GITHUB-440, LIBCLOUD-658) [Loic Lambiel] Storage ~~~~~~~ - Allow user to pass ``headers`` argument to the ``upload_object`` and ``upload_object_via_stream`` method. This way user can specify CORS headers with the drivers which support that. (GITHUB-403, GITHUB-404) [Peter Schmidt] - Fix upload_object_via_stream so it works correctly under Python 3.x if user manually passes an iterator to the method. Also improve how reading a file in chunks works with drivers which support chunked encoding - always try to fill a chunk with CHUNK_SIZE bytes instead of directly streaming the chunk which iterator returns. Previously, if iterator returned 1 byte in one iteration, we would directly send this as a single chunk to the API. (GITHUB-408, LIBCLOUD-639) [Peter Schmidt] Loadbalancer ~~~~~~~~~~~~ - Updates to CloudStack driver. (GITHUB-434) [Jeroen de Korte] DNS ~~~ - New driver for Softlayer DNS service. (GITHUB-413, LIBCLOUD-640) [Vanč Levstik] - Fix a bug with ``ex_create_multi_value_record`` method in the Route53 driver only returning a single record. (GITHUB-431, LIBCLOUD-650) [Itxaka Serrano] Changes with Apache Libcloud 0.16.0 ----------------------------------- General ~~~~~~~ - Add new ``OpenStackIdentity_3_0_Connection`` class for working with OpenStack Identity (Keystone) service API v3. [Tomaz Muraus] - Add support for prettifying JSON or XML response body which is printed to a file like object when using ``LIBCLOUD_DEBUG`` environment variable. This option can be enabled by setting ``LIBCLOUD_DEBUG_PRETTY_PRINT_RESPONSE`` environment variable. [Tomaz Muraus] - Add support for using an HTTP proxy for outgoing HTTP and HTTPS requests. [Tomaz Muraus, Philip Kershaw] Compute ~~~~~~~ - Fix an issue with ``LIBCLOUD_DEBUG`` not working correctly with the Linode driver. [Tomaz Muraus, Juan Carlos Moreno] (LIBCLOUD-598, GITHUB-342) - Add new driver for VMware vSphere (http://www.vmware.com/products/vsphere/) based clouds. [Tomaz Muraus] - Add two new default node states - ``NodeState.SUSPENDED`` and ``NodeState.ERROR``. [Tomaz Muraus] - Fix to join networks properly in ``deploy_node`` in the CloudStack driver. (LIBCLOUD-593, GITUHB-336) [Atsushi Sasaki] - Create ``CloudStackFirewallRule`` class and corresponding methods. (LIBCLOUD-594, GITHUB-337) [Atsushi Sasaki] - Add support for SSD disks to Google Compute driver. (GITHUB-339) [Eric Johnson] - Add utility ``get_regions`` and ``get_service_names`` methods to the ``OpenStackServiceCatalog`` class. [Andrew Mann, Tomaz Muraus] - Fix a bug in ``ex_get_console_output`` in the EC2 driver which would cause an exception to be thrown if there was no console output for a particular node. Reported by Chris DeRamus. [Tomaz Muraus] - Add ip_address parameter in CloudStack driver ``create_node`` method. (GITHUB-346) [Roeland Kuipers] - Fix ``ParamikoSSHClient.run`` and ``deploy_node`` method to work correctly under Python 3. (GITHUB-347) [Eddy Reyes] - Update OpenStack driver to map more node states to states recognized by Libcloud. [Chris DeRamus] - Fix a bug with ``ex_metadata`` argument handling in the Google Compute Engine driver ``create_node`` method. (LIBCLOUD-544, GITHUB-349, GITHUB-353) [Raphael Theberge] - Add SSH key pair management methods to the Softlayer driver. (GITHUB-321, GITHUB-354) [Itxaka Serrano] - Correctly categorize node IP addresses into public and private when dealing with OpenStack floating IPs. [Andrew Mann] - Add new t2 instance types to the EC2 driver. [Tomaz Muraus] - Add support for Amazon GovCloud to the EC2 driver (us-gov-west-1 region). [Chris DeRamus] - Allow user to pass "gp2" for "ex_volume_type" argument to the create_volume method in the EC2 driver. Reported by Xavier Barbosa. [Tomaz Muraus, Xavier Barbosa] - Add new driver for ProfitBricks provider. (LIBCLOUD-589, GITHUB-352) [Matt Baldwin] - Various improvements and bugs fixes in the GCE driver. For a list, see https://github.com/apache/libcloud/pull/360/commits (GITHUB-360) [Evgeny Egorochkin] - Allow user to specify virtualization type when registering an EC2 image by passing ``virtualization_type`` argument to the ``ex_register_image`` method. (GITHUB-361) [Andy Grimm] - Add ``ex_create_image`` method to the GCE driver. (GITHUB-358, LIBCLOUD-611) [Katriel Traum] - Add some methods to CloudStack driver: create_volume_snapshot, list_snapshots, destroy_volume_snapshot create_snapshot_template, ex_list_os_types) (GITHUB-363, LIBCLOUD-616) [Oleg Suharev] - Added VPC support and Egress Firewall rule support fo CloudStack (GITHUB-363) [Jeroen de Korte] - Add additional attributes to the ``extra`` dictionary of OpenStack StorageVolume object. (GITHUB-366) [Gertjan Oude Lohuis] - Fix ``create_volume`` method in the OpenStack driver to return a created volume object (instance of StorageVolume) on success, instead of a boolean indicating operation success. (GITHUB-365) [Gertjan Oude Lohuis] - Add optional project parameters for ex_list_networks() to CloudStack driver (GITHUB-367, LIBCLOUD-615) [Rene Moser] - CLOUDSTACK: option to start VM in a STOPPED state (GITHUB-368) [Roeland Kuipers] - Support "config_drive" in the OpenStack driver. Allow users to pass ``ex_config_drive`` argument to the ``create_node`` and ``ex_rebuild_node`` method. (GITHUB-370) [Nirmal Ranganathan] - Add support for service scopes to the ``create_node`` method in the GCE driver. (LIBCLOUD-578, GITHUB-373) [Eric Johnson] - Update GCE driver to allow for authentication with internal metadata service. (LIBCLOUD-625, LIBCLOUD-276, GITHUB-276) [Eric Johnson] - Fix a bug in Elasticstack node creation method where it would raise exceptions because of missing data in a response, and also fix pulling the IP from the proper data item. (GITHUB-325) [Michael Bennett] - Fix a bug which prevented user to connect and instantiate multiple EC2 driver instances for different regions at the same time. (GITHUB-325) [Michael Bennett] - Add methods in CloudStack driver to manage mutiple nics per vm. (GITHUB-369) [Roeland Kuipers] - Implements VPC network ACLs for CloudStack driver. (GITHUB-371) [Jeroen de Korte] Storage ~~~~~~~ - Fix a bug with CDN requests in the CloudFiles driver. [Tomaz Muraus] - Fix a bug with not being able to specify meta_data / tags when uploading an object using Google Storage driver. (LIBCLOUD-612, GITHUB-356) [Stefan Friesel] Loadbalancer ~~~~~~~~~~~~ - Allow user to specify session affinity algorithm in the GCE driver by passing ``ex_session_affinity`` argument to the ``create_balancer`` method. (LIBCLOUD-595, GITHUB-341) [Lee Verberne, Eric Johnson] DNS ~~~ - Various fixes in the Google DNS driver. (GITHUB-378) [Franck Cuny] Changes with Apache Libcloud 0.15.1 ----------------------------------- Compute ~~~~~~~ - Allow user to limit a list of subnets which are returned by passing ``subnet_ids`` and ``filters`` argument to the ``ex_list_subnets`` method in the EC2 driver. (LIBCLOUD-571, GITHUB-306) [Lior Goikhburg] - Allow user to limit a list of internet gateways which are returned by passing ``gateway_ids`` and ``filters`` argument to the ``ex_list_internet_gateways`` method in the EC2 driver. (LIBCLOUD-572, GITHUB-307) [Lior Goikhburg] - Allow user to filter which nodes are returned by passing ``ex_filters`` argument to the ``list_nodes`` method in the EC2 driver. (LIBCLOUD-580, GITHUB-320) [Lior Goikhburg] - Add network_association_id to ex_list_public_ips and CloudstackAddress object (GITHUB-327) [Roeland Kuipers] - Allow user to specify admin password by passing ``ex_admin_pass`` argument to the ``create_node`` method in the Openstack driver. (GITHUB-315) [Marcus Devich] - Fix a possible race condition in deploy_node which would occur if node is online and can be accessed via SSH, but the SSH key we want to use hasn't been installed yet. Previously, we would immediately throw if we can connect, but the SSH key hasn't been installed yet. (GITHUB-331) [David Gay] - Propagate an exception in ``deploy_node`` method if user specified an invalid path to the private key file. Previously this exception was silently swallowed and ignored. [Tomaz Muraus] DNS ~~~ - Include a better message in the exception which is thrown when a request in the Rackspace driver ends up in an ``ERROR`` state. [Tomaz Muraus] Changes with Apache Libcloud 0.15.0 ----------------------------------- General ~~~~~~~ - Use lxml library (if available) for parsing XML. This should substantially reduce parsing time and memory usage for large XML responses (e.g. retrieving all the available images in the EC2 driver). [Andrew Mann] - Use --head flag instead of -X HEAD when logging curl lines for HEAD requests in debug mode. Reported by Brian Metzler. (LIBCLOUD-552) [Tomaz Muraus] - Fix Python 3 compatibility bugs in the following functions: * import_key_pair_from_string in the EC2 driver * publickey._to_md5_fingerprint * publickey.get_pubkey_ssh2_fingerprint (GITHUB-301) [Csaba Hoch] - Update CA_CERTS_PATH to also look for CA cert bundle which comes with openssl Homebrew formula on OS x (/usr/local/etc/openssl/cert.pem). (GITHUB-309) [Pedro Romano] - Update Google drivers to allow simultaneous authornization for all the supported Google Services. (GITHUB-302) [Eric Johnson] Compute ~~~~~~~ - Fix create_key_pair method which was not returning private key. (LIBCLOUD-566) [Sebastien Goasguen] - Map "Stopped" node state in the CloudStack driver to NodeState.STOPPED instead of NodeState.TERMINATED, "Stopping" to NodeState.PENDING instead of NodeState.TERMINATED and "Expunging" to NodeState.PENDING instead of NodeState.TERMINATED. (GITHUB-246) [Chris DeRamus, Tomaz Muraus] - Add ex_create_tags and ex_delete_tags method to the CloudStack driver. (LIBCLOUD-514, GITHUB-248) [Chris DeRamus] - Add new G2 instances to the EC2 driver. [Tomaz Muraus] - Add support for multiple API versions to the Eucalyptus driver and allows user to pass "api_version" argument to the driver constructor. (LIBCLOUD-516, GITHUB-249) [Chris DeRamus] - Map "Powered Off" state in the vCloud driver from "TERMINATED" to "STOPPED". (GITHUB-251) [Ash Berlin] - Add ex_rename_node method to the DigitalOcean driver. (GITHUB-252) [Rahul Ranjan] - Improve error parsing in the DigitalOcean driver. Reported by Deni Bertovic. [Tomaz Muraus] - Add extension methods for the VPC internet gateway management to the EC2 driver. (LIBCLOUD-525, GITHUB-255) [Chris DeRamus] - Add CloudStackProject class to the CloudStack driver and add option to select project and disk offering on node creation. (LIBCLOUD-526, GITHUB-257) [Jim Divine] - Fix IP address handling in the OpenStack driver. (LIBCLOUD-503, GITHUB-235) [Markos Gogoulos] - Ad new ex_delete_image and ex_deprecate_image method to the GCE driver. (GITHUB-260) [Franck Cuny] - Ad new ex_copy_image method to the GCE driver. (GITHUB-258) [Franck Cuny] - Ad new ex_set_volume_auto_delete method to the GCE driver. (GITHUB-264) [Franck Cuny] - Add ex_revoke_security_group_ingress method to the CloudStack driver. [Chris DeRamus, Tomaz Muraus] - Allow user to pass ex_ebs_optimized argument to the create_node method in the EC2 driver. (GITHUB-272) [zerthimon] - Add "deprecated" attribute to the Node object in the Google Compute Engine driver. (GITHUB-276) [Chris / bassdread] - Update Softlayer driver to use "fullyQualifiedDomainName" instead of "hostname" attribute for the node name. (GITHUB-280) [RoelVanNyen] - Allow user to specify target tags using target_tags attribute when creating a firewall rule in the GCE driver. (GITHUB-278) [zerthimon] - Add new standard API for image management and initial implementation for the EC2 and Rackspace driver. (GITHUB-277) [Matt Lehman] - Allow user to specify "displayname" attribute when creating a CloudStack node by passing "ex_displayname" argument to the method. Also allow "name" argument to be empty (None). This way CloudStack automatically uses Node's UUID for the name. (GITHUB-289) [Jeff Moody] - Deprecate "key" argument in the SSHClient class in favor of new "key_files" argument. Also add a new "key_material" argument. This argument can contain raw string version of a private key. Note 1: "key_files" and "key_material" arguments are mutually exclusive. Note 2: "key_material" argument is not supported in the ShellOutSSHClient. - Use node id attribute instead of the name for the "lconfig" label in the Linode driver. This way the label is never longer than 48 characters. (GITHUB-287) [earthgecko] - Add a new driver for Outscale SAS and Outscale INC cloud (http://www.outscale.com). (GITHUB-285, GITHUB-293, LIBCLOUD-536, LIBCLOUD-553) [Benoit Canet] - Add new driver for HP Public Cloud (Helion) available via Provider.HPCLOUD constant. [Tomaz Muraus] - Allow user to specify availability zone when creating an OpenStack node by passing "ex_availability_zone" argument to the create_node method. Note: This will only work if the OpenStack installation is running availability zones extension. (GITHUB-295, LIBCLOUD-555) [syndicut] - Allow user to pass filters to ex_list_networks method in the EC2 driver. (GITHUB-294) [zerthimon] - Allow user to retrieve container images using ex_get_image method in the Google Compute Engine driver. (GITHUB-299, LIBCLOUD-562) [Magnus Andersson] - Add new driver for Kili public cloud (http://kili.io/) [Tomaz Muraus] - Add "timeout" argument to the ParamikoSSHClient.run method. If this argument is specified and the command passed to run method doesn't finish in the defined timeout, `SSHCommandTimeoutError` is throw and the connection to the remote server is closed. Note #1: If timed out happens, this functionality doesn't guarantee that the underlying command will be stopped / killed. The way it works it simply closes a connect to the remote server. [Tomaz Muraus] Note #2: "timeout" argument is only available in the Paramiko SSH client. - Make "cidrs_ips" argument in the ex_authorize_security_group_egress method in the EC2 driver mandatory. (GITHUB-301) [Csaba Hoch] - Add extension methods for managing floating IPs (ex_get_floating_ip, ex_create_floating_ip, ex_delete_floating_ip) to the Openstack 1.1 driver. (GITHUB-301) [Csaba Hoch] - Fix bug in RimuHosting driver which caused driver not to work when the provider returned compressed (gzip'ed) response. (LIBCLOUD-569, GITHUB-303) [amastracci] - Fix issue with overwriting the server memory values in the RimuHosting driver. (GUTHUB-308) [Dustin Oberloh] - Add ex_all_tenants argument to the list_nodes method in the OpenStack driver. (GITHUB-312) [LIBCLOUD-575, Zak Estrada] - Add support for network management for advanced zones (ex_list_network_offerings, ex_create_network, ex_delete_network) in the CloudStack driver. (GITHUB-316) [Roeland Kuipers] - Add extension methods for routes and route table management to the EC2 driver (ex_list_route_tables, ex_create_route_table, ex_delete_route_table, ex_associate_route_table, ex_dissociate_route_table, ex_replace_route_table_association, ex_create_route, ex_delete_route, ex_replace_route) (LIBCLOUD-574, GITHUB-313) [Lior Goikhburg] - Fix ex_list_snapshots for HP Helion OpenStack based driver. [Tomaz Muraus] - Allow user to specify volume type and number of IOPS when creating a new volume in the EC2 driver by passing ``ex_volume_type`` and ``ex_iops`` argument to the ``create_volume`` method. [Tomaz Muraus] - Fix ex_unpause_node method in the OpenStack driver. (GITHUB-317) [Pablo Orduña] - Allow user to launch EC2 node in a specific VPC subnet by passing ``ex_subnet`` argument to the create_node method. (GITHUB-318) [Lior Goikhburg] Storage ~~~~~~~ - Fix container name encoding in the iterate_container_objects and get_container_cdn_url method in the CloudFiles driver. Previously, those methods would throw an exception if user passed in a container name which contained a whitespace. Reported by Brian Metzler. (LIBCLOUD-552) [Tomaz MUraus] - Fix a bug in the OpenStack Swift driver which prevented the driver to work with installations where region names in the service catalog weren't upper case. (LIBCLOUD-576, GITHUB-311) [Zak Estrada] Load Balancer ~~~~~~~~~~~~~ - Add extension methods for policy managagement to the ELB driver. (LIBCLOUD-522, GITHUB-253) [Rahul Ranjan] DNS ~~~ - Fix update_record method in the Route56 driver so it works correctly for records with multiple values. [Tomaz Muraus] - Add ex_create_multi_value_record method to the Route53 driver which allows user to create a record with multiple values with a single call. [Tomaz Muraus] - Add new driver for Google DNS. (GITHUB-269) [Franck Cuny] Changes with Apache Libcloud 0.14.1 ----------------------------------- Compute ~~~~~~~ - Add new m3.medium and m3.large instance information to the EC2 driver. [Tomaz Muraus] - Add a new driver for CloudSigma API v2.0. [Tomaz Muraus] - Add "volume_id" attribute to the Node "extra" dictionary in the EC2 driver. Also fix the value of the "device" extra attribute in the StorageVolume object. (LIBCLOUD-501) [Oleg Suharev] - Add the following extension methods to the OpenStack driver: ex_pause_node, ex_unpause_node, ex_suspend_node, ex_resume_node. (LIBCLOUD-505, GITHUB-238) [Chris DeRamus] - Add ex_limits method to the CloudStack driver. (LIBCLOUD-507, GITHUB-240) [Chris DeRamus] - Add "extra" dictionary to the CloudStackNode object and include more attributes in the "extra" dictionary of the network and volume object. (LIBCLOUD-506, GITHUB-239) [Chris DeRamus] - Add ex_register_image method to the EC2 driver. (LIBCLOUD-508, GITHUB-241) [Chris DeRamus] - Add methods for managing volume snapshots to the OpenStack driver. (LIBCLOUD-512, GITHUB-245) [Chris DeRamus] Load Balancer ~~~~~~~~~~~~~ - Fix a bug in the ex_targetpool_add_node and ex_targetpool_remove_node method in the GCE driver. [Rick Wright] Storage ~~~~~~~ - Allow user to use an internal endpoint in the CloudFiles driver by passing "use_internal_url" argument to the driver constructor. (GITHUB-229, GITHUB-231) [John Obelenus] DNS ~~~ - Add PTR to the supported record types in the Rackspace driver. [Tomaz Muraus] - Fix Zerigo driver to set Record.name attribute for records which refer to the bare domain to "None" instead of an empty string. [Tomaz Muraus] - For consistency with other drivers, update Rackspace driver to set Record.name attribute for the records which refer to the bare domain to "None" instead of setting them to FQDN. [Tomaz Muraus] - Update Rackspace driver to support paginating through zones and records. (GITHUB-230) [Roy Wellington] - Update Route53 driver so it supports handling records with multiple values (e.g. MX). (LIBCLOUD-504, GITHUB-237) [Chris DeRamus] - Update Route53 driver to better handle SRV records. [Tomaz Muraus] - Update Route53 driver, make sure "ttl" attribute in the Record extra dictionary is always an int. [Tomaz Muraus] Changes with Apache Libcloud 0.14.0 ----------------------------------- General ~~~~~~~ - Update API endpoints which are used in the HostVirtual drivers. (LIBCLOUD-489) [Dinesh Bhoopathy] - Add support for Amazon security token to the Amazon drivers. (LIBCLOUD-498, GITHUB-223) [Noah Kantrowitz] Compute ~~~~~~~ - Remove Slicehost driver. SliceHost API has been shut down in 2012 so it makes no sense to keep this driver. [Tomaz Muraus] - Modify drivers for public cloud providers which use HTTP Basic authentication to not allow insecure connections (secure constructor kwarg being set to False) by default. This way credentials can't accidentally be sent in plain text over the write. Affected drivers: Bluebox, Joyent, NephoScale, OpSource, VPSNet [Tomaz Muraus] - Remove "public_ip" and "private_ip" property which has been deprecated in 0.7.0 from the Node object. [Tomaz Muraus] - Move "is_private_ip" and "is_valid_ip_address" function from libcloud.compute.base into libcloud.utils.networking module. [Tomaz Muraus] - Allow user to pass "url" argument to the CloudStack driver constructor. This argument can be provided instead of "host" and "path" arguments and can contain a full URL to the API endpoint. (LIBCLOUD-430) [Tomaz Muraus] - Allow user to pass None as a "location" argument to the create_node method. (LIBCLOUD-431) [Tomaz Muraus] - Refactor CloudStack Connection class so it looks more like other connection classes and user can specify which attributes to send as part of query parameters in the GET request and which inside the body of a POST request. [Tomaz Muraus, Philipp Strube] - Add a new driver for Exoscale (https://www.exoscale.ch/) provider. [Tomaz Muraus] - Fix a bug in Abiquo driver which caused the driver to fail if the endpoint URL didn't start with "/api". (LIBCLOUD-447) Reported by Igor Ajdisek. [Tomaz Muraus] - Modify CloudStack driver to correctly throw InvalidCredsError exception if invalid credentials are provided. [Tomaz Muraus] - Don't throw an exception if a node object is missing an "image" attribute in the list nodes / get node response. This could happen if node is in an error state. (LIBCLOUD-455) [Dustin Spicuzza, Tomaz Muraus] - Update CloudStack driver to better handle errors and throw ProviderError instead of a generic Exception. [Tomaz Muraus] - Modify ex_list_networks methods in CloudStack driver to not thrown if there are no networks available. [Tomaz Muraus] - Bump API version used in the EC2 driver from 2010-08-21 to 2013-10-15. (LIBCLOUD-454) [Tomaz Muraus] - Add ex_get_limits method for retrieving account resource limits to the EC2 driver. [Tomaz Muraus] - Update us-west-1 region in the EC2 driver to include c3 instance types. Also include pricing information. [Tomaz Muraus] - For consistency, rename "ex_add_ip_forwarding_rule" method to "ex_create_ip_forwarding_rule". (GITHUB-196) [Oleg Suharev] - Add support for new "i2" instance types to Amazon EC2 driver. Also update pricing file. (LIBCLOUD-465) [Chris DeRamus] - Allow user to specify VPC id when creating a security group in the EC2 driver by passing "vpc_id" argument to ex_create_security_group method. (LIBCLOUD-463, GITHUB-201) [Chris DeRamus] - Add extension methods for managing security group rules (ex_authorize_security_group_ingress, ex_authorize_security_group_egress, ex_revoke_security_group_ingress, ex_revoke_security_group_egress) to the EC2 driver. (LIBCLOUD-466, GITHUB-202) [Chris DeRamus] - Add extension methods for deleting security groups (ex_delete_security_group, ex_delete_security_group_by_id, ex_delete_security_group_by_name) to the EC2 driver. (LIBCLOUD-464, GITHUB-199) [Chris DeRamus] - Add extension method for listing reserved instances (ex_list_reserved_nodes) to the EC2 driver. (LIBCLOUD-469, GITHUB-205) [Chris DeRamus] - Add extension methods for VPC management (ex_list_networks, ex_create_network, ex_delete_network) to the EC2 driver. (LIBCLOUD-467, GITHUB-203) [Chris DeRamus] - Add extension methods for VPC subnet management (ex_list_subnets, ex_create_subnet, ex_delete_subnet) to the EC2 driver. (LIBCLOUD-468, GITHUB-207) [Chris DeRamus] - Add ex_get_console_output extension method to the EC2 driver. (LIBCLOUD-471, GITHUB-209) [Chris DeRamus] - Include additional provider-specific attributes in the 'extra' dictionary of the StorageVolume class in the EC2 driver. (LIBCLOUD-473, GITHUB-210) [Chris DeRamus] - Change attribute name in the 'extra' dictionary of EC2 and CloudStack Node object from "keyname" to "key_name". (LIBCLOUD-475) [Oleg Suharev] - Fix a deployment issue which would some times cause a process to hang if the executed deployment script printed a lot of output to stdout or stderr. [Tomaz Muraus] - Add additional attributes to the "extra" dictionary of the VolumeSnapshot object in the EC2 driver. Also modify create_volume_snapshot method to correctly handle "name" argument. Previous, "name" argument was used as a snapshot description, now it's used as a Tag with a key "Name". (LIBCLOUD-480, GITHUB-214) [Chris DeRamus] - Store additional attributes (iops, tags, block_device_mapping) in the "extra" dictionary of the NodeImage object in the EC2 driver. Also fix ex_image_ids filtering in the list_images method. (LIBCLOUD-481, GITHUB-215) [Chris DeRamus] - Add extension methods for network interface management (ex_list_network_interfaces, ex_create_network_interface, ex_attach_network_interface_to_node, ex_detach_network_interface, ex_delete_network_interface) to the EC2 driver. (LIBCLOUD-474) [Chris DeRamus] - Update Google Compute Engine driver to use and work with API v1. (LIBCLOUD-450) [Rick Wright] - Modify ParamikoSSHClient so that "password" and "key" arguments are not mutually exclusive and both can be provided. (LIBCLOUD-461, GITHUB-194) [Markos Gogoulos] - Add extension methods for the Elastic IP management to the EC2 driver. Also modify "ex_allocate_address" and "ex_release_address" method to take "domain" argument so it also works with VPC. (LIBCLOUD-470, GITHUB-208, GITHUB-220) [Chris DeRamus] - Add additional provider specific attributes to the "extra" dictionary of the Node object in the EC2 driver. (LIBCLOUD-493, GITHUB-221) [Chris DeRamus] - Add ex_copy_image and ex_create_image_from_node method to the EC2 driver. (LIBCLOUD-494, GITHUB-222) [Chris DeRamus] Storage ~~~~~~~ - Allow user to specify 'Content-Disposition' header in the CloudFiles driver by passing 'content_disposition' key in the extra dictionary of the upload object methods. (LIBCLOUD-430) [Michael Farrell] - Fix CloudFiles driver so it references a correct service catalog entry for the CDN endpoint. This was broken in the 0.14.0-beta3 release when we migrated all the Rackspace drivers to use auth 2.0 by default. (GITHUB-186) [John Obelenus] - Update storage drivers to default to "application/octet-stream" Content-Type if none is provided and none can be guessed. (LIBCLOUD-433) [Michael Farrell] - Fix a bug so you can now upload 0 bytes sized objects using multipart upload in the S3 driver. (LIBCLOUD-490) Reported by Noah Kantrowitz. [Tomaz Muraus] - Update OpenStack Swift driver constructor so it accepts "region", "ex_force_service_type" and "ex_force_service_name" argument. [Tomaz Muraus] - Deprecate "CLOUDFILES_SWIFT" provider constant in favor of new "OPENSTACK_SWIFT" one. [Tomaz Muraus] - Add support for setting an ACL when uploading and object. (LIBCLOUD-497, GITHUB-223) [Noah Kantrowitz] - Modify get_container method to use a more efficient "HEAD" approach instead of calling list_containers + doing late filterting. (LIBCLOUD-498, GITHUB-223) [Noah Kantrowitz] DNS ~~~ - Implement iterate_* methods in the Route53 driver and makes it work correctly if there are more results which can fit on a single page. Previously, only first 100 results were returned. (LIBCLOUD-434) [Chris Clarke] - Update HostVirtual driver constructor to only take "key" and other valid arguments. Previously it also took "secret" argument which it silently ignored. (LIBCLOUD-483) Reported by Andrew Udvare. [Tomaz Muraus] - Fix list_records method in the HostVirtual driver. (LIBCLOUD-484, GITHUB-218) Reported by Andrew Udvare. [Dinesh Bhoopathy] Changes with Apache Libcloud 0.14.0-beta3 ----------------------------------------- General ~~~~~~~ - If the file exists, read pricing data from ~/.libcloud/pricing.json by default. If the file doesn't exist, fall back to the old behavior and use pricing data which is bundled with the release. [Tomaz Muraus] - Add libcloud.pricing.download_pricing_file function for downloading and updating the pricing file. [Tomaz Muraus] - Fix libcloud.utils.py3.urlquote so it works with unicode strings under Python 2. (LIBCLOUD-429) [Michael Farrell] Compute ~~~~~~~ - Refactor Rackspace driver classes and make them easier to use. Now there are two Rackspace provider constants - Provider.RACKSPACE which represents new next-gen OpenStack servers and Provider.RACKSPACE_FIRST_GEN which represents old first-gen cloud servers. Note: This change is backward incompatible. For more information on those changes and how to update your code, please visit "Upgrade Notes" documentation page - http://s.apache.org/lc0140un [Tomaz Muraus] - Deprecate the following EC2 provider constants: EC2_US_EAST, EC2_EU, EC2_EU_WEST, EC2_AP_SOUTHEAST, EC2_AP_NORTHEAST, EC2_US_WEST_OREGON, EC2_SA_EAST, EC2_SA_EAST and replace it with a new EC2 constant. Driver referenced by this new constant now takes a "region" argument which dictates to which region to connect. Note: Deprecated constants will continue to work until the next major release. For more information on those changes and how to update your code, please visit "Upgrade Notes" documentation page - http://s.apache.org/lc0140un [Tomaz Muraus] - Add support for volume related functions to OpenNebula driver. (LIBCLOUD-354) [Emanuele Rocca] - Add methods for managing storage volumes to the OpenStack driver. (LIBCLOUD-353) [Bernard Kerckenaere] - Add new driver for Google Compute Engine (LIBCLOUD-266, LIBCLOUD-386) [Rick Wright] - Fix create_node "features" metadata and update affected drivers. (LIBCLOUD-367) [John Carr] - Update EC2 driver to accept the auth kwarg (it will accept NodeAuthSSH objects and automatically import a public key that is not already uploaded to the EC2 keyring). (Follow on from LIBCLOUD-367). [John Carr] - Unify extension argument names for assigning a node to security groups in EC2 and OpenStack driver. Argument in the EC2 driver has been renamed from ex_securitygroup to ex_security_groups. For backward compatibility reasons, old argument will continue to work until the next major release. (LIBCLOUD-375) [Tomaz Muraus] - Add ex_import_keypair_from_string and ex_import_keypair method to the CloudStack driver. (LIBCLOUD-380) [Sebastien Goasguen] - Add support for managing floating IP addresses to the OpenStack driver. (LIBCLOUD-382) [Ivan Kusalic] - Add extension methods for handling port forwarding to the CloudStack driver, rename CloudStackForwardingRule class to CloudStackIPForwardingRule. (LIBCLOUD-348, LIBCLOUD-381) [sebastien goasguen] - Hook up deploy_node functionality in the CloudStack driver and unify extension arguments for handling security groups. (LIBCLOUD-388) [sebastien goasguen] - Allow user to pass "args" argument to the ScriptDeployment and ScriptFileDeployment class. This argument tells which command line arguments get passed to the ScriptDeployment script. (LIBCLOUD-394) Note: This change is backward incompatible. For more information on how this affects your code and how to update it, visit "Upgrade Notes" documentation page - http://s.apache.org/lc0140un [Tomaz Muraus] - Allow user to specify IAM profile to use when creating an EC2 node. (LIBCLOUD-403) [Xavier Barbosa] - Add support for keypair management to the OpenStack driver. (LIBCLOUD-392) [L. Schaub] - Allow user to specify disk partitioning mode using ex_disk_config argument in the OpenStack based drivers. (LIBCLOUD-402) [Brian Curtin] - Add new driver for NephoScale provider (http://nephoscale.com/). (LIBCLOUD-404) [Markos Gogoulos] - Update network related extension methods so they work correctly with both, OpenStack and Rackspace driver. (LIBCLOUD-368) [Tomaz Muraus] - Add tests for networking functionality in the OpenStack and Rackspace driver. [Tomaz Muraus] - Allow user to pass all supported extension arguments to ex_rebuild_server method in the OpenStack driver. (LIBCLOUD-408) [Dave King] - Add pricing information for Rackspace Cloud Sydney region. [Tomaz Muraus] - Update EC2 instance type map and pricing data. High Storage instances are now also available in Sydney and Singapore region. [Tomaz Muraus] - Add new methods for managing storage volumes and snapshots to the EC2 driver (list_volumes, list_snapshots, destroy_volume_snapshot, create_volume_snapshot) (LIBCLOUD-409) [Oleg Suharev] - Add the following new extension methods to EC2 driver: ex_destroy_image, ex_modify_instance_attributes, ex_delete_keypair. (LIBCLOUD-409) [Oleg Suharev] - Allow user to specify a port range when creating a port forwarding rule. (LIBCLOUD-409) [Oleg Suharev] - Align Joyent driver with other drivers and deprecate "location" argument in the driver constructor in favor of "region" argument. Note: Deprecated argument will continue to work until the next major release. [Tomaz Muraus] - Deprecate the following ElasticHosts provider constants: ELASTICHOSTS_UK1, ELASTICHOSTS_UK2, ELASTICHOSTS_US1, ELASTICHOSTS_US2, ELASTICHOSTS_US3, ELASTICHOSTS_CA1, ELASTICHOSTS_AU1, ELASTICHOSTS_CN1 and replace it with a new ELASTICHOSTS constant. Driver referenced by this new constant now takes a "region" argument which dictates to which region to connect. Note: Deprecated constants will continue to work until the next major release. For more information on those changes and how to update your code, please visit "Upgrade Notes" documentation page - http://s.apache.org/lc0140un (LIBCLOUD-383) [Michael Bennett, Tomaz Muraus] - Add log statements to our ParamikoSSHClient wrapper. This should make debugging deployment issues easier. (LIBCLOUD-414) [Tomaz Muraus] - Add new "NodeState.STOPPED" node state. Update HostVirual and EC2 driver to also recognize this new state. (LIBCLOUD-296) [Jayy Vis] - Add new Hong Kong endpoint to Rackspace driver. [Brian Curtin] - Fix ex_delete_keypair method in the EC2 driver. (LIBCLOUD-415) [Oleg Suharev] - Add the following new extension methods for elastic IP management to the EC2 driver: ex_allocate_address, ex_disassociate_address, ex_release_address. (LIBCLOUD-417) [Patrick Armstrong] - For consistency and accuracy, rename "ex_associate_addresses" method in the EC2 driver to "ex_associate_address_with_node". Note: Old method will continue to work until the next major release. [Tomaz Muraus] - Add new driver for CloudFrames (http://www.cloudfounders.com/CloudFrames) provider. (LIBCLOUD-358) [Bernard Kerckenaere] - Update default kernel versions which are used when creating a Linode server. Old default kernel versions: - x86 - 2.6.18.8-x86_64-linode1 - x86_64 - 2.6.39.1-linode34 New default kernel versions: - x86 - 3.9.3-x86-linode52 - x86_64 - 3.9.3-x86_64-linode33 (LIBCLOUD-424) [Tomaz Muraus, Jon Chen] - Disable cache busting functionality in the OpenStack and Rackspace next-gen driver and enable it only for Rackspace first-gen driver. [Tomaz Muraus] - Update Google Compute Engine driver to v1beta16. [Rick Wright] - Modify auth_url variable in the OpenStack drivers so it works more like users would expect it to. Previously path specified in the auth_url was ignored and only protocol, hostname and port were used. Now user can provide a full url for the auth_url variable and the path provided in the url is also used. [DaeMyung Kang, Tomaz Muraus] - Allow user to associate arbitrary key/value pairs with a node by passing "ex_metadata" argument (dictionary) to create_node method in the EC2 driver. Those values are associated with a node using tags functionality. (LIBCLOUD-395) [Ivan Kusalic] - Add "ex_get_metadata" method to EC2 and OpenStack driver. This method reads metadata dictionary from the Node object. (LIBCLOUD-395) [Ivan Kusalic] - Multiple improvements in the Softlayer driver: - Map "INITIATING" node state to NodeState.PENDING - If node is launching remap "halted" state to "pending" - Add more node sizes - Add ex_stop_node and ex_start_node method - Update tests response fixtures (LIBCLOUD-416) [Markos Gogoulos] - Modify list_sizes method in the KT UCloud driver to work, even if the item doesn't have 'diskofferingid' attribute. (LIBCLOUD-435) [DaeMyung Kang] - Add new c3 instance types to the EC2 driver. [Tomaz Muraus] - Fix an issue with the ex_list_keypairs and ex_list_security_groups method in the CloudStack driver which caused an exception to be thrown if the API returned no keypairs / security groups. (LIBCLOUD-438) [Carlos Reategui, Tomaz Muraus] - Fix a bug in the OpenStack based drivers with not correctly checking if the auth token has expired before re-using it. (LIBCLOUD-428) Reported by Michael Farrell. [Tomaz Muraus, Michael Farrell] Storage ~~~~~~~ - Deprecate CLOUDFILES_US and CLOUDFILES_UK provider constant and replace it with a new CLOUDFILES constant. Driver referenced by this new constant takes a "region" keyword argument which can be one of 'ord', 'dfw', 'iad', 'syd', 'lon'. Note: Deprecated constants will continue to work until the next major release. For more information on this change, please visit "Upgrade Notes" documentation section - http://s.apache.org/lc0140un [Tomaz Muraus] - Allow users to filter objects starting with a prefix by passing ex_prefix argument to the list_container_objects method in the S3, Google Storage and CloudFiles driver. (LIBCLOUD-369) [Stefan Friesel] - Fix an issue with mutating connectionCls.host attribute in the Azure driver. This bug prevented user from having multiple Azure drivers with different keys instantiated at the same time. (LIBCLOUD-399) [Olivier Grisel] - Add a new driver for KT UCloud based on the OpenStack Swift driver. (LIBCLOUD-431). [DaeMyung Kang] Load Balancer ~~~~~~~~~~~~~ - Deprecate RACKSPACE_US and RACKSPACE_UK provider constant and replace it with a new RACKSPACE constant. Driver referenced by this new constant takes a "region" keyword argument which can be one of the following: 'ord', 'dfw', 'iad', 'syd', 'lon'. Note: Deprecated constants will continue to work until the next major release. For more information on this change, please visit "Upgrade Notes" documentation section - http://s.apache.org/lc0140un [Tomaz Muraus] - Add new driver for Google Compute Engine (LIBCLOUD-386) [Rick Wright] - Add new Hong Kong endpoint to Rackspace driver. [Brian Curtin] DNS ~~~ - Deprecate RACKSPACE_US and RACKSPACE_UK provider constant and replace it with a new RACKSPACE constant. Driver referenced by this new constant takes a "region" keyword argument which can be one of the following: 'us', 'uk'. Note: Deprecated constants will continue to work until the next major release. For more information on this change, please visit "Upgrade Notes" documentation section - http://s.apache.org/lc0140un [Tomaz Muraus] - Use string instead of integer for RecordType ENUM value. Note: If you directly use an integer instead of RecordType ENUM class you need to update your code to use the RecordType ENUM otherwise the code won't work. For more information on how to do that, see "Upgrade Notes" documentation section - http://s.apache.org/lc0140un [Tomaz Muraus] - Add "export_zone_to_bind_format" and export_zone_to_bind_zone_file method which allows users to export Libcloud Zone to BIND zone format. (LIBCLOUD-398) [Tomaz Muraus] - Update issue with inexistent zone / record handling in the get_zone and get_record method in the Linode driver. Those issues were related to changes in the Linode API. (LIBCLOUD-425) [Jon Chen] Changes with Apache Libcloud 0.13.3 ----------------------------------- Compute ~~~~~~~ - Send "scrub_data" query parameter when destroying a DigitalOcean node. This will cause disk to be scrubbed (overwritten with 0's) when destroying a node. (LIBCLOUD-487) Note: This fixes a security issue with a potential leak of data contained on the destroyed node which only affects users of the DigitalOcean driver. (CVE-2013-6480) [Tomaz Muraus] Changes with Apache Libcloud 0.13.2 ----------------------------------- General ~~~~~~~ - Don't sent Content-Length: 0 header with POST and PUT request if "raw" mode is used. This fixes a regression which could cause broken behavior in some storage driver when uploading a file from disk. (LIBCLOUD-396) [Ivan Kusalic] Compute ~~~~~~~ - Added Ubuntu Linux 12.04 image to ElasticHost driver image list. (LIBCLOUD-364) [Bob Thompson] - Update ElasticHosts driver to store drive UUID in the node 'extra' field. (LIBCLOUD-357) [Bob Thompson] Storage ~~~~~~~ - Store last_modified timestamp in the Object extra dictionary in the S3 driver. (LIBCLOUD-373) [Stefan Friesel] Load Balancer ~~~~~~~~~~~~~ - Expose CloudStack driver directly through the Provider.CLOUDSTACK constant. [Tomaz Muraus] DNS ~~~ - Modify Zerigo driver to include record TTL in the record 'extra' attribute if a record has a TTL set. [Tomaz Muraus] - Modify values in the Record 'extra' dictionary attribute in the Zerigo DNS driver to be set to None instead of an empty string ('') if a value for the provided key is not set. [Tomaz Muraus] Changes with Apache Libcloud 0.13.1 ----------------------------------- General ~~~~~~~ - Fix a regression introduced in 0.13.0 and make sure to include Content-Length 0 with PUT and POST requests. (LIBCLOUD-362, LIBCLOUD-390) [Tomaz Muraus] Compute ~~~~~~~ - Fix a bug in the ElasticHosts driver and check for right HTTP status code when determining drive imaging success. (LIBCLOUD-363) [Bob Thompson] - Update Opsource driver to include node public ip address (if available). (LIBCLOUD-384) [Michael Bennett] Storage ~~~~~~~ - Fix a regression with calling encode_container_name instead of encode_object_name on object name in get_object method. Reported by Ben Meng (LIBCLOUD-366) [Tomaz Muraus] - Ensure that AWS S3 multipart upload works for small iterators. (LIBCLOUD-378) [Mahendra M] Changes with Apache Libcloud 0.13.0 ----------------------------------- General ~~~~~~~ - Add homebrew curl-ca-bundle path to CA_CERTS_PATH. This will make Libcloud use homebrew curl ca bundle file (if available) for server certificate validation. (LIBCLOUD-324) [Robert Chiniquy] - Modify OpenStackAuthConnection and change auth_token_expires attribute to be a datetime object instead of a string. [Tomaz Muraus] - Modify OpenStackAuthConnection to support re-using of the existing auth token if it's still valid instead of re-authenticating on every authenticate() call. [Tomaz Muraus] - Modify base Connection class to not send Content-Length header if body is not provided. [Tomaz Muraus] - Add the new error class ProviderError and modify InvalidCredsError to inherit from it. (LIBCLOUD-331) [Jayy Vis] Misc ---- - Add unittest2 library dependency for tests and update some tests to use it. [Tomaz Muraus] Compute ~~~~~~~ - Fix destroy_node method in the experimental libvirt driver. [Aymen Fitati] - Add ex_start_node method to the Joyent driver. (LIBCLOUD-319) [rszabo50] - Fix Python 3 compatibility issue in the ScriptFileDeployment class. (LIBCLOUD-321) [Arfrever Frehtes Taifersar Arahesis] - Add ex_set_metadata_entry and ex_get_metadata method to the VCloud driver. (LIBCLOUD-318) [Michel Samia] - Various improvements and bug-fixes in the VCloud driver. (LIBCLOUD-323) [Michel Samia] - Various bug fixes and improvements in the HostVirtual driver. (LIBCLOUD-249) [Dinesh Bhoopathy] - Modify list_sizes method in the OpenStack driver to include OpenStackNodeSize object which includes 'vcpus' attribute which holds a number of virtual CPUs for this size. (LIBCLOUD-325) [Carlo] - For consistency rename "ex_describe_keypairs" method in the EC2 driver to "ex_describe_keypair". [Tomaz Muraus] - Modify "ex_describe_keypair" method to return key fingerprint in the return value. (LIBCLOUD-326) [Andre Merzky, Tomaz Muraus] - Populate private_ips attribute in the CloudStack drive when returning a Node object from the create_node method. (LIBCLOUD-329) [Sebastien Goasguen, Tomaz Muraus] - Allow user to pass extra arguments via "extra_args" argument which are then passed to the "deployVirtualMachine" call in the CloudStack driver create_node method. (LIBCLOUD-330) [Sebastien Goasguen, Tomaz Muraus] - Update Gandi driver to handle new billing model. (LIBCLOUD-317) [Aymeric Barantal] - Fix a bug in the Linode driver and remove extra newline which is added when generating a random root password in create_node. (LIBCLOUD-334) [Juan Carlos Moreno] - Add extension methods for managing keypairs to the CloudStack driver. (LIBCLOUD-333) [sebastien goasguen] - Add extension methods for managing security groups to the CloudStack driver. (LIBCLOUD-332) [sebastien goasguen] - Add extension methods for starting and stoping the node to the CloudStack driver. (LIBCLOUD-338) [sebastien goasguen] - Fix old _wait_until_running method. (LIBCLOUD-339) [Bob Thompson] - Allow user to override default async task completion timeout by specifying ex_clone_timeout argument. (LIBCLOUD-340) [Michal Galet] - Fix a bug in the GoGrid driver get_uuid method. (LIBCLOUD-341) [Bob Thompson] - Fix a bug with deploy_node not respecting 'timeout' kwarg. [Kevin Carter] - Modify create_node method in CloudStack driver to return an instance of CloudStackNode and add a new "expunging" node state. (LIBCLOUD-345) [sebastien goasguen] - Update API endpoint hostnames in the ElasticHost driver and use hostnames which return a valid SSL certificate. (LIBCLOUD-346) [Bob Thompson] - Add ex_list_networks method and missing tests for list_templates to the CloudStack driver. (LIBCLOUD-349) [Philipp Strube] - Correctly throw InvalidCredsError if user passes invalid credentials to the DigitalOcean driver. [Tomaz Muraus] Storage ~~~~~~~ - Fix an issue with double encoding the container name in the CloudFiles driver upload_object method. Also properly encode container and object name used in the HTTP request in the get_container and get_object method. (LIBCLOUD-328) [Tomaz Muraus] Load Balancer ~~~~~~~~~~~~~ - Add ex_list_current_usage method to the Rackspace driver. Changes with Apache Libcloud 0.12.4 ----------------------------------- Compute ~~~~~~~ - Fix a regression in Softlayer driver caused by the xmlrpclib changes. (LIBCLOUD-310) [Jason Johnson] - Allow user to pass alternate ssh usernames to deploy_node (ssh_alternate_usernames kwarg) which are used for authentication if the default one doesn't work. (LIBCLOUD-309) [Chris Psaltis, Tomaz Muraus] - Fix a bug in EC2 list_locations method - 'name' attribute didn't contain a the right value. [Tomaz Muraus] - Add new ScriptFileDeployment deployment class which reads deploy script from a file. [Rudolf J Streif] - Add support for API version 5.1 to the vCloud driver and accept any value which is a multiple of four for ex_vm_memory kwarg in create_node method. (LIBCLOUD-314) [Trevor Powell] Storage ~~~~~~~ - Fix a regression with removed ex_force_service_region constructor kwarg in the CloudFiles driver. (LIBCLOUD-260) Changes with Apache Libcloud 0.12.3 ----------------------------------- General ~~~~~~~ - Fix Python 3.x related regressions. (LIBCLOUD-245) Reported by Arfrever Frehtes Taifersar Arahesis. [Tomaz Muraus] - Fix a regression introduced with recent xmlrpiclib changes which broke all the Gandi.net drivers. (LIBCLOUD-288) Reported by Hutson Betts. [Tomaz Muraus] - Improve deploy code to work correctly if the ssh user doesn't have access to the /root directory. Previously the ScriptDeployment script was stored in /root folder by default. Now it's stored in users home directory under filename ~/libcloud_deploymeny_.sh. (LIBCLOUD-302) Reported by rotem on #libcloud. [Tomaz Muraus] Compute ~~~~~~~ - Improve public and private IP address handling in OpenStack 1.1 driver. Assume every IP address which doesn't have a label "public" or "internet" is private. (LIBCLOUD-297) [Grischa Meyer, Tomaz Muraus] - Add new driver for DigitalOcean provider - https://www.digitalocean.com/. (LIBCLOUD-304) [Tomaz Muraus] - Fix a regression in ParamikoSSHClient.run method which caused this methid to only work as expected if you passed an absolute or a relative path to the script to it. (LIBCLOUD-278) [Tomaz Muraus] DNS ~~~ - Allow user to specify 'priority' extra argument when creating a MX or SRV record. [Brian Jinwright, Tomaz Muraus] Changes with Apache Libcloud 0.12.1 ----------------------------------- General ~~~~~~~ - Deprecate LazyList method of iteration over large paginated collections and use a new, more efficient generator based approach which doesn't require the iterator to be pre-exhausted and buffering all of the values in memory. Existing list_* methods which previously used LazyList class are preserving the old behavior and new iterate_* methods which use a new generator based approach have been added. (LIBCLOUD-254) [Mahendra M] - Replace old ENUM style provider constants and replace them with a string version. This change allows users to dynamically register new drivers using a new set_driver method. (LIBCLOUD-255) [Mahendra M] - Allow user to explicitly specify which CA file is used for verifying the server certificate by setting 'SSL_CERT_FILE' environment variable. Note: When this variable is specified, the specified path is the only CA file which is used to verifying the server certificate. (LIBCLOUD-283) [Tomaz Muraus, Erinn Looney-Triggs] - Add a common module (libcloud.common.xmlrpc) for handling XML-RPC requests using Libcloud http layer. Also refactor existing drivers which use xmlrpclib directly (VCL, Gandi, Softlayer) to use this module. This change allows drivers to support LIBCLOUD_DEBUG and SSL certificate validation functionality. Previously they have bypassed Libcloud http layer so this functionality was not available. (LIBCLOUD-288) [John Carr] Compute ~~~~~~~ - Fix string interpolation bug in __repr__ methods in the IBM SCE driver. (LIBCLOUD-242) [Tomaz Muraus] - Fix test failures which happened in Python 3.3 due to: - hash randomization - changes in xml.etree module - changes in xmlrpc module (LIBCLOUD-245) [Tomaz Muraus] - Improvements and additions in vCloud driver: - Expose generic query method (ex_query) - Provide functionality to get and set control access for vApps. This way created vApps can be shared between users/groups or everyone. (LIBCLOUD-251) [Michal Galet] - Update EC2 pricing data to reflect new, lower prices - http://aws.typepad.com/aws/2012/10/new-ec2-second-generation-standard-instances-and-price-reductions-1.html [Tomaz Muraus] - Update EC2 instance size to reflect new m3 instance types. Also refactor the code to make it easier to maintain. [Tomaz Muraus] - Add a new driver for HostVirtual (http://www.vr.org) provider. (LIBCLOUD-249) [Dinesh Bhoopathy] - Fix a bug where a numeric instead of a string value was used for the content-length header in VCloud driver. (LIBCLOUD-256) [Brian DeGeeter, Tomaz Muraus] - Add a new driver for new Asia Pacific (Sydney) EC2 region. [Tomaz Muraus] - Add support for managing security groups to the OpenStack driver. This patch adds the following extension methods: - ex_list_security_groups, ex_get_node_security_groups methods - ex_create_security_group, ex_delete_security_group - ex_create_security_group_rule, ex_delete_security_group_rule (LIBCLOUD-253) [L. Schaub] - Modify ElasticStack driver class to pass 'vnc auto' instead of 'vnc:ip auto' argument to the API when creating a server. It looks like 'vnc:ip' has been replaced with 'vnc'. [Rick Copeland, Tomaz Muraus] - Add new EC2 instance type - High Storage Eight Extra Large Instance (hs1.8xlarge). [Tomaz Muraus] - Map 'shutting-down' node state in EC2 driver to UNKNOWN. Previously it was mapped to TERMINATED. (LIBCLOUD-280) Note: This change is backward incompatible which means you need to update your code if you rely on the old behavior. [Tomaz Muraus, Marcin Kuzminski] - Change _wait_until_running method so it supports waiting on multiple nodes and make it public (wait_until_running). (LIBCLOUD-274) [Nick Bailey] - Add new EC2 instance type - High Memory Cluster Eight Extra Large. (cr1.8xlarge). [Tomaz Muraus] - Add new driver for Abiquo provider - http://www.abiquo.com (LIBCLOUD-250). [Jaume Devesa] - Allow user to pass 'ex_blockdevicemappings' kwarg to the EC2 driver 'create_node' method. (LIBCLOUD-282) [Joe Miller, Tomaz Muraus] - Improve error handling in the Brightbox driver. [Tomaz Muraus] - Fix the ScriptDeployment step to work correctly if user provides a relative path for the script argument. (LIBCLOUD-278) [Jaume Devesa] - Fix Softlayer driver and make sure all the code is up to date and works with the latest version of the actual Softlayer deployment (v3). (LIBCLOUD-287) [Kevin McDonald] - Update EC2 driver, m3 instance types are now available in all the regions except Brazil. Also update pricing to reflect new (lower) prices. [Tomaz Muraus] - Minor improvements in the HostVirtual driver and add new ex_get_node and ex_build_node extension method. (LIBCLOUD-249) [Dinesh Bhoopathy] - Add ex_destroy_image method to IBM SCE driver. (LIBCLOUD-291) [Perry Zou] - Add the following new regions to the ElasticHosts driver: sjc-c, syd-v, hkg-e. (LIBCLOUD-293) [Tomaz Muraus] - Fix create_node in OpenStack driver to work correctly if 'adminPass' attribute is not present in the response. [Gavin McCance, Tomaz Muraus] - Allow users to filter images returned by the list_images method in the EC2 driver by providing ex_image_ids argument. (LIBCLOUD-294) [Chris Psaltis, Joseph Hall] - Add support for OpenNebula 3.8. (LIBCLOUD-295) [Guillaume ZITTA] - Add missing 'deletd' -> terminated mapping to OpenStack driver. (LIBCLOUD-276) [Jayy Vis] - Fix create_node in OpenStack driver to work correctly if 'adminPass' attribute is not present in the response. (LIBCLOUD-292) [Gavin McCance, Tomaz Muraus] Storage ~~~~~~~ - Add a new local storage driver. (LIBCLOUD-252, LIBCLOUD-258, LIBCLOUD-265, LIBCLOUD-273) [Mahendra M] - Fix a bug which caused the connection to not be closed when using Python 2.6 and calling get_object on an object which doesn't exist in the S3 driver. (LIBCLOUD-257) [John Carr] - Add a new generator based method for listing / iterating over the containers (iterate_containers). (LIBCLOUD-261) [Mahendra M] - Add ex_purge_object_from_cdn method to the CloudFiles driver. (LIBCLOUD-267) [Tomaz Muraus] - Support for multipart uploads and other improvements in the S3 driver so it can more easily be re-used with other implementations (e.g. Google Storage, etc.). Also default to a multipart upload when using upload_object_via_stream. This methods is more efficient compared to old approach because it only requires buffering a single multipart chunk (5 MB) in memory. (LIBCLOUD-269) [Mahendra M] - Add new driver for Windows Azure Storage with support for block and page blobs. (LIBCLOUD-80) [Mahendra M] DNS ~~~ - Update 'if type' checks in the update_record methods to behave correctly if users passes in RecordType.A with a value of 0 - if type is not None. (LIBCLOUD-247) [Tomaz Muraus] - New driver for HostVirtual provider (www.vr.org). (LIBCLOUD-249) [Dinesh Bhoopathy] - Finish Amazon Route53 driver. (LIBCLOUD-132) [John Carr] - Add new driver for Gandi provider (https://www.gandi.net). (LIBCLOUD-281) [John Carr] Load-Balancer ~~~~~~~~~~~~~ - Add new driver for AWS Elastic Load Balancing service. (LIBCLOUD-169) [John Carr] Changes with Apache Libcloud 0.11.4 ----------------------------------- General ~~~~~~~ - Fix some of tests failures which happened in Python 3.3 due to randomized dictionary ordering. (LIBCLOUD-245) [Tomaz Muraus] Compute ~~~~~~~ - Fix a bug where a numeric instead of a string value was used for the content-length header in VCloud driver. (LIBCLOUD-256) [Brian DeGeeter, Tomaz Muraus] Storage ~~~~~~~ - Don't ignore ex_force_service_region argument in the CloudFiles driver. (LIBCLOUD-260) [Dan Di Spaltro] - Fix a bug which caused the connection to not be closed when using Python 2.6 and calling get_object on an object which doesn't exist in the S3 driver. (LIBCLOUD-257) [John Carr] DNS ~~~ - Update 'if type' checks in the update_record methods to behave correctly if users passes in RecordType.A with a value of 0 - if type is not None. (LIBCLOUD-247) [Tomaz Muraus] Changes with Apache Libcloud 0.11.3 ----------------------------------- Storage ~~~~~~~ - Include 'last_modified' and 'content_type' attribute in the Object 'extra' dictionary when retrieving object using get_object in the S3 driver. Also modify 'meta_data' dictionary to include all the headers prefixed with 'x-amz-meta-'. [Tomaz Muraus] Changes with Apache Libcloud 0.11.2 ----------------------------------- General ~~~~~~~ - Fix a bug with the Libcloud SSL verification code. Code was too strict and didn't allow "-" character in the sub-domain when using a wildcard certificate. Note: This is NOT a security vulnerability. (LIBCLOUD-244) [Tomaz Muraus] Compute ~~~~~~~ - Add new Rackspace Nova driver for Chicago (ORD) location (LIBCLOUD-234) [Brian McDaniel] - Add capacity information to Vdc objects and implement power operations. (LIBCLOUD-239) [Michal Galet] - Allow user to pass 'timeout' argument to the 'deploy_node' method. [Tomaz Muraus] - Add ex_list_security_groups, ex_authorize_security_group and ex_describe_all_keypairs methods to the EC2 driver. (LIBCLOUD-241, LIBCLOUD-243) [Nick Bailey] - Add new methods for managing storage volumes and other extenstion methods to the IBM SCE driver. (LIBCLOUD-242) [Sengor Kusturica] Storage ~~~~~~~ - Add the following new methods to the CloudFiles driver: ex_set_account_metadata_temp_url_key, ex_get_object_temp_url. (GITHUB-72) [Shawn Smith] Load-balancer ~~~~~~~~~~~~~ - Add 'balancer' attribute to the Member instance. This attribute refers to the LoadBalancer instance this member belongs to. [Tomaz Muraus] Changes with Apache Libcloud 0.11.1 ----------------------------------- General ~~~~~~~ - Fix hostname validation in the SSL verification code (CVE-2012-3446). Reported by researchers from the University of Texas at Austin (Martin Georgiev, Suman Jana and Vitaly Shmatikov). Changes with Apache Libcloud 0.11.0 ----------------------------------- Compute ~~~~~~~ - Add a timeout of 10 seconds to OpenStackAuthConnection class. (LIBCLOUD-199) [Chris Gilmer] - Add time.sleep(wait_period) to _ssh_client_connect to prevent busy loops when we immediately can't connect to a server. (LIBCLOUD-197) [Jay Doane] - Fix a bug with Python 3 support in the following drivers - IBM SCE, - CloudStack - CloudSigma - OpenNebula - VpsNet - EC2 - ElasticStack - vCloud - OpSource - Slicehost - Joyent (LIBCLOUD-204) [Sengor Kusturica, Hutson Betts, Tomaz Muraus] - Make CloudStack driver more robust and make it work if list_images() call returns no images. (LIBCLOUD-202) [Gabriel Reid] - Add force_ipv4 argument to _wait_until_running and default it to True. This will make Libcloud ignore IPv6 addresses when using deploy_node. (LIBCLOUD-200) [Jay Doane, Tomaz Muraus] - Include error text if a CloudStack async job returns an error code. (LIBCLOUD-207) [Gabriel Reid] - Add extenstion methods for block storage volume management to the CloudStack driver. (LIBCLOUD-208) [Gabriel Reid] - New driver for KT UCloud (http://home.ucloud.olleh.com/main.kt) based on the CloudStack driver. [DaeMyung Kang] - Add a standard API and methods for managing storage volumes to the EC2 and CloudStack drivers. Base API consistent of the following methods: create_volume, destroy_volume, attach_volume, detach_volume. (LIBCLOUD-213) [Gabriel Reid] - Change ex_describe_tags, ex_create_tags and ex_delete_tags methods signature in the EC2 driver. Argument is now called resource (previously it was called node). This methods work with both Node and StorageVolume objects. (LIBCLOUD-213) [Gabriel Reid, Tomaz Muraus] - Add Rackspace Nova London driver. [Chris Gilmer] - Fix a bug - If user doesn't pass in 'network_id' argument to the create_node method in the CloudStack driver, don't explicitly define it. (LIBCLOUD-219) [Bruno Mahé, Tomaz Muraus] - Modify EC2 driver to also return cc2.8xlarge cluster compute instance in the eu-west-1 region. [Tomaz Muraus] - Add 'auth_user_variable' to the OpenStackAuthConnection class. [Mark Everett] - Fix a bug with repeated URLs in some requests the vCloud driver. (LIBCLOUD-222) [Michal Galet] - New Gridspot driver with basic list and destroy functionality. (LIBCLOUD-223) [Amir Elaguizy] - Add methods for managing storage volumes to the Gandi driver. (LIBCLOUD-225) [Aymeric Barantal] DNS ~~~ - Add support for GEO RecordType to Zerigo driver. (LIBCLOUD-203) [Gary Wilson] - Fix a bug with Python 3 support in the following drivers (LIBCLOUD-204) - Zerigo [Tomaz Muraus] - Add support for URL RecordType to Zerigo driver. (LIBCLOUD-209) [Bojan Mihelac] - Properly handle record creation when user doesn't provider a record name and wants to create a record for the actual domain. Reported by Matt Perry (LIBCLOUD-224) [Tomaz Muraus] Storage ~~~~~~~ - Fix a bug with Python 3 support in the following drivers - Atmos - Google Storage - Amazon S3 (LIBCLOUD-204) [Tomaz Muraus] - Fix a bug in the CloudFiles driver which prevented it to work with accounts which use a non ORD endpoint. (LIBCLOUD-205) [Geoff Greer] - Fix a bug in the enable_container_cdn method. (LIBCLOUD-206) [Geoff Greer] - Allow user to specify container CDN TTL when calling container.enable_cd() using ex_ttl keyword argument in the CloudFiles driver. [Tomaz Muraus] - Add ex_enable_static_website and ex_set_error_page method to the CloudFiles driver. [Tomaz Muraus] - Propagate kwargs passed to container.download_object() to driver.download_object(). (LIBCLOUD-227) [Benno Rice] - Fix a bug with not escaping container and object name in the Atmos driver. [Russell Keith-Magee, Benno Rice] - Fix upload_object_via_stream method in the Atmos driver. (LIBCLOUD-228) [Benno Rice] - Fix a bug with uploading zero-sized files in the OpenStack Swift / CloudFiles driver. [Tomaz Muraus] - Fix a bug with content_type and encoding of object and path names in the Atmos driver. [Russell Keith-Magee] Other ~~~~~ - Unify docstrings formatting in the compute drivers. (LIBCLOUD-229) [Ilgiz Islamgulov] Changes with Apache Libcloud 0.10.1 ----------------------------------- General ~~~~~~~ - Add timeout attribute to base 'Connection' class and pass it to the connection class constructor if Python version is not 2.5. [Chris Gilmer] Compute ~~~~~~~ - Update IBM SBC driver so it works with IBM Smart Cloud Enterprise. (LIBCLOUD-195) [Sengor Kusturica] - Add ex_register_iso method to the CloudStack driver. (LIBCLOUD-196) [Daemian Mack] - Allow user to specify which IP to use when calling deploy_node. (defaults to 'public_ips'). Previously it only worked with public IP, now user can pass 'private_ips' as an argument and SSH client will try to connect to the node first private IP address. [Jay Doane] - Fix CloudSigmaLvsNodeDriver connectionCls bug. [Jerry Chen] - Add 'ex_keyname' argument to the create_node method in the OpenStack driver. (LIBCLOUD-177) [Jay Doane] - Fix a problem in deploy_node - make it work with providers which don't instantly return created node in the list_node response. Also add __str__ and __repr__ method to DeploymentError so the error message is more useful. (LIBCLOUD-176) [Jouke Waleson, Tomaz Muraus] - Add 'ssh_key' feature to Brigthbox driver. This way it works with deploy_node. (LIBCLOUD-179) [Neil Wilson] - Add Joyent compute driver. [Tomaz Muraus] - Store auth token expire times on the connection class in the attribute called 'auth_token_expires'. (LIBCLOUD-178) [Chris Gilmer, Brad Morgan] - Add new driver for VCL cloud (http://www.educause.edu/blog/hes8/CloudComputingandtheVirtualCom/167931) (LIBCLOUD-180) [Jason Gionta, Tomaz Muraus] - Improve and add new features to Brightbox driver - Update fixtures to represent actual api output - Update compute tests to 100% coverage - Add userdata and server group extensions to create_node - Add ipv6 support to public ip list - Improve in line documentation - Add lots of api output information to Node and Image 'extra' attributes - Allow variable API versions (api_version argument) - Allow reverse dns updates for cloud ip extensions (LIBCLOUD-184) [Neil Wilson, Tomaz Muraus] - Add ex_userdata argument to the OpenStack 1.1 driver. (LIBCLOUD-185) [Jay Doane] - Modify Vmware vCloud driver and implement new features for the vCloud version 1.5. (LIBCLOUD-183) [Michal Galet, Sengor Kusturica] - Allow user to pass mode argument to SSHClient.put method and default it to 'w'. (LIBCLOUD-188) [Jay Doane] - Modify SSHKeyDeployment step to use append mode so it doesn't overwrite existing entries in .ssh/authorized_keys. (LIBCLOUD-187) [Jay Doane] - Modify ParamikoSSHClient to connect to the SSH agent and automatically look for private keys in ~/.ssh if the 'auth' and 'ssh_key' argument is not specified when calling deploy_node. (LIBCLOUD-182) [Tomaz Muraus] - Add ex_rescue and ex_unrescue method to OpenStack 1.1 driver. (LIBCLOUD-193) [Shawn Smith] - Include 'password' in the node extra dictionary when calling deploy_node if the password auth is used. [Juan Carlos Moreno] - Add FileDeployment class to libcloud.compute.deployment module. This can be used as a replacement for ex_files argument if the provider supports deployment functionality. (LIBCLOUD-190) [Jay Doane] Storage ~~~~~~~ - Large object upload support for CloudFiles driver - Add CLOUDFILES_SWIFT driver to connect to OpenStack Swift [Dmitry Russkikh, Roman Bogorodskiy] Load-balancer ~~~~~~~~~~~~~ - Don't include 'body_regex' attribute in the Rackspace driver body if body_regex is None or empty string. (LIBCLOUD-186) [Bill Woodward] - Don't split Load balancer IP addresses into public and private list. Include all the addresses in the 'virtualIps' variable in the extra dictionary (Rackspace driver). (LIBCLOUD-191) [Adam Pickeral] Changes with Apache Libcloud 0.9.1 ---------------------------------- General ~~~~~~~ - Make parsing of the Auth API responses in the OpenStack drivers more flexible and extensible. Now, every connection class that inherits from the openstack base connection must implement get_endpoint(), who's job is to return the correct endpoint out of the service catalog. Note: The openstack.py base driver no longer works by default with Rackspace nova. The default endpoint parsed from the service catalog is the default compute endpoint for devstack. (LIBCLOUD-151) [Brad Morgan] - Allow user to pass ex_tenant_name keyword argument to the OpenStack node driver class. This scopes all the endpoints returned by the Auth API endpoint to the provided tenant. (LIBCLOUD-172) [James E. Blair] - Allow user to specify OpenStack service catalog parameters (service type, name and region). This way base OpenStack driver can be used with different providers without needing to subclass. (LIBCLOUD-173) [James E. Blair] - Fix a bug with handling compressed responses in the Linode driver. (LIBCLOUD-158) [Ben Agricola] Compute ~~~~~~~ - Add new RackspaceNovaBeta and RackspaveNovaDfw driver based on the OpenStack. (LIBCLOUD-151) [Brad Morgan] - Include 'created' and 'updated' attribute in the OpenStack 1.1 driver. (LIBCLOUD-155) [Chris Gilmer] - Include 'minRam' and 'minDisk' attribute in the OpenStack 1.1 driver Node extra dictionary. (LIBCLOUD-163) [Chris Gilmer] - Allow users to use a list of tuples for the query string parameters inside the OpenStack connection classes. This way same key can be specified multiple times (LIBCLOUD-153) [Dave King] - Allow user to pass 'max_tries' keyword argument to deploy_node method. [Tomaz Muraus] - Include original exception error message when re-throwing an exception inside _run_deployment_script method. [Tomaz Muraus] - Add support for ElasticHosts new United States (Los Angeles) and Canada (Toronto) locations. (GITHUB-53) [Jaime Irurzun] - Add serverId attribute to the NodeImage object extra dictionary in the OpenStack driver. [Mark Everett] - Add new EC2 instance type - m1.medium. [Tomaz Muraus] - Allow user to re-use auth tokens and pass 'ex_force_auth_token' keyword argument to the OpenStack driver constructor. (LIBCLOUD-164) [Dave King] - Add new experimental libvirt driver. [Tomaz Muraus] - Properly handle OpenStack providers which return public IP addresses under the 'internet' key in the addresses dictionary. [Tomaz Muraus] - Update create_node in Linode driver and make it return a Node object instead of a list. Reported by Jouke Waleson. (LIBCLOUD-175) [Tomaz Muraus] Storage ~~~~~~~ - Don't lowercase special header names in the Amazon S3 storage driver. (LIBCLOUD-149) [Tomaz Muraus] Load-balancer ~~~~~~~~~~~~~ - Allow user to specify a condition and weight when adding a member in the Rackspace driver. [Adam Pickeral] - Add an extension method (ex_balancer_attach_members) for attaching multiple members to a load balancer in the Rackspace driver. (LIBCLOUD-152) [Adam Pickeral] - Add ex_creaate_balancer method to the Rackspace driver and allow user to pass 'vip' argument to it. (LIBCLOUD-166) [Adam Pickeral] - Update Rackspace driver to support Auth 2.0. (LIBCLOUD-165) [Dave King] - Add new ex_create_balancer_access_rule and ex_create_balancer_access_rule_no_poll method to the Rackspace driver. (LIBCLOUD-170) [Dave King] DNS ~~~ - Update Rackspace driver to support Auth 2.0. (LIBCLOUD-165) [Dave King] Changes with Apache Libcloud 0.8.0 ---------------------------------- General ~~~~~~~ - Add 'request_kwargs' argument to the get_poll_request_kwargs method. This argument contains kwargs which were previously used to initiate the poll request. [Mark Everett] - Add support for handling compressed responses (deflate, gzip). Also send "Accept-Encoding" "gzip,deflate" header with all the requests. [Tomaz Muraus] - Fix debug module (LIBCLOUD_DEBUG env variable) so it works with Python 3 [Tomaz Muraus] Compute ~~~~~~~ - Added support for retrieving OpenNebula v3.2 instance types, OpenNebula v3.0 network Public attribute support, and additional code coverage tests. [Hutson Betts] - Add implementation for ex_save_image method to the OpenStack 1.1 driver. [Shawn Smith] - Add support for Amazon new South America (Sao Paulo) location. [Tomaz Muraus] - Fix a bug in OpenStack driver when 2.0_apikey or 2.0_password 'auth_version' is used. [Tomaz Muraus] - Current OpenNebula OCCI implementation does not support a proper restart method. Rather it suspends and resumes. Therefore, restart_node has been removed from the OpenNebula driver. [Hutson Betts] - Enable ex_delete_image method in the OpenStack 1.1 driver. [Shawn Smith] - Return NodeImage instance in OpenStack 1.1 driver ex_save_image method (LIBCLOUD-138) [Shawn Smith] - Enable reboot_node method in the OpenNebula 3.2 driver. [Hutson Betts] - Fix a public_ips Node variable assignment in the Gandi.net driver. [Aymeric Barantal] - Updated the list of node states for OpenNebula drivers. (LIBCLOUD-148) [Hutson Betts] Storage ~~~~~~~ - Propagate extra keyword arguments passed to the Rackspace driver connection class. [Dave King] Load-balancer ~~~~~~~~~~~~~ - Add 'extra' attribute to the LoadBalancer object and retrieve all the virtual IP addresses in the Rackspace driver. [Dave King] - Add list_supported_algorithms() method to the base LoadBalancer class. This method returns a list of supported algorithms by the provider. [Dave King] - Update Rackspace driver: - Add two new supported algorithms: WEIGHTED_ROUND_ROBIN, WEIGHTED_LEAST_CONNECTIONS - Add ex_list_algorithm_names method - Add ex_get_balancer_error_page method - Add ex_balancer_access_list method - Populate LoadBalancer extra dictionary with more attributes - Add support for health monitors and connection throttling - Add more balancer states - ex_list_protocols_with_default_ports [Dave King] - Propagate extra keyword arguments passed to the Rackspace driver connection class. [Dave King] - Add 'extra' attribute to the Member object and populate it in the Rackspace driver. [Mark Everett] - Adds status to the Member object and conditions an 'enum' (Rackspace driver). [Mark Everett] - Add update_balancer method to the base LoadBalancer class. [Mark Everett] - Add update_balancer method to the Rackspace driver. [Mark Everett] - Add created and updated attribute to the LoadBalancer extra dictionary in the Rackspace driver. [Mark Everett] - Fix protocol name maping in the Rackspace driver. [Bill Woodward] Changes with Apache Libcloud 0.7.1 ---------------------------------- General ~~~~~~~ - Fix a minor bug in debug mode (LIBCLOUD_DEBUG=/dev/stderr) which has been introduced when adding Python 3 compatibility layer. [Paul Querna] - Update OpenStack Auth API endpoint paths. [Paul Querna] Changes with Apache Libcloud 0.7.0 ---------------------------------- General ~~~~~~~ - Add support for Python 3.x. [Tomaz Muraus] - Remove old deprecated paths. [Tomaz Muraus] Compute ~~~~~~~ - Update CloudSigma Zurich API endpoint address. [Tomaz Muraus] - Add new US Las Vegas endpoint to CloudSigma driver (types.CLOUDSIGMA_US) [Tomaz Muraus] - Allow user to specify drive type (hdd, ssd) when creating a CloudSigma server. Note 'ssd' drive_type doesn't work with the API yet. [Tomaz Muraus] - Update OpenStack 1.1 driver to comply with the API specs. Need to make another call to retrieve node name and ip addresses when creating a node, because the first call only returns an id an the password. (GITHUB-40) [Dave King] - Add ex_node_ids argument to the EC2 driver list_nodes method. (GITHUB-39) [Suvish Vt] - If OpenStack Auth 2.0 API is used, also parse out tenant id and name and save it on the connection class (conn.tenant['id'], conn.tenant['name']). [Tomaz Muraus] - Add new "Cluster Compute Eight Extra Large" size to the Amazon EC2 driver. [Tomaz Muraus] - Add the following extension methods to the EC2 compute driver: ex_describe_all_addresses, ex_associate_addresses, ex_start_node, ex_stop_node. [Suvish Vt] - Change public_ip and private_ip attribute on the Node object to the public_ips and private_ips since both of the objects are always a list. Note: For backward compatibility you can still access public_ip and private_ip attributes, but this will be removed in the next release. [Tomaz Muraus] - Fix an inconsistency in IBM SBC driver and make sure public_ips and private_ips attributes are a list. [Tomaz Muraus] - Fix an inconsistency in OpSource driver and make sure public_ips is an empty list ([]), not 'unknown' [Tomaz Muraus] - Updated support for OpenNebula.org v1.4, v2.x, and v3.x APIs and included additional compute tests validating functionality. (LIBCLOUD-121) [Hutson Betts] Load-balancer ~~~~~~~~~~~~~ - Add ex_member_address argument to the Rackspace driver list_balancers method. If this argument is provided, only loadbalancers which have a member with the provided IP address attached are returned. [Tomaz Muraus] Changes with Apache Libcloud 0.6.2 ---------------------------------- General ~~~~~~~ - Fix a bug in PollingConnection class - actually use and don't ignore the poll_interval [Tomaz Muraus] Compute ~~~~~~~ - Add support for Auth 2.0 API (keystone) to the OpenStack Auth connection class. [Brad Morgan] - Add list_locations method to the OpenStack driver and fix some inconsistencies in the OpenStack driver extension method signatures. [Brad Morgan] - Update Amazon EC2 driver and pricing data to support a new region - US West 2 (Oregon) [Tomaz Muraus] - Expose 'CLOUDSTACK' provider. This driver can be used with an arbitrary CloudStack installation. [Tomaz Muraus] Storage ~~~~~~~ - Update Amazon S3 driver to support a new region - US West 2 (Oregon) [Tomaz Muraus] DNS ~~~ - Increase the default poll interval in the Rackspace driver to 2.5 seconds. [Tomaz Muraus] - Fix a bug in Rackspace Cloud DNS driver and make sure to throw an exception if an unexpected status code is returned. Reported by "jeblair". [Tomaz Muraus] Changes with Apache Libcloud 0.6.1 ---------------------------------- General ~~~~~~~ - Modify ParamikoSSHClient.connect so it supports authentication using a key file, (LIBCLOUD-116) [Jay Doane] - User must now explicitly specify a path when using LIBCLOUD_DEBUG environment variable. (LIBCLOUD-95) [daveb, Tomaz Muraus] - Add new XmlResponse and JsonResponse base class and modify all the driver-specific response classes to inherit from one of those two classes where applicable. [Caio Romão] - Add new 'PollingConnection' class. This class can work with 'async' APIs. It sends and an initial request and then periodically poll the API until the job has completed or a timeout has been reached. [Tomaz Muraus] Compute ~~~~~~~ - Add 24GB size to the GoGrid driver [Roman Bogorodskiy] - Fix API endpoint URL in the Softlayer driver [Tomaz Muraus] - Add support for OpenNebula 3.0 API (LIBCLOUD-120) [Hutson Betts] - Add more attributes to the extra dictionary in the EC2 driver. (GITHUB-31) [Juan Carlos Moreno] - Fix IP address assignment in the EC2 driver. Don't include "None" in the public_ip and private_ip Node list attribute. [Tomaz Muraus] - Make deploy_node functionality more robust and don't start deployment if node public_ip attribute is an empty list. [Tomaz Muraus] - Support SSH key authentication when using deploy_node. [Russell Haering, Tomaz Muraus] - Enable deploy_node functionality in the EC2 driver using SSH key authentication [Russell Haering, Tomaz Muraus] - Enable paramiko library debug log level if LIBCLOUD_DEBUG is used and paramiko is installed. [Tomaz Muraus] - Fix the request signature generation in the base EC2 compute driver. If the endpoint is using a non-standard port (Eucalyptus based installations), append it to the hostname used to generate the signature. [Simon Delamare] - Add new "unavailable" state to the BrightboxNodeDriver class. [Tim Fletcher] - Increase a PollingConnection timeout in the CloudStack connection and fix the context dictionary creation in the _async_request method. [Oleg Suharev] - Fix networks retrieval in the CloudStack driver create_node method. Also only pass 'networkids' field to the API if there are any networks available. [Oleg Suharev, Tomaz Muraus] - Fix list_nodes in the CloudStack driver. Private IPs aren't always available. [Tomaz Muraus] Load-baancer ~~~~~~~~~~~~ - Add a missing argument to the method call inside LoadBalancer.attach_compute_node and Driver.balancer_attach_compute_node. [Tim Fletcher, Tomaz Muraus] - Add missing destroy() method to the LoadBalancer class. [Tomaz Muraus] DNS ~~~ - New drivers for Rackspace Cloud DNS (US and UK region) [Tomaz Muraus] - Add list_record_types() method. This method returns a list of record types supported by the provider. [Tomaz Muraus] Changes with Apache Libcloud 0.6.0-beta1 ---------------------------------------- General ~~~~~~~ - All the driver classes now inherit from the BaseDriver class [Tomaz Muraus] - Prefer simplejson (if available) over json module. (LIBCLOUD-112) [Geoff Greer] - Update compute demo and change the syntax of test credentials stored in test/secrets.py-dist. (LIBCLOUD-111) [Mike Nerone] - Enable SSL certificate verification by default and throw an exception if CA certificate files cannot be found. This can be overridden by setting libcloud.security.VERIFY_SSL_CERT_STRICT to False. [Tomaz Muraus] Compute ~~~~~~~ - Support for 1.1 API and many other improvements in the OpenStack driver ; LIBCLOUD-83 [Mike Nerone, Paul Querna, Brad Morgan, Tomaz Muraus] - Add some extra methods to the Gandi.net driver (LIBCLOUD-115) [Aymeric Barantal] - Add ex_delete_image method to the Rackspace driver. (GITHUB-27) [David Busby] - Linode driver now supports new 'Japan' location [Jed Smith] - Rackspace driver now inherits from the OpenStack one instead of doing it vice versa. (LIBCLOUD-110) [Mike Nerone] - Properly populate NodeImage "details" dictionary in the Rackspace compute driver. (LIBCLOUD-107) [Lucy Mendel] - Fix a bug in Eucalyptus driver ex_describe_addresses method. [Tomaz Muraus] - Add the following new extenstion methods to the Rackspace driver: ex_resize, ex_confirm_resize, ex_revert_resize. [Tomaz Muraus] - Also allow user to pass in Node object to some ex\_ methods in the Rackspace compute driver. [Tomaz Muraus] - Throw an exception in deploy_node if paramiko library is not available [Tomaz Muraus] - Fix chmod argument value which is passed to the sftpclient.put method; GITHUB-17 [John Carr] - New driver for Ninefold.com. (LIBCLOUD-98) [Benno Rice] Storage ~~~~~~~ - New driver for Google Storage based on the v1.0 / legacy API [Tomaz Muraus] - New driver for Ninefold.com. (GITHUB-19) [Benno Rice] - Fix a bug in uploading an object with some versions of Python 2.7 where httplib library doesn't automatically call str() on the header values. [Tomaz Muraus] - Allow users to upload (create) 0-bytes large (empty) objects [Tomaz Muraus] Load-balancer ~~~~~~~~~~~~~ - New driver for Rackspace UK location [Tomaz Muraus] - New driver for Ninefold.com. (LIBCLOUD-98) [Benno Rice] DNS ~~~ - Drivers for Linode DNS and Zerigo DNS [Tomaz Muraus] - Brand new DNS API! [Tomaz Muraus] Changes with Apache Libcloud 0.5.2 ---------------------------------- Compute ~~~~~~~ - New driver for serverlove.com and skalicloud.com [Tomaz Muraus] - Fix node name and tag handling in the Amazon EC2 driver [Wiktor Kolodziej] - Fix pricing and response handling in the OpenStack driver [Andrey Zhuchkov] - Fix deploy_node() method and make it more robust [Tomaz Muraus] - Users can now pass file like objects to ScriptDeployment and SSHKeyDeployment constructor. [Tomaz Muraus] - Include node tags when calling list_nodes() in the Amazon EC2 driver [Trevor Pounds] - Properly handle response errors in the Rackspace driver and only throw InvalidCredsError if the returned status code is 401 [Brad Morgan] - Fix the create_node method in the Nimbus driver and make the "ex_create_tag" method a no-op, because Nimbus doesn't support creating tags. [Tomaz Muraus] Storage ~~~~~~~ - Fix handling of the containers with a lot of objects. Now a LazyList object is returned when user calls list_container_objects() method and this object transparently handles pagination. [Danny Clark, Wiktor Kolodziej] Changes with Apache Libcloud 0.5.0 ---------------------------------- - Existing APIs directly on the libcloud.* module have been deprecated and will be removed in version 0.6.0. Most methods were moved to the libcloud.compute.* module. - Add new libcloud.loadbalancers API, with initial support for: - GoGrid Load Balancers - Rackspace Load Balancers [Roman Bogorodskiy] - Add new libcloud.storage API, with initial support for: - Amazon S3 - Rackspace CloudFiles [Tomaz Muraus] - Add new libcloud.compute drivers for: - Bluebox [Christian Paredes] - Gandi.net [Aymeric Barantal] - Nimbus [David LaBissoniere] - OpenStack [Roman Bogorodskiy] - Opsource.net [Joe Miller] - Added "pricing" module and improved pricing handling. [Tomaz Muraus] - Updates to the GoGrid compute driver: - Use API version 1.0. - Remove sandbox flag. - Add ex_list_ips() to list IP addresses assigned to the account. - Implement ex_edit_image method which allows changing image attributes like name, description and make image public or private. [Roman Bogorodskiy] - Updates to the Amazon EC2 compute driver: - When creating a Node, use the name argument to set a Tag with the value. [Tomaz Muraus] - Add extension method for modifying node attributes and changing the node size. [Tomaz Muraus] - Add support for the new Amazon Region (Tokyo). [Tomaz Muraus] - Added ex_create_tags and ex_delete_tags. [Brandon Rhodes] - Include node Elastic IP addresses in the node public_ip attribute for the EC2 nodes. [Tomaz Muraus] - Use ipAddress and privateIpAddress attribute for the EC 2node public and private ip. [Tomaz Muraus] - Add ex_describe_addresses method to the EC2 driver. [Tomaz Muraus] - Updates to the Rackspace CloudServers compute driver: - Add ex_rebuild() and ex_get_node_details() [Andrew Klochkov] - Expose URI of a Rackspace node to the node meta data. [Paul Querna] - Minor fixes to get the library and tests working on Python 2.7 and PyPy. [Tomaz Muraus] Changes with Apache Libcloud 0.4.2 (Released January 18, 2011) -------------------------------------------------------------- - Fix EC2 create_node to become backward compatible for NodeLocation. [Tomaz Muraus] - Update code for compatibility with CPython 2.5 [Jerry Chen] - Implement ex_edit_node method for GoGrid driver which allows changing node attributes like amount of RAM or description. [Roman Bogorodskiy] - Add ex_set_password and ex_set_server_name to Rackspace driver. [Peter Herndon, Paul Querna] - Add Hard and Soft reboot methods to Rackspace driver. [Peter Herndon] - EC2 Driver availability zones, via ex_list_availability_zones; list_locations rewrite to include availability zones [Tomaz Muraus] - EC2 Driver Idempotency capability in create_node; LIBCLOUD-69 [David LaBissoniere] - SSL Certificate Name Verification: - libcloud.security module - LibcloudHTTPSConnection, LibcloudHTTPConnection (alias) - Emits warning when not verifying, or CA certs not found - Append ORD1 to available Rackspace location, but keep in the same node as DFW1, because it's not readable or writeable from the API. [Per suggestion of Grig Gheorghiu] - ex_create_ip_group, ex_list_ip_groups, ex_delete_ip_group, ex_share_ip, ex_unshare_ip, ex_list_ip_addresses additions to Rackspace driver [Andrew Klochkov] - New driver for CloudSigma. [Tomaz Muraus] - New driver for Brightbox Cloud. (LIBCLOUD-63) [Tim Fletcher] - Deployment capability to ElasticHosts [Tomaz Muraus] - Allow deploy_node to use non-standard SSH username and port [Tomaz Muraus] - Added Rackspace UK (London) support [Chmouel Boudjnah] - GoGrid driver: add support for locations, i.e. listing of locations and creation of a node in specified location [Roman Bogorodskiy] - GoGrid and Rackspace drivers: add ex_save_image() extra call to convert running node to an image [Roman Bogorodskiy] - GoGrid driver: add support for creating 'sandbox' server and populate isSandbox flag in node's extra information. [Roman Bogorodskiy] - Add ImportKeyPair and DescribeKeyPair to EC2. (LIBCLOUD-62) [Philip Schwartz] - Update EC2 driver and test fixtures for new API. [Philip Schwartz] Changes with Apache Libcloud 0.4.0 [Released October 6, 2010] ------------------------------------------------------------- - Add create keypair functionality to EC2 Drivers. (LIBCLOUD-57) [Grig Gheorghiu] - Improve handling of GoGrid accounts with limited access API keys. [Paul Querna] - New Driver for ElasticHosts. (LIBCLOUD-45) [Tomaz Muraus] - Use more consistent name for GoGrid driver and use http POST method for 'unsafe' operations [Russell Haering] - Implement password handling and add deployment support for GoGrid nodes. [Roman Bogorodskiy] - Fix behavior of GoGrid's create_node to wait for a Node ID. [Roman Bogorodskiy] - Add ex_create_node_nowait to GoGrid driver if you don't need to wait for a Node ID when creating a node. [Roman Bogorodskiy] - Removed libcloud.interfaces module. [Paul Querna] - Removed dependency on zope.interfaces. [Paul Querna] - RimuHosting moved API endpoint address. [Paul Querna] - Fix regression and error in GoGrid driver for parsing node objects. [Roman Bogorodskiy] - Added more test cases for GoGrid driver. (LIBCLOUD-34) [Roman Bogorodskiy, Jerry Chen] - Fix parsing of Slicehost nodes with multiple Public IP addresses. [Paul Querna] - Add exit_status to ScriptDeployment. (LIBCLOUD-36) [Paul Querna] - Update prices for several drivers. [Brad Morgan, Paul Querna] - Update Linode driver to reflect new plan sizes. [Jed Smith] - Change default of 'location' in Linode create_node. (LIBCLOUD-41) [Jed Smith, Steve Steiner] - Document the Linode driver. [Jed Smith] - Request a private, LAN IP address at Linode creation. [Jed Smith] Changes with Apache Libcloud 0.3.1 [Released May 11, 2010] ---------------------------------------------------------- - Updates to Apache License blocks to correctly reflect status as an Apache Project. - Fix NOTICE file to use 2010 copyright date. - Improve error messages for when running the test cases without first setting up a secrets.py Changes with Apache Libcloud 0.3.0 [Tagged May 6, 2010, not released] --------------------------------------------------------------------- - New Drivers for: - Dreamhost - Eucalyptus - Enomaly ECP - IBM Developer Cloud - OpenNebula - SoftLayer - Added new deployment and bootstrap API. - Improved Voxel driver. - Added support for Amazon EC2 Asia Pacific (Singapore) Region. - Improved test coverage for all drivers. - Add support for multiple security groups in EC2. - Fixed bug in Rackspace and RimuHosting when using multiple threads. - Improved debugging and logging of HTTP requests. - Improved documentation for all classes and methods. Changes with Apache Libcloud 0.2.0 [Tagged February 2, 2010] ------------------------------------------------------------ - First public release. apache-libcloud-2.8.0/LICENSE0000664000175000017500000002613613535474530015451 0ustar kamikami00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 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 [yyyy] [name of copyright owner] 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. apache-libcloud-2.8.0/MANIFEST.in0000664000175000017500000000145613535474530016200 0ustar kamikami00000000000000include LICENSE include NOTICE include example_*.py include CHANGES.rst include README.rst include tox.ini include .pylintrc include requirements-tests.txt include libcloud/data/pricing.json prune libcloud/test/secrets.py include demos/* include scripts/check_file_names.sh include libcloud/test/*.py include libcloud/test/pricing_test.json include libcloud/test/secrets.py-dist include libcloud/test/common/*.py include libcloud/test/compute/*.py include libcloud/test/storage/*.py include libcloud/test/loadbalancer/*.py include libcloud/test/dns/*.py include libcloud/test/common/fixtures/*/* include libcloud/test/compute/fixtures/*/* include libcloud/test/compute/fixtures/*/*/* include libcloud/test/storage/fixtures/*/* include libcloud/test/loadbalancer/fixtures/*/* include libcloud/test/dns/fixtures/*/* apache-libcloud-2.8.0/NOTICE0000664000175000017500000000040113535474530015333 0ustar kamikami00000000000000Apache Libcloud Copyright (c) 2010-2015 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). This product includes software developed by Cloudkick (http://www.cloudkick.com/). apache-libcloud-2.8.0/PKG-INFO0000664000175000017500000001163413600223624015523 0ustar kamikami00000000000000Metadata-Version: 1.2 Name: apache-libcloud Version: 2.8.0 Summary: A standard Python library that abstracts away differences among multiple cloud provider APIs. For more information and documentation, please see http://libcloud.apache.org Home-page: http://libcloud.apache.org/ Author: Apache Software Foundation Author-email: dev@libcloud.apache.org License: Apache License (2.0) Description: Apache Libcloud - a unified interface for the cloud ==================================================== Apache Libcloud is a Python library which hides differences between different cloud provider APIs and allows you to manage different cloud resources through a unified and easy to use API. .. image:: https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat :target: https://libcloud.readthedocs.org .. image:: https://img.shields.io/pypi/v/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/travis/apache/libcloud/trunk.svg :target: http://travis-ci.org/apache/libcloud .. image:: https://img.shields.io/codecov/c/github/apache/libcloud/trunk.svg :target: https://codecov.io/github/apache/libcloud?branch=trunk .. image:: https://img.shields.io/pypi/pyversions/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/pypi/wheel/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/github/license/apache/libcloud.svg :target: https://github.com/apache/libcloud/blob/trunk/LICENSE .. image:: https://bestpractices.coreinfrastructure.org/projects/152/badge :target: https://bestpractices.coreinfrastructure.org/projects/152 :Code: https://github.com/apache/libcloud :License: Apache 2.0; see LICENSE file :Issues: https://issues.apache.org/jira/projects/LIBCLOUD/issues :Website: https://libcloud.apache.org/ :Documentation: https://libcloud.readthedocs.io Resources you can manage with Libcloud are divided into the following categories: * **Compute** - Cloud Servers and Block Storage - services such as Amazon EC2 and Rackspace Cloud Servers (``libcloud.compute.*``) * **Storage** - Cloud Object Storage and CDN - services such as Amazon S3 and Rackspace CloudFiles (``libcloud.storage.*``) * **Load Balancers** - Load Balancers as a Service, LBaaS (``libcloud.loadbalancer.*``) * **DNS** - DNS as a Service, DNSaaS (``libcloud.dns.*``) * **Container** - Container virtualization services (``libcloud.container.*``) Apache Libcloud is an Apache project, see for more information. Documentation ============= Documentation can be found at . Feedback ======== Please send feedback to the mailing list at , or Github repo at . Contributing ============ For information on how to contribute, please see the Contributing chapter in our documentation License ======= Apache Libcloud is licensed under the Apache 2.0 license. For more information, please see LICENSE_ and NOTICE_ file. .. _LICENSE: https://github.com/apache/libcloud/blob/trunk/LICENSE .. _NOTICE: https://github.com/apache/libcloud/blob/trunk/NOTICE Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4 apache-libcloud-2.8.0/README.rst0000664000175000017500000000570613576514553016140 0ustar kamikami00000000000000Apache Libcloud - a unified interface for the cloud ==================================================== Apache Libcloud is a Python library which hides differences between different cloud provider APIs and allows you to manage different cloud resources through a unified and easy to use API. .. image:: https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat :target: https://libcloud.readthedocs.org .. image:: https://img.shields.io/pypi/v/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/travis/apache/libcloud/trunk.svg :target: http://travis-ci.org/apache/libcloud .. image:: https://img.shields.io/codecov/c/github/apache/libcloud/trunk.svg :target: https://codecov.io/github/apache/libcloud?branch=trunk .. image:: https://img.shields.io/pypi/pyversions/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/pypi/wheel/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/github/license/apache/libcloud.svg :target: https://github.com/apache/libcloud/blob/trunk/LICENSE .. image:: https://bestpractices.coreinfrastructure.org/projects/152/badge :target: https://bestpractices.coreinfrastructure.org/projects/152 :Code: https://github.com/apache/libcloud :License: Apache 2.0; see LICENSE file :Issues: https://issues.apache.org/jira/projects/LIBCLOUD/issues :Website: https://libcloud.apache.org/ :Documentation: https://libcloud.readthedocs.io Resources you can manage with Libcloud are divided into the following categories: * **Compute** - Cloud Servers and Block Storage - services such as Amazon EC2 and Rackspace Cloud Servers (``libcloud.compute.*``) * **Storage** - Cloud Object Storage and CDN - services such as Amazon S3 and Rackspace CloudFiles (``libcloud.storage.*``) * **Load Balancers** - Load Balancers as a Service, LBaaS (``libcloud.loadbalancer.*``) * **DNS** - DNS as a Service, DNSaaS (``libcloud.dns.*``) * **Container** - Container virtualization services (``libcloud.container.*``) Apache Libcloud is an Apache project, see for more information. Documentation ============= Documentation can be found at . Feedback ======== Please send feedback to the mailing list at , or Github repo at . Contributing ============ For information on how to contribute, please see the Contributing chapter in our documentation License ======= Apache Libcloud is licensed under the Apache 2.0 license. For more information, please see LICENSE_ and NOTICE_ file. .. _LICENSE: https://github.com/apache/libcloud/blob/trunk/LICENSE .. _NOTICE: https://github.com/apache/libcloud/blob/trunk/NOTICE apache-libcloud-2.8.0/apache_libcloud.egg-info/0000775000175000017500000000000013600223624021211 5ustar kamikami00000000000000apache-libcloud-2.8.0/apache_libcloud.egg-info/PKG-INFO0000664000175000017500000001163413600223624022313 0ustar kamikami00000000000000Metadata-Version: 1.2 Name: apache-libcloud Version: 2.8.0 Summary: A standard Python library that abstracts away differences among multiple cloud provider APIs. For more information and documentation, please see http://libcloud.apache.org Home-page: http://libcloud.apache.org/ Author: Apache Software Foundation Author-email: dev@libcloud.apache.org License: Apache License (2.0) Description: Apache Libcloud - a unified interface for the cloud ==================================================== Apache Libcloud is a Python library which hides differences between different cloud provider APIs and allows you to manage different cloud resources through a unified and easy to use API. .. image:: https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat :target: https://libcloud.readthedocs.org .. image:: https://img.shields.io/pypi/v/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/travis/apache/libcloud/trunk.svg :target: http://travis-ci.org/apache/libcloud .. image:: https://img.shields.io/codecov/c/github/apache/libcloud/trunk.svg :target: https://codecov.io/github/apache/libcloud?branch=trunk .. image:: https://img.shields.io/pypi/pyversions/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/pypi/wheel/apache-libcloud.svg :target: https://pypi.python.org/pypi/apache-libcloud/ .. image:: https://img.shields.io/github/license/apache/libcloud.svg :target: https://github.com/apache/libcloud/blob/trunk/LICENSE .. image:: https://bestpractices.coreinfrastructure.org/projects/152/badge :target: https://bestpractices.coreinfrastructure.org/projects/152 :Code: https://github.com/apache/libcloud :License: Apache 2.0; see LICENSE file :Issues: https://issues.apache.org/jira/projects/LIBCLOUD/issues :Website: https://libcloud.apache.org/ :Documentation: https://libcloud.readthedocs.io Resources you can manage with Libcloud are divided into the following categories: * **Compute** - Cloud Servers and Block Storage - services such as Amazon EC2 and Rackspace Cloud Servers (``libcloud.compute.*``) * **Storage** - Cloud Object Storage and CDN - services such as Amazon S3 and Rackspace CloudFiles (``libcloud.storage.*``) * **Load Balancers** - Load Balancers as a Service, LBaaS (``libcloud.loadbalancer.*``) * **DNS** - DNS as a Service, DNSaaS (``libcloud.dns.*``) * **Container** - Container virtualization services (``libcloud.container.*``) Apache Libcloud is an Apache project, see for more information. Documentation ============= Documentation can be found at . Feedback ======== Please send feedback to the mailing list at , or Github repo at . Contributing ============ For information on how to contribute, please see the Contributing chapter in our documentation License ======= Apache Libcloud is licensed under the Apache 2.0 license. For more information, please see LICENSE_ and NOTICE_ file. .. _LICENSE: https://github.com/apache/libcloud/blob/trunk/LICENSE .. _NOTICE: https://github.com/apache/libcloud/blob/trunk/NOTICE Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4 apache-libcloud-2.8.0/apache_libcloud.egg-info/SOURCES.txt0000664000175000017500000052522013600223624023103 0ustar kamikami00000000000000.pylintrc CHANGES.rst LICENSE MANIFEST.in NOTICE README.rst example_compute.py example_dns.py example_loadbalancer.py example_storage.py requirements-tests.txt setup.cfg setup.py tox.ini apache_libcloud.egg-info/PKG-INFO apache_libcloud.egg-info/SOURCES.txt apache_libcloud.egg-info/dependency_links.txt apache_libcloud.egg-info/not-zip-safe apache_libcloud.egg-info/requires.txt apache_libcloud.egg-info/top_level.txt demos/__init__.py demos/compute_demo.py demos/example_aliyun_ecs.py demos/example_aliyun_oss.py demos/example_aliyun_slb.py demos/example_openstack.py demos/gce_demo.py demos/secrets.py-dist libcloud/__init__.py libcloud/base.py libcloud/http.py libcloud/pricing.py libcloud/py.typed libcloud/security.py libcloud/backup/__init__.py libcloud/backup/base.py libcloud/backup/providers.py libcloud/backup/types.py libcloud/backup/drivers/__init__.py libcloud/backup/drivers/dimensiondata.py libcloud/backup/drivers/dummy.py libcloud/backup/drivers/ebs.py libcloud/backup/drivers/gce.py libcloud/common/__init__.py libcloud/common/abiquo.py libcloud/common/aliyun.py libcloud/common/aws.py libcloud/common/azure.py libcloud/common/azure_arm.py libcloud/common/base.py libcloud/common/brightbox.py libcloud/common/buddyns.py libcloud/common/cloudsigma.py libcloud/common/cloudstack.py libcloud/common/digitalocean.py libcloud/common/dimensiondata.py libcloud/common/dnsimple.py libcloud/common/dnspod.py libcloud/common/durabledns.py libcloud/common/exceptions.py libcloud/common/gandi.py libcloud/common/gandi_live.py libcloud/common/gogrid.py libcloud/common/google.py libcloud/common/gridscale.py libcloud/common/hostvirtual.py libcloud/common/linode.py libcloud/common/liquidweb.py libcloud/common/luadns.py libcloud/common/maxihost.py libcloud/common/nfsn.py libcloud/common/nsone.py libcloud/common/nttcis.py libcloud/common/onapp.py libcloud/common/openstack.py libcloud/common/openstack_identity.py libcloud/common/ovh.py libcloud/common/pointdns.py libcloud/common/providers.py libcloud/common/rackspace.py libcloud/common/softlayer.py libcloud/common/types.py libcloud/common/upcloud.py libcloud/common/vultr.py libcloud/common/worldwidedns.py libcloud/common/xmlrpc.py libcloud/common/zonomi.py libcloud/compute/__init__.py libcloud/compute/base.py libcloud/compute/constants.py libcloud/compute/deployment.py libcloud/compute/deprecated.py libcloud/compute/providers.py libcloud/compute/ssh.py libcloud/compute/types.py libcloud/compute/drivers/__init__.py libcloud/compute/drivers/abiquo.py libcloud/compute/drivers/auroracompute.py libcloud/compute/drivers/azure.py libcloud/compute/drivers/azure_arm.py libcloud/compute/drivers/bluebox.py libcloud/compute/drivers/brightbox.py libcloud/compute/drivers/bsnl.py libcloud/compute/drivers/cloudscale.py libcloud/compute/drivers/cloudsigma.py libcloud/compute/drivers/cloudstack.py libcloud/compute/drivers/cloudwatt.py libcloud/compute/drivers/digitalocean.py libcloud/compute/drivers/dimensiondata.py libcloud/compute/drivers/dummy.py libcloud/compute/drivers/ec2.py libcloud/compute/drivers/ecp.py libcloud/compute/drivers/ecs.py libcloud/compute/drivers/elastichosts.py libcloud/compute/drivers/elasticstack.py libcloud/compute/drivers/exoscale.py libcloud/compute/drivers/gandi.py libcloud/compute/drivers/gce.py libcloud/compute/drivers/gogrid.py libcloud/compute/drivers/gridscale.py libcloud/compute/drivers/gridspot.py libcloud/compute/drivers/hostvirtual.py libcloud/compute/drivers/ikoula.py libcloud/compute/drivers/indosat.py libcloud/compute/drivers/internetsolutions.py libcloud/compute/drivers/joyent.py libcloud/compute/drivers/kili.py libcloud/compute/drivers/ktucloud.py libcloud/compute/drivers/libvirt_driver.py libcloud/compute/drivers/linode.py libcloud/compute/drivers/maxihost.py libcloud/compute/drivers/medone.py libcloud/compute/drivers/nephoscale.py libcloud/compute/drivers/ntta.py libcloud/compute/drivers/nttcis.py libcloud/compute/drivers/onapp.py libcloud/compute/drivers/oneandone.py libcloud/compute/drivers/opennebula.py libcloud/compute/drivers/openstack.py libcloud/compute/drivers/ovh.py libcloud/compute/drivers/packet.py libcloud/compute/drivers/profitbricks.py libcloud/compute/drivers/rackspace.py libcloud/compute/drivers/rimuhosting.py libcloud/compute/drivers/scaleway.py libcloud/compute/drivers/serverlove.py libcloud/compute/drivers/skalicloud.py libcloud/compute/drivers/softlayer.py libcloud/compute/drivers/upcloud.py libcloud/compute/drivers/vcl.py libcloud/compute/drivers/vcloud.py libcloud/compute/drivers/voxel.py libcloud/compute/drivers/vpsnet.py libcloud/compute/drivers/vsphere.py libcloud/compute/drivers/vultr.py libcloud/container/__init__.py libcloud/container/base.py libcloud/container/providers.py libcloud/container/types.py libcloud/container/drivers/__init__.py libcloud/container/drivers/docker.py libcloud/container/drivers/dummy.py libcloud/container/drivers/ecs.py libcloud/container/drivers/gke.py libcloud/container/drivers/joyent.py libcloud/container/drivers/kubernetes.py libcloud/container/drivers/rancher.py libcloud/container/utils/__init__.py libcloud/container/utils/docker.py libcloud/data/pricing.json libcloud/dns/__init__.py libcloud/dns/base.py libcloud/dns/providers.py libcloud/dns/types.py libcloud/dns/drivers/__init__.py libcloud/dns/drivers/auroradns.py libcloud/dns/drivers/buddyns.py libcloud/dns/drivers/cloudflare.py libcloud/dns/drivers/digitalocean.py libcloud/dns/drivers/dnsimple.py libcloud/dns/drivers/dnspod.py libcloud/dns/drivers/dummy.py libcloud/dns/drivers/durabledns.py libcloud/dns/drivers/gandi.py libcloud/dns/drivers/gandi_live.py libcloud/dns/drivers/godaddy.py libcloud/dns/drivers/google.py libcloud/dns/drivers/hostvirtual.py libcloud/dns/drivers/linode.py libcloud/dns/drivers/liquidweb.py libcloud/dns/drivers/luadns.py libcloud/dns/drivers/nfsn.py libcloud/dns/drivers/nsone.py libcloud/dns/drivers/onapp.py libcloud/dns/drivers/pointdns.py libcloud/dns/drivers/powerdns.py libcloud/dns/drivers/rackspace.py libcloud/dns/drivers/rcodezero.py libcloud/dns/drivers/route53.py libcloud/dns/drivers/softlayer.py libcloud/dns/drivers/vultr.py libcloud/dns/drivers/worldwidedns.py libcloud/dns/drivers/zerigo.py libcloud/dns/drivers/zonomi.py libcloud/loadbalancer/__init__.py libcloud/loadbalancer/base.py libcloud/loadbalancer/providers.py libcloud/loadbalancer/types.py libcloud/loadbalancer/drivers/__init__.py libcloud/loadbalancer/drivers/alb.py libcloud/loadbalancer/drivers/brightbox.py libcloud/loadbalancer/drivers/cloudstack.py libcloud/loadbalancer/drivers/dimensiondata.py libcloud/loadbalancer/drivers/elb.py libcloud/loadbalancer/drivers/gce.py libcloud/loadbalancer/drivers/gogrid.py libcloud/loadbalancer/drivers/ninefold.py libcloud/loadbalancer/drivers/nttcis.py libcloud/loadbalancer/drivers/rackspace.py libcloud/loadbalancer/drivers/slb.py libcloud/loadbalancer/drivers/softlayer.py libcloud/storage/__init__.py libcloud/storage/base.py libcloud/storage/providers.py libcloud/storage/types.py libcloud/storage/drivers/__init__.py libcloud/storage/drivers/atmos.py libcloud/storage/drivers/auroraobjects.py libcloud/storage/drivers/azure_blobs.py libcloud/storage/drivers/backblaze_b2.py libcloud/storage/drivers/cloudfiles.py libcloud/storage/drivers/digitalocean_spaces.py libcloud/storage/drivers/dummy.py libcloud/storage/drivers/google_storage.py libcloud/storage/drivers/ktucloud.py libcloud/storage/drivers/local.py libcloud/storage/drivers/nimbus.py libcloud/storage/drivers/ninefold.py libcloud/storage/drivers/oss.py libcloud/storage/drivers/rgw.py libcloud/storage/drivers/s3.py libcloud/test/__init__.py libcloud/test/conftest.py libcloud/test/file_fixtures.py libcloud/test/pricing_test.json libcloud/test/secrets.py-dist libcloud/test/test_connection.py libcloud/test/test_file_fixtures.py libcloud/test/test_http.py libcloud/test/test_init.py libcloud/test/test_logging_connection.py libcloud/test/test_pricing.py libcloud/test/test_response_classes.py libcloud/test/test_types.py libcloud/test/test_utils.py libcloud/test/backup/__init__.py libcloud/test/backup/test_dimensiondata_v2_3.py libcloud/test/backup/test_dimensiondata_v2_4.py libcloud/test/backup/fixtures/dimensiondata/_backup_DISABLE.xml libcloud/test/backup/fixtures/dimensiondata/_backup_ENABLE.xml libcloud/test/backup/fixtures/dimensiondata/_backup_EXISTS.xml libcloud/test/backup/fixtures/dimensiondata/_backup_INFO.xml libcloud/test/backup/fixtures/dimensiondata/_backup_INFO_DISABLED.xml libcloud/test/backup/fixtures/dimensiondata/_backup_INFO_NOCLIENT.xml libcloud/test/backup/fixtures/dimensiondata/_backup_INFO_NOJOB.xml libcloud/test/backup/fixtures/dimensiondata/_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml libcloud/test/backup/fixtures/dimensiondata/_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml libcloud/test/backup/fixtures/dimensiondata/_backup_client_SUCCESS_PUT.xml libcloud/test/backup/fixtures/dimensiondata/_backup_client_schedulePolicy.xml libcloud/test/backup/fixtures/dimensiondata/_backup_client_storagePolicy.xml libcloud/test/backup/fixtures/dimensiondata/_backup_client_type.xml libcloud/test/backup/fixtures/dimensiondata/_backup_modify.xml libcloud/test/backup/fixtures/dimensiondata/_remove_backup_client.xml libcloud/test/backup/fixtures/dimensiondata/_remove_backup_client_FAIL.xml libcloud/test/backup/fixtures/dimensiondata/oec_0_9_myaccount.xml libcloud/test/backup/fixtures/dimensiondata/server_server.xml libcloud/test/backup/fixtures/dimensiondata/server_server_NOBACKUP.xml libcloud/test/backup/fixtures/dimensiondata/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml libcloud/test/backup/fixtures/dimensiondata/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml libcloud/test/common/__init__.py libcloud/test/common/test_aliyun.py libcloud/test/common/test_aws.py libcloud/test/common/test_azure.py libcloud/test/common/test_base.py libcloud/test/common/test_base_driver.py libcloud/test/common/test_cloudstack.py libcloud/test/common/test_digitalocean_v2.py libcloud/test/common/test_gandi.py libcloud/test/common/test_gandi_live.py libcloud/test/common/test_google.py libcloud/test/common/test_nfsn.py libcloud/test/common/test_openstack.py libcloud/test/common/test_openstack_identity.py libcloud/test/common/test_ovh.py libcloud/test/common/test_retry_limit.py libcloud/test/common/test_upcloud.py libcloud/test/common/fixtures/digitalocean/_v1_events_12345670.json libcloud/test/common/fixtures/digitalocean/_v1_events_12345670_UNAUTHORIZED.json libcloud/test/common/fixtures/digitalocean/_v2_account.json libcloud/test/common/fixtures/digitalocean/_v2_account_UNAUTHORIZED.json libcloud/test/common/fixtures/digitalocean/_v2_actions.json libcloud/test/common/fixtures/digitalocean/_v2_actions_12345670.json libcloud/test/common/fixtures/digitalocean/_v2_actions_page_1.json libcloud/test/common/fixtures/digitalocean/_v2_actions_page_2.json libcloud/test/common/fixtures/google/pkey.json libcloud/test/common/fixtures/google/pkey.pem libcloud/test/compute/__init__.py libcloud/test/compute/test_abiquo.py libcloud/test/compute/test_auroracompute.py libcloud/test/compute/test_azure.py libcloud/test/compute/test_azure_arm.py libcloud/test/compute/test_base.py libcloud/test/compute/test_bluebox.py libcloud/test/compute/test_brightbox.py libcloud/test/compute/test_bsnl.py libcloud/test/compute/test_cloudscale.py libcloud/test/compute/test_cloudsigma_v1_0.py libcloud/test/compute/test_cloudsigma_v2_0.py libcloud/test/compute/test_cloudstack.py libcloud/test/compute/test_cloudwatt.py libcloud/test/compute/test_deployment.py libcloud/test/compute/test_digitalocean_v2.py libcloud/test/compute/test_dimensiondata_v2_3.py libcloud/test/compute/test_dimensiondata_v2_4.py libcloud/test/compute/test_ec2.py libcloud/test/compute/test_ecp.py libcloud/test/compute/test_ecs.py libcloud/test/compute/test_elasticstack.py libcloud/test/compute/test_exoscale.py libcloud/test/compute/test_gandi.py libcloud/test/compute/test_gce.py libcloud/test/compute/test_gogrid.py libcloud/test/compute/test_gridscale.py libcloud/test/compute/test_gridspot.py libcloud/test/compute/test_hostvirtual.py libcloud/test/compute/test_ikoula.py libcloud/test/compute/test_indosat.py libcloud/test/compute/test_internetsolutions.py libcloud/test/compute/test_joyent.py libcloud/test/compute/test_kili.py libcloud/test/compute/test_ktucloud.py libcloud/test/compute/test_libvirt_driver.py libcloud/test/compute/test_linode.py libcloud/test/compute/test_maxihost.py libcloud/test/compute/test_medone.py libcloud/test/compute/test_nephoscale.py libcloud/test/compute/test_ntta.py libcloud/test/compute/test_nttcis.py libcloud/test/compute/test_onapp.py libcloud/test/compute/test_oneandone.py libcloud/test/compute/test_opennebula.py libcloud/test/compute/test_openstack.py libcloud/test/compute/test_ovh.py libcloud/test/compute/test_packet.py libcloud/test/compute/test_profitbricks.py libcloud/test/compute/test_rackspace.py libcloud/test/compute/test_rimuhosting.py libcloud/test/compute/test_scaleway.py libcloud/test/compute/test_softlayer.py libcloud/test/compute/test_ssh_client.py libcloud/test/compute/test_types.py libcloud/test/compute/test_upcloud.py libcloud/test/compute/test_vcl.py libcloud/test/compute/test_vcloud.py libcloud/test/compute/test_voxel.py libcloud/test/compute/test_vpsnet.py libcloud/test/compute/test_vultr.py libcloud/test/compute/fixtures/abiquo/dcs.xml libcloud/test/compute/fixtures/abiquo/ent_1.xml libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2.xml libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_template_11.xml libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_templates.xml libcloud/test/compute/fixtures/abiquo/ent_1_dcreps.xml libcloud/test/compute/fixtures/abiquo/login.xml libcloud/test/compute/fixtures/abiquo/not_found_error.xml libcloud/test/compute/fixtures/abiquo/privilege_errors.html libcloud/test/compute/fixtures/abiquo/unauthorized_user.html libcloud/test/compute/fixtures/abiquo/vdc_4.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_needs_sync.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vm_3_not_allocated.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vms.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task_failed.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_allocated.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task_failed.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deployed.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_nics.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset_task.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task_failed.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_creation_ok.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms_allocated.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_creation_ok.xml libcloud/test/compute/fixtures/abiquo/vdc_4_vapps.xml libcloud/test/compute/fixtures/abiquo/vdcs.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_locations.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_operations_acc33f6756cda6fd96826394fce4c9f3.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deployments_dc03_roleinstances_dc13.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deploymentslots_Production.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest02_deploymentslots_Production.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03_deploymentslots_Production.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest04.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz1_deploymentslots_Production.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz2_deploymentslots_Production.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz5_deploymentslots_Production.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdc1234.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deployments.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deploymentslots_Production.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc_deployments.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_images.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_storageservices_dss123.xml libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_vmimages.xml libcloud/test/compute/fixtures/azure/libcloud.pem libcloud/test/compute/fixtures/azure_arm/_77777777_7777_7777_7777_777777777777_oauth2_token.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Commerce_RateCard.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_disks.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_locations_eastus_vmSizes.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_snapshots.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_networkInterfaces.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_virtualnetworks.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_disks_test_disk_1.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_snapshots_test_snap_1.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1_InstanceView.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Network_networkInterfaces_test_node_1_nic.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_111111_providers_Microsoft_Compute_disks.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_111111_providers_Microsoft_Compute_snapshots.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_networkInterfaces_test_nic.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_publicIPAddresses_test_public_ip.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_virtualNetworks_test_network_CheckIPAddressAvailability.json libcloud/test/compute/fixtures/azure_arm/_subscriptions_subid_resourceGroups_rg1_providers_Microsoft_Network_publicIPAddresses_test_ip.json libcloud/test/compute/fixtures/bluebox/api_block_products_json.json libcloud/test/compute/fixtures/bluebox/api_block_templates_json.json libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json libcloud/test/compute/fixtures/bluebox/api_blocks_json.json libcloud/test/compute/fixtures/bluebox/api_blocks_json_post.json libcloud/test/compute/fixtures/brightbox/create_cloud_ip.json libcloud/test/compute/fixtures/brightbox/create_server.json libcloud/test/compute/fixtures/brightbox/create_server_gb1_a.json libcloud/test/compute/fixtures/brightbox/create_server_gb1_b.json libcloud/test/compute/fixtures/brightbox/list_cloud_ips.json libcloud/test/compute/fixtures/brightbox/list_images.json libcloud/test/compute/fixtures/brightbox/list_server_types.json libcloud/test/compute/fixtures/brightbox/list_servers.json libcloud/test/compute/fixtures/brightbox/list_zones.json libcloud/test/compute/fixtures/brightbox/token.json libcloud/test/compute/fixtures/cloudscale/create_node.json libcloud/test/compute/fixtures/cloudscale/list_images.json libcloud/test/compute/fixtures/cloudscale/list_nodes.json libcloud/test/compute/fixtures/cloudscale/list_sizes.json libcloud/test/compute/fixtures/cloudsigma/drives_clone.txt libcloud/test/compute/fixtures/cloudsigma/drives_info.txt libcloud/test/compute/fixtures/cloudsigma/drives_single_info.txt libcloud/test/compute/fixtures/cloudsigma/drives_standard_info.txt libcloud/test/compute/fixtures/cloudsigma/resources_ip_create.txt libcloud/test/compute/fixtures/cloudsigma/resources_ip_list.txt libcloud/test/compute/fixtures/cloudsigma/servers_create.txt libcloud/test/compute/fixtures/cloudsigma/servers_info.txt libcloud/test/compute/fixtures/cloudsigma/servers_set.txt libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json libcloud/test/compute/fixtures/cloudsigma_2_0/create_subscription.json libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json libcloud/test/compute/fixtures/cloudsigma_2_0/drives_avail_groups.json libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.json libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_avail_groups.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create_with_vlan.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json libcloud/test/compute/fixtures/cloudstack/addNicToVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/associateIpAddress_default.json libcloud/test/compute/fixtures/cloudstack/attachVolume_default.json libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json libcloud/test/compute/fixtures/cloudstack/createAffinityGroup_default.json libcloud/test/compute/fixtures/cloudstack/createEgressFirewallRule_default.json libcloud/test/compute/fixtures/cloudstack/createFirewallRule_default.json libcloud/test/compute/fixtures/cloudstack/createFirewallRule_firewallicmp.json libcloud/test/compute/fixtures/cloudstack/createNetworkACLList_default.json libcloud/test/compute/fixtures/cloudstack/createNetworkACL_default.json libcloud/test/compute/fixtures/cloudstack/createNetwork_default.json libcloud/test/compute/fixtures/cloudstack/createPortForwardingRule_default.json libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json libcloud/test/compute/fixtures/cloudstack/createSnapshot_default.json libcloud/test/compute/fixtures/cloudstack/createTags_default.json libcloud/test/compute/fixtures/cloudstack/createTemplate_default.json libcloud/test/compute/fixtures/cloudstack/createVPC_default.json libcloud/test/compute/fixtures/cloudstack/createVolume_default.json libcloud/test/compute/fixtures/cloudstack/createVolume_withcustomdisksize.json libcloud/test/compute/fixtures/cloudstack/createVolume_withvolumetype.json libcloud/test/compute/fixtures/cloudstack/createVpnConnection_default.json libcloud/test/compute/fixtures/cloudstack/createVpnCustomerGateway_default.json libcloud/test/compute/fixtures/cloudstack/createVpnGateway_default.json libcloud/test/compute/fixtures/cloudstack/deleteAffinityGroup_default.json libcloud/test/compute/fixtures/cloudstack/deleteEgressFirewallRule_default.json libcloud/test/compute/fixtures/cloudstack/deleteFirewallRule_default.json libcloud/test/compute/fixtures/cloudstack/deleteNetwork_default.json libcloud/test/compute/fixtures/cloudstack/deletePortForwardingRule_default.json libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json libcloud/test/compute/fixtures/cloudstack/deleteSnapshot_default.json libcloud/test/compute/fixtures/cloudstack/deleteTags_default.json libcloud/test/compute/fixtures/cloudstack/deleteVPC_default.json libcloud/test/compute/fixtures/cloudstack/deleteVolume_default.json libcloud/test/compute/fixtures/cloudstack/deleteVpnConnection_default.json libcloud/test/compute/fixtures/cloudstack/deleteVpnCustomerGateway_default.json libcloud/test/compute/fixtures/cloudstack/deleteVpnGateway_default.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployip.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploykeyname.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploynetworks.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploysecuritygroup.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_rootdisksize.json libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_stoppedvm.json libcloud/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/detachVolume_default.json libcloud/test/compute/fixtures/cloudstack/disassociateIpAddress_default.json libcloud/test/compute/fixtures/cloudstack/dummy_rsa.pub libcloud/test/compute/fixtures/cloudstack/listAffinityGroupTypes_default.json libcloud/test/compute/fixtures/cloudstack/listAffinityGroups_default.json libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_default.json libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withcustomdisksize.json libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withvolumetype.json libcloud/test/compute/fixtures/cloudstack/listEgressFirewallRules_default.json libcloud/test/compute/fixtures/cloudstack/listFirewallRules_default.json libcloud/test/compute/fixtures/cloudstack/listFirewallRules_firewallicmp.json libcloud/test/compute/fixtures/cloudstack/listIpForwardingRules_default.json libcloud/test/compute/fixtures/cloudstack/listNetworkACLLists_default.json libcloud/test/compute/fixtures/cloudstack/listNetworkACLs_default.json libcloud/test/compute/fixtures/cloudstack/listNetworkOfferings_default.json libcloud/test/compute/fixtures/cloudstack/listNetworks_default.json libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail.json libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json libcloud/test/compute/fixtures/cloudstack/listNetworks_deployip.json libcloud/test/compute/fixtures/cloudstack/listNetworks_deploynetworks.json libcloud/test/compute/fixtures/cloudstack/listNetworks_rootdisksize.json libcloud/test/compute/fixtures/cloudstack/listNetworks_stoppedvm.json libcloud/test/compute/fixtures/cloudstack/listNics_default.json libcloud/test/compute/fixtures/cloudstack/listOsTypes_default.json libcloud/test/compute/fixtures/cloudstack/listPortForwardingRules_default.json libcloud/test/compute/fixtures/cloudstack/listProjects_default.json libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_firewallicmp.json libcloud/test/compute/fixtures/cloudstack/listResourceLimits_default.json libcloud/test/compute/fixtures/cloudstack/listRouters_default.json libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one.json libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one_doesnt_exist.json libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_no_keys.json libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_no_groups.json libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_default.json libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_deployip.json libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_deploynetworks.json libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_rootdisksize.json libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_stoppedvm.json libcloud/test/compute/fixtures/cloudstack/listSnapshots_default.json libcloud/test/compute/fixtures/cloudstack/listTemplates_default.json libcloud/test/compute/fixtures/cloudstack/listTemplates_deployip.json libcloud/test/compute/fixtures/cloudstack/listTemplates_deploynetworks.json libcloud/test/compute/fixtures/cloudstack/listTemplates_notemplates.json libcloud/test/compute/fixtures/cloudstack/listTemplates_rootdisksize.json libcloud/test/compute/fixtures/cloudstack/listTemplates_stoppedvm.json libcloud/test/compute/fixtures/cloudstack/listVPCOfferings_default.json libcloud/test/compute/fixtures/cloudstack/listVPCs_default.json libcloud/test/compute/fixtures/cloudstack/listVirtualMachines_default.json libcloud/test/compute/fixtures/cloudstack/listVirtualMachines_noipaddress.json libcloud/test/compute/fixtures/cloudstack/listVolumes_default.json libcloud/test/compute/fixtures/cloudstack/listVolumes_rootdisksize.json libcloud/test/compute/fixtures/cloudstack/listVpnConnections_default.json libcloud/test/compute/fixtures/cloudstack/listVpnCustomerGateways_default.json libcloud/test/compute/fixtures/cloudstack/listVpnGateways_default.json libcloud/test/compute/fixtures/cloudstack/listZones_default.json libcloud/test/compute/fixtures/cloudstack/listZones_deployfail.json libcloud/test/compute/fixtures/cloudstack/listZones_deployfail2.json libcloud/test/compute/fixtures/cloudstack/listZones_deployip.json libcloud/test/compute/fixtures/cloudstack/listZones_deploynetworks.json libcloud/test/compute/fixtures/cloudstack/listZones_rootdisksize.json libcloud/test/compute/fixtures/cloudstack/listZones_stoppedvm.json libcloud/test/compute/fixtures/cloudstack/listZones_withcustomdisksize.json libcloud/test/compute/fixtures/cloudstack/listZones_withvolumetype.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11111.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_111112.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11112.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11113.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11114.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11115.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11116.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149341.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149342.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149343.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149366.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300001.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300002.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300003.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300004.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300005.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300006.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_88776.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_88777.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_addnictovm.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_attachvolumejob.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnConnection.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnCustomerGateway.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnGateway.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createtagsjob.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createvolumejob.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteNetwork.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVPC.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnConnection.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnCustomerGateway.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnGateway.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deletetagsjob.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployrootdisksize.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployvmstopped.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployvmwithid.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_detachvolumejob.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_removenic.json libcloud/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_default.json libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_error.json libcloud/test/compute/fixtures/cloudstack/removeNicFromVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/restoreVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/scaleVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/updateVMAffinityGroup_default.json libcloud/test/compute/fixtures/digitalocean/create_image.json libcloud/test/compute/fixtures/digitalocean/create_key_pair.json libcloud/test/compute/fixtures/digitalocean/error.json libcloud/test/compute/fixtures/digitalocean/ex_power_on_node.json libcloud/test/compute/fixtures/digitalocean/ex_shutdown_node.json libcloud/test/compute/fixtures/digitalocean/get_image.json libcloud/test/compute/fixtures/digitalocean/list_key_pairs.json libcloud/test/compute/fixtures/digitalocean/list_nodes_page_1.json libcloud/test/compute/fixtures/digitalocean_v2/attach_floating_ip.json libcloud/test/compute/fixtures/digitalocean_v2/attach_volume.json libcloud/test/compute/fixtures/digitalocean_v2/create_floating_ip.json libcloud/test/compute/fixtures/digitalocean_v2/create_image.json libcloud/test/compute/fixtures/digitalocean_v2/create_key_pair.json libcloud/test/compute/fixtures/digitalocean_v2/create_node.json libcloud/test/compute/fixtures/digitalocean_v2/create_volume.json libcloud/test/compute/fixtures/digitalocean_v2/create_volume_snapshot.json libcloud/test/compute/fixtures/digitalocean_v2/detach_floating_ip.json libcloud/test/compute/fixtures/digitalocean_v2/detach_volume.json libcloud/test/compute/fixtures/digitalocean_v2/error.json libcloud/test/compute/fixtures/digitalocean_v2/error_invalid_image.json libcloud/test/compute/fixtures/digitalocean_v2/ex_change_kernel.json libcloud/test/compute/fixtures/digitalocean_v2/ex_enable_ipv6.json libcloud/test/compute/fixtures/digitalocean_v2/ex_hard_reboot.json libcloud/test/compute/fixtures/digitalocean_v2/ex_power_on_node.json libcloud/test/compute/fixtures/digitalocean_v2/ex_rebuild_node.json libcloud/test/compute/fixtures/digitalocean_v2/ex_rename_node.json libcloud/test/compute/fixtures/digitalocean_v2/ex_resize_node.json libcloud/test/compute/fixtures/digitalocean_v2/ex_shutdown_node.json libcloud/test/compute/fixtures/digitalocean_v2/get_image.json libcloud/test/compute/fixtures/digitalocean_v2/list_floating_ips.json libcloud/test/compute/fixtures/digitalocean_v2/list_images.json libcloud/test/compute/fixtures/digitalocean_v2/list_key_pairs.json libcloud/test/compute/fixtures/digitalocean_v2/list_locations.json libcloud/test/compute/fixtures/digitalocean_v2/list_node.json libcloud/test/compute/fixtures/digitalocean_v2/list_nodes.json libcloud/test/compute/fixtures/digitalocean_v2/list_nodes_empty.json libcloud/test/compute/fixtures/digitalocean_v2/list_nodes_page_1.json libcloud/test/compute/fixtures/digitalocean_v2/list_sizes.json libcloud/test/compute/fixtures/digitalocean_v2/list_volume_snapshots.json libcloud/test/compute/fixtures/digitalocean_v2/list_volumes.json libcloud/test/compute/fixtures/digitalocean_v2/list_volumes_empty.json libcloud/test/compute/fixtures/digitalocean_v2/reboot_node.json libcloud/test/compute/fixtures/dimensiondata/_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml libcloud/test/compute/fixtures/dimensiondata/audit_log.csv libcloud/test/compute/fixtures/dimensiondata/detailed_usage_report.csv libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml libcloud/test/compute/fixtures/dimensiondata/image_customerImage_BAD_REQUEST.xml libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml libcloud/test/compute/fixtures/dimensiondata/image_osImage_BAD_REQUEST.xml libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml libcloud/test/compute/fixtures/dimensiondata/infrastructure_datacenter.xml libcloud/test/compute/fixtures/dimensiondata/infrastructure_datacenter_NA9.xml libcloud/test/compute/fixtures/dimensiondata/ip_address_list_create.xml libcloud/test/compute/fixtures/dimensiondata/ip_address_list_delete.xml libcloud/test/compute/fixtures/dimensiondata/ip_address_list_edit.xml libcloud/test/compute/fixtures/dimensiondata/ip_address_lists.xml libcloud/test/compute/fixtures/dimensiondata/ip_address_lists_FILTERBYNAME.xml libcloud/test/compute/fixtures/dimensiondata/network_addPublicIpBlock.xml libcloud/test/compute/fixtures/dimensiondata/network_createFirewallRule.xml libcloud/test/compute/fixtures/dimensiondata/network_createNatRule.xml libcloud/test/compute/fixtures/dimensiondata/network_deleteFirewallRule.xml libcloud/test/compute/fixtures/dimensiondata/network_deleteNatRule.xml libcloud/test/compute/fixtures/dimensiondata/network_deleteNetworkDomain.xml libcloud/test/compute/fixtures/dimensiondata/network_deleteVlan.xml libcloud/test/compute/fixtures/dimensiondata/network_deployNetworkDomain.xml libcloud/test/compute/fixtures/dimensiondata/network_deployVlan.xml libcloud/test/compute/fixtures/dimensiondata/network_editFirewallRule.xml libcloud/test/compute/fixtures/dimensiondata/network_editNetworkDomain.xml libcloud/test/compute/fixtures/dimensiondata/network_editVlan.xml libcloud/test/compute/fixtures/dimensiondata/network_expandVlan.xml libcloud/test/compute/fixtures/dimensiondata/network_firewallRule.xml libcloud/test/compute/fixtures/dimensiondata/network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xml libcloud/test/compute/fixtures/dimensiondata/network_natRule.xml libcloud/test/compute/fixtures/dimensiondata/network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xml libcloud/test/compute/fixtures/dimensiondata/network_networkDomain.xml libcloud/test/compute/fixtures/dimensiondata/network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock.xml libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xml libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xml libcloud/test/compute/fixtures/dimensiondata/network_removePublicIpBlock.xml libcloud/test/compute/fixtures/dimensiondata/network_vlan.xml libcloud/test/compute/fixtures/dimensiondata/network_vlan_0e56433f_d808_4669_821d_812769517ff8.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_4bba37be_506f_11e3_b29c_001517c4643e.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_POST.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSize.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSpeed.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_image.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_imageWithDiskSpeed.xml libcloud/test/compute/fixtures/dimensiondata/oec_0_9_myaccount.xml libcloud/test/compute/fixtures/dimensiondata/port_list_create.xml libcloud/test/compute/fixtures/dimensiondata/port_list_delete.xml libcloud/test/compute/fixtures/dimensiondata/port_list_edit.xml libcloud/test/compute/fixtures/dimensiondata/port_list_get.xml libcloud/test/compute/fixtures/dimensiondata/port_list_lists.xml libcloud/test/compute/fixtures/dimensiondata/report_usageMonitoring.xml libcloud/test/compute/fixtures/dimensiondata/server_GetServer.xml libcloud/test/compute/fixtures/dimensiondata/server_addDisk.xml libcloud/test/compute/fixtures/dimensiondata/server_addNic.xml libcloud/test/compute/fixtures/dimensiondata/server_antiAffinityRule_list.xml libcloud/test/compute/fixtures/dimensiondata/server_antiAffinityRule_list_PAGINATED.xml libcloud/test/compute/fixtures/dimensiondata/server_changeServerMonitoringPlan.xml libcloud/test/compute/fixtures/dimensiondata/server_cleanServer.xml libcloud/test/compute/fixtures/dimensiondata/server_deleteServer.xml libcloud/test/compute/fixtures/dimensiondata/server_deleteServer_RESOURCEBUSY.xml libcloud/test/compute/fixtures/dimensiondata/server_deployServer.xml libcloud/test/compute/fixtures/dimensiondata/server_disableServerMonitoring.xml libcloud/test/compute/fixtures/dimensiondata/server_enableServerMonitoring.xml libcloud/test/compute/fixtures/dimensiondata/server_powerOffServer.xml libcloud/test/compute/fixtures/dimensiondata/server_powerOffServer_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/server_rebootServer.xml libcloud/test/compute/fixtures/dimensiondata/server_rebootServer_RESOURCEBUSY.xml libcloud/test/compute/fixtures/dimensiondata/server_reconfigureServer.xml libcloud/test/compute/fixtures/dimensiondata/server_removeDisk.xml libcloud/test/compute/fixtures/dimensiondata/server_removeNic.xml libcloud/test/compute/fixtures/dimensiondata/server_resetServer.xml libcloud/test/compute/fixtures/dimensiondata/server_server.xml libcloud/test/compute/fixtures/dimensiondata/server_server_NA3.xml libcloud/test/compute/fixtures/dimensiondata/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml libcloud/test/compute/fixtures/dimensiondata/server_server_paginated.xml libcloud/test/compute/fixtures/dimensiondata/server_server_paginated_empty.xml libcloud/test/compute/fixtures/dimensiondata/server_shutdownServer.xml libcloud/test/compute/fixtures/dimensiondata/server_shutdownServer_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/server_startServer.xml libcloud/test/compute/fixtures/dimensiondata/server_startServer_INPROGRESS.xml libcloud/test/compute/fixtures/dimensiondata/server_updateVmwareTools.xml libcloud/test/compute/fixtures/dimensiondata/summary_usage_report.csv libcloud/test/compute/fixtures/dimensiondata/tag_applyTags.xml libcloud/test/compute/fixtures/dimensiondata/tag_applyTags_BADREQUEST.xml libcloud/test/compute/fixtures/dimensiondata/tag_createTagKey.xml libcloud/test/compute/fixtures/dimensiondata/tag_createTagKey_BADREQUEST.xml libcloud/test/compute/fixtures/dimensiondata/tag_deleteTagKey.xml libcloud/test/compute/fixtures/dimensiondata/tag_deleteTagKey_BADREQUEST.xml libcloud/test/compute/fixtures/dimensiondata/tag_editTagKey.xml libcloud/test/compute/fixtures/dimensiondata/tag_editTagKey_BADREQUEST.xml libcloud/test/compute/fixtures/dimensiondata/tag_removeTag.xml libcloud/test/compute/fixtures/dimensiondata/tag_removeTag_BADREQUEST.xml libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xml libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xml libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_list.xml libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_list_SINGLE.xml libcloud/test/compute/fixtures/dimensiondata/tag_tag_list.xml libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_response.xml libcloud/test/compute/fixtures/dimensiondata/2.4/deploy_customised_server.xml libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.xml libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml libcloud/test/compute/fixtures/dimensiondata/2.4/import_image_response.xml libcloud/test/compute/fixtures/dimensiondata/2.4/server_GetServer.xml libcloud/test/compute/fixtures/dimensiondata/2.4/server_cleanServer.xml libcloud/test/compute/fixtures/dimensiondata/2.4/server_clone_response.xml libcloud/test/compute/fixtures/dimensiondata/2.4/server_server.xml libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_NA3.xml libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_paginated.xml libcloud/test/compute/fixtures/ec2/allocate_address.xml libcloud/test/compute/fixtures/ec2/allocate_vpc_address.xml libcloud/test/compute/fixtures/ec2/associate_address.xml libcloud/test/compute/fixtures/ec2/associate_vpc_address.xml libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml libcloud/test/compute/fixtures/ec2/attach_network_interface.xml libcloud/test/compute/fixtures/ec2/attach_volume.xml libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml libcloud/test/compute/fixtures/ec2/authorize_security_group_ingress.xml libcloud/test/compute/fixtures/ec2/copy_image.xml libcloud/test/compute/fixtures/ec2/create_encrypted_volume.xml libcloud/test/compute/fixtures/ec2/create_image.xml libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml libcloud/test/compute/fixtures/ec2/create_key_pair.xml libcloud/test/compute/fixtures/ec2/create_network_interface.xml libcloud/test/compute/fixtures/ec2/create_placement_groups.xml libcloud/test/compute/fixtures/ec2/create_security_group.xml libcloud/test/compute/fixtures/ec2/create_snapshot.xml libcloud/test/compute/fixtures/ec2/create_subnet.xml libcloud/test/compute/fixtures/ec2/create_tags.xml libcloud/test/compute/fixtures/ec2/create_volume.xml libcloud/test/compute/fixtures/ec2/create_vpc.xml libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml libcloud/test/compute/fixtures/ec2/delete_key_pair.xml libcloud/test/compute/fixtures/ec2/delete_network_interface.xml libcloud/test/compute/fixtures/ec2/delete_placement_groups.xml libcloud/test/compute/fixtures/ec2/delete_security_group.xml libcloud/test/compute/fixtures/ec2/delete_snapshot.xml libcloud/test/compute/fixtures/ec2/delete_subnet.xml libcloud/test/compute/fixtures/ec2/delete_tags.xml libcloud/test/compute/fixtures/ec2/delete_volume.xml libcloud/test/compute/fixtures/ec2/delete_vpc.xml libcloud/test/compute/fixtures/ec2/deregister_image.xml libcloud/test/compute/fixtures/ec2/describe_account_attributes.xml libcloud/test/compute/fixtures/ec2/describe_addresses.xml libcloud/test/compute/fixtures/ec2/describe_addresses_all.xml libcloud/test/compute/fixtures/ec2/describe_addresses_multi.xml libcloud/test/compute/fixtures/ec2/describe_addresses_single.xml libcloud/test/compute/fixtures/ec2/describe_availability_zones.xml libcloud/test/compute/fixtures/ec2/describe_images.xml libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks.xml libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks_active.xml libcloud/test/compute/fixtures/ec2/describe_instance_types.xml libcloud/test/compute/fixtures/ec2/describe_instances.xml libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml libcloud/test/compute/fixtures/ec2/describe_key_pairs.xml libcloud/test/compute/fixtures/ec2/describe_key_pairs_doesnt_exist.xml libcloud/test/compute/fixtures/ec2/describe_network_interfaces.xml libcloud/test/compute/fixtures/ec2/describe_placement_groups.xml libcloud/test/compute/fixtures/ec2/describe_reserved_instances.xml libcloud/test/compute/fixtures/ec2/describe_security_groups.xml libcloud/test/compute/fixtures/ec2/describe_snapshots.xml libcloud/test/compute/fixtures/ec2/describe_subnets.xml libcloud/test/compute/fixtures/ec2/describe_tags.xml libcloud/test/compute/fixtures/ec2/describe_volumes.xml libcloud/test/compute/fixtures/ec2/describe_volumes_modifications.xml libcloud/test/compute/fixtures/ec2/describe_vpcs.xml libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml libcloud/test/compute/fixtures/ec2/detach_network_interface.xml libcloud/test/compute/fixtures/ec2/detach_volume.xml libcloud/test/compute/fixtures/ec2/disassociate_address.xml libcloud/test/compute/fixtures/ec2/get_console_output.xml libcloud/test/compute/fixtures/ec2/import_key_pair.xml libcloud/test/compute/fixtures/ec2/import_snapshot.xml libcloud/test/compute/fixtures/ec2/modify_image_attribute.xml libcloud/test/compute/fixtures/ec2/modify_instance_attribute.xml libcloud/test/compute/fixtures/ec2/modify_snapshot_attribute.xml libcloud/test/compute/fixtures/ec2/modify_subnet_attribute.xml libcloud/test/compute/fixtures/ec2/modify_volume.xml libcloud/test/compute/fixtures/ec2/reboot_instances.xml libcloud/test/compute/fixtures/ec2/register_image.xml libcloud/test/compute/fixtures/ec2/release_address.xml libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml libcloud/test/compute/fixtures/ec2/run_instances.xml libcloud/test/compute/fixtures/ec2/run_instances_iam_profile.xml libcloud/test/compute/fixtures/ec2/run_instances_idem.xml libcloud/test/compute/fixtures/ec2/run_instances_idem_mismatch.xml libcloud/test/compute/fixtures/ec2/run_instances_with_subnet_and_security_group.xml libcloud/test/compute/fixtures/ec2/start_instances.xml libcloud/test/compute/fixtures/ec2/stop_instances.xml libcloud/test/compute/fixtures/ec2/terminate_instances.xml libcloud/test/compute/fixtures/ecp/htemplate_list.json libcloud/test/compute/fixtures/ecp/network_list.json libcloud/test/compute/fixtures/ecp/ptemplate_list.json libcloud/test/compute/fixtures/ecp/vm_1_action_delete.json libcloud/test/compute/fixtures/ecp/vm_1_action_start.json libcloud/test/compute/fixtures/ecp/vm_1_action_stop.json libcloud/test/compute/fixtures/ecp/vm_1_get.json libcloud/test/compute/fixtures/ecp/vm_list.json libcloud/test/compute/fixtures/ecp/vm_put.json libcloud/test/compute/fixtures/ecs/attach_disk.xml libcloud/test/compute/fixtures/ecs/copy_image.xml libcloud/test/compute/fixtures/ecs/create_disk.xml libcloud/test/compute/fixtures/ecs/create_image.xml libcloud/test/compute/fixtures/ecs/create_instance.xml libcloud/test/compute/fixtures/ecs/create_node_describe_instances.xml libcloud/test/compute/fixtures/ecs/create_public_ip.xml libcloud/test/compute/fixtures/ecs/create_security_group.xml libcloud/test/compute/fixtures/ecs/create_snapshot.xml libcloud/test/compute/fixtures/ecs/create_volume_describe_disks.xml libcloud/test/compute/fixtures/ecs/delete_disk.xml libcloud/test/compute/fixtures/ecs/delete_image.xml libcloud/test/compute/fixtures/ecs/delete_instance.xml libcloud/test/compute/fixtures/ecs/delete_security_group_by_id.xml libcloud/test/compute/fixtures/ecs/delete_snapshot.xml libcloud/test/compute/fixtures/ecs/describe_disks.xml libcloud/test/compute/fixtures/ecs/describe_images.xml libcloud/test/compute/fixtures/ecs/describe_instance_types.xml libcloud/test/compute/fixtures/ecs/describe_instances.xml libcloud/test/compute/fixtures/ecs/describe_regions.xml libcloud/test/compute/fixtures/ecs/describe_security_group_attributes.xml libcloud/test/compute/fixtures/ecs/describe_security_groups.xml libcloud/test/compute/fixtures/ecs/describe_snapshots.xml libcloud/test/compute/fixtures/ecs/describe_zones.xml libcloud/test/compute/fixtures/ecs/destroy_node_describe_instances.xml libcloud/test/compute/fixtures/ecs/destroy_volume_describe_disks.xml libcloud/test/compute/fixtures/ecs/detach_disk.xml libcloud/test/compute/fixtures/ecs/detach_volume_describe_disks.xml libcloud/test/compute/fixtures/ecs/get_image_describe_images.xml libcloud/test/compute/fixtures/ecs/join_security_group_by_id.xml libcloud/test/compute/fixtures/ecs/leave_security_group_by_id.xml libcloud/test/compute/fixtures/ecs/modify_security_group_by_id.xml libcloud/test/compute/fixtures/ecs/pages_describe_images.xml libcloud/test/compute/fixtures/ecs/pages_describe_images_page2.xml libcloud/test/compute/fixtures/ecs/reboot_instance.xml libcloud/test/compute/fixtures/ecs/reboot_node_describe_instances.xml libcloud/test/compute/fixtures/ecs/start_instance.xml libcloud/test/compute/fixtures/ecs/stop_instance.xml libcloud/test/compute/fixtures/ecs/stop_node_describe_instances.xml libcloud/test/compute/fixtures/elastichosts/drives_create.json libcloud/test/compute/fixtures/elastichosts/drives_info.json libcloud/test/compute/fixtures/elastichosts/offline_servers_info.json libcloud/test/compute/fixtures/elastichosts/servers_create.json libcloud/test/compute/fixtures/elastichosts/servers_info.json libcloud/test/compute/fixtures/fcu/ex_describe_instance_types.xml libcloud/test/compute/fixtures/fcu/ex_describe_product_types.xml libcloud/test/compute/fixtures/fcu/ex_describe_quotas.xml libcloud/test/compute/fixtures/fcu/ex_get_product_type.xml libcloud/test/compute/fixtures/fcu/ex_modify_instance_keypair.xml libcloud/test/compute/fixtures/gandi/account_info.xml libcloud/test/compute/fixtures/gandi/account_info_rating.xml libcloud/test/compute/fixtures/gandi/datacenter_list.xml libcloud/test/compute/fixtures/gandi/disk_attach.xml libcloud/test/compute/fixtures/gandi/disk_create.xml libcloud/test/compute/fixtures/gandi/disk_create_from.xml libcloud/test/compute/fixtures/gandi/disk_delete.xml libcloud/test/compute/fixtures/gandi/disk_detach.xml libcloud/test/compute/fixtures/gandi/disk_info.xml libcloud/test/compute/fixtures/gandi/disk_list.xml libcloud/test/compute/fixtures/gandi/disk_update.xml libcloud/test/compute/fixtures/gandi/iface_attach.xml libcloud/test/compute/fixtures/gandi/iface_detach.xml libcloud/test/compute/fixtures/gandi/iface_list.xml libcloud/test/compute/fixtures/gandi/image_list_dc0.xml libcloud/test/compute/fixtures/gandi/ip_list.xml libcloud/test/compute/fixtures/gandi/operation_info.xml libcloud/test/compute/fixtures/gandi/ssh_delete.xml libcloud/test/compute/fixtures/gandi/ssh_info.xml libcloud/test/compute/fixtures/gandi/ssh_list.xml libcloud/test/compute/fixtures/gandi/vm_create_from.xml libcloud/test/compute/fixtures/gandi/vm_delete.xml libcloud/test/compute/fixtures/gandi/vm_info.xml libcloud/test/compute/fixtures/gandi/vm_list.xml libcloud/test/compute/fixtures/gandi/vm_reboot.xml libcloud/test/compute/fixtures/gandi/vm_stop.xml libcloud/test/compute/fixtures/gce/_zones_us_central1_a_instanceGroupManagers_myinstancegroup_listManagedInstances.json libcloud/test/compute/fixtures/gce/aggregated_addresses.json libcloud/test/compute/fixtures/gce/aggregated_autoscalers.json libcloud/test/compute/fixtures/gce/aggregated_disks.json libcloud/test/compute/fixtures/gce/aggregated_disktypes.json libcloud/test/compute/fixtures/gce/aggregated_forwardingRules.json libcloud/test/compute/fixtures/gce/aggregated_instanceGroupManagers.json libcloud/test/compute/fixtures/gce/aggregated_instances.json libcloud/test/compute/fixtures/gce/aggregated_machineTypes.json libcloud/test/compute/fixtures/gce/aggregated_subnetworks.json libcloud/test/compute/fixtures/gce/aggregated_targetInstances.json libcloud/test/compute/fixtures/gce/aggregated_targetPools.json libcloud/test/compute/fixtures/gce/generic_disk.json libcloud/test/compute/fixtures/gce/global_addresses.json libcloud/test/compute/fixtures/gce/global_addresses_lcaddressglobal.json libcloud/test/compute/fixtures/gce/global_addresses_lcaddressglobal_delete.json libcloud/test/compute/fixtures/gce/global_addresses_post.json libcloud/test/compute/fixtures/gce/global_backendServices-empty.json libcloud/test/compute/fixtures/gce/global_backendServices-web-service.json libcloud/test/compute/fixtures/gce/global_backendServices_no_backends.json libcloud/test/compute/fixtures/gce/global_backendServices_post.json libcloud/test/compute/fixtures/gce/global_backendServices_web_service.json libcloud/test/compute/fixtures/gce/global_backendServices_web_service_delete.json libcloud/test/compute/fixtures/gce/global_custom_image_setLabels_post.json libcloud/test/compute/fixtures/gce/global_firewalls.json libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall-deny.json libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall-egress.json libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall.json libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_delete.json libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_put.json libcloud/test/compute/fixtures/gce/global_firewalls_post.json libcloud/test/compute/fixtures/gce/global_forwardingRules.json libcloud/test/compute/fixtures/gce/global_forwardingRules_http_rule.json libcloud/test/compute/fixtures/gce/global_forwardingRules_http_rule_delete.json libcloud/test/compute/fixtures/gce/global_forwardingRules_post.json libcloud/test/compute/fixtures/gce/global_httpHealthChecks.json libcloud/test/compute/fixtures/gce/global_httpHealthChecks_basic-check.json libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck.json libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_delete.json libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_put.json libcloud/test/compute/fixtures/gce/global_httpHealthChecks_libcloud-lb-demo-healthcheck.json libcloud/test/compute/fixtures/gce/global_httpHealthChecks_post.json libcloud/test/compute/fixtures/gce/global_images.json libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20131014_deprecate.json libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20131120_delete.json libcloud/test/compute/fixtures/gce/global_images_family_notfound.json libcloud/test/compute/fixtures/gce/global_images_post.json libcloud/test/compute/fixtures/gce/global_instanceTemplates.json libcloud/test/compute/fixtures/gce/global_instanceTemplates_insert.json libcloud/test/compute/fixtures/gce/global_instanceTemplates_my_instance_template1.json libcloud/test/compute/fixtures/gce/global_instanceTemplates_my_instance_template_shared_network.json libcloud/test/compute/fixtures/gce/global_networks.json libcloud/test/compute/fixtures/gce/global_networks_cf.json libcloud/test/compute/fixtures/gce/global_networks_custom_network.json libcloud/test/compute/fixtures/gce/global_networks_default.json libcloud/test/compute/fixtures/gce/global_networks_lcnetwork.json libcloud/test/compute/fixtures/gce/global_networks_lcnetwork_delete.json libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-europe-network.json libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-network.json libcloud/test/compute/fixtures/gce/global_networks_post.json libcloud/test/compute/fixtures/gce/global_operations_operation_setImageLabels_post.json libcloud/test/compute/fixtures/gce/global_routes.json libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute.json libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute_delete.json libcloud/test/compute/fixtures/gce/global_routes_post.json libcloud/test/compute/fixtures/gce/global_snapshots.json libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot.json libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot_delete.json libcloud/test/compute/fixtures/gce/global_sslcertificates.json libcloud/test/compute/fixtures/gce/global_sslcertificates_example.json libcloud/test/compute/fixtures/gce/global_sslcertificates_post.json libcloud/test/compute/fixtures/gce/global_targetHttpProxies.json libcloud/test/compute/fixtures/gce/global_targetHttpProxies_post.json libcloud/test/compute/fixtures/gce/global_targetHttpProxies_web_proxy.json libcloud/test/compute/fixtures/gce/global_targetHttpProxies_web_proxy_delete.json libcloud/test/compute/fixtures/gce/global_urlMaps.json libcloud/test/compute/fixtures/gce/global_urlMaps_post.json libcloud/test/compute/fixtures/gce/global_urlMaps_web_map.json libcloud/test/compute/fixtures/gce/global_urlMaps_web_map_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_addresses_lcaddressglobal_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_addresses_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_backendServices_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_backendServices_web_service_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_put.json libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_forwardingRules_http_rule_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_forwardingRules_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_put.json libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_image_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_images_debian7_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_instanceTemplates_insert.json libcloud/test/compute/fixtures/gce/operations_operation_global_networks_lcnetwork_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_networks_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_routes_lcdemoroute_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_routes_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_snapshots_lcsnapshot_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_sslcertificates_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_targetHttpProxies_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_targetHttpProxies_web_proxy_delete.json libcloud/test/compute/fixtures/gce/operations_operation_global_urlMaps_post.json libcloud/test/compute/fixtures/gce/operations_operation_global_urlMaps_web_map_delete.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_lcaddress_delete.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_lcforwardingrule_delete.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_subnetworks_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lb_pool_setBackup_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addInstance_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_delete.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeInstance_post.json libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_post.json libcloud/test/compute/fixtures/gce/operations_operation_setCommonInstanceMetadata.json libcloud/test/compute/fixtures/gce/operations_operation_setUsageExportBucket.json libcloud/test/compute/fixtures/gce/operations_operation_zones_europe-west1-a_instances_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_createSnapshot_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_delete.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_resize_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_setLabels_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-000_delete.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-001_delete.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_attachDisk_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_delete.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_detachDisk_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_reset_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_setTags_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_addAccessConfig_done.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_addAccessConfig_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_deleteAccessConfig_done.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_deleteAccessConfig_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_targetInstances_lctargetinstance_delete.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_targetInstances_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_insert.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_addInstances.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_delete.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_removeInstances.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_setNamedPorts.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setLabels_post.json libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setMetadata_post.json libcloud/test/compute/fixtures/gce/project.json libcloud/test/compute/fixtures/gce/projects_centos-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images_family_coreos_beta.json libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images_family_coreos_stable.json libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_licenses_coreos_stable.json libcloud/test/compute/fixtures/gce/projects_cos-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_opensuse-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_cf.json libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_lcnetwork.json libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_shared_network_for_mig.json libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1.json libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1_subnetworks_cf_972cf02e6ad49114.json libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1_subnetworks_shared_subnetwork_for_mig.json libcloud/test/compute/fixtures/gce/projects_rhel-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_rhel-cloud_global_licenses_rhel_server.json libcloud/test/compute/fixtures/gce/projects_suse-byos-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_11.json libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_12.json libcloud/test/compute/fixtures/gce/projects_suse-sap-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_ubuntu-os-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_windows-cloud_global_images.json libcloud/test/compute/fixtures/gce/projects_windows-cloud_global_licenses_windows_server_2008_r2_dc.json libcloud/test/compute/fixtures/gce/projects_windows-sql-cloud_global_images.json libcloud/test/compute/fixtures/gce/regions-paged-1.json libcloud/test/compute/fixtures/gce/regions-paged-2.json libcloud/test/compute/fixtures/gce/regions.json libcloud/test/compute/fixtures/gce/regions_asia-east1.json libcloud/test/compute/fixtures/gce/regions_europe-west1.json libcloud/test/compute/fixtures/gce/regions_us-central1.json libcloud/test/compute/fixtures/gce/regions_us-central1_addresses.json libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress.json libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress_delete.json libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddressinternal.json libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_testaddress.json libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules.json libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule.json libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule_delete.json libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_libcloud-lb-demo-lb.json libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks.json libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_cf_972cf02e6ad49112.json libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_subnet_1.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_backup_pool.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool_getHealth.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool_setBackup_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addInstance_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_delete.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeInstance_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_sticky.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_libcloud-lb-demo-lb-tp.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_post.json libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_www-pool.json libcloud/test/compute/fixtures/gce/regions_us-east1.json libcloud/test/compute/fixtures/gce/regions_us-east1_subnetworks_cf_972cf02e6ad49113.json libcloud/test/compute/fixtures/gce/setCommonInstanceMetadata_post.json libcloud/test/compute/fixtures/gce/setUsageExportBucket_post.json libcloud/test/compute/fixtures/gce/zones.json libcloud/test/compute/fixtures/gce/zones_asia-east1-b.json libcloud/test/compute/fixtures/gce/zones_europe-west1-a_diskTypes_pd_standard.json libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances.json libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances_post.json libcloud/test/compute/fixtures/gce/zones_europe-west1-a_machineTypes_n1-standard-1.json libcloud/test/compute/fixtures/gce/zones_us-central1-a.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_diskTypes.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_diskTypes_pd_ssd.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_diskTypes_pd_standard.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_createSnapshot_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_delete.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_resize_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_setLabel_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_disktypes_pd-ssd.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_insert.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_myinstancegroup.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_myinstancegroup_shared_network.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstancegroup.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstancegroup2.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstancegroup_shared_network.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000_delete.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001_delete.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_attachDisk_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_delete.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_detachDisk_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_reset_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_setTags_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node_name_getSerialOutput.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_sn-node-name.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_operations_operation_zones_us-central1-a_instanceGroupManagers_insert_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_lctargetinstance.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_lctargetinstance_delete.json libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_post.json libcloud/test/compute/fixtures/gce/zones_us-central1-b_instanceGroupManagers_myinstancegroup.json libcloud/test/compute/fixtures/gce/zones_us-central1-b_instanceGroup_myinstancegroup.json libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-000.json libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-001.json libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-002.json libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-nopubip-001.json libcloud/test/compute/fixtures/gce/zones_us-east1-b.json libcloud/test/compute/fixtures/gce/zones_us-east1-b_instanceGroupManagers.json libcloud/test/compute/fixtures/gce/zones_us-east1-b_instanceGroup_myinstancegroup.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_acceleratorTypes_nvidia_tesla_k80.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_insert.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_addInstances.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_delete.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_listInstances.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_removeInstances.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_setNamedPorts.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_custom_node.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setDiskAutoDelete.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setLabels_post.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setMachineType.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setMetadata_post.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_stop.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_setMachineType.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_start.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_stop.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_setMachineType.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_setMachineType_notstopped.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_startnode.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_stopnode.json libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_volume_auto_delete.json libcloud/test/compute/fixtures/gogrid/image_list.json libcloud/test/compute/fixtures/gogrid/image_save.json libcloud/test/compute/fixtures/gogrid/ip_list.json libcloud/test/compute/fixtures/gogrid/ip_list_empty.json libcloud/test/compute/fixtures/gogrid/lookup_list_ip_datacenter.json libcloud/test/compute/fixtures/gogrid/password_list.json libcloud/test/compute/fixtures/gogrid/server_add.json libcloud/test/compute/fixtures/gogrid/server_delete.json libcloud/test/compute/fixtures/gogrid/server_edit.json libcloud/test/compute/fixtures/gogrid/server_list.json libcloud/test/compute/fixtures/gogrid/server_power.json libcloud/test/compute/fixtures/gogrid/server_power_fail.json libcloud/test/compute/fixtures/gridscale/create_image.json libcloud/test/compute/fixtures/gridscale/create_image_dict.json libcloud/test/compute/fixtures/gridscale/create_ip.json libcloud/test/compute/fixtures/gridscale/create_ip_response_dict.json libcloud/test/compute/fixtures/gridscale/create_network.json libcloud/test/compute/fixtures/gridscale/create_node.json libcloud/test/compute/fixtures/gridscale/create_node_dict.json libcloud/test/compute/fixtures/gridscale/create_node_response_dict.json libcloud/test/compute/fixtures/gridscale/create_volume.json libcloud/test/compute/fixtures/gridscale/create_volume_response_dict.json libcloud/test/compute/fixtures/gridscale/ex_list_ips.json libcloud/test/compute/fixtures/gridscale/ex_list_networks.json libcloud/test/compute/fixtures/gridscale/ex_start_node.json libcloud/test/compute/fixtures/gridscale/get_image.json libcloud/test/compute/fixtures/gridscale/ips_to_node.json libcloud/test/compute/fixtures/gridscale/list_images.json libcloud/test/compute/fixtures/gridscale/list_key_pairs.json libcloud/test/compute/fixtures/gridscale/list_locations.json libcloud/test/compute/fixtures/gridscale/list_nodes.json libcloud/test/compute/fixtures/gridscale/list_volume_snapshots.json libcloud/test/compute/fixtures/gridscale/list_volumes.json libcloud/test/compute/fixtures/gridscale/list_volumes_empty.json libcloud/test/compute/fixtures/gridscale/network_to_node.json libcloud/test/compute/fixtures/gridscale/volume_to_node.json libcloud/test/compute/fixtures/hostvirtual/cancel_package.json libcloud/test/compute/fixtures/hostvirtual/get_node.json libcloud/test/compute/fixtures/hostvirtual/list_images.json libcloud/test/compute/fixtures/hostvirtual/list_locations.json libcloud/test/compute/fixtures/hostvirtual/list_nodes.json libcloud/test/compute/fixtures/hostvirtual/list_packages.json libcloud/test/compute/fixtures/hostvirtual/list_sizes.json libcloud/test/compute/fixtures/hostvirtual/node_reboot.json libcloud/test/compute/fixtures/hostvirtual/node_start.json libcloud/test/compute/fixtures/hostvirtual/node_stop.json libcloud/test/compute/fixtures/hostvirtual/order_package.json libcloud/test/compute/fixtures/hostvirtual/unlink_package.json libcloud/test/compute/fixtures/joyent/my_datasets.json libcloud/test/compute/fixtures/joyent/my_machines.json libcloud/test/compute/fixtures/joyent/my_machines_create.json libcloud/test/compute/fixtures/joyent/my_packages.json libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_default.json libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail.json libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail2.json libcloud/test/compute/fixtures/ktucloud/destroyVirtualMachine_default.json libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_default.json libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_nodisk.json libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_notemplates.json libcloud/test/compute/fixtures/ktucloud/listIpForwardingRules_default.json libcloud/test/compute/fixtures/ktucloud/listPortForwardingRules_default.json libcloud/test/compute/fixtures/ktucloud/listPublicIpAddresses_default.json libcloud/test/compute/fixtures/ktucloud/listVirtualMachines_default.json libcloud/test/compute/fixtures/ktucloud/listZones_default.json libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17164.json libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17165.json libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17166.json libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17177.json libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_attachvolumejob.json libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_createvolumejob.json libcloud/test/compute/fixtures/ktucloud/rebootVirtualMachine_default.json libcloud/test/compute/fixtures/linode/_avail_datacenters.json libcloud/test/compute/fixtures/linode/_avail_distributions.json libcloud/test/compute/fixtures/linode/_avail_kernels.json libcloud/test/compute/fixtures/linode/_avail_linodeplans.json libcloud/test/compute/fixtures/linode/_batch.json libcloud/test/compute/fixtures/linode/_linode_disk_list.json libcloud/test/compute/fixtures/linode/_linode_ip_list.json libcloud/test/compute/fixtures/linode/_linode_list.json libcloud/test/compute/fixtures/maxihost/images.json libcloud/test/compute/fixtures/maxihost/keys.json libcloud/test/compute/fixtures/maxihost/node.json libcloud/test/compute/fixtures/maxihost/nodes.json libcloud/test/compute/fixtures/maxihost/plans.json libcloud/test/compute/fixtures/maxihost/regions.json libcloud/test/compute/fixtures/meta/helloworld.txt libcloud/test/compute/fixtures/meta/unicode.json libcloud/test/compute/fixtures/meta/unicode.txt libcloud/test/compute/fixtures/meta/unicode.xml libcloud/test/compute/fixtures/misc/test_dsa.key libcloud/test/compute/fixtures/misc/test_dsa_non_paramiko_recognized_header.key libcloud/test/compute/fixtures/misc/test_ecdsa.key libcloud/test/compute/fixtures/misc/test_ecdsa_non_paramiko_recognized_header.key libcloud/test/compute/fixtures/misc/test_rsa.key libcloud/test/compute/fixtures/misc/test_rsa.pub libcloud/test/compute/fixtures/misc/test_rsa_non_paramiko_recognized_header.key libcloud/test/compute/fixtures/misc/test_rsa_non_pem_format.key libcloud/test/compute/fixtures/misc/test_rsa_non_pem_format.pub libcloud/test/compute/fixtures/nephoscale/list_images.json libcloud/test/compute/fixtures/nephoscale/list_keys.json libcloud/test/compute/fixtures/nephoscale/list_locations.json libcloud/test/compute/fixtures/nephoscale/list_nodes.json libcloud/test/compute/fixtures/nephoscale/list_password_keys.json libcloud/test/compute/fixtures/nephoscale/list_sizes.json libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json libcloud/test/compute/fixtures/nephoscale/success_action.json libcloud/test/compute/fixtures/nttcis/audit_log.csv libcloud/test/compute/fixtures/nttcis/cg_by_src_network_domain.xml libcloud/test/compute/fixtures/nttcis/change_disk_size.xml libcloud/test/compute/fixtures/nttcis/change_disk_speed.xml libcloud/test/compute/fixtures/nttcis/change_nic_networkadapter_response.xml libcloud/test/compute/fixtures/nttcis/create_preview_server.xml libcloud/test/compute/fixtures/nttcis/datacenter_snapshotWindows.xml libcloud/test/compute/fixtures/nttcis/deploy_customised_server.xml libcloud/test/compute/fixtures/nttcis/detailed_usage_report.csv libcloud/test/compute/fixtures/nttcis/disable_server_snapshot_service.xml libcloud/test/compute/fixtures/nttcis/drs_create_cg.xml libcloud/test/compute/fixtures/nttcis/drs_delete_consistency_group.xml libcloud/test/compute/fixtures/nttcis/drs_expand_journal.xml libcloud/test/compute/fixtures/nttcis/drs_fail_create_cg_ineligible.xml libcloud/test/compute/fixtures/nttcis/drs_fail_create_cg_not_supported.xml libcloud/test/compute/fixtures/nttcis/drs_fail_create_consistency_group.xml libcloud/test/compute/fixtures/nttcis/drs_initiate_failover.xml libcloud/test/compute/fixtures/nttcis/drs_invalid_status.xml libcloud/test/compute/fixtures/nttcis/drs_snap_shots_by_min_max_time.xml libcloud/test/compute/fixtures/nttcis/drs_snapshots_by_min.xml libcloud/test/compute/fixtures/nttcis/drs_start_failover_preview.xml libcloud/test/compute/fixtures/nttcis/drs_stop_failover_preview.xml libcloud/test/compute/fixtures/nttcis/enable_snapshot_service.xml libcloud/test/compute/fixtures/nttcis/exchange_nic_vlans_response.xml libcloud/test/compute/fixtures/nttcis/geographic_regions.xml libcloud/test/compute/fixtures/nttcis/get_cg_by_name_or_id.xml libcloud/test/compute/fixtures/nttcis/image_customerImage.xml libcloud/test/compute/fixtures/nttcis/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml libcloud/test/compute/fixtures/nttcis/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml libcloud/test/compute/fixtures/nttcis/image_osImage.xml libcloud/test/compute/fixtures/nttcis/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml libcloud/test/compute/fixtures/nttcis/image_osImage_BAD_REQUEST.xml libcloud/test/compute/fixtures/nttcis/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml libcloud/test/compute/fixtures/nttcis/import_image_response.xml libcloud/test/compute/fixtures/nttcis/infrastructure_datacenter.xml libcloud/test/compute/fixtures/nttcis/infrastructure_datacenter_NA9.xml libcloud/test/compute/fixtures/nttcis/initiate_manual_snapshot.xml libcloud/test/compute/fixtures/nttcis/ip_address_list_create.xml libcloud/test/compute/fixtures/nttcis/ip_address_list_delete.xml libcloud/test/compute/fixtures/nttcis/ip_address_list_edit.xml libcloud/test/compute/fixtures/nttcis/ip_address_lists.xml libcloud/test/compute/fixtures/nttcis/ip_address_lists_FILTERBYNAME.xml libcloud/test/compute/fixtures/nttcis/list_consistency_groups.xml libcloud/test/compute/fixtures/nttcis/list_drs_snapshots.xml libcloud/test/compute/fixtures/nttcis/list_server_snapshots.xml libcloud/test/compute/fixtures/nttcis/manual_snapshot_server.xml libcloud/test/compute/fixtures/nttcis/networkWithLocation.xml libcloud/test/compute/fixtures/nttcis/network_addPublicIpBlock.xml libcloud/test/compute/fixtures/nttcis/network_createFirewallRule.xml libcloud/test/compute/fixtures/nttcis/network_createNatRule.xml libcloud/test/compute/fixtures/nttcis/network_deleteFirewallRule.xml libcloud/test/compute/fixtures/nttcis/network_deleteNatRule.xml libcloud/test/compute/fixtures/nttcis/network_deleteNetworkDomain.xml libcloud/test/compute/fixtures/nttcis/network_deleteVlan.xml libcloud/test/compute/fixtures/nttcis/network_deployNetworkDomain.xml libcloud/test/compute/fixtures/nttcis/network_deployVlan.xml libcloud/test/compute/fixtures/nttcis/network_editFirewallRule.xml libcloud/test/compute/fixtures/nttcis/network_editNetworkDomain.xml libcloud/test/compute/fixtures/nttcis/network_editVlan.xml libcloud/test/compute/fixtures/nttcis/network_expandVlan.xml libcloud/test/compute/fixtures/nttcis/network_firewallRule.xml libcloud/test/compute/fixtures/nttcis/network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xml libcloud/test/compute/fixtures/nttcis/network_natRule.xml libcloud/test/compute/fixtures/nttcis/network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xml libcloud/test/compute/fixtures/nttcis/network_networkDomain.xml libcloud/test/compute/fixtures/nttcis/network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml libcloud/test/compute/fixtures/nttcis/network_publicIpBlock.xml libcloud/test/compute/fixtures/nttcis/network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xml libcloud/test/compute/fixtures/nttcis/network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xml libcloud/test/compute/fixtures/nttcis/network_removePublicIpBlock.xml libcloud/test/compute/fixtures/nttcis/network_vlan.xml libcloud/test/compute/fixtures/nttcis/network_vlan_0e56433f_d808_4669_821d_812769517ff8.xml libcloud/test/compute/fixtures/nttcis/oec_0_9_myaccount.xml libcloud/test/compute/fixtures/nttcis/port_list_create.xml libcloud/test/compute/fixtures/nttcis/port_list_delete.xml libcloud/test/compute/fixtures/nttcis/port_list_edit.xml libcloud/test/compute/fixtures/nttcis/port_list_get.xml libcloud/test/compute/fixtures/nttcis/port_list_lists.xml libcloud/test/compute/fixtures/nttcis/report_usageMonitoring.xml libcloud/test/compute/fixtures/nttcis/server_GetServer.xml libcloud/test/compute/fixtures/nttcis/server_addDisk.xml libcloud/test/compute/fixtures/nttcis/server_addNic.xml libcloud/test/compute/fixtures/nttcis/server_antiAffinityRule_list.xml libcloud/test/compute/fixtures/nttcis/server_antiAffinityRule_list_PAGINATED.xml libcloud/test/compute/fixtures/nttcis/server_changeServerMonitoringPlan.xml libcloud/test/compute/fixtures/nttcis/server_cleanServer.xml libcloud/test/compute/fixtures/nttcis/server_clone_response.xml libcloud/test/compute/fixtures/nttcis/server_createAntiAffinityRule.xml libcloud/test/compute/fixtures/nttcis/server_createAntiAffinityRule_FAIL.xml libcloud/test/compute/fixtures/nttcis/server_deleteAntiAffinityRule.xml libcloud/test/compute/fixtures/nttcis/server_deleteAntiAffinityRule_FAIL.xml libcloud/test/compute/fixtures/nttcis/server_deleteServer.xml libcloud/test/compute/fixtures/nttcis/server_deleteServer_RESOURCEBUSY.xml libcloud/test/compute/fixtures/nttcis/server_deployServer.xml libcloud/test/compute/fixtures/nttcis/server_disableServerMonitoring.xml libcloud/test/compute/fixtures/nttcis/server_editServerMetadata.xml libcloud/test/compute/fixtures/nttcis/server_enableServerMonitoring.xml libcloud/test/compute/fixtures/nttcis/server_powerOffServer.xml libcloud/test/compute/fixtures/nttcis/server_powerOffServer_INPROGRESS.xml libcloud/test/compute/fixtures/nttcis/server_rebootServer.xml libcloud/test/compute/fixtures/nttcis/server_rebootServer_RESOURCEBUSY.xml libcloud/test/compute/fixtures/nttcis/server_reconfigureServer.xml libcloud/test/compute/fixtures/nttcis/server_removeDisk.xml libcloud/test/compute/fixtures/nttcis/server_removeNic.xml libcloud/test/compute/fixtures/nttcis/server_resetServer.xml libcloud/test/compute/fixtures/nttcis/server_server.xml libcloud/test/compute/fixtures/nttcis/server_server_NA3.xml libcloud/test/compute/fixtures/nttcis/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml libcloud/test/compute/fixtures/nttcis/server_server_paginated.xml libcloud/test/compute/fixtures/nttcis/server_server_paginated_empty.xml libcloud/test/compute/fixtures/nttcis/server_shutdownServer.xml libcloud/test/compute/fixtures/nttcis/server_shutdownServer_INPROGRESS.xml libcloud/test/compute/fixtures/nttcis/server_startServer.xml libcloud/test/compute/fixtures/nttcis/server_startServer_INPROGRESS.xml libcloud/test/compute/fixtures/nttcis/server_updateVmwareTools.xml libcloud/test/compute/fixtures/nttcis/summary_usage_report.csv libcloud/test/compute/fixtures/nttcis/tag_applyTags.xml libcloud/test/compute/fixtures/nttcis/tag_applyTags_BADREQUEST.xml libcloud/test/compute/fixtures/nttcis/tag_createTagKey.xml libcloud/test/compute/fixtures/nttcis/tag_createTagKey_BADREQUEST.xml libcloud/test/compute/fixtures/nttcis/tag_deleteTagKey.xml libcloud/test/compute/fixtures/nttcis/tag_deleteTagKey_BADREQUEST.xml libcloud/test/compute/fixtures/nttcis/tag_editTagKey.xml libcloud/test/compute/fixtures/nttcis/tag_editTagKey_BADREQUEST.xml libcloud/test/compute/fixtures/nttcis/tag_removeTag.xml libcloud/test/compute/fixtures/nttcis/tag_removeTag_BADREQUEST.xml libcloud/test/compute/fixtures/nttcis/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xml libcloud/test/compute/fixtures/nttcis/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xml libcloud/test/compute/fixtures/nttcis/tag_tagKey_list.xml libcloud/test/compute/fixtures/nttcis/tag_tagKey_list_SINGLE.xml libcloud/test/compute/fixtures/nttcis/tag_tag_list.xml libcloud/test/compute/fixtures/onapp/create_node.json libcloud/test/compute/fixtures/onapp/get_key_pair.json libcloud/test/compute/fixtures/onapp/import_key_pair.json libcloud/test/compute/fixtures/onapp/list_images.json libcloud/test/compute/fixtures/onapp/list_key_pairs.json libcloud/test/compute/fixtures/onapp/list_nodes.json libcloud/test/compute/fixtures/onapp/profile.json libcloud/test/compute/fixtures/oneandone/auth_error.json libcloud/test/compute/fixtures/oneandone/create_node.json libcloud/test/compute/fixtures/oneandone/describe_firewall_policy.json libcloud/test/compute/fixtures/oneandone/describe_id_firewall_policy.json libcloud/test/compute/fixtures/oneandone/describe_server.json libcloud/test/compute/fixtures/oneandone/describe_shared_stoage.json libcloud/test/compute/fixtures/oneandone/ex_list_datacenters.json libcloud/test/compute/fixtures/oneandone/fixed_instance_sizes.json libcloud/test/compute/fixtures/oneandone/get_image.json libcloud/test/compute/fixtures/oneandone/get_server_image.json libcloud/test/compute/fixtures/oneandone/list_firewall_policies.json libcloud/test/compute/fixtures/oneandone/list_images.json libcloud/test/compute/fixtures/oneandone/list_load_balancer.json libcloud/test/compute/fixtures/oneandone/list_monitoring_policies.json libcloud/test/compute/fixtures/oneandone/list_public_ips.json libcloud/test/compute/fixtures/oneandone/list_servers.json libcloud/test/compute/fixtures/oneandone/list_shared_storages.json libcloud/test/compute/fixtures/oneandone/load_balancer.json libcloud/test/compute/fixtures/oneandone/load_balancer_rule.json libcloud/test/compute/fixtures/oneandone/load_balancer_rules.json libcloud/test/compute/fixtures/oneandone/load_balancer_server_ip.json libcloud/test/compute/fixtures/oneandone/load_balancer_server_ips.json libcloud/test/compute/fixtures/oneandone/monitoring_policy.json libcloud/test/compute/fixtures/oneandone/monitoring_policy_port.json libcloud/test/compute/fixtures/oneandone/monitoring_policy_ports.json libcloud/test/compute/fixtures/oneandone/monitoring_policy_process.json libcloud/test/compute/fixtures/oneandone/monitoring_policy_processes.json libcloud/test/compute/fixtures/oneandone/monitoring_policy_servers.json libcloud/test/compute/fixtures/oneandone/public_ip.json libcloud/test/compute/fixtures/oneandone/server_hardware.json libcloud/test/compute/fixtures/oneandone/server_ip.json libcloud/test/compute/fixtures/oneandone/server_ips.json libcloud/test/compute/fixtures/oneandone/shared_storage.json libcloud/test/compute/fixtures/oneandone/ttt.json libcloud/test/compute/fixtures/opennebula_1_4/compute_15.xml libcloud/test/compute/fixtures/opennebula_1_4/compute_25.xml libcloud/test/compute/fixtures/opennebula_1_4/compute_5.xml libcloud/test/compute/fixtures/opennebula_1_4/computes.xml libcloud/test/compute/fixtures/opennebula_1_4/disk_15.xml libcloud/test/compute/fixtures/opennebula_1_4/disk_5.xml libcloud/test/compute/fixtures/opennebula_1_4/network_15.xml libcloud/test/compute/fixtures/opennebula_1_4/network_5.xml libcloud/test/compute/fixtures/opennebula_1_4/networks.xml libcloud/test/compute/fixtures/opennebula_1_4/storage.xml libcloud/test/compute/fixtures/opennebula_2_0/compute_15.xml libcloud/test/compute/fixtures/opennebula_2_0/compute_25.xml libcloud/test/compute/fixtures/opennebula_2_0/compute_5.xml libcloud/test/compute/fixtures/opennebula_2_0/compute_collection.xml libcloud/test/compute/fixtures/opennebula_2_0/network_15.xml libcloud/test/compute/fixtures/opennebula_2_0/network_5.xml libcloud/test/compute/fixtures/opennebula_2_0/network_collection.xml libcloud/test/compute/fixtures/opennebula_2_0/storage_15.xml libcloud/test/compute/fixtures/opennebula_2_0/storage_5.xml libcloud/test/compute/fixtures/opennebula_2_0/storage_collection.xml libcloud/test/compute/fixtures/opennebula_3_0/network_15.xml libcloud/test/compute/fixtures/opennebula_3_0/network_5.xml libcloud/test/compute/fixtures/opennebula_3_0/network_collection.xml libcloud/test/compute/fixtures/opennebula_3_2/compute_5.xml libcloud/test/compute/fixtures/opennebula_3_2/instance_type_collection.xml libcloud/test/compute/fixtures/opennebula_3_6/compute_15.xml libcloud/test/compute/fixtures/opennebula_3_6/compute_5.xml libcloud/test/compute/fixtures/opennebula_3_6/disk_10.xml libcloud/test/compute/fixtures/opennebula_3_6/disk_15.xml libcloud/test/compute/fixtures/opennebula_3_6/storage_5.xml libcloud/test/compute/fixtures/opennebula_3_8/instance_type_collection.xml libcloud/test/compute/fixtures/opennebula_3_8/instance_type_large.xml libcloud/test/compute/fixtures/opennebula_3_8/instance_type_medium.xml libcloud/test/compute/fixtures/opennebula_3_8/instance_type_small.xml libcloud/test/compute/fixtures/openstack/300_multiple_choices.json libcloud/test/compute/fixtures/openstack/_v1_1__auth.json libcloud/test/compute/fixtures/openstack/_v1_1__auth_mssing_token.json libcloud/test/compute/fixtures/openstack/_v1_1__auth_unauthorized.json libcloud/test/compute/fixtures/openstack/_v2_0__auth.json libcloud/test/compute/fixtures/openstack/_v2_0__auth_deployment.json libcloud/test/compute/fixtures/openstack/_v2_0__auth_lon.json libcloud/test/compute/fixtures/openstack/_v3__auth.json libcloud/test/compute/fixtures/openstack/v1_slug_flavors_detail.xml libcloud/test/compute/fixtures/openstack/v1_slug_images_detail.xml libcloud/test/compute/fixtures/openstack/v1_slug_images_post.xml libcloud/test/compute/fixtures/openstack/v1_slug_limits.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_ipv6.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_missing.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_multiple_nodes.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_no_ip.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_pending.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_same_uuid.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_success.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_empty.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_metadata.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_ips.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_metadata.xml libcloud/test/compute/fixtures/openstack/v1_slug_servers_no_admin_pass.xml libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_group.xml libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups.xml libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups_detail.xml libcloud/test/compute/fixtures/openstack_identity/v2/v2_0_tenants.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_create_user.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_domains.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_domains_default.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_domains_default_users_a_roles.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_projects.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_roles.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_users.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_a.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_a_projects.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_b.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_c.json libcloud/test/compute/fixtures/openstack_identity/v3/v3_versions.json libcloud/test/compute/fixtures/openstack_v1.1/README libcloud/test/compute/fixtures/openstack_v1.1/_flavors_7.json libcloud/test/compute/fixtures/openstack_v1.1/_flavors_detail.json libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip.json libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip_pools.json libcloud/test/compute/fixtures/openstack_v1.1/_floating_ips.json libcloud/test/compute/fixtures/openstack_v1.1/_images_13.json libcloud/test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.json libcloud/test/compute/fixtures/openstack_v1.1/_images_8af1a54e_a1b2_4df8_b747_4bec97abc799_members.json libcloud/test/compute/fixtures/openstack_v1.1/_images_9af1a54e_a1b2_4df8_b747_4bec97abc799_members.json libcloud/test/compute/fixtures/openstack_v1.1/_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members.json libcloud/test/compute/fixtures/openstack_v1.1/_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members_016926dff12345e8b10329f24c99745b.json libcloud/test/compute/fixtures/openstack_v1.1/_images_detail.json libcloud/test/compute/fixtures/openstack_v1.1/_images_f24a3c1b-d52a-4116-91da-25b3eee8f55d.json libcloud/test/compute/fixtures/openstack_v1.1/_images_f24a3c1b-d52a-4116-91da-25b3eee8f55e.json libcloud/test/compute/fixtures/openstack_v1.1/_images_v2.json libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs.json libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create.json libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create_import.json libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_get_one.json libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_not_found.json libcloud/test/compute/fixtures/openstack_v1.1/_os_networks.json libcloud/test/compute/fixtures/openstack_v1.1/_os_networks_POST.json libcloud/test/compute/fixtures/openstack_v1.1/_os_quota_sets_aTenantId.json libcloud/test/compute/fixtures/openstack_v1.1/_os_security_group_rules_create.json libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups.json libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups_create.json libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshot.json libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshot_rackspace.json libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create_rackspace.json libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_rackspace.json libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d.json libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_create.json libcloud/test/compute/fixtures/openstack_v1.1/_port_v2.json libcloud/test/compute/fixtures/openstack_v1.1/_ports_v2.json libcloud/test/compute/fixtures/openstack_v1.1/_servers.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_12063_metadata_two_keys.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064_updated_name_bob.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_12065_os_volume_attachments.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_12086_console_output.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_1c01300f-ef97-4937-8f03-ac676d6234be_os-security-groups.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_create.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_create_disk_config.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_EMPTY.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_ERROR_STATE.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_pause.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_resume.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_suspend.json libcloud/test/compute/fixtures/openstack_v1.1/_servers_unpause.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingip.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingips.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_POST.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_public.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__router.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__router_interface.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__routers.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__security_group.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__security_group_rule.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__security_groups.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__snapshot.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__snapshots.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__snapshots_paginate_start.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__subnet.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__subnets.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__volume.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__volume_abc6a3a1_c4ce_40f6_9b9f_07a61508938d.json libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__volumes.json libcloud/test/compute/fixtures/openstack_v1.1/delete_floating_ip_167_138_123_111.json libcloud/test/compute/fixtures/ovh/auth_time_get.json libcloud/test/compute/fixtures/ovh/flavor_get.json libcloud/test/compute/fixtures/ovh/flavor_get_detail.json libcloud/test/compute/fixtures/ovh/image_get.json libcloud/test/compute/fixtures/ovh/image_get_detail.json libcloud/test/compute/fixtures/ovh/instance_get.json libcloud/test/compute/fixtures/ovh/instance_get_detail.json libcloud/test/compute/fixtures/ovh/instance_post.json libcloud/test/compute/fixtures/ovh/region_get.json libcloud/test/compute/fixtures/ovh/ssh_get.json libcloud/test/compute/fixtures/ovh/ssh_get_detail.json libcloud/test/compute/fixtures/ovh/volume_get.json libcloud/test/compute/fixtures/ovh/volume_get_detail.json libcloud/test/compute/fixtures/ovh/volume_snapshot_get.json libcloud/test/compute/fixtures/ovh/volume_snapshot_get_details.json libcloud/test/compute/fixtures/packet/associate_ip.json libcloud/test/compute/fixtures/packet/attach_volume.json libcloud/test/compute/fixtures/packet/bgp_config_project_1.json libcloud/test/compute/fixtures/packet/bgp_config_project_2.json libcloud/test/compute/fixtures/packet/bgp_config_project_3.json libcloud/test/compute/fixtures/packet/bgp_session_create.json libcloud/test/compute/fixtures/packet/bgp_session_get.json libcloud/test/compute/fixtures/packet/bgp_sessions.json libcloud/test/compute/fixtures/packet/create_volume.json libcloud/test/compute/fixtures/packet/device_create.json libcloud/test/compute/fixtures/packet/device_events.json libcloud/test/compute/fixtures/packet/devices.json libcloud/test/compute/fixtures/packet/devices_for_project.json libcloud/test/compute/fixtures/packet/facilities.json libcloud/test/compute/fixtures/packet/ip_address.json libcloud/test/compute/fixtures/packet/ip_assignments.json libcloud/test/compute/fixtures/packet/node_bandwidth.json libcloud/test/compute/fixtures/packet/operatingsystems.json libcloud/test/compute/fixtures/packet/plans.json libcloud/test/compute/fixtures/packet/project_events.json libcloud/test/compute/fixtures/packet/project_ips.json libcloud/test/compute/fixtures/packet/projects.json libcloud/test/compute/fixtures/packet/reserve_ip.json libcloud/test/compute/fixtures/packet/sshkey_create.json libcloud/test/compute/fixtures/packet/sshkeys.json libcloud/test/compute/fixtures/packet/volumes.json libcloud/test/compute/fixtures/profitbricks/attach_volume.json libcloud/test/compute/fixtures/profitbricks/create_node.json libcloud/test/compute/fixtures/profitbricks/create_volume.json libcloud/test/compute/fixtures/profitbricks/create_volume_snapshot.json libcloud/test/compute/fixtures/profitbricks/error_resource_not_found.json libcloud/test/compute/fixtures/profitbricks/ex_create_datacenter.json libcloud/test/compute/fixtures/profitbricks/ex_create_firewall_rule.json libcloud/test/compute/fixtures/profitbricks/ex_create_ip_block.json libcloud/test/compute/fixtures/profitbricks/ex_create_lan.json libcloud/test/compute/fixtures/profitbricks/ex_create_load_balancer.json libcloud/test/compute/fixtures/profitbricks/ex_create_network_interface.json libcloud/test/compute/fixtures/profitbricks/ex_describe_datacenter.json libcloud/test/compute/fixtures/profitbricks/ex_describe_firewall_rule.json libcloud/test/compute/fixtures/profitbricks/ex_describe_image.json libcloud/test/compute/fixtures/profitbricks/ex_describe_ip_block.json libcloud/test/compute/fixtures/profitbricks/ex_describe_lan.json libcloud/test/compute/fixtures/profitbricks/ex_describe_load_balancer.json libcloud/test/compute/fixtures/profitbricks/ex_describe_location.json libcloud/test/compute/fixtures/profitbricks/ex_describe_network_interface.json libcloud/test/compute/fixtures/profitbricks/ex_describe_node.json libcloud/test/compute/fixtures/profitbricks/ex_describe_snapshot.json libcloud/test/compute/fixtures/profitbricks/ex_describe_volume.json libcloud/test/compute/fixtures/profitbricks/ex_list_attached_volumes.json libcloud/test/compute/fixtures/profitbricks/ex_list_datacenters.json libcloud/test/compute/fixtures/profitbricks/ex_list_firewall_rules.json libcloud/test/compute/fixtures/profitbricks/ex_list_ip_blocks.json libcloud/test/compute/fixtures/profitbricks/ex_list_lans.json libcloud/test/compute/fixtures/profitbricks/ex_list_load_balanced_nics.json libcloud/test/compute/fixtures/profitbricks/ex_list_load_balancers.json libcloud/test/compute/fixtures/profitbricks/ex_list_network_interfaces.json libcloud/test/compute/fixtures/profitbricks/ex_rename_datacenter.json libcloud/test/compute/fixtures/profitbricks/ex_update_firewall_rule.json libcloud/test/compute/fixtures/profitbricks/ex_update_image.json libcloud/test/compute/fixtures/profitbricks/ex_update_lan.json libcloud/test/compute/fixtures/profitbricks/ex_update_load_balancer.json libcloud/test/compute/fixtures/profitbricks/ex_update_network_interface.json libcloud/test/compute/fixtures/profitbricks/ex_update_node.json libcloud/test/compute/fixtures/profitbricks/ex_update_snapshot.json libcloud/test/compute/fixtures/profitbricks/ex_update_volume.json libcloud/test/compute/fixtures/profitbricks/list_images.json libcloud/test/compute/fixtures/profitbricks/list_locations.json libcloud/test/compute/fixtures/profitbricks/list_nodes.json libcloud/test/compute/fixtures/profitbricks/list_snapshots.json libcloud/test/compute/fixtures/profitbricks/list_volumes.json libcloud/test/compute/fixtures/rimuhosting/r_distributions.json libcloud/test/compute/fixtures/rimuhosting/r_orders.json libcloud/test/compute/fixtures/rimuhosting/r_orders_new_vps.json libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps.json libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps_running_state.json libcloud/test/compute/fixtures/rimuhosting/r_pricing_plans.json libcloud/test/compute/fixtures/scaleway/create_image.json libcloud/test/compute/fixtures/scaleway/create_node.json libcloud/test/compute/fixtures/scaleway/create_volume.json libcloud/test/compute/fixtures/scaleway/create_volume_snapshot.json libcloud/test/compute/fixtures/scaleway/error.json libcloud/test/compute/fixtures/scaleway/error_invalid_image.json libcloud/test/compute/fixtures/scaleway/get_image.json libcloud/test/compute/fixtures/scaleway/list_availability.json libcloud/test/compute/fixtures/scaleway/list_images.json libcloud/test/compute/fixtures/scaleway/list_nodes.json libcloud/test/compute/fixtures/scaleway/list_nodes_empty.json libcloud/test/compute/fixtures/scaleway/list_sizes.json libcloud/test/compute/fixtures/scaleway/list_volume_snapshots.json libcloud/test/compute/fixtures/scaleway/list_volumes.json libcloud/test/compute/fixtures/scaleway/list_volumes_empty.json libcloud/test/compute/fixtures/scaleway/reboot_node.json libcloud/test/compute/fixtures/scaleway/token_info.json libcloud/test/compute/fixtures/scaleway/user_info.json libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml libcloud/test/compute/fixtures/softlayer/empty.xml libcloud/test/compute/fixtures/softlayer/fail.xml libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Account_getSshKeys.xml libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_createObject.xml libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_deleteObject.xml libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_getObject.xml libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml libcloud/test/compute/fixtures/terremark/api_v0_8_catalogItem_5.xml libcloud/test/compute/fixtures/terremark/api_v0_8_login.xml libcloud/test/compute/fixtures/terremark/api_v0_8_org_240.xml libcloud/test/compute/fixtures/terremark/api_v0_8_task_10496.xml libcloud/test/compute/fixtures/terremark/api_v0_8_task_11001.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_action_deploy.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_get.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_powerOn.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_poweroff.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_reset.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_action_instantiateVAppTemplate.xml libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_catalog.xml libcloud/test/compute/fixtures/upcloud/api_1_2_plan.json libcloud/test/compute/fixtures/upcloud/api_1_2_price.json libcloud/test/compute/fixtures/upcloud/api_1_2_server.json libcloud/test/compute/fixtures/upcloud/api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.json libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.json libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_cdrom.json libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_template.json libcloud/test/compute/fixtures/upcloud/api_1_2_storage_cdrom.json libcloud/test/compute/fixtures/upcloud/api_1_2_storage_template.json libcloud/test/compute/fixtures/upcloud/api_1_2_zone.json libcloud/test/compute/fixtures/upcloud/api_1_2_zone_failed_auth.json libcloud/test/compute/fixtures/vcl/XMLRPCaddRequest.xml libcloud/test/compute/fixtures/vcl/XMLRPCendRequest.xml libcloud/test/compute/fixtures/vcl/XMLRPCextendRequest.xml libcloud/test/compute/fixtures/vcl/XMLRPCgetImages.xml libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestConnectData.xml libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestIds.xml libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestStatus.xml libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Account_getVirtualGuests.xml libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Location_Datacenter_getDatacenters.xml libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml libcloud/test/compute/fixtures/vcloud_1_5/api_catalogItem_3132e037_759b_4627_9056_ca66466fa607.xml libcloud/test/compute/fixtures/vcloud_1_5/api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4.xml libcloud/test/compute/fixtures/vcloud_1_5/api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4.xml libcloud/test/compute/fixtures/vcloud_1_5/api_org.xml libcloud/test/compute/fixtures/vcloud_1_5/api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xml libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml libcloud/test/compute/fixtures/vcloud_1_5/api_query_vm.xml libcloud/test/compute/fixtures/vcloud_1_5/api_sessions.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_2518935e_b315_4d8e_9e99_9275f751877c.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_deploy.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_fab4b26f_4f2e_4d49_ad01_ae9324bbfe48.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_fe75d3af_f5a3_44a5_b016_ae0bdadfc32b.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy_error.xml libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy_power_off.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_undeployTest.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_powerOn.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_reset.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_create_snapshot.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_remove_snapshots.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_revert_snapshot.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6d.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_access_to_resource_forbidden.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vm_test.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_get_metadata.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_post_metadata.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate.xml libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_brokenVdc.xml libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_cpu.xml libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_disks.xml libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_memory.xml libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_cpu.xml libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_disks.xml libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_memory.xml libcloud/test/compute/fixtures/voxel/create_node.xml libcloud/test/compute/fixtures/voxel/failure.xml libcloud/test/compute/fixtures/voxel/images.xml libcloud/test/compute/fixtures/voxel/locations.xml libcloud/test/compute/fixtures/voxel/nodes.xml libcloud/test/compute/fixtures/voxel/success.xml libcloud/test/compute/fixtures/voxel/unauthorized.xml libcloud/test/compute/fixtures/vpsnet/_available_clouds_api10json_templates.json libcloud/test/compute/fixtures/vultr/create_key_pair.json libcloud/test/compute/fixtures/vultr/create_node.json libcloud/test/compute/fixtures/vultr/error_rate_limit.txt libcloud/test/compute/fixtures/vultr/list_images.json libcloud/test/compute/fixtures/vultr/list_key_pairs.json libcloud/test/compute/fixtures/vultr/list_locations.json libcloud/test/compute/fixtures/vultr/list_nodes.json libcloud/test/compute/fixtures/vultr/list_sizes.json libcloud/test/container/__init__.py libcloud/test/container/test_docker.py libcloud/test/container/test_docker_utils.py libcloud/test/container/test_ecs.py libcloud/test/container/test_gke.py libcloud/test/container/test_joyent.py libcloud/test/container/test_kubernetes.py libcloud/test/container/test_rancher.py libcloud/test/container/fixtures/docker/linux_124/container_a68.json libcloud/test/container/fixtures/docker/linux_124/containers.json libcloud/test/container/fixtures/docker/linux_124/create_container.json libcloud/test/container/fixtures/docker/linux_124/create_image.txt libcloud/test/container/fixtures/docker/linux_124/images.json libcloud/test/container/fixtures/docker/linux_124/logs.txt libcloud/test/container/fixtures/docker/linux_124/search.json libcloud/test/container/fixtures/docker/linux_124/version.json libcloud/test/container/fixtures/docker/mac_124/containers.json libcloud/test/container/fixtures/docker/mac_124/create_container.json libcloud/test/container/fixtures/docker/mac_124/create_image.txt libcloud/test/container/fixtures/docker/mac_124/search.json libcloud/test/container/fixtures/docker/mac_124/version.json libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu.json libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu_tags.json libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu_tags_latest.json libcloud/test/container/fixtures/ecs/createcluster.json libcloud/test/container/fixtures/ecs/createservice.json libcloud/test/container/fixtures/ecs/deletecluster.json libcloud/test/container/fixtures/ecs/deleteservice.json libcloud/test/container/fixtures/ecs/describeclusters.json libcloud/test/container/fixtures/ecs/describerepositories.json libcloud/test/container/fixtures/ecs/describeservices.json libcloud/test/container/fixtures/ecs/describetasks.json libcloud/test/container/fixtures/ecs/getauthorizationtoken.json libcloud/test/container/fixtures/ecs/listclusters.json libcloud/test/container/fixtures/ecs/listimages.json libcloud/test/container/fixtures/ecs/listservices.json libcloud/test/container/fixtures/ecs/listtasks.json libcloud/test/container/fixtures/ecs/registertaskdefinition.json libcloud/test/container/fixtures/ecs/runtask.json libcloud/test/container/fixtures/ecs/stoptask.json libcloud/test/container/fixtures/gke/zones_us-central1-a_instance_serverconfig.json libcloud/test/container/fixtures/gke/zones_us-central1-a_list.json libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces.json libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default.json libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default_DELETE.json libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default_pods_POST.json libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_test.json libcloud/test/container/fixtures/kubernetes/_api_v1_nodes.json libcloud/test/container/fixtures/kubernetes/_api_v1_nodes_127_0_0_1.json libcloud/test/container/fixtures/kubernetes/_api_v1_pods.json libcloud/test/container/fixtures/rancher/deploy_container.json libcloud/test/container/fixtures/rancher/ex_activate_service.json libcloud/test/container/fixtures/rancher/ex_activate_stack.json libcloud/test/container/fixtures/rancher/ex_deploy_service.json libcloud/test/container/fixtures/rancher/ex_deploy_stack.json libcloud/test/container/fixtures/rancher/ex_destroy_service.json libcloud/test/container/fixtures/rancher/ex_destroy_stack.json libcloud/test/container/fixtures/rancher/ex_list_services.json libcloud/test/container/fixtures/rancher/ex_list_stacks.json libcloud/test/container/fixtures/rancher/ex_search_containers.json libcloud/test/container/fixtures/rancher/ex_search_services.json libcloud/test/container/fixtures/rancher/list_containers.json libcloud/test/container/fixtures/rancher/start_container.json libcloud/test/container/fixtures/rancher/stop_container.json libcloud/test/dns/__init__.py libcloud/test/dns/test_auroradns.py libcloud/test/dns/test_base.py libcloud/test/dns/test_buddyns.py libcloud/test/dns/test_cloudflare.py libcloud/test/dns/test_digitalocean.py libcloud/test/dns/test_dnsimple.py libcloud/test/dns/test_dnspod.py libcloud/test/dns/test_durabledns.py libcloud/test/dns/test_gandi.py libcloud/test/dns/test_gandi_live.py libcloud/test/dns/test_godaddy.py libcloud/test/dns/test_google.py libcloud/test/dns/test_hostvirtual.py libcloud/test/dns/test_linode.py libcloud/test/dns/test_liquidweb.py libcloud/test/dns/test_luadns.py libcloud/test/dns/test_nfsn.py libcloud/test/dns/test_nsone.py libcloud/test/dns/test_onapp.py libcloud/test/dns/test_pointdns.py libcloud/test/dns/test_powerdns.py libcloud/test/dns/test_rackspace.py libcloud/test/dns/test_rcodezero.py libcloud/test/dns/test_route53.py libcloud/test/dns/test_softlayer.py libcloud/test/dns/test_vultr.py libcloud/test/dns/test_worldwidedns.py libcloud/test/dns/test_zerigo.py libcloud/test/dns/test_zonomi.py libcloud/test/dns/fixtures/auroradns/zone_create.json libcloud/test/dns/fixtures/auroradns/zone_example_com.json libcloud/test/dns/fixtures/auroradns/zone_example_com_health_check.json libcloud/test/dns/fixtures/auroradns/zone_example_com_health_checks.json libcloud/test/dns/fixtures/auroradns/zone_example_com_record_localhost.json libcloud/test/dns/fixtures/auroradns/zone_example_com_records.json libcloud/test/dns/fixtures/auroradns/zone_list.json libcloud/test/dns/fixtures/buddyns/create_zone_success.json libcloud/test/dns/fixtures/buddyns/delete_zone_success.json libcloud/test/dns/fixtures/buddyns/empty_zones_list.json libcloud/test/dns/fixtures/buddyns/get_zone_success.json libcloud/test/dns/fixtures/buddyns/list_zones.json libcloud/test/dns/fixtures/buddyns/zone_already_exists.json libcloud/test/dns/fixtures/buddyns/zone_does_not_exist.json libcloud/test/dns/fixtures/cloudflare/memberships_GET.json libcloud/test/dns/fixtures/cloudflare/record_DELETE.json libcloud/test/dns/fixtures/cloudflare/record_GET.json libcloud/test/dns/fixtures/cloudflare/record_GET_400.json libcloud/test/dns/fixtures/cloudflare/record_GET_404.json libcloud/test/dns/fixtures/cloudflare/record_PUT.json libcloud/test/dns/fixtures/cloudflare/records_GET_1.json libcloud/test/dns/fixtures/cloudflare/records_GET_2.json libcloud/test/dns/fixtures/cloudflare/records_POST.json libcloud/test/dns/fixtures/cloudflare/zone_DELETE.json libcloud/test/dns/fixtures/cloudflare/zone_GET.json libcloud/test/dns/fixtures/cloudflare/zone_GET_400.json libcloud/test/dns/fixtures/cloudflare/zone_GET_404.json libcloud/test/dns/fixtures/cloudflare/zone_PATCH.json libcloud/test/dns/fixtures/cloudflare/zones_GET.json libcloud/test/dns/fixtures/cloudflare/zones_POST.json libcloud/test/dns/fixtures/digitalocean/_v2_domains.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_CREATE.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_EMPTY.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_UNAUTHORIZED.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_NOT_FOUND.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234560.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234561.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234562.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_NOT_FOUND.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_UPDATE.json libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_CREATE.json libcloud/test/dns/fixtures/dnsimple/create_domain.json libcloud/test/dns/fixtures/dnsimple/create_domain_record.json libcloud/test/dns/fixtures/dnsimple/get_domain.json libcloud/test/dns/fixtures/dnsimple/get_domain_record.json libcloud/test/dns/fixtures/dnsimple/list_domain_records.json libcloud/test/dns/fixtures/dnsimple/list_domains.json libcloud/test/dns/fixtures/dnsimple/update_domain_record.json libcloud/test/dns/fixtures/dnspod/create_zone_success.json libcloud/test/dns/fixtures/dnspod/delete_record_record_does_not_exist.json libcloud/test/dns/fixtures/dnspod/delete_record_success.json libcloud/test/dns/fixtures/dnspod/delete_zone_success.json libcloud/test/dns/fixtures/dnspod/empty_zones_list.json libcloud/test/dns/fixtures/dnspod/get_record.json libcloud/test/dns/fixtures/dnspod/get_zone_success.json libcloud/test/dns/fixtures/dnspod/list_records.json libcloud/test/dns/fixtures/dnspod/list_zones.json libcloud/test/dns/fixtures/dnspod/record_already_exists.json libcloud/test/dns/fixtures/dnspod/zone_already_exists.json libcloud/test/dns/fixtures/dnspod/zone_does_not_exist.json libcloud/test/dns/fixtures/durabledns/create_record_NO_EXTRA_PARAMS.xml libcloud/test/dns/fixtures/durabledns/create_record_WITH_EXTRA_PARAMS.xml libcloud/test/dns/fixtures/durabledns/create_record_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/create_zone.xml libcloud/test/dns/fixtures/durabledns/create_zone_ZONE_ALREADY_EXIST.xml libcloud/test/dns/fixtures/durabledns/delete_record.xml libcloud/test/dns/fixtures/durabledns/delete_record_RECORD_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/delete_record_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/delete_zone.xml libcloud/test/dns/fixtures/durabledns/delete_zone_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/get_record.xml libcloud/test/dns/fixtures/durabledns/get_record_RECORD_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/get_record_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/get_zone.xml libcloud/test/dns/fixtures/durabledns/get_zone_NO_EXTRA_PARAMS.xml libcloud/test/dns/fixtures/durabledns/get_zone_UPDATE_ZONE.xml libcloud/test/dns/fixtures/durabledns/get_zone_WITH_EXTRA_PARAMS.xml libcloud/test/dns/fixtures/durabledns/get_zone_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/list_records.xml libcloud/test/dns/fixtures/durabledns/list_records_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/list_zones.xml libcloud/test/dns/fixtures/durabledns/update_record.xml libcloud/test/dns/fixtures/durabledns/update_record_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/durabledns/update_record_success.xml libcloud/test/dns/fixtures/durabledns/update_zone_UPDATE_ZONE.xml libcloud/test/dns/fixtures/durabledns/update_zone_ZONE_DOES_NOT_EXIST.xml libcloud/test/dns/fixtures/gandi/create_record.xml libcloud/test/dns/fixtures/gandi/create_zone.xml libcloud/test/dns/fixtures/gandi/delete_record.xml libcloud/test/dns/fixtures/gandi/delete_record_doesnotexist.xml libcloud/test/dns/fixtures/gandi/delete_zone.xml libcloud/test/dns/fixtures/gandi/delete_zone_fail.xml libcloud/test/dns/fixtures/gandi/get_zone.xml libcloud/test/dns/fixtures/gandi/list_records.xml libcloud/test/dns/fixtures/gandi/list_records_empty.xml libcloud/test/dns/fixtures/gandi/list_zones.xml libcloud/test/dns/fixtures/gandi/new_version.xml libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml libcloud/test/dns/fixtures/gandi_live/create_bad_zone.json libcloud/test/dns/fixtures/gandi_live/create_domain.json libcloud/test/dns/fixtures/gandi_live/create_existing_record.json libcloud/test/dns/fixtures/gandi_live/create_record.json libcloud/test/dns/fixtures/gandi_live/create_zone.json libcloud/test/dns/fixtures/gandi_live/delete_gandi_zone.json libcloud/test/dns/fixtures/gandi_live/delete_record.json libcloud/test/dns/fixtures/gandi_live/get_bad_zone.json libcloud/test/dns/fixtures/gandi_live/get_mx_record.json libcloud/test/dns/fixtures/gandi_live/get_nonexistent_record.json libcloud/test/dns/fixtures/gandi_live/get_nonexistent_zone.json libcloud/test/dns/fixtures/gandi_live/get_record.json libcloud/test/dns/fixtures/gandi_live/get_zone.json libcloud/test/dns/fixtures/gandi_live/list_records.json libcloud/test/dns/fixtures/gandi_live/list_records_bind.txt libcloud/test/dns/fixtures/gandi_live/list_zones.json libcloud/test/dns/fixtures/gandi_live/update_bad_record.json libcloud/test/dns/fixtures/gandi_live/update_gandi_zone.json libcloud/test/dns/fixtures/gandi_live/update_mx_record.json libcloud/test/dns/fixtures/gandi_live/update_record.json libcloud/test/dns/fixtures/godaddy/purchase_request.json libcloud/test/dns/fixtures/godaddy/v1_domains.json libcloud/test/dns/fixtures/godaddy/v1_domains_agreements.json libcloud/test/dns/fixtures/godaddy/v1_domains_aperture_platform_com.json libcloud/test/dns/fixtures/godaddy/v1_domains_aperture_platform_com_records.json libcloud/test/dns/fixtures/godaddy/v1_domains_aperture_platform_com_records_A_www.json libcloud/test/dns/fixtures/godaddy/v1_domains_available.json libcloud/test/dns/fixtures/godaddy/v1_domains_purchase.json libcloud/test/dns/fixtures/godaddy/v1_domains_purchase_schema_com.json libcloud/test/dns/fixtures/godaddy/v1_domains_tlds.json libcloud/test/dns/fixtures/google/get_zone_does_not_exists.json libcloud/test/dns/fixtures/google/managed_zones_1.json libcloud/test/dns/fixtures/google/no_record.json libcloud/test/dns/fixtures/google/record.json libcloud/test/dns/fixtures/google/record_changes.json libcloud/test/dns/fixtures/google/records_list.json libcloud/test/dns/fixtures/google/zone.json libcloud/test/dns/fixtures/google/zone_create.json libcloud/test/dns/fixtures/google/zone_list.json libcloud/test/dns/fixtures/hostvirtual/get_record.json libcloud/test/dns/fixtures/hostvirtual/get_zone.json libcloud/test/dns/fixtures/hostvirtual/list_records.json libcloud/test/dns/fixtures/hostvirtual/list_records_none.json libcloud/test/dns/fixtures/hostvirtual/list_zones.json libcloud/test/dns/fixtures/hostvirtual/zone_does_not_exist.json libcloud/test/dns/fixtures/linode/create_domain.json libcloud/test/dns/fixtures/linode/create_domain_validation_error.json libcloud/test/dns/fixtures/linode/create_resource.json libcloud/test/dns/fixtures/linode/delete_domain.json libcloud/test/dns/fixtures/linode/delete_domain_does_not_exist.json libcloud/test/dns/fixtures/linode/delete_resource.json libcloud/test/dns/fixtures/linode/delete_resource_does_not_exist.json libcloud/test/dns/fixtures/linode/domain_list.json libcloud/test/dns/fixtures/linode/get_record.json libcloud/test/dns/fixtures/linode/get_record_does_not_exist.json libcloud/test/dns/fixtures/linode/get_zone.json libcloud/test/dns/fixtures/linode/get_zone_does_not_exist.json libcloud/test/dns/fixtures/linode/resource_list.json libcloud/test/dns/fixtures/linode/resource_list_does_not_exist.json libcloud/test/dns/fixtures/linode/update_domain.json libcloud/test/dns/fixtures/linode/update_resource.json libcloud/test/dns/fixtures/liquidweb/create_zone_success.json libcloud/test/dns/fixtures/liquidweb/delete_record.json libcloud/test/dns/fixtures/liquidweb/delete_zone.success.json libcloud/test/dns/fixtures/liquidweb/delete_zone_success.json libcloud/test/dns/fixtures/liquidweb/duplicate_record.json libcloud/test/dns/fixtures/liquidweb/empty_records_list.json libcloud/test/dns/fixtures/liquidweb/empty_zones_list.json libcloud/test/dns/fixtures/liquidweb/get_record.json libcloud/test/dns/fixtures/liquidweb/get_zone.json libcloud/test/dns/fixtures/liquidweb/record_does_not_exist.json libcloud/test/dns/fixtures/liquidweb/records_list.json libcloud/test/dns/fixtures/liquidweb/update_record.json libcloud/test/dns/fixtures/liquidweb/zone_does_not_exist.json libcloud/test/dns/fixtures/liquidweb/zones_list.json libcloud/test/dns/fixtures/luadns/create_record_success.json libcloud/test/dns/fixtures/luadns/create_zone_success.json libcloud/test/dns/fixtures/luadns/delete_record_success.json libcloud/test/dns/fixtures/luadns/delete_zone_success.json libcloud/test/dns/fixtures/luadns/empty_records_list.json libcloud/test/dns/fixtures/luadns/empty_zones_list.json libcloud/test/dns/fixtures/luadns/get_record.json libcloud/test/dns/fixtures/luadns/get_zone.json libcloud/test/dns/fixtures/luadns/record_does_not_exist.json libcloud/test/dns/fixtures/luadns/records_list.json libcloud/test/dns/fixtures/luadns/zone_already_exists.json libcloud/test/dns/fixtures/luadns/zone_does_not_exist.json libcloud/test/dns/fixtures/luadns/zones_list.json libcloud/test/dns/fixtures/nfsn/list_one_record.json libcloud/test/dns/fixtures/nfsn/list_records.json libcloud/test/dns/fixtures/nfsn/list_records_created.json libcloud/test/dns/fixtures/nfsn/record_not_removed.json libcloud/test/dns/fixtures/nfsn/zone_not_found.json libcloud/test/dns/fixtures/nsone/create_zone_success.json libcloud/test/dns/fixtures/nsone/delete_record_success.json libcloud/test/dns/fixtures/nsone/delete_zone_success.json libcloud/test/dns/fixtures/nsone/empty_zones_list.json libcloud/test/dns/fixtures/nsone/get_record_success.json libcloud/test/dns/fixtures/nsone/get_zone_success.json libcloud/test/dns/fixtures/nsone/list_records_empty.json libcloud/test/dns/fixtures/nsone/list_zones.json libcloud/test/dns/fixtures/nsone/record_does_not_exist.json libcloud/test/dns/fixtures/nsone/zone_already_exists.json libcloud/test/dns/fixtures/nsone/zone_does_not_exist.json libcloud/test/dns/fixtures/onapp/create_record.json libcloud/test/dns/fixtures/onapp/create_zone.json libcloud/test/dns/fixtures/onapp/dns_zone_not_found.json libcloud/test/dns/fixtures/onapp/get_record.json libcloud/test/dns/fixtures/onapp/get_record_after_update.json libcloud/test/dns/fixtures/onapp/get_zone.json libcloud/test/dns/fixtures/onapp/list_records.json libcloud/test/dns/fixtures/onapp/list_zones.json libcloud/test/dns/fixtures/pointdns/_zones_1_DELETE.json libcloud/test/dns/fixtures/pointdns/_zones_1_ZONE_UPDATE.json libcloud/test/dns/fixtures/pointdns/_zones_1_mail_redirects_CREATE.json libcloud/test/dns/fixtures/pointdns/_zones_1_mail_redirects_DELETE.json libcloud/test/dns/fixtures/pointdns/_zones_1_mail_redirects_GET.json libcloud/test/dns/fixtures/pointdns/_zones_1_mail_redirects_LIST.json libcloud/test/dns/fixtures/pointdns/_zones_1_mail_redirects_UPDATE.json libcloud/test/dns/fixtures/pointdns/_zones_1_records_141_GET.json libcloud/test/dns/fixtures/pointdns/_zones_1_records_141_UPDATE.json libcloud/test/dns/fixtures/pointdns/_zones_1_records_150_DELETE.json libcloud/test/dns/fixtures/pointdns/_zones_1_records_GET.json libcloud/test/dns/fixtures/pointdns/_zones_1_redirects_CREATE.json libcloud/test/dns/fixtures/pointdns/_zones_1_redirects_DELETE.json libcloud/test/dns/fixtures/pointdns/_zones_1_redirects_GET.json libcloud/test/dns/fixtures/pointdns/_zones_1_redirects_LIST.json libcloud/test/dns/fixtures/pointdns/_zones_1_redirects_UPDATE.json libcloud/test/dns/fixtures/pointdns/_zones_CREATE.json libcloud/test/dns/fixtures/pointdns/_zones_GET.json libcloud/test/dns/fixtures/pointdns/_zones_GET_1.json libcloud/test/dns/fixtures/pointdns/_zones_example_com_UPDATE.json libcloud/test/dns/fixtures/pointdns/_zones_example_com_records_CREATE.json libcloud/test/dns/fixtures/pointdns/error.json libcloud/test/dns/fixtures/pointdns/not_found.json libcloud/test/dns/fixtures/pointdns/redirect_error.json libcloud/test/dns/fixtures/powerdns/list_records.json libcloud/test/dns/fixtures/powerdns/list_zones.json libcloud/test/dns/fixtures/rackspace/auth_1_1.json libcloud/test/dns/fixtures/rackspace/auth_2_0.json libcloud/test/dns/fixtures/rackspace/create_ptr_record_success.json libcloud/test/dns/fixtures/rackspace/create_record_success.json libcloud/test/dns/fixtures/rackspace/create_zone_success.json libcloud/test/dns/fixtures/rackspace/create_zone_validation_error.json libcloud/test/dns/fixtures/rackspace/delete_ptr_record_success.json libcloud/test/dns/fixtures/rackspace/delete_record_success.json libcloud/test/dns/fixtures/rackspace/delete_zone_success.json libcloud/test/dns/fixtures/rackspace/does_not_exist.json libcloud/test/dns/fixtures/rackspace/get_record_success.json libcloud/test/dns/fixtures/rackspace/get_zone_success.json libcloud/test/dns/fixtures/rackspace/list_ptr_records_success.json libcloud/test/dns/fixtures/rackspace/list_records_no_results.json libcloud/test/dns/fixtures/rackspace/list_records_success.json libcloud/test/dns/fixtures/rackspace/list_zones_no_results.json libcloud/test/dns/fixtures/rackspace/list_zones_success.json libcloud/test/dns/fixtures/rackspace/unauthorized.json libcloud/test/dns/fixtures/rackspace/update_record_success.json libcloud/test/dns/fixtures/rackspace/update_zone_success.json libcloud/test/dns/fixtures/rcodezero/get_zone_details.json libcloud/test/dns/fixtures/rcodezero/list_records.json libcloud/test/dns/fixtures/rcodezero/list_zones.json libcloud/test/dns/fixtures/route53/create_zone.xml libcloud/test/dns/fixtures/route53/get_zone.xml libcloud/test/dns/fixtures/route53/invalid_change_batch.xml libcloud/test/dns/fixtures/route53/list_records.xml libcloud/test/dns/fixtures/route53/list_zones.xml libcloud/test/dns/fixtures/route53/record_does_not_exist.xml libcloud/test/dns/fixtures/route53/zone_does_not_exist.xml libcloud/test/dns/fixtures/softlayer/not_found.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_ResourceRecord_createObject.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_ResourceRecord_deleteObject.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_ResourceRecord_editObject.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_ResourceRecord_getObject.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_ResourceRecord_getObject_changed.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_createObject.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_deleteObject.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_getByDomainName.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_getObject.xml libcloud/test/dns/fixtures/softlayer/v3_SoftLayer_Dns_Domain_getResourceRecords.xml libcloud/test/dns/fixtures/vultr/delete_zone.json libcloud/test/dns/fixtures/vultr/empty_records_list.json libcloud/test/dns/fixtures/vultr/empty_zones_list.json libcloud/test/dns/fixtures/vultr/get_record.json libcloud/test/dns/fixtures/vultr/get_zone.json libcloud/test/dns/fixtures/vultr/list_domains.json libcloud/test/dns/fixtures/vultr/list_records.json libcloud/test/dns/fixtures/vultr/test_zone.json libcloud/test/dns/fixtures/worldwidedns/_api_dns_modify_asp_CREATE_RECORD_MAX_ENTRIES_WITH_ENTRY libcloud/test/dns/fixtures/worldwidedns/api_dns_list libcloud/test/dns/fixtures/worldwidedns/api_dns_list_domain_asp libcloud/test/dns/fixtures/worldwidedns/api_dns_list_domain_asp_CREATE_RECORD libcloud/test/dns/fixtures/worldwidedns/api_dns_list_domain_asp_CREATE_RECORD_MAX_ENTRIES libcloud/test/dns/fixtures/worldwidedns/api_dns_list_domain_asp_CREATE_SECOND_RECORD libcloud/test/dns/fixtures/worldwidedns/api_dns_list_domain_asp_DELETE_RECORD libcloud/test/dns/fixtures/worldwidedns/api_dns_list_domain_asp_UPDATE_RECORD libcloud/test/dns/fixtures/worldwidedns/api_dns_list_domain_asp_UPDATE_ZONE libcloud/test/dns/fixtures/zerigo/create_record.xml libcloud/test/dns/fixtures/zerigo/create_zone.xml libcloud/test/dns/fixtures/zerigo/create_zone_validation_error.xml libcloud/test/dns/fixtures/zerigo/get_record.xml libcloud/test/dns/fixtures/zerigo/get_zone.xml libcloud/test/dns/fixtures/zerigo/list_records.xml libcloud/test/dns/fixtures/zerigo/list_records_no_results.xml libcloud/test/dns/fixtures/zerigo/list_zones.xml libcloud/test/dns/fixtures/zerigo/list_zones_no_results.xml libcloud/test/dns/fixtures/zonomi/converted_to_master.xml libcloud/test/dns/fixtures/zonomi/converted_to_slave.xml libcloud/test/dns/fixtures/zonomi/couldnt_convert.xml libcloud/test/dns/fixtures/zonomi/create_record.xml libcloud/test/dns/fixtures/zonomi/create_record_already_exists.xml libcloud/test/dns/fixtures/zonomi/create_zone.xml libcloud/test/dns/fixtures/zonomi/create_zone_already_exists.xml libcloud/test/dns/fixtures/zonomi/delete_record.xml libcloud/test/dns/fixtures/zonomi/delete_record_does_not_exist.xml libcloud/test/dns/fixtures/zonomi/delete_zone.xml libcloud/test/dns/fixtures/zonomi/delete_zone_does_not_exist.xml libcloud/test/dns/fixtures/zonomi/empty_zones_list.xml libcloud/test/dns/fixtures/zonomi/list_records.xml libcloud/test/dns/fixtures/zonomi/list_zones.xml libcloud/test/loadbalancer/__init__.py libcloud/test/loadbalancer/test_alb.py libcloud/test/loadbalancer/test_brightbox.py libcloud/test/loadbalancer/test_cloudstack.py libcloud/test/loadbalancer/test_dimensiondata_v2_3.py libcloud/test/loadbalancer/test_dimensiondata_v2_4.py libcloud/test/loadbalancer/test_elb.py libcloud/test/loadbalancer/test_gce.py libcloud/test/loadbalancer/test_gogrid.py libcloud/test/loadbalancer/test_ninefold.py libcloud/test/loadbalancer/test_nttcis.py libcloud/test/loadbalancer/test_rackspace.py libcloud/test/loadbalancer/test_slb.py libcloud/test/loadbalancer/test_softlayer.py libcloud/test/loadbalancer/fixtures/alb/create_balancer.xml libcloud/test/loadbalancer/fixtures/alb/create_listener.xml libcloud/test/loadbalancer/fixtures/alb/create_rule.xml libcloud/test/loadbalancer/fixtures/alb/create_target_group.xml libcloud/test/loadbalancer/fixtures/alb/describe_load_balancer_listeters.xml libcloud/test/loadbalancer/fixtures/alb/describe_load_balancer_rules.xml libcloud/test/loadbalancer/fixtures/alb/describe_load_balancer_target_groups.xml libcloud/test/loadbalancer/fixtures/alb/describe_load_balancers.xml libcloud/test/loadbalancer/fixtures/alb/describe_tags.xml libcloud/test/loadbalancer/fixtures/alb/describe_target_health.xml libcloud/test/loadbalancer/fixtures/alb/register_targets.xml libcloud/test/loadbalancer/fixtures/brightbox/load_balancers.json libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_lba_1235f.json libcloud/test/loadbalancer/fixtures/brightbox/load_balancers_post.json libcloud/test/loadbalancer/fixtures/brightbox/token.json libcloud/test/loadbalancer/fixtures/cloudstack/assignToLoadBalancerRule_default.json libcloud/test/loadbalancer/fixtures/cloudstack/associateIpAddress_default.json libcloud/test/loadbalancer/fixtures/cloudstack/createLoadBalancerRule_default.json libcloud/test/loadbalancer/fixtures/cloudstack/deleteLoadBalancerRule_default.json libcloud/test/loadbalancer/fixtures/cloudstack/disassociateIpAddress_default.json libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRuleInstances_default.json libcloud/test/loadbalancer/fixtures/cloudstack/listLoadBalancerRules_default.json libcloud/test/loadbalancer/fixtures/cloudstack/listZones_default.json libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17340.json libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17341.json libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17342.json libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17344.json libcloud/test/loadbalancer/fixtures/cloudstack/queryAsyncJobResult_17346.json libcloud/test/loadbalancer/fixtures/cloudstack/removeFromLoadBalancerRule_default.json libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_addPoolMember.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_createNode.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_createPool.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_createVirtualListener.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_defaultHealthMonitor.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_defaultIrule.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_defaultPersistenceProfile.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_deleteNode.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_deletePool.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_deleteVirtualListener.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_editNode.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_editPool.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_editPoolMember.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_node.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_pool.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_poolMember.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_removePoolMember.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_virtualListener.xml libcloud/test/loadbalancer/fixtures/dimensiondata/networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml libcloud/test/loadbalancer/fixtures/dimensiondata/oec_0_9_myaccount.xml libcloud/test/loadbalancer/fixtures/elb/create_load_balancer.xml libcloud/test/loadbalancer/fixtures/elb/create_load_balancer_policy.xml libcloud/test/loadbalancer/fixtures/elb/deregister_instances_from_load_balancer.xml libcloud/test/loadbalancer/fixtures/elb/describe_load_balancer_policies.xml libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers.xml libcloud/test/loadbalancer/fixtures/elb/describe_load_balancers_policy_types.xml libcloud/test/loadbalancer/fixtures/elb/describe_tags.xml libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_for_backend_server.xml libcloud/test/loadbalancer/fixtures/elb/set_load_balancer_policies_of_listener.xml libcloud/test/loadbalancer/fixtures/gogrid/ip_list.json libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_add.json libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_edit.json libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_get.json libcloud/test/loadbalancer/fixtures/gogrid/loadbalancer_list.json libcloud/test/loadbalancer/fixtures/gogrid/unexpected_error.json libcloud/test/loadbalancer/fixtures/nttcis/alice.crt libcloud/test/loadbalancer/fixtures/nttcis/alice.key libcloud/test/loadbalancer/fixtures/nttcis/chain.crt libcloud/test/loadbalancer/fixtures/nttcis/create_ssl_offload_profile.xml libcloud/test/loadbalancer/fixtures/nttcis/delete_ssl_certificate_chain.xml libcloud/test/loadbalancer/fixtures/nttcis/delete_ssl_domain_certificate.xml libcloud/test/loadbalancer/fixtures/nttcis/delete_ssl_offload_profile.xml libcloud/test/loadbalancer/fixtures/nttcis/denis.crt libcloud/test/loadbalancer/fixtures/nttcis/denis.key libcloud/test/loadbalancer/fixtures/nttcis/edit_ssl_offload_profile.xml libcloud/test/loadbalancer/fixtures/nttcis/get_cert.xml libcloud/test/loadbalancer/fixtures/nttcis/get_ssl_offload_profile.xml libcloud/test/loadbalancer/fixtures/nttcis/list_ssl_offload_profiles.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_addPoolMember.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_createNode.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_createPool.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_createVirtualListener.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_defaultHealthMonitor.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_defaultIrule.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_defaultPersistenceProfile.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_deleteNode.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_deletePool.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_deleteVirtualListener.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_editNode.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_editPool.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_editPoolMember.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_node.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_pool.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_poolMember.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_removePoolMember.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_virtualListener.xml libcloud/test/loadbalancer/fixtures/nttcis/networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml libcloud/test/loadbalancer/fixtures/nttcis/oec_0_9_myaccount.xml libcloud/test/loadbalancer/fixtures/nttcis/ssl_cert_by_name.xml libcloud/test/loadbalancer/fixtures/nttcis/ssl_cert_list.xml libcloud/test/loadbalancer/fixtures/nttcis/ssl_get_cert_chain.xml libcloud/test/loadbalancer/fixtures/nttcis/ssl_import_cert_chain.xml libcloud/test/loadbalancer/fixtures/nttcis/ssl_import_fail.xml libcloud/test/loadbalancer/fixtures/nttcis/ssl_import_success.xml libcloud/test/loadbalancer/fixtures/nttcis/ssl_list_cert_chain_by_name.xml libcloud/test/loadbalancer/fixtures/rackspace/_v2_0__auth.json libcloud/test/loadbalancer/fixtures/rackspace/auth_2_0.json libcloud/test/loadbalancer/fixtures/rackspace/error_page_default.json libcloud/test/loadbalancer/fixtures/rackspace/v1_0_slug_loadbalancers_8290_usage_current.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_accesslist.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_errorpage.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_ex_public_ips.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18941_ex_private_ips.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18945_ex_public_ips.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_3xxx.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_errorpage.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes_post.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8291.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292_nodes_post.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94692_weighted_round_robin.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94693_weighted_least_connections.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94694_unknown_algorithm.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94695_full_details.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94696_http_health_monitor.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94697_https_health_monitor.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_access_list.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_with_access_list.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94700_http_health_monitor_no_body_regex.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_algorithms.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_nodeaddress.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_post.json libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_protocols.json libcloud/test/loadbalancer/fixtures/slb/add_backend_servers.xml libcloud/test/loadbalancer/fixtures/slb/create_load_balancer.xml libcloud/test/loadbalancer/fixtures/slb/create_load_balancer_http_listener.xml libcloud/test/loadbalancer/fixtures/slb/delete_load_balancer.xml libcloud/test/loadbalancer/fixtures/slb/delete_server_certificate.xml libcloud/test/loadbalancer/fixtures/slb/describe_load_balancer_attribute.xml libcloud/test/loadbalancer/fixtures/slb/describe_load_balancers.xml libcloud/test/loadbalancer/fixtures/slb/describe_server_certificates.xml libcloud/test/loadbalancer/fixtures/slb/remove_backend_servers.xml libcloud/test/loadbalancer/fixtures/slb/set_server_certificate_name.xml libcloud/test/loadbalancer/fixtures/slb/start_load_balancer_listener.xml libcloud/test/loadbalancer/fixtures/slb/upload_server_certificate.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Account_getAdcLoadBalancers.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Billing_Item_cancelService.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Location_Datacenter_getDatacenters.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_Service_deleteObject.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_editObject.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_getBillingItem.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_getObject.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Subnet_IpAddress_getByIpAddress.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Product_Order_placeOrder.xml libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Product_Package_getItems.xml libcloud/test/storage/__init__.py libcloud/test/storage/test_atmos.py libcloud/test/storage/test_aurora.py libcloud/test/storage/test_azure_blobs.py libcloud/test/storage/test_backblaze_b2.py libcloud/test/storage/test_base.py libcloud/test/storage/test_cloudfiles.py libcloud/test/storage/test_digitalocean_spaces.py libcloud/test/storage/test_dummy.py libcloud/test/storage/test_google_storage.py libcloud/test/storage/test_local.py libcloud/test/storage/test_ninefold.py libcloud/test/storage/test_oss.py libcloud/test/storage/test_rgw.py libcloud/test/storage/test_s3.py libcloud/test/storage/fixtures/atmos/already_exists.xml libcloud/test/storage/fixtures/atmos/empty_directory_listing.xml libcloud/test/storage/fixtures/atmos/list_containers.xml libcloud/test/storage/fixtures/atmos/not_empty.xml libcloud/test/storage/fixtures/atmos/not_found.xml libcloud/test/storage/fixtures/azure_blobs/list_containers_1.xml libcloud/test/storage/fixtures/azure_blobs/list_containers_2.xml libcloud/test/storage/fixtures/azure_blobs/list_containers_empty.xml libcloud/test/storage/fixtures/azure_blobs/list_objects_1.xml libcloud/test/storage/fixtures/azure_blobs/list_objects_2.xml libcloud/test/storage/fixtures/azure_blobs/list_objects_empty.xml libcloud/test/storage/fixtures/azurite_blobs/list_containers_1.xml libcloud/test/storage/fixtures/azurite_blobs/list_containers_2.xml libcloud/test/storage/fixtures/azurite_blobs/list_containers_empty.xml libcloud/test/storage/fixtures/azurite_blobs/list_objects_1.xml libcloud/test/storage/fixtures/azurite_blobs/list_objects_2.xml libcloud/test/storage/fixtures/azurite_blobs/list_objects_empty.xml libcloud/test/storage/fixtures/backblaze_b2/b2_create_bucket.json libcloud/test/storage/fixtures/backblaze_b2/b2_delete_bucket.json libcloud/test/storage/fixtures/backblaze_b2/b2_delete_file_version.json libcloud/test/storage/fixtures/backblaze_b2/b2_get_upload_url.json libcloud/test/storage/fixtures/backblaze_b2/b2_hide_file.json libcloud/test/storage/fixtures/backblaze_b2/b2_list_buckets.json libcloud/test/storage/fixtures/backblaze_b2/b2_list_file_names.json libcloud/test/storage/fixtures/backblaze_b2/b2_list_file_versions.json libcloud/test/storage/fixtures/backblaze_b2/b2_upload_file.json libcloud/test/storage/fixtures/cloudfiles/_v2_0__auth.json libcloud/test/storage/fixtures/cloudfiles/list_container_objects.json libcloud/test/storage/fixtures/cloudfiles/list_container_objects_empty.json libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted1.json libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted2.json libcloud/test/storage/fixtures/cloudfiles/list_containers.json libcloud/test/storage/fixtures/cloudfiles/list_containers_empty.json libcloud/test/storage/fixtures/cloudfiles/meta_data.json libcloud/test/storage/fixtures/google_storage/get_container.json libcloud/test/storage/fixtures/google_storage/get_object.json libcloud/test/storage/fixtures/google_storage/list_container_acl.json libcloud/test/storage/fixtures/google_storage/list_container_objects.xml libcloud/test/storage/fixtures/google_storage/list_container_objects_empty.xml libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted1.xml libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted2.xml libcloud/test/storage/fixtures/google_storage/list_containers.xml libcloud/test/storage/fixtures/google_storage/list_containers_empty.xml libcloud/test/storage/fixtures/google_storage/list_object_acl.json libcloud/test/storage/fixtures/oss/complete_multipart_upload.xml libcloud/test/storage/fixtures/oss/ex_iterate_multipart_uploads_p1.xml libcloud/test/storage/fixtures/oss/ex_iterate_multipart_uploads_p2.xml libcloud/test/storage/fixtures/oss/initiate_multipart_upload.xml libcloud/test/storage/fixtures/oss/list_container_objects.xml libcloud/test/storage/fixtures/oss/list_container_objects_chinese.xml libcloud/test/storage/fixtures/oss/list_container_objects_empty.xml libcloud/test/storage/fixtures/oss/list_container_objects_prefix.xml libcloud/test/storage/fixtures/oss/list_containers.xml libcloud/test/storage/fixtures/oss/list_containers_empty.xml libcloud/test/storage/fixtures/s3/complete_multipart.xml libcloud/test/storage/fixtures/s3/initiate_multipart.xml libcloud/test/storage/fixtures/s3/list_container_objects.xml libcloud/test/storage/fixtures/s3/list_container_objects_empty.xml libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted1.xml libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted2.xml libcloud/test/storage/fixtures/s3/list_containers.xml libcloud/test/storage/fixtures/s3/list_containers_empty.xml libcloud/test/storage/fixtures/s3/list_multipart_1.xml libcloud/test/storage/fixtures/s3/list_multipart_2.xml libcloud/utils/__init__.py libcloud/utils/connection.py libcloud/utils/decorators.py libcloud/utils/dist.py libcloud/utils/escape.py libcloud/utils/files.py libcloud/utils/iso8601.py libcloud/utils/logging.py libcloud/utils/loggingconnection.py libcloud/utils/misc.py libcloud/utils/networking.py libcloud/utils/publickey.py libcloud/utils/py3.py libcloud/utils/xml.py scripts/check_file_names.shapache-libcloud-2.8.0/apache_libcloud.egg-info/dependency_links.txt0000664000175000017500000000000113600223624025257 0ustar kamikami00000000000000 apache-libcloud-2.8.0/apache_libcloud.egg-info/not-zip-safe0000664000175000017500000000000113600223624023437 0ustar kamikami00000000000000 apache-libcloud-2.8.0/apache_libcloud.egg-info/requires.txt0000664000175000017500000000016513600223624023613 0ustar kamikami00000000000000requests>=2.5.0 [:python_version < "2.7.9"] backports.ssl_match_hostname [:python_version < "3.4.0"] typing enum34 apache-libcloud-2.8.0/apache_libcloud.egg-info/top_level.txt0000664000175000017500000000001113600223624023733 0ustar kamikami00000000000000libcloud apache-libcloud-2.8.0/demos/0000775000175000017500000000000013600223624015530 5ustar kamikami00000000000000apache-libcloud-2.8.0/demos/__init__.py0000664000175000017500000000000013535474530017642 0ustar kamikami00000000000000apache-libcloud-2.8.0/demos/compute_demo.py0000664000175000017500000000701113570310635020566 0ustar kamikami00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This example provides both a running script (invoke from command line) # and an importable module one can play with in Interactive Mode. # # See docstrings for usage examples. # try: import secrets except ImportError: secrets = None import os.path import sys # Add parent dir of this file's dir to sys.path (OS-agnostically) sys.path.append(os.path.normpath(os.path.join(os.path.dirname(__file__), os.path.pardir))) from libcloud.common.types import InvalidCredsError from libcloud.compute.types import Provider from libcloud.compute.providers import get_driver from pprint import pprint def get_demo_driver(provider_name='RACKSPACE', *args, **kwargs): """An easy way to play with a driver interactively. # Load credentials from secrets.py: >>> from compute_demo import get_demo_driver >>> driver = get_demo_driver('RACKSPACE') # Or, provide credentials: >>> from compute_demo import get_demo_driver >>> driver = get_demo_driver('RACKSPACE', 'username', 'api_key') # Note that these parameters vary by driver ^^^ # Do things like the demo: >>> driver.load_nodes() >>> images = driver.load_images() >>> sizes = driver.load_sizes() # And maybe do more than that: >>> node = driver.create_node( ... name='my_first_node', ... image=images[0], ... size=sizes[0], ... ) >>> node.destroy() """ provider_name = provider_name.upper() DriverClass = get_driver(getattr(Provider, provider_name)) if not args: args = getattr(secrets, provider_name + '_PARAMS', ()) if not kwargs: kwargs = getattr(secrets, provider_name + '_KEYWORD_PARAMS', {}) try: return DriverClass(*args, **kwargs) except InvalidCredsError: raise InvalidCredsError( 'valid values should be put in secrets.py') def main(argv): """Main Compute Demo When invoked from the command line, it will connect using secrets.py (see secrets.py-dist for instructions and examples), and perform the following tasks: - List current nodes - List available images (up to 10) - List available sizes (up to 10) """ try: driver = get_demo_driver() except InvalidCredsError as e: print("Invalid Credentials: " + e.value) return 1 try: print(">> Loading nodes...") pprint(driver.list_nodes()) print(">> Loading images... (showing up to 10)") pprint(driver.list_images()[:10]) print(">> Loading sizes... (showing up to 10)") pprint(driver.list_sizes()[:10]) except Exception as e: print("A fatal error occurred: " + e) return 1 if __name__ == '__main__': sys.exit(main(sys.argv)) apache-libcloud-2.8.0/demos/example_aliyun_ecs.py0000664000175000017500000000530313535474530021764 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.compute.types import Provider from libcloud.compute.providers import get_driver from libcloud.compute.base import NodeAuthPassword ECSDriver = get_driver(Provider.ALIYUN_ECS) region = 'cn-hangzhou' your_access_key_id = '' your_access_key_secret = '' ecs = ECSDriver(your_access_key_id, your_access_key_secret, region=region) sizes = ecs.list_sizes() small = sizes[1] locations = ecs.list_locations() location = None for each in locations: if each.id == region: location = each break if location is None: print('could not find cn-qingdao location') sys.exit(-1) print(location.name) images = ecs.list_images() print('Found %d images' % len(images)) for each in images: if 'ubuntu' in each.id.lower(): image = each break else: image = images[0] print('Use image %s' % image) sgs = ecs.ex_list_security_groups() print('Found %d security groups' % len(sgs)) if len(sgs) == 0: sg = ecs.ex_create_security_group(description='test') print('Create security group %s' % sg) else: sg = sgs[0].id print('Use security group %s' % sg) nodes = ecs.list_nodes() print('Found %d nodes' % len(nodes)) if len(nodes) == 0: print('Starting create a new node') data_disk = { 'size': 5, 'category': ecs.disk_categories.CLOUD, 'disk_name': 'data_disk1', 'delete_with_instance': True} auth = NodeAuthPassword('P@$$w0rd') ex_internet_charge_type = ecs.internet_charge_types.BY_TRAFFIC node = ecs.create_node(image=image, size=small, name='test', ex_security_group_id=sg, ex_internet_charge_type=ex_internet_charge_type, ex_internet_max_bandwidth_out=1, ex_data_disk=data_disk, auth=auth) print('Created node %s' % node) nodes = ecs.list_nodes() for each in nodes: print('Found node %s' % each) apache-libcloud-2.8.0/demos/example_aliyun_oss.py0000664000175000017500000000523213535474530022017 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.storage.types import Provider from libcloud.storage.providers import get_driver OSSDriver = get_driver(Provider.ALIYUN_OSS) your_access_key_id = '' your_access_key_secret = '' oss = OSSDriver(your_access_key_id, your_access_key_secret) container_name = 'CONTAINER_NAME_FOR_TEST' object_name = 'OBJECT_NAME_FOR_TEST' local_file_path = 'LOCAL_FILE_FULL_PATH_TO_UPLOAD' upload_object_name = 'OBJECT_NAME_FOR_UPLOAD_FILE' for container in oss.iterate_containers(): print('container: %s' % container) c1 = oss.get_container(container_name) print('Got container %s:' % c1) objects = c1.list_objects() count = len(objects) print('Has %d objects' % count) objects = oss.list_container_objects(c1, ex_prefix='en') print('Has %d objects with prefix "en"' % len(objects)) for each in objects: print(each) obj = oss.get_object(container_name, object_name) print('Got object %s:' % obj) # Download object oss.download_object(obj, object_name, overwrite_existing=True) for trunk in oss.download_object_as_stream(obj): print(trunk) # Upload object obj = oss.upload_object(local_file_path, c1, upload_object_name) # Upload multipart uploads = list(oss.ex_iterate_multipart_uploads(c1)) print('Found %d incompleted uploads' % len(uploads)) if len(uploads) > 0: oss.ex_abort_all_multipart_uploads(c1) print('Abort them all') def data_iter(limit): i = 0 while True: yield i i += 1 if i >= limit: break print('Starting to upload 1MB using multipart api') one_mb = 1024 * 1024 obj = oss.upload_object_via_stream(data_iter(one_mb), c1, upload_object_name) print('Finish uploading') # Delete objects print('Delete object %s' % obj) oss.delete_object(obj) # Create container # c2 = oss.create_container(container_name='20160117') # c2 = oss.create_container(container_name='20160117', # ex_location='oss-cn-beijing') # c2_got = oss.get_container('20160117') apache-libcloud-2.8.0/demos/example_aliyun_slb.py0000664000175000017500000000434613535474530022000 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.types import Provider as NodeProvider from libcloud.compute.providers import get_driver as get_node_driver from libcloud.loadbalancer.providers import get_driver from libcloud.loadbalancer.base import Algorithm, Member from libcloud.loadbalancer.types import Provider SLBDriver = get_driver(Provider.ALIYUN_SLB) ECSDriver = get_node_driver(NodeProvider.ALIYUN_ECS) region = 'cn-hangzhou' your_access_key_id = '' your_access_key_secret = '' slb = SLBDriver(your_access_key_id, your_access_key_secret, region=region) ecs = ECSDriver(your_access_key_id, your_access_key_secret, region=region) protos = slb.list_protocols() print('Found %d protocols: %s' % (len(protos), protos)) balancers = slb.list_balancers() print('Found %d load balancers' % len(balancers)) print(balancers) if len(balancers) > 0: b1 = balancers[0] print('Delete %s' % b1) slb.destroy_balancer(b1) else: extra = {'AddressType': 'internet', 'Bandwidth': 1, 'StickySession': 'off', 'HealthCheck': 'off'} nodes = ecs.list_nodes() print('Found %d nodes' % len(nodes)) members = [Member(node.id, node.public_ips[0], 80, extra={'Weight': 50 * (i + 1)}) for i, node in enumerate(nodes)] new_b = slb.create_balancer('test-balancer', 80, 'http', Algorithm.WEIGHTED_ROUND_ROBIN, members, **extra) print('Created balancer %s' % new_b) apache-libcloud-2.8.0/demos/example_openstack.py0000664000175000017500000000233513570310635021614 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from pprint import pprint from libcloud.compute.providers import get_driver from libcloud.compute.types import Provider Openstack = get_driver(Provider.OPENSTACK) con = Openstack( 'admin', 'password', ex_force_auth_url='http://23.12.198.36/identity/v3/auth/tokens', ex_force_base_url='http://23.12.198.36:8774/v2.1', api_version='2.0', ex_tenant_name='demo') pprint(con.list_locations()) pprint(con.list_images()) pprint(con.list_nodes()) apache-libcloud-2.8.0/demos/gce_demo.py0000775000175000017500000011041213600144066017650 0ustar kamikami00000000000000#!/usr/bin/env python # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This example performs several tasks on Google Compute Platform. It can be # run directly or can be imported into an interactive python session. This # can also serve as live integration tests. # # To run directly, use python 2.7 or greater: # - $ python gce_demo.py --help # to see the help screen # - $ python gce_demo.py # to run all demos / tests # # To run interactively: # - Make sure you have valid values in secrets.py # (For more information about setting up your credentials, see the # libcloud/common/google.py docstring) # - Run 'python' in this directory, then: # import gce_demo # gce = gce_demo.get_gce_driver() # gce.list_nodes() # etc. # - Or, to run the full demo from the interactive python shell: # import gce_demo # gce_demo.CLEANUP = False # optional # gce_demo.MAX_NODES = 4 # optional # gce_demo.DATACENTER = 'us-central1-a' # optional # gce_demo.main_compute() # 'compute' only demo # gce_demo.main_load_balancer() # 'load_balancer' only demo # gce_demo.main_dns() # 'dns only demo # gce_demo.main() # all demos / tests import os.path import sys import datetime import time try: import argparse except Exception: print('This script uses the python "argparse" module. Please use Python ' '2.7 or greater.') raise try: import secrets except ImportError: print('"demos/secrets.py" not found.\n\n' 'Please copy secrets.py-dist to secrets.py and update the GCE* ' 'values with appropriate authentication information.\n' 'Additional information about setting these values can be found ' 'in the docstring for:\n' 'libcloud/common/google.py\n') sys.exit(1) # Add parent dir of this file's dir to sys.path (OS-agnostically) sys.path.append( os.path.normpath(os.path.join(os.path.dirname(__file__), os.path.pardir))) from libcloud.compute.types import Provider from libcloud.compute.providers import get_driver from libcloud.common.google import ResourceNotFoundError from libcloud.loadbalancer.types import Provider as Provider_lb from libcloud.loadbalancer.providers import get_driver as get_driver_lb from libcloud.dns.types import Provider as Provider_dns from libcloud.dns.providers import get_driver as get_driver_dns from libcloud.dns.base import Record, Zone from libcloud.utils.py3 import PY3 if PY3: # pylint: disable=no-name-in-module,import-error import urllib.request as url_req else: import urllib2 as url_req # Maximum number of 1-CPU nodes to allow to run simultaneously MAX_NODES = 5 # String that all resource names created by the demo will start with # WARNING: Any resource that has a matching name will be destroyed. DEMO_BASE_NAME = 'lct' # Datacenter to create resources in DATACENTER = 'us-central1-f' BACKUP_DATACENTER = 'us-east1-c' # Clean up resources at the end (can be set to false in order to # inspect resources at the end of the run). Resources will be cleaned # at the beginning regardless. CLEANUP = True args = getattr(secrets, 'GCE_PARAMS', ()) kwargs = getattr(secrets, 'GCE_KEYWORD_PARAMS', {}) # Add datacenter to kwargs for Python 2.5 compatibility kwargs = kwargs.copy() kwargs['datacenter'] = DATACENTER # ==== HELPER FUNCTIONS ==== def get_gce_driver(): driver = get_driver(Provider.GCE)(*args, **kwargs) return driver def get_gcelb_driver(gce_driver=None): # The GCE Load Balancer driver uses the GCE Compute driver for all of its # API calls. You can either provide the driver directly, or provide the # same authentication information so the LB driver can get its own # Compute driver. if gce_driver: driver = get_driver_lb(Provider_lb.GCE)(gce_driver=gce_driver) else: driver = get_driver_lb(Provider_lb.GCE)(*args, **kwargs) return driver def get_dns_driver(gce_driver=None): # The Google DNS driver uses the GCE Compute driver for all of its # API calls. You can either provide the driver directly, or provide the # same authentication information so the LB driver can get its own # Compute driver. if gce_driver: driver = get_driver_dns(Provider_dns.GOOGLE)(gce_driver=gce_driver) else: driver = get_driver_dns(Provider_dns.GOOGLE)(*args, **kwargs) return driver def create_mig(gce, mig_base_name, zone, template, postfix, num_instances=2): """ Creates MIG, sets named ports, modifies various text with 'postfix'. :param gce: An initalized GCE driver. :type gce: :class`GCENodeDriver` :param zone: Zone to create Managed Instance Group in. :type zone: :class:`GCEZone` or ``str`` :param template: Instance Template to use in creating MIG. :type template: :class:`GCEInstanceTemplate` :param postfix: string to append to mig name, etc. Example: 'east', 'central' :type postfix: ``str`` :param num_instances: number of instances to create in MIG. Default is 2. :type num_instances: ``int`` :returns: initialized Managed Instance Group. :rtype: :class:`GCEInstanceGroupManager` """ mig_name = '%s-%s' % (mig_base_name, postfix) mig = gce.ex_create_instancegroupmanager( mig_name, zone, template, num_instances, base_instance_name=mig_name, description='Demo for %s' % postfix) display(' Managed Instance Group [%s] "%s" created' % (postfix.upper(), mig.name)) display(' ... MIG instances created: %s' % ','.join([x['name'] for x in mig.list_managed_instances()])) # set the named_ports on the Instance Group. named_ports = [{'name': '%s-http' % DEMO_BASE_NAME, 'port': 80}] mig.set_named_ports(named_ports=named_ports) display(' ... MIG ports set: %s' % named_ports) return mig def display(title, resource_list=[]): """ Display a list of resources. :param title: String to be printed at the heading of the list. :type title: ``str`` :param resource_list: List of resources to display :type resource_list: Any ``object`` with a C{name} attribute """ print('=> %s' % title) for item in resource_list: if isinstance(item, Record): if item.name.startswith(DEMO_BASE_NAME): print('=> name=%s, type=%s' % (item.name, item.type)) else: print(' name=%s, type=%s' % (item.name, item.type)) elif isinstance(item, Zone): if item.domain.startswith(DEMO_BASE_NAME): print('=> name=%s, dnsname=%s' % (item.id, item.domain)) else: print(' name=%s, dnsname=%s' % (item.id, item.domain)) elif hasattr(item, 'name'): if item.name.startswith(DEMO_BASE_NAME): print('=> %s' % item.name) else: print(' %s' % item.name) else: if item.startswith(DEMO_BASE_NAME): print('=> %s' % item) else: print(' %s' % item) def cleanup_only(): start_time = datetime.datetime.now() display('Clean-up start time: %s' % str(start_time)) gce = get_gce_driver() # Get project info and print name project = gce.ex_get_project() display('Project: %s' % project.name) # == Get Lists of Everything and Display the lists (up to 10) == # These can either just return values for the current datacenter (zone) # or for everything. all_nodes = gce.list_nodes(ex_zone='all') display('Nodes:', all_nodes) all_addresses = gce.ex_list_addresses(region='all') display('Addresses:', all_addresses) all_volumes = gce.list_volumes(ex_zone='all') display('Volumes:', all_volumes) # This can return everything, but there is a large amount of overlap, # so we'll just get the sizes from the current zone. sizes = gce.list_sizes() display('Sizes:', sizes) # These are global firewalls = gce.ex_list_firewalls() display('Firewalls:', firewalls) networks = gce.ex_list_networks() display('Networks:', networks) images = gce.list_images() display('Images:', images) locations = gce.list_locations() display('Locations:', locations) zones = gce.ex_list_zones() display('Zones:', zones) snapshots = gce.ex_list_snapshots() display('Snapshots:', snapshots) gfrs = gce.ex_list_forwarding_rules(global_rules=True) display("Global Forwarding Rules", gfrs) targetproxies = gce.ex_list_targethttpproxies() display("Target HTTP Proxies", targetproxies) urlmaps = gce.ex_list_urlmaps() display("URLMaps", urlmaps) bes = gce.ex_list_backendservices() display("Backend Services", bes) migs = gce.ex_list_instancegroupmanagers(zone='all') display("Instance Group Managers", migs) its = gce.ex_list_instancetemplates() display("Instance Templates", its) hcs = gce.ex_list_healthchecks() display("Health Checks", hcs) # == Clean up any old demo resources == display('Cleaning up any "%s" resources' % DEMO_BASE_NAME) clean_up(gce, DEMO_BASE_NAME, None, gfrs + targetproxies + urlmaps + bes + hcs + migs + its) # == Pause to let cleanup occur and repopulate volume and node lists == if len(migs): time.sleep(10) all_volumes = gce.list_volumes(ex_zone='all') all_nodes = gce.list_nodes(ex_zone='all') clean_up(gce, DEMO_BASE_NAME, all_nodes, all_addresses + all_volumes + firewalls + networks + snapshots) volumes = gce.list_volumes() clean_up(gce, DEMO_BASE_NAME, None, volumes) end_time = datetime.datetime.now() display('Total runtime: %s' % str(end_time - start_time)) def clean_up(gce, base_name, node_list=None, resource_list=None): """ Destroy all resources that have a name beginning with 'base_name'. :param base_name: String with the first part of the name of resources to destroy :type base_name: ``str`` :keyword node_list: List of nodes to consider for deletion :type node_list: ``list`` of :class:`Node` :keyword resource_list: List of resources to consider for deletion :type resource_list: ``list`` of I{Resource Objects} """ if node_list is None: node_list = [] if resource_list is None: resource_list = [] # Use ex_destroy_multiple_nodes to destroy nodes del_nodes = [] for node in node_list: if node.name.startswith(base_name): del_nodes.append(node) result = gce.ex_destroy_multiple_nodes(del_nodes) for i, success in enumerate(result): if success: display(' Deleted %s' % del_nodes[i].name) else: display(' Failed to delete %s' % del_nodes[i].name) # Destroy everything else with just the destroy method for resrc in resource_list: if resrc.name.startswith(base_name): try: resrc.destroy() class_name = resrc.__class__.__name__ display(' Deleted %s (%s)' % (resrc.name, class_name)) except ResourceNotFoundError: display(' Not found: %s (%s)' % (resrc.name, resrc.__class__.__name__)) except Exception: class_name = resrc.__class__.__name__ display(' Failed to Delete %s (%s)' % (resrc.name, class_name)) raise def main_compute(): start_time = datetime.datetime.now() display('Compute demo/test start time: %s' % str(start_time)) gce = get_gce_driver() # Get project info and print name project = gce.ex_get_project() display('Project: %s' % project.name) # == Get Lists of Everything and Display the lists (up to 10) == # These can either just return values for the current datacenter (zone) # or for everything. all_nodes = gce.list_nodes(ex_zone='all') display('Nodes:', all_nodes) all_addresses = gce.ex_list_addresses(region='all') display('Addresses:', all_addresses) all_volumes = gce.list_volumes(ex_zone='all') display('Volumes:', all_volumes) # This can return everything, but there is a large amount of overlap, # so we'll just get the sizes from the current zone. sizes = gce.list_sizes() display('Sizes:', sizes) # These are global firewalls = gce.ex_list_firewalls() display('Firewalls:', firewalls) subnetworks = gce.ex_list_subnetworks() display('Subnetworks:', subnetworks) networks = gce.ex_list_networks() display('Networks:', networks) images = gce.list_images() display('Images:', images) locations = gce.list_locations() display('Locations:', locations) zones = gce.ex_list_zones() display('Zones:', zones) snapshots = gce.ex_list_snapshots() display('Snapshots:', snapshots) # == Clean up any old demo resources == display('Cleaning up any "%s" resources' % DEMO_BASE_NAME) # Delete subnetworks first, networks last clean_up(gce, DEMO_BASE_NAME, None, subnetworks) clean_up(gce, DEMO_BASE_NAME, all_nodes, all_addresses + all_volumes + firewalls + snapshots + networks) # == Create a Legacy Network == display('Creating Legacy Network:') name = '%s-legacy-network' % DEMO_BASE_NAME cidr = '10.10.0.0/16' network_legacy = gce.ex_create_network(name, cidr) display(' Network %s created' % name) # == Delete the Legacy Network == display('Delete Legacy Network:') network_legacy.destroy() display(' Network %s delete' % name) # == Create an auto network == display('Creating Auto Network:') name = '%s-auto-network' % DEMO_BASE_NAME network_auto = gce.ex_create_network(name, cidr=None, mode='auto') display(' AutoNetwork %s created' % network_auto.name) # == Display subnetworks from the auto network == subnets = [] for sn in network_auto.subnetworks: subnets.append(gce.ex_get_subnetwork(sn)) display('Display subnetworks:', subnets) # == Delete the auto network == display('Delete Auto Network:') network_auto.destroy() display(' AutoNetwork %s deleted' % name) # == Create an custom network == display('Creating Custom Network:') name = '%s-custom-network' % DEMO_BASE_NAME network_custom = gce.ex_create_network(name, cidr=None, mode='custom') display(' Custom Network %s created' % network_custom.name) # == Create a subnetwork == display('Creating Subnetwork:') sname = '%s-subnetwork' % DEMO_BASE_NAME region = 'us-central1' cidr = '192.168.17.0/24' subnet = gce.ex_create_subnetwork(sname, cidr, network_custom, region) display(' Subnetwork %s created' % subnet.name) # Refresh object, now that it has a subnet network_custom = gce.ex_get_network(name) # == Display subnetworks from the auto network == subnets = [] for sn in network_custom.subnetworks: subnets.append(gce.ex_get_subnetwork(sn)) display('Display custom subnetworks:', subnets) # == Launch instance in custom subnetwork == display('Creating Node in custom subnetwork:') name = '%s-subnet-node' % DEMO_BASE_NAME node_1 = gce.create_node(name, 'g1-small', 'debian-8', ex_disk_auto_delete=True, ex_network=network_custom, ex_subnetwork=subnet) display(' Node %s created' % name) # == Destroy instance in custom subnetwork == display('Destroying Node in custom subnetwork:') node_1.destroy() display(' Node %s destroyed' % name) # == Delete an subnetwork == display('Delete Custom Subnetwork:') subnet.destroy() display(' Custom Subnetwork %s deleted' % sname) is_deleted = False while not is_deleted: time.sleep(3) try: subnet = gce.ex_get_subnetwork(sname, region) except ResourceNotFoundError: is_deleted = True # == Delete the auto network == display('Delete Custom Network:') network_custom.destroy() display(' Custom Network %s deleted' % name) # == Create Node with disk auto-created == if MAX_NODES > 1: display('Creating a node with boot/local-ssd using GCE structure:') name = '%s-gstruct' % DEMO_BASE_NAME img_url = "projects/debian-cloud/global/images/" img_url += "backports-debian-7-wheezy-v20141205" disk_type_url = "projects/%s/zones/us-central1-f/" % project.name disk_type_url += "diskTypes/local-ssd" gce_disk_struct = [ { "type": "PERSISTENT", "deviceName": '%s-gstruct' % DEMO_BASE_NAME, "initializeParams": { "diskName": '%s-gstruct' % DEMO_BASE_NAME, "sourceImage": img_url }, "boot": True, "autoDelete": True }, { "type": "SCRATCH", "deviceName": '%s-gstruct-lssd' % DEMO_BASE_NAME, "initializeParams": { "diskType": disk_type_url }, "autoDelete": True } ] node_gstruct = gce.create_node(name, 'n1-standard-1', None, 'us-central1-f', ex_disks_gce_struct=gce_disk_struct) num_disks = len(node_gstruct.extra['disks']) display(' Node %s created with %d disks' % (node_gstruct.name, num_disks)) display('Creating Node with auto-created SSD:') name = '%s-np-node' % DEMO_BASE_NAME node_1 = gce.create_node(name, 'n1-standard-1', 'debian-7', ex_tags=['libcloud'], ex_disk_type='pd-ssd', ex_disk_auto_delete=False) display(' Node %s created' % name) # Stop the node and change to a custom machine type (e.g. size) display('Stopping node, setting custom size, starting node:') name = '%s-np-node' % DEMO_BASE_NAME gce.ex_stop_node(node_1) gce.ex_set_machine_type(node_1, 'custom-2-4096') # 2 vCPU, 4GB RAM gce.ex_start_node(node_1) node_1 = gce.ex_get_node(name) display(' %s: state=%s, size=%s' % (name, node_1.extra['status'], node_1.size)) # == Create, and attach a disk == display('Creating a new disk:') disk_name = '%s-attach-disk' % DEMO_BASE_NAME volume = gce.create_volume(10, disk_name) if gce.attach_volume(node_1, volume, ex_auto_delete=True): display(' Attached %s to %s' % (volume.name, node_1.name)) display(' Disabled auto-delete for %s on %s' % (volume.name, node_1.name)) gce.ex_set_volume_auto_delete(volume, node_1, auto_delete=False) if CLEANUP: # == Detach the disk == if gce.detach_volume(volume, ex_node=node_1): display(' Detached %s from %s' % (volume.name, node_1.name)) # == Create Snapshot == display('Creating a snapshot from existing disk:') # Create a disk to snapshot vol_name = '%s-snap-template' % DEMO_BASE_NAME image = gce.ex_get_image('debian-7') vol = gce.create_volume(None, vol_name, image=image) display('Created disk %s to shapshot:' % DEMO_BASE_NAME) # Snapshot volume snapshot = vol.snapshot('%s-snapshot' % DEMO_BASE_NAME) display(' Snapshot %s created' % snapshot.name) # == Create Node with existing disk == display('Creating Node with existing disk:') name = '%s-persist-node' % DEMO_BASE_NAME # Use objects this time instead of names # Get latest Debian 7 image image = gce.ex_get_image('debian-7') # Get Machine Size size = gce.ex_get_size('n1-standard-1') # Create Disk from Snapshot created above volume_name = '%s-boot-disk' % DEMO_BASE_NAME volume = gce.create_volume(None, volume_name, snapshot=snapshot) display(' Created %s from snapshot' % volume.name) # Create Node with Disk node_2 = gce.create_node(name, size, image, ex_tags=['libcloud'], ex_boot_disk=volume, ex_disk_auto_delete=False) display(' Node %s created with attached disk %s' % (node_2.name, volume.name)) # == Update Tags for Node == display('Updating Tags for %s:' % node_2.name) tags = node_2.extra['tags'] tags.append('newtag') if gce.ex_set_node_tags(node_2, tags): display(' Tags updated for %s' % node_2.name) check_node = gce.ex_get_node(node_2.name) display(' New tags: %s' % check_node.extra['tags']) # == Setting Metadata for Node == display('Setting Metadata for %s:' % node_2.name) if gce.ex_set_node_metadata(node_2, {'foo': 'bar', 'baz': 'foobarbaz'}): display(' Metadata updated for %s' % node_2.name) check_node = gce.ex_get_node(node_2.name) display(' New Metadata: %s' % check_node.extra['metadata']) # == Create Multiple nodes at once == base_name = '%s-multiple-nodes' % DEMO_BASE_NAME number = MAX_NODES - 2 if number > 0: display('Creating Multiple Nodes (%s):' % number) multi_nodes = gce.ex_create_multiple_nodes( base_name, size, image, number, ex_tags=['libcloud'], ex_disk_auto_delete=True) for node in multi_nodes: display(' Node %s created' % node.name) # == Create a Network == display('Creating Network:') name = '%s-network' % DEMO_BASE_NAME cidr = '10.10.0.0/16' network_1 = gce.ex_create_network(name, cidr) display(' Network %s created' % network_1.name) # == Create a Firewall == display('Creating a Firewall:') name = '%s-firewall' % DEMO_BASE_NAME allowed = [{'IPProtocol': 'tcp', 'ports': ['3141']}] firewall_1 = gce.ex_create_firewall(name, allowed, network=network_1, source_tags=['libcloud']) display(' Firewall %s created' % firewall_1.name) # == Create a Static Address == display('Creating an Address:') name = '%s-address' % DEMO_BASE_NAME address_1 = gce.ex_create_address(name) display(' Address %s created with IP %s' % (address_1.name, address_1.address)) # == List Updated Resources in current zone/region == display('Updated Resources in current zone/region') nodes = gce.list_nodes() display('Nodes:', nodes) addresses = gce.ex_list_addresses() display('Addresses:', addresses) firewalls = gce.ex_list_firewalls() display('Firewalls:', firewalls) subnetworks = gce.ex_list_subnetworks() display('Subnetworks:', subnetworks) networks = gce.ex_list_networks() display('Networks:', networks) snapshots = gce.ex_list_snapshots() display('Snapshots:', snapshots) if CLEANUP: display('Cleaning up %s resources created' % DEMO_BASE_NAME) clean_up(gce, DEMO_BASE_NAME, None, subnetworks) clean_up(gce, DEMO_BASE_NAME, nodes, addresses + firewalls + snapshots + networks) volumes = gce.list_volumes() clean_up(gce, DEMO_BASE_NAME, None, volumes) end_time = datetime.datetime.now() display('Total runtime: %s' % str(end_time - start_time)) # ==== LOAD BALANCER CODE STARTS HERE ==== def main_load_balancer(): start_time = datetime.datetime.now() display('Load-balancer demo/test start time: %s' % str(start_time)) gce = get_gce_driver() gcelb = get_gcelb_driver(gce) # Get project info and print name project = gce.ex_get_project() display('Project: %s' % project.name) # Existing Balancers balancers = gcelb.list_balancers() display('Load Balancers', balancers) # Protocols protocols = gcelb.list_protocols() display('Protocols', protocols) # Healthchecks healthchecks = gcelb.ex_list_healthchecks() display('Health Checks', healthchecks) # This demo is based on the GCE Load Balancing Quickstart described here: # https://developers.google.com/compute/docs/load-balancing/lb-quickstart # == Clean-up and existing demo resources == all_nodes = gce.list_nodes(ex_zone='all') firewalls = gce.ex_list_firewalls() display('Cleaning up any "%s" resources' % DEMO_BASE_NAME) clean_up(gce, DEMO_BASE_NAME, all_nodes, balancers + healthchecks + firewalls) # == Create 3 nodes to balance between == startup_script = ('apt-get -y update && ' 'apt-get -y install apache2 && ' 'hostname > /var/www/index.html') tag = '%s-www' % DEMO_BASE_NAME base_name = '%s-www' % DEMO_BASE_NAME image = gce.ex_get_image('debian-7') size = gce.ex_get_size('n1-standard-1') number = 3 display('Creating %d nodes' % number) metadata = {'items': [{'key': 'startup-script', 'value': startup_script}]} lb_nodes = gce.ex_create_multiple_nodes( base_name, size, image, number, ex_tags=[tag], ex_metadata=metadata, ex_disk_auto_delete=True, ignore_errors=False) display('Created Nodes', lb_nodes) # == Create a Firewall for instances == display('Creating a Firewall') name = '%s-firewall' % DEMO_BASE_NAME allowed = [{'IPProtocol': 'tcp', 'ports': ['80']}] firewall = gce.ex_create_firewall(name, allowed, target_tags=[tag]) display(' Firewall %s created' % firewall.name) # == Create a Health Check == display('Creating a HealthCheck') name = '%s-healthcheck' % DEMO_BASE_NAME # These are all the default values, but listed here as an example. To # create a healthcheck with the defaults, only name is required. hc = gcelb.ex_create_healthcheck( name, host=None, path='/', port='80', interval=5, timeout=5, unhealthy_threshold=2, healthy_threshold=2) display('Healthcheck %s created' % hc.name) # == Create Load Balancer == display('Creating Load Balancer') name = '%s-lb' % DEMO_BASE_NAME port = 80 protocol = 'tcp' algorithm = None members = lb_nodes[:2] # Only attach the first two initially healthchecks = [hc] balancer = gcelb.create_balancer(name, port, protocol, algorithm, members, ex_healthchecks=healthchecks) display(' Load Balancer %s created' % balancer.name) # == Attach third Node == display('Attaching additional node to Load Balancer') member = balancer.attach_compute_node(lb_nodes[2]) display(' Attached %s to %s' % (member.id, balancer.name)) # == Show Balancer Members == members = balancer.list_members() display('Load Balancer Members') for member in members: display(' ID: %s IP: %s' % (member.id, member.ip)) # == Remove a Member == display('Removing a Member') detached = members[0] detach = balancer.detach_member(detached) if detach: display(' Member %s detached from %s' % (detached.id, balancer.name)) # == Show Updated Balancer Members == members = balancer.list_members() display('Updated Load Balancer Members') for member in members: display(' ID: %s IP: %s' % (member.id, member.ip)) # == Reattach Member == display('Reattaching Member') member = balancer.attach_member(detached) display(' Member %s attached to %s' % (member.id, balancer.name)) # == Test Load Balancer by connecting to it multiple times == PAUSE = 60 display('Sleeping for %d seconds for LB members to serve...' % PAUSE) time.sleep(PAUSE) rounds = 200 url = 'http://%s/' % balancer.ip line_length = 75 display('Connecting to %s %s times' % (url, rounds)) for x in range(rounds): response = url_req.urlopen(url) if PY3: output = str(response.read(), encoding='utf-8').strip() else: output = response.read().strip() if 'www-001' in output: padded_output = output.center(line_length) elif 'www-002' in output: padded_output = output.rjust(line_length) else: padded_output = output.ljust(line_length) sys.stdout.write('\r%s' % padded_output) sys.stdout.flush() time.sleep(.25) print('') if CLEANUP: balancers = gcelb.list_balancers() healthchecks = gcelb.ex_list_healthchecks() nodes = gce.list_nodes(ex_zone='all') firewalls = gce.ex_list_firewalls() display('Cleaning up %s resources created' % DEMO_BASE_NAME) clean_up(gce, DEMO_BASE_NAME, nodes, balancers + healthchecks + firewalls) end_time = datetime.datetime.now() display('Total runtime: %s' % str(end_time - start_time)) # ==== BACKEND SERVICE LOAD BALANCER CODE STARTS HERE ==== def main_backend_service(): start_time = datetime.datetime.now() display('Backend Service w/Global Forwarding Rule demo/test start time: %s' % str(start_time)) gce = get_gce_driver() # Get project info and print name project = gce.ex_get_project() display('Project: %s' % project.name) # Based on the instructions at: # https://cloud.google.com/compute/docs/load-balancing/http/#overview zone_central = DATACENTER zone_east = BACKUP_DATACENTER it_name = '%s-instancetemplate' % DEMO_BASE_NAME mig_name = '%s-mig' % DEMO_BASE_NAME hc_name = '%s-healthcheck' % DEMO_BASE_NAME bes_name = '%s-bes' % DEMO_BASE_NAME urlmap_name = '%s-urlmap' % DEMO_BASE_NAME targethttpproxy_name = '%s-httptargetproxy' % DEMO_BASE_NAME address_name = '%s-address' % DEMO_BASE_NAME gfr_name = '%s-gfr' % DEMO_BASE_NAME firewall_name = '%s-firewall' % DEMO_BASE_NAME startup_script = ('apt-get -y update && ' 'apt-get -y install apache2 && ' 'echo "$(hostname)" > /var/www/html/index.html') tag = '%s-mig-www' % DEMO_BASE_NAME metadata = {'items': [{'key': 'startup-script', 'value': startup_script}]} mig_central = None mig_east = None bes = None urlmap = None tp = None address = None gfr = None firewall = None display('Create a BackendService') # == Create an Instance Template == it = gce.ex_create_instancetemplate(it_name, size='n1-standard-1', image='debian-8', network='default', metadata=metadata, tags=[tag]) display(' InstanceTemplate "%s" created' % it.name) # == Create a MIG == mig_central = create_mig(gce, mig_name, zone_central, it, 'central') mig_east = create_mig(gce, mig_name, zone_east, it, 'east') # == Create a Health Check == hc = gce.ex_create_healthcheck(hc_name, host=None, path='/', port='80', interval=30, timeout=10, unhealthy_threshold=10, healthy_threshold=1) display(' Healthcheck %s created' % hc.name) # == Create a Backend Service == be_central = gce.ex_create_backend( instance_group=mig_central.instance_group) be_east = gce.ex_create_backend(instance_group=mig_east.instance_group) bes = gce.ex_create_backendservice( bes_name, [hc], backends=[be_central, be_east], port_name='%s-http' % DEMO_BASE_NAME, protocol='HTTP', description='%s bes desc' % DEMO_BASE_NAME, timeout_sec=60, enable_cdn=False) display(' Backend Service "%s" created' % bes.name) # == Create a URLMap == urlmap = gce.ex_create_urlmap(urlmap_name, default_service=bes) display(' URLMap "%s" created' % urlmap.name) # == Create a Target (HTTP) Proxy == tp = gce.ex_create_targethttpproxy(targethttpproxy_name, urlmap) display(' TargetProxy "%s" created' % tp.name) # == Create a Static Address == address = gce.ex_create_address(address_name, region='global') display(' Address "%s" created with IP "%s"' % (address.name, address.address)) # == Create a Global Forwarding Rule == gfr = gce.ex_create_forwarding_rule( gfr_name, target=tp, address=address, port_range='80', description='%s libcloud forwarding rule http test' % DEMO_BASE_NAME, global_rule=True) display(' Global Forwarding Rule "%s" created' % (gfr.name)) # == Create a Firewall for instances == allowed = [{'IPProtocol': 'tcp', 'ports': ['80']}] firewall = gce.ex_create_firewall(firewall_name, allowed, target_tags=[tag]) display(' Firewall %s created' % firewall.name) # TODO(supertom): launch instances to demostrate that it works # take backends out of service. Adding in this functionality # will also add 10-15 minutes to the demo. # display("Sleeping for 10 minutes, starting at %s" % # str(datetime.datetime.now())) # time.sleep(600) if CLEANUP: display('Cleaning up %s resources created' % DEMO_BASE_NAME) clean_up(gce, DEMO_BASE_NAME, None, resource_list=[firewall, gfr, address, tp, urlmap, bes, hc, mig_central, mig_east, it]) end_time = datetime.datetime.now() display('Total runtime: %s' % str(end_time - start_time)) # ==== GOOGLE DNS CODE STARTS HERE ==== def main_dns(): start_time = datetime.datetime.now() display('DNS demo/test start time: %s' % str(start_time)) gce = get_gce_driver() gdns = get_dns_driver() # Get project info and print name project = gce.ex_get_project() display('Project: %s' % project.name) # Get list of managed zones zones = gdns.iterate_zones() display('Zones', zones) # Get list of records zones = gdns.iterate_zones() for z in zones: records = gdns.iterate_records(z) display('Records for managed zone "%s"' % z.id, records) # TODO(erjohnso): Finish this DNS section. Challenging in that you need to # own a domain, so testing will require user customization. Perhaps a new # command-line required flag unless --skip-dns is supplied. Also, real # e2e testing should try to do DNS lookups on new records, but DNS TTL # and propagation delays will introduce limits on what can be tested. end_time = datetime.datetime.now() display('Total runtime: %s' % str(end_time - start_time)) if __name__ == '__main__': parser = argparse.ArgumentParser( description='Google Cloud Platform Demo / Live Test Script') parser.add_argument("--compute", help="perform compute demo / live tests", dest="compute", action="store_true") parser.add_argument("--load-balancer", help="perform load-balancer demo / live tests", dest="lb", action="store_true") parser.add_argument("--backend-service", help="perform backend-service demo / live tests", dest="bes", action="store_true") parser.add_argument("--dns", help="perform DNS demo / live tests", dest="dns", action="store_true") parser.add_argument("--cleanup-only", help="perform clean-up (skips all tests)", dest="cleanup", action="store_true") cl_args = parser.parse_args() if cl_args.cleanup: cleanup_only() else: if cl_args.compute: main_compute() if cl_args.lb: main_load_balancer() if cl_args.dns: main_dns() if cl_args.bes: main_backend_service() apache-libcloud-2.8.0/demos/secrets.py-dist0000664000175000017500000000344613535474530020535 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Make a copy of this file named 'secrets.py' and add your credentials there. # Note you can run unit tests without setting your credentials. BLUEBOX_PARAMS = ('customer_id', 'api_key') BRIGHTBOX_PARAMS = ('client_id', 'client_secret') EC2_PARAMS = ('access_id', 'secret') ECP_PARAMS = ('user_name', 'password') GANDI_PARAMS = ('user',) # Service Account Authentication GCE_PARAMS = ('email@developer.gserviceaccount.com', 'key') # GCE_PARAMS = ('client_id', 'client_secret') # Installed App Authentication GCE_KEYWORD_PARAMS = {'project': 'project_name'} HOSTINGCOM_PARAMS = ('user', 'secret') IBM_PARAMS = ('user', 'secret') # OPENSTACK_PARAMS = ('user_name', 'api_key', secure_bool, 'host', port_int) OPENSTACK_PARAMS = ('user_name', 'api_key', False, 'host', 8774) OPENNEBULA_PARAMS = ('user', 'key') OPSOURCE_PARAMS = ('user', 'password') RACKSPACE_PARAMS = ('user', 'key') SLICEHOST_PARAMS = ('key',) SOFTLAYER_PARAMS = ('user', 'api_key') VCLOUD_PARAMS = ('user', 'secret') VOXEL_PARAMS = ('key', 'secret') VPSNET_PARAMS = ('user', 'key') apache-libcloud-2.8.0/example_compute.py0000664000175000017500000000353213576514553020205 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.types import Provider from libcloud.compute.providers import get_driver from libcloud.compute.drivers.ec2 import EC2NodeDriver from libcloud.compute.drivers.rackspace import RackspaceNodeDriver from typing import Type, cast ec2_cls = get_driver(Provider.EC2) rackspace_cls = get_driver(Provider.RACKSPACE) # NOTE: If you are using driver methods which are not part of the standard API, # you need to explicitly cast the driver class reference to the correct class # for type checking to work correctly EC2 = cast(Type[EC2NodeDriver], ec2_cls) Rackspace = cast(Type[RackspaceNodeDriver], rackspace_cls) drivers = [EC2('access key id', 'secret key', region='us-east-1'), Rackspace('username', 'api key', region='iad')] nodes = [] for driver in drivers: nodes.extend(driver.list_nodes()) print(nodes) # [ , # , ... ] # grab the node named "test" node = [n for n in nodes if n.name == 'test'][0] # reboot "test" node.reboot() apache-libcloud-2.8.0/example_dns.py0000664000175000017500000000204413535474530017305 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from pprint import pprint from libcloud.dns.types import Provider from libcloud.dns.providers import get_driver Zerigo = get_driver(Provider.ZERIGO) driver = Zerigo('email', 'key') zones = driver.list_zones() pprint(zones) records = zones[0].list_records() pprint(records) apache-libcloud-2.8.0/example_loadbalancer.py0000664000175000017500000000466313535474530021141 0ustar kamikami00000000000000#!/usr/bin/env python # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import time from libcloud.loadbalancer.base import Member, Algorithm from libcloud.loadbalancer.types import Provider, State from libcloud.loadbalancer.providers import get_driver def main(): cls = get_driver(Provider.RACKSPACE) driver = cls('username', 'api key', region='ord') balancers = driver.list_balancers() print(balancers) # creating a balancer which balances traffic across two # nodes: 192.168.86.1:80 and 192.168.86.2:8080. Balancer # itself listens on port 80/tcp new_balancer_name = 'testlb' + os.urandom(4).encode('hex') members = (Member(None, '192.168.86.1', 80), Member(None, '192.168.86.2', 8080)) new_balancer = driver.create_balancer(name=new_balancer_name, algorithm=Algorithm.ROUND_ROBIN, port=80, protocol='http', members=members) print(new_balancer) # wait for balancer to become ready # NOTE: in real life code add timeout to not end up in # endless loop when things go wrong on provider side while True: balancer = driver.get_balancer(balancer_id=new_balancer.id) if balancer.state == State.RUNNING: break print('sleeping for 30 seconds for balancers to become ready') time.sleep(30) # fetch list of members members = balancer.list_members() print(members) # remove first member balancer.detach_member(members[0]) # remove the balancer driver.destroy_balancer(new_balancer) if __name__ == '__main__': main() apache-libcloud-2.8.0/example_storage.py0000664000175000017500000000221513565233442020163 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from pprint import pprint from libcloud.storage.types import Provider from libcloud.storage.providers import get_driver CloudFiles = get_driver(Provider.CLOUDFILES) driver = CloudFiles('access key id', 'secret key', region='ord') containers = driver.list_containers() container_objects = driver.list_container_objects(containers[0]) pprint(containers) pprint(container_objects) apache-libcloud-2.8.0/libcloud/0000775000175000017500000000000013600223624016216 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/__init__.py0000664000175000017500000000704513600177265020346 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ libcloud provides a unified interface to the cloud computing resources. :var __version__: Current version of libcloud """ import logging import os import codecs import atexit from libcloud.base import DriverType # NOQA from libcloud.base import DriverTypeFactoryMap # NOQA from libcloud.base import get_driver # NOQA try: import paramiko # NOQA have_paramiko = True except ImportError: have_paramiko = False try: import requests # NOQA have_requests = True except ImportError: have_requests = False __all__ = [ '__version__', 'enable_debug' ] __version__ = '2.8.0' def enable_debug(fo): """ Enable library wide debugging to a file-like object. :param fo: Where to append debugging information :type fo: File like object, only write operations are used. """ from libcloud.common.base import Connection from libcloud.utils.loggingconnection import LoggingConnection LoggingConnection.log = fo Connection.conn_class = LoggingConnection # Ensure the file handle is closed on exit def close_file(fd): try: fd.close() except Exception: pass atexit.register(close_file, fo) def _init_once(): """ Utility function that is ran once on Library import. This checks for the LIBCLOUD_DEBUG environment variable, which if it exists is where we will log debug information about the provider transports. This also checks for known environment/dependency incompatibilities. """ path = os.getenv('LIBCLOUD_DEBUG') if path: mode = 'a' # Special case for /dev/stderr and /dev/stdout on Python 3. from libcloud.utils.py3 import PY3 # Opening those files in append mode will throw "illegal seek" # exception there. # Late import to avoid setup.py related side affects if path in ['/dev/stderr', '/dev/stdout'] and PY3: mode = 'w' fo = codecs.open(path, mode, encoding='utf8') enable_debug(fo) if have_paramiko and hasattr(paramiko.util, 'log_to_file'): paramiko.util.log_to_file(filename=path, level=logging.DEBUG) # check for broken `yum install python-requests` if have_requests and requests.__version__ == '2.6.0': chardet_version = requests.packages.chardet.__version__ required_chardet_version = '2.3.0' assert chardet_version == required_chardet_version, ( 'Known bad version of requests detected! This can happen when ' 'requests was installed from a source other than PyPI, e.g. via ' 'a package manager such as yum. Please either install requests ' 'from PyPI or run `pip install chardet==%s` to resolve this ' 'issue.' % required_chardet_version ) _init_once() apache-libcloud-2.8.0/libcloud/backup/0000775000175000017500000000000013600223624017463 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/backup/__init__.py0000664000175000017500000000000013535474530021575 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/backup/base.py0000664000175000017500000003675313535474530021000 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.base import ConnectionUserAndKey, BaseDriver from libcloud.backup.types import BackupTargetType __all__ = [ 'BackupTarget', 'BackupDriver', 'BackupTargetJob', 'BackupTargetRecoveryPoint' ] class BackupTarget(object): """ A backup target """ def __init__(self, id, name, address, type, driver, extra=None): """ :param id: Target id :type id: ``str`` :param name: Name of the target :type name: ``str`` :param address: Hostname, FQDN, IP, file path etc. :type address: ``str`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`.BackupTargetType` :param driver: BackupDriver instance. :type driver: :class:`.BackupDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.name = name self.address = address self.type = type self.driver = driver self.extra = extra or {} def update(self, name=None, address=None, extra=None): return self.driver.update_target(target=self, name=name, address=address, extra=extra) def delete(self): return self.driver.delete_target(target=self) def _get_numeric_id(self): target_id = self.id if target_id.isdigit(): target_id = int(target_id) return target_id def __repr__(self): return ('' % (self.id, self.name, self.address, self.type, self.driver.name)) class BackupTargetJob(object): """ A backup target job """ def __init__(self, id, status, progress, target, driver, extra=None): """ :param id: Job id :type id: ``str`` :param status: Status of the job :type status: :class:`BackupTargetJobStatusType` :param progress: Progress of the job, as a percentage :type progress: ``int`` :param target: BackupTarget instance. :type target: :class:`.BackupTarget` :param driver: BackupDriver instance. :type driver: :class:`.BackupDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.status = status self.progress = progress self.target = target self.driver = driver self.extra = extra or {} def cancel(self): return self.driver.cancel_target_job(job=self) def suspend(self): return self.driver.suspend_target_job(job=self) def resume(self): return self.driver.resume_target_job(job=self) def __repr__(self): return ('' % (self.id, self.status, self.progress, self.target.id, self.driver.name)) class BackupTargetRecoveryPoint(object): """ A backup target recovery point """ def __init__(self, id, date, target, driver, extra=None): """ :param id: Job id :type id: ``str`` :param date: The date taken :type date: :class:`datetime.datetime` :param target: BackupTarget instance. :type target: :class:`.BackupTarget` :param driver: BackupDriver instance. :type driver: :class:`.BackupDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.date = date self.target = target self.driver = driver self.extra = extra or {} def recover(self, path=None): """ Recover this recovery point :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`.BackupTargetJob` """ return self.driver.recover_target(target=self.target, recovery_point=self, path=path) def recover_to(self, recovery_target, path=None): """ Recover this recovery point out of place :param recovery_target: Backup target with to recover the data to :type recovery_target: Instance of :class:`.BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`.BackupTargetJob` """ return self.driver.recover_target_out_of_place( target=self.target, recovery_point=self, recovery_target=recovery_target, path=path) def __repr__(self): return ('' % (self.id, self.date, self.target.id, self.driver.name)) class BackupDriver(BaseDriver): """ A base BackupDriver class to derive from This class is always subclassed by a specific driver. """ connectionCls = ConnectionUserAndKey name = None website = None def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs): """ :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Some providers only support HTTPS, and it is on by default. :type secure: ``bool`` :param host: Override hostname used for connections. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :return: ``None`` """ super(BackupDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def get_supported_target_types(self): """ Get a list of backup target types this driver supports :return: ``list`` of :class:``BackupTargetType`` """ raise NotImplementedError( 'get_supported_target_types not implemented for this driver') def list_targets(self): """ List all backuptargets :rtype: ``list`` of :class:`.BackupTarget` """ raise NotImplementedError( 'list_targets not implemented for this driver') def create_target(self, name, address, type=BackupTargetType.VIRTUAL, extra=None): """ Creates a new backup target :param name: Name of the target :type name: ``str`` :param address: Hostname, FQDN, IP, file path etc. :type address: ``str`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`.BackupTarget` """ raise NotImplementedError( 'create_target not implemented for this driver') def create_target_from_node(self, node, type=BackupTargetType.VIRTUAL, extra=None): """ Creates a new backup target from an existing node. By default, this will use the first public IP of the node :param node: The Node to backup :type node: ``Node`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`.BackupTarget` """ return self.create_target(name=node.name, address=node.public_ips[0], type=type, extra=None) def create_target_from_storage_container(self, container, type=BackupTargetType.OBJECT, extra=None): """ Creates a new backup target from an existing storage container :param node: The Container to backup :type node: ``Container`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`.BackupTarget` """ return self.create_target(name=container.name, address=container.get_cdn_url(), type=type, extra=None) def update_target(self, target, name, address, extra): """ Update the properties of a backup target :param target: Backup target to update :type target: Instance of :class:`.BackupTarget` :param name: Name of the target :type name: ``str`` :param address: Hostname, FQDN, IP, file path etc. :type address: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`.BackupTarget` """ raise NotImplementedError( 'update_target not implemented for this driver') def delete_target(self, target): """ Delete a backup target :param target: Backup target to delete :type target: Instance of :class:`.BackupTarget` """ raise NotImplementedError( 'delete_target not implemented for this driver') def list_recovery_points(self, target, start_date=None, end_date=None): """ List the recovery points available for a target :param target: Backup target to delete :type target: Instance of :class:`.BackupTarget` :param start_date: The start date to show jobs between (optional) :type start_date: :class:`datetime.datetime` :param end_date: The end date to show jobs between (optional) :type end_date: :class:`datetime.datetime`` :rtype: ``list`` of :class:`.BackupTargetRecoveryPoint` """ raise NotImplementedError( 'list_recovery_points not implemented for this driver') def recover_target(self, target, recovery_point, path=None): """ Recover a backup target to a recovery point :param target: Backup target to delete :type target: Instance of :class:`.BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`.BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`.BackupTargetJob` """ raise NotImplementedError( 'recover_target not implemented for this driver') def recover_target_out_of_place(self, target, recovery_point, recovery_target, path=None): """ Recover a backup target to a recovery point out-of-place :param target: Backup target with the backup data :type target: Instance of :class:`.BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`.BackupTarget` :param recovery_target: Backup target with to recover the data to :type recovery_target: Instance of :class:`.BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'recover_target_out_of_place not implemented for this driver') def get_target_job(self, target, id): """ Get a specific backup job by ID :param target: Backup target with the backup data :type target: Instance of :class:`.BackupTarget` :param id: Backup target with the backup data :type id: Instance of :class:`.BackupTarget` :rtype: :class:`BackupTargetJob` """ jobs = self.list_target_jobs(target) return list(filter(lambda x: x.id == id, jobs))[0] def list_target_jobs(self, target): """ List the backup jobs on a target :param target: Backup target with the backup data :type target: Instance of :class:`.BackupTarget` :rtype: ``list`` of :class:`.BackupTargetJob` """ raise NotImplementedError( 'list_target_jobs not implemented for this driver') def create_target_job(self, target, extra=None): """ Create a new backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`.BackupTarget` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'create_target_job not implemented for this driver') def resume_target_job(self, job): """ Resume a suspended backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`.BackupTarget` :param job: Backup target job to resume :type job: Instance of :class:`.BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'resume_target_job not implemented for this driver') def suspend_target_job(self, job): """ Suspend a running backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`.BackupTarget` :param job: Backup target job to suspend :type job: Instance of :class:`.BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'suspend_target_job not implemented for this driver') def cancel_target_job(self, job): """ Cancel a backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`.BackupTarget` :param job: Backup target job to cancel :type job: Instance of :class:`.BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'cancel_target_job not implemented for this driver') apache-libcloud-2.8.0/libcloud/backup/drivers/0000775000175000017500000000000013600223624021141 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/backup/drivers/__init__.py0000664000175000017500000000000013535474530023253 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/backup/drivers/dimensiondata.py0000664000175000017500000006232113535474530024351 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import ET from libcloud.backup.base import BackupDriver, BackupTarget, BackupTargetJob from libcloud.backup.types import BackupTargetType from libcloud.backup.types import Provider from libcloud.common.dimensiondata import dd_object_to_id from libcloud.common.dimensiondata import DimensionDataConnection from libcloud.common.dimensiondata import DimensionDataBackupClient from libcloud.common.dimensiondata import DimensionDataBackupClientAlert from libcloud.common.dimensiondata import DimensionDataBackupClientType from libcloud.common.dimensiondata import DimensionDataBackupDetails from libcloud.common.dimensiondata import DimensionDataBackupSchedulePolicy from libcloud.common.dimensiondata import DimensionDataBackupStoragePolicy from libcloud.common.dimensiondata import API_ENDPOINTS, DEFAULT_REGION from libcloud.common.dimensiondata import TYPES_URN from libcloud.common.dimensiondata import GENERAL_NS, BACKUP_NS from libcloud.utils.xml import fixxpath, findtext, findall # pylint: disable=no-member DEFAULT_BACKUP_PLAN = 'Advanced' class DimensionDataBackupDriver(BackupDriver): """ DimensionData backup driver. """ selected_region = None connectionCls = DimensionDataConnection name = 'Dimension Data Backup' website = 'https://cloud.dimensiondata.com/' type = Provider.DIMENSIONDATA api_version = 1.0 network_domain_id = None def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS and host is None: raise ValueError( 'Invalid region: %s, no host specified' % (region)) if region is not None: self.selected_region = API_ENDPOINTS[region] super(DimensionDataBackupDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) def _ex_connection_class_kwargs(self): """ Add the region to the kwargs before the connection is instantiated """ kwargs = super(DimensionDataBackupDriver, self)._ex_connection_class_kwargs() kwargs['region'] = self.selected_region return kwargs def get_supported_target_types(self): """ Get a list of backup target types this driver supports :return: ``list`` of :class:``BackupTargetType`` """ return [BackupTargetType.VIRTUAL] def list_targets(self): """ List all backuptargets :rtype: ``list`` of :class:`BackupTarget` """ targets = self._to_targets( self.connection.request_with_orgId_api_2('server/server').object) return targets def create_target(self, name, address, type=BackupTargetType.VIRTUAL, extra=None): """ Creates a new backup target :param name: Name of the target (not used) :type name: ``str`` :param address: The ID of the node in Dimension Data Cloud :type address: ``str`` :param type: Backup target type, only Virtual supported :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ if extra is not None: service_plan = extra.get('servicePlan', DEFAULT_BACKUP_PLAN) else: service_plan = DEFAULT_BACKUP_PLAN extra = {'servicePlan': service_plan} create_node = ET.Element('NewBackup', {'xmlns': BACKUP_NS}) create_node.set('servicePlan', service_plan) response = self.connection.request_with_orgId_api_1( 'server/%s/backup' % (address), method='POST', data=ET.tostring(create_node)).object asset_id = None for info in findall(response, 'additionalInformation', GENERAL_NS): if info.get('name') == 'assetId': asset_id = findtext(info, 'value', GENERAL_NS) return BackupTarget( id=asset_id, name=name, address=address, type=type, extra=extra, driver=self ) def create_target_from_node(self, node, type=BackupTargetType.VIRTUAL, extra=None): """ Creates a new backup target from an existing node :param node: The Node to backup :type node: ``Node`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ return self.create_target(name=node.name, address=node.id, type=BackupTargetType.VIRTUAL, extra=extra) def create_target_from_container(self, container, type=BackupTargetType.OBJECT, extra=None): """ Creates a new backup target from an existing storage container :param node: The Container to backup :type node: ``Container`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ return NotImplementedError( 'create_target_from_container not supported for this driver') def update_target(self, target, name=None, address=None, extra=None): """ Update the properties of a backup target, only changing the serviceplan is supported. :param target: Backup target to update :type target: Instance of :class:`BackupTarget` or ``str`` :param name: Name of the target :type name: ``str`` :param address: Hostname, FQDN, IP, file path etc. :type address: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ if extra is not None: service_plan = extra.get('servicePlan', DEFAULT_BACKUP_PLAN) else: service_plan = DEFAULT_BACKUP_PLAN request = ET.Element('ModifyBackup', {'xmlns': BACKUP_NS}) request.set('servicePlan', service_plan) server_id = self._target_to_target_address(target) self.connection.request_with_orgId_api_1( 'server/%s/backup/modify' % (server_id), method='POST', data=ET.tostring(request)).object if isinstance(target, BackupTarget): target.extra = extra else: target = self.ex_get_target_by_id(server_id) return target def delete_target(self, target): """ Delete a backup target :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` or ``str`` :rtype: ``bool`` """ server_id = self._target_to_target_address(target) response = self.connection.request_with_orgId_api_1( 'server/%s/backup?disable' % (server_id), method='GET').object response_code = findtext(response, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def list_recovery_points(self, target, start_date=None, end_date=None): """ List the recovery points available for a target :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` :param start_date: The start date to show jobs between (optional) :type start_date: :class:`datetime.datetime` :param end_date: The end date to show jobs between (optional) :type end_date: :class:`datetime.datetime`` :rtype: ``list`` of :class:`BackupTargetRecoveryPoint` """ raise NotImplementedError( 'list_recovery_points not implemented for this driver') def recover_target(self, target, recovery_point, path=None): """ Recover a backup target to a recovery point :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'recover_target not implemented for this driver') def recover_target_out_of_place(self, target, recovery_point, recovery_target, path=None): """ Recover a backup target to a recovery point out-of-place :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`BackupTarget` :param recovery_target: Backup target with to recover the data to :type recovery_target: Instance of :class:`BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'recover_target_out_of_place not implemented for this driver') def get_target_job(self, target, id): """ Get a specific backup job by ID :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param id: Backup target with the backup data :type id: Instance of :class:`BackupTarget` :rtype: :class:`BackupTargetJob` """ jobs = self.list_target_jobs(target) return list(filter(lambda x: x.id == id, jobs))[0] def list_target_jobs(self, target): """ List the backup jobs on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :rtype: ``list`` of :class:`BackupTargetJob` """ raise NotImplementedError( 'list_target_jobs not implemented for this driver') def create_target_job(self, target, extra=None): """ Create a new backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'create_target_job not implemented for this driver') def resume_target_job(self, target, job): """ Resume a suspended backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param job: Backup target job to resume :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'resume_target_job not implemented for this driver') def suspend_target_job(self, target, job): """ Suspend a running backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param job: Backup target job to suspend :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'suspend_target_job not implemented for this driver') def cancel_target_job(self, job, ex_client=None, ex_target=None): """ Cancel a backup job on a target :param job: Backup target job to cancel. If it is ``None`` ex_client and ex_target must be set :type job: Instance of :class:`BackupTargetJob` or ``None`` :param ex_client: Client of the job to cancel. Not necessary if job is specified. DimensionData only has 1 job per client :type ex_client: Instance of :class:`DimensionDataBackupClient` or ``str`` :param ex_target: Target to cancel a job from. Not necessary if job is specified. :type ex_target: Instance of :class:`BackupTarget` or ``str`` :rtype: ``bool`` """ if job is None: if ex_client is None or ex_target is None: raise ValueError("Either job or ex_client and " "ex_target have to be set") server_id = self._target_to_target_address(ex_target) client_id = self._client_to_client_id(ex_client) else: server_id = job.target.address client_id = job.extra['clientId'] response = self.connection.request_with_orgId_api_1( 'server/%s/backup/client/%s?cancelJob' % (server_id, client_id), method='GET').object response_code = findtext(response, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_get_target_by_id(self, id): """ Get a target by server id :param id: The id of the target you want to get :type id: ``str`` :rtype: :class:`BackupTarget` """ node = self.connection.request_with_orgId_api_2( 'server/server/%s' % id).object return self._to_target(node) def ex_add_client_to_target(self, target, client_type, storage_policy, schedule_policy, trigger, email): """ Add a client to a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` or ``str`` :param client: Client to add to the target :type client: Instance of :class:`DimensionDataBackupClientType` or ``str`` :param storage_policy: The storage policy for the client :type storage_policy: Instance of :class:`DimensionDataBackupStoragePolicy` or ``str`` :param schedule_policy: The schedule policy for the client :type schedule_policy: Instance of :class:`DimensionDataBackupSchedulePolicy` or ``str`` :param trigger: The notify trigger for the client :type trigger: ``str`` :param email: The notify email for the client :type email: ``str`` :rtype: ``bool`` """ server_id = self._target_to_target_address(target) backup_elm = ET.Element('NewBackupClient', {'xmlns': BACKUP_NS}) if isinstance(client_type, DimensionDataBackupClientType): ET.SubElement(backup_elm, "type").text = client_type.type else: ET.SubElement(backup_elm, "type").text = client_type if isinstance(storage_policy, DimensionDataBackupStoragePolicy): ET.SubElement(backup_elm, "storagePolicyName").text = storage_policy.name else: ET.SubElement(backup_elm, "storagePolicyName").text = storage_policy if isinstance(schedule_policy, DimensionDataBackupSchedulePolicy): ET.SubElement(backup_elm, "schedulePolicyName").text = schedule_policy.name else: ET.SubElement(backup_elm, "schedulePolicyName").text = schedule_policy alerting_elm = ET.SubElement(backup_elm, "alerting") alerting_elm.set('trigger', trigger) ET.SubElement(alerting_elm, "emailAddress").text = email response = self.connection.request_with_orgId_api_1( 'server/%s/backup/client' % (server_id), method='POST', data=ET.tostring(backup_elm)).object response_code = findtext(response, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_remove_client_from_target(self, target, backup_client): """ Removes a client from a backup target :param target: The backup target to remove the client from :type target: :class:`BackupTarget` or ``str`` :param backup_client: The backup client to remove :type backup_client: :class:`DimensionDataBackupClient` or ``str`` :rtype: ``bool`` """ server_id = self._target_to_target_address(target) client_id = self._client_to_client_id(backup_client) response = self.connection.request_with_orgId_api_1( 'server/%s/backup/client/%s?disable' % (server_id, client_id), method='GET').object response_code = findtext(response, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_get_backup_details_for_target(self, target): """ Returns a backup details object for a target :param target: The backup target to get details for :type target: :class:`BackupTarget` or ``str`` :rtype: :class:`DimensionDataBackupDetails` """ if not isinstance(target, BackupTarget): target = self.ex_get_target_by_id(target) if target is None: return response = self.connection.request_with_orgId_api_1( 'server/%s/backup' % (target.address), method='GET').object return self._to_backup_details(response, target) def ex_list_available_client_types(self, target): """ Returns a list of available backup client types :param target: The backup target to list available types for :type target: :class:`BackupTarget` or ``str`` :rtype: ``list`` of :class:`DimensionDataBackupClientType` """ server_id = self._target_to_target_address(target) response = self.connection.request_with_orgId_api_1( 'server/%s/backup/client/type' % (server_id), method='GET').object return self._to_client_types(response) def ex_list_available_storage_policies(self, target): """ Returns a list of available backup storage policies :param target: The backup target to list available policies for :type target: :class:`BackupTarget` or ``str`` :rtype: ``list`` of :class:`DimensionDataBackupStoragePolicy` """ server_id = self._target_to_target_address(target) response = self.connection.request_with_orgId_api_1( 'server/%s/backup/client/storagePolicy' % (server_id), method='GET').object return self._to_storage_policies(response) def ex_list_available_schedule_policies(self, target): """ Returns a list of available backup schedule policies :param target: The backup target to list available policies for :type target: :class:`BackupTarget` or ``str`` :rtype: ``list`` of :class:`DimensionDataBackupSchedulePolicy` """ server_id = self._target_to_target_address(target) response = self.connection.request_with_orgId_api_1( 'server/%s/backup/client/schedulePolicy' % (server_id), method='GET').object return self._to_schedule_policies(response) def _to_storage_policies(self, object): elements = object.findall(fixxpath('storagePolicy', BACKUP_NS)) return [self._to_storage_policy(el) for el in elements] def _to_storage_policy(self, element): return DimensionDataBackupStoragePolicy( retention_period=int(element.get('retentionPeriodInDays')), name=element.get('name'), secondary_location=element.get('secondaryLocation') ) def _to_schedule_policies(self, object): elements = object.findall(fixxpath('schedulePolicy', BACKUP_NS)) return [self._to_schedule_policy(el) for el in elements] def _to_schedule_policy(self, element): return DimensionDataBackupSchedulePolicy( name=element.get('name'), description=element.get('description') ) def _to_client_types(self, object): elements = object.findall(fixxpath('backupClientType', BACKUP_NS)) return [self._to_client_type(el) for el in elements] def _to_client_type(self, element): description = element.get('description') if description is None: description = findtext(element, 'description', BACKUP_NS) return DimensionDataBackupClientType( type=element.get('type'), description=description, is_file_system=bool(element.get('isFileSystem') == 'true') ) def _to_backup_details(self, object, target): return DimensionDataBackupDetails( asset_id=object.get('assetId'), service_plan=object.get('servicePlan'), status=object.get('state'), clients=self._to_clients(object, target) ) def _to_clients(self, object, target): elements = object.findall(fixxpath('backupClient', BACKUP_NS)) return [self._to_client(el, target) for el in elements] def _to_client(self, element, target): client_id = element.get('id') return DimensionDataBackupClient( id=client_id, type=self._to_client_type(element), status=element.get('status'), schedule_policy=findtext(element, 'schedulePolicyName', BACKUP_NS), storage_policy=findtext(element, 'storagePolicyName', BACKUP_NS), download_url=findtext(element, 'downloadUrl', BACKUP_NS), running_job=self._to_backup_job(element, target, client_id), alert=self._to_alert(element) ) def _to_alert(self, element): alert = element.find(fixxpath('alerting', BACKUP_NS)) if alert is not None: notify_list = [ email_addr.text for email_addr in alert.findall(fixxpath('emailAddress', BACKUP_NS)) ] return DimensionDataBackupClientAlert( trigger=element.get('trigger'), notify_list=notify_list ) return None def _to_backup_job(self, element, target, client_id): running_job = element.find(fixxpath('runningJob', BACKUP_NS)) if running_job is not None: return BackupTargetJob( id=running_job.get('id'), status=running_job.get('status'), progress=int(running_job.get('percentageComplete')), driver=self.connection.driver, target=target, extra={'clientId': client_id} ) return None def _to_targets(self, object): node_elements = object.findall(fixxpath('server', TYPES_URN)) return [self._to_target(el) for el in node_elements] def _to_target(self, element): backup = findall(element, 'backup', TYPES_URN) if len(backup) == 0: return extra = { 'description': findtext(element, 'description', TYPES_URN), 'sourceImageId': findtext(element, 'sourceImageId', TYPES_URN), 'datacenterId': element.get('datacenterId'), 'deployedTime': findtext(element, 'createTime', TYPES_URN), 'servicePlan': backup[0].get('servicePlan') } n = BackupTarget(id=backup[0].get('assetId'), name=findtext(element, 'name', TYPES_URN), address=element.get('id'), driver=self.connection.driver, type=BackupTargetType.VIRTUAL, extra=extra) return n @staticmethod def _client_to_client_id(backup_client): return dd_object_to_id(backup_client, DimensionDataBackupClient) @staticmethod def _target_to_target_address(target): return dd_object_to_id(target, BackupTarget, id_value='address') apache-libcloud-2.8.0/libcloud/backup/drivers/dummy.py0000664000175000017500000000266413535474530022671 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.backup.base import BackupDriver class DummyBackupDriver(BackupDriver): """ Dummy Backup driver. >>> from libcloud.backup.drivers.dummy import DummyBackupDriver >>> driver = DummyBackupDriver('key', 'secret') >>> driver.name 'Dummy Backup Provider' """ name = 'Dummy Backup Provider' website = 'http://example.com' def __init__(self, api_key, api_secret): """ :param api_key: API key or username to used (required) :type api_key: ``str`` :param api_secret: Secret password to be used (required) :type api_secret: ``str`` :rtype: ``None`` """ apache-libcloud-2.8.0/libcloud/backup/drivers/ebs.py0000664000175000017500000003246513535474530022311 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'EBSBackupDriver' ] from libcloud.utils.xml import findtext, findall from libcloud.utils.iso8601 import parse_date from libcloud.backup.base import BackupDriver, BackupTargetRecoveryPoint,\ BackupTargetJob, BackupTarget from libcloud.backup.types import BackupTargetType, BackupTargetJobStatusType from libcloud.common.aws import AWSGenericResponse, SignedAWSConnection VERSION = '2015-10-01' HOST = 'ec2.amazonaws.com' ROOT = '/%s/' % (VERSION) NS = 'http://ec2.amazonaws.com/doc/%s/' % (VERSION, ) class EBSResponse(AWSGenericResponse): """ Amazon EBS response class. """ namespace = NS exceptions = {} xpath = 'Error' class EBSConnection(SignedAWSConnection): version = VERSION host = HOST responseCls = EBSResponse service_name = 'backup' class EBSBackupDriver(BackupDriver): name = 'Amazon EBS Backup Driver' website = 'http://aws.amazon.com/ebs/' connectionCls = EBSConnection def __init__(self, access_id, secret, region): super(EBSBackupDriver, self).__init__(access_id, secret) self.region = region self.connection.host = HOST % (region) def get_supported_target_types(self): """ Get a list of backup target types this driver supports :return: ``list`` of :class:``BackupTargetType`` """ return [BackupTargetType.VOLUME] def list_targets(self): """ List all backuptargets :rtype: ``list`` of :class:`BackupTarget` """ raise NotImplementedError( 'list_targets not implemented for this driver') def create_target(self, name, address, type=BackupTargetType.VOLUME, extra=None): """ Creates a new backup target :param name: Name of the target :type name: ``str`` :param address: The volume ID. :type address: ``str`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ # Does nothing since any volume can be snapped at anytime. return self.ex_get_target_by_volume_id(address) def create_target_from_node(self, node, type=BackupTargetType.VIRTUAL, extra=None): """ Creates a new backup target from an existing node :param node: The Node to backup :type node: ``Node`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ # Get the first EBS volume. device_mapping = node.extra['block_device_mapping'] if device_mapping is not None: return self.create_target( name=node.name, address=device_mapping['ebs'][0]['volume_id'], type=BackupTargetType.VOLUME, extra=None) else: raise RuntimeError("Node does not have any block devices") def create_target_from_container(self, container, type=BackupTargetType.OBJECT, extra=None): """ Creates a new backup target from an existing storage container :param node: The Container to backup :type node: ``Container`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ raise NotImplementedError( 'create_target_from_container not implemented for this driver') def update_target(self, target, name, address, extra): """ Update the properties of a backup target :param target: Backup target to update :type target: Instance of :class:`BackupTarget` :param name: Name of the target :type name: ``str`` :param address: Hostname, FQDN, IP, file path etc. :type address: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ # Does nothing since any volume can be snapped at anytime. return self.ex_get_target_by_volume_id(address) def delete_target(self, target): """ Delete a backup target :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` """ raise NotImplementedError( 'delete_target not implemented for this driver') def list_recovery_points(self, target, start_date=None, end_date=None): """ List the recovery points available for a target :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` :param start_date: The start date to show jobs between (optional) :type start_date: :class:`datetime.datetime` :param end_date: The end date to show jobs between (optional) :type end_date: :class:`datetime.datetime`` :rtype: ``list`` of :class:`BackupTargetRecoveryPoint` """ params = { 'Action': 'DescribeSnapshots', 'Filter.1.Name': 'volume-id', 'Filter.1.Value': target.extra['volume-id'] } data = self.connection.request(ROOT, params=params).object return self._to_recovery_points(data, target) def recover_target(self, target, recovery_point, path=None): """ Recover a backup target to a recovery point :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'delete_target not implemented for this driver') def recover_target_out_of_place(self, target, recovery_point, recovery_target, path=None): """ Recover a backup target to a recovery point out-of-place :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`BackupTarget` :param recovery_target: Backup target with to recover the data to :type recovery_target: Instance of :class:`BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'delete_target not implemented for this driver') def get_target_job(self, target, id): """ Get a specific backup job by ID :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param id: Backup target with the backup data :type id: Instance of :class:`BackupTarget` :rtype: :class:`BackupTargetJob` """ jobs = self.list_target_jobs(target) return list(filter(lambda x: x.id == id, jobs))[0] def list_target_jobs(self, target): """ List the backup jobs on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :rtype: ``list`` of :class:`BackupTargetJob` """ params = { 'Action': 'DescribeSnapshots', 'Filter.1.Name': 'volume-id', 'Filter.1.Value': target.extra['volume-id'], 'Filter.2.Name': 'status', 'Filter.2.Value': 'pending' } data = self.connection.request(ROOT, params=params).object return self._to_jobs(data) def create_target_job(self, target, extra=None): """ Create a new backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTargetJob` """ params = { 'Action': 'CreateSnapshot', 'VolumeId': target.extra['volume-id'] } data = self.connection.request(ROOT, params=params).object xpath = 'CreateSnapshotResponse' return self._to_job(findall(element=data, xpath=xpath, namespace=NS)[0]) def resume_target_job(self, job): """ Resume a suspended backup job on a target :param job: Backup target job to resume :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'resume_target_job not supported for this driver') def suspend_target_job(self, job): """ Suspend a running backup job on a target :param job: Backup target job to suspend :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'suspend_target_job not supported for this driver') def cancel_target_job(self, job): """ Cancel a backup job on a target :param job: Backup target job to cancel :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'cancel_target_job not supported for this driver') def _to_recovery_points(self, data, target): xpath = 'DescribeSnapshotsResponse/snapshotSet/item' return [self._to_recovery_point(el, target) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_recovery_point(self, el, target): id = findtext(element=el, xpath='snapshotId', namespace=NS) date = parse_date( findtext(element=el, xpath='startTime', namespace=NS)) tags = self._get_resource_tags(el) point = BackupTargetRecoveryPoint( id=id, date=date, target=target, driver=self.connection.driver, extra={ 'snapshot-id': id, 'tags': tags }, ) return point def _to_jobs(self, data): xpath = 'DescribeSnapshotsResponse/snapshotSet/item' return [self._to_job(el) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_job(self, el): id = findtext(element=el, xpath='snapshotId', namespace=NS) progress = findtext(element=el, xpath='progress', namespace=NS)\ .replace('%', '') volume_id = findtext(element=el, xpath='volumeId', namespace=NS) target = self.ex_get_target_by_volume_id(volume_id) job = BackupTargetJob( id=id, status=BackupTargetJobStatusType.PENDING, progress=int(progress), target=target, driver=self.connection.driver, extra={ }, ) return job def ex_get_target_by_volume_id(self, volume_id): return BackupTarget( id=volume_id, name=volume_id, address=volume_id, type=BackupTargetType.VOLUME, driver=self.connection.driver, extra={ "volume-id": volume_id } ) def _get_resource_tags(self, element): """ Parse tags from the provided element and return a dictionary with key/value pairs. :rtype: ``dict`` """ tags = {} # Get our tag set by parsing the element tag_set = findall(element=element, xpath='tagSet/item', namespace=NS) for tag in tag_set: key = findtext(element=tag, xpath='key', namespace=NS) value = findtext(element=tag, xpath='value', namespace=NS) tags[key] = value return tags apache-libcloud-2.8.0/libcloud/backup/drivers/gce.py0000664000175000017500000004065013535474530022271 0ustar kamikami00000000000000 # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'GCEBackupDriver' ] from libcloud.utils.iso8601 import parse_date from libcloud.backup.base import BackupDriver, BackupTargetRecoveryPoint,\ BackupTargetJob, BackupTarget from libcloud.backup.types import BackupTargetType, BackupTargetJobStatusType from libcloud.common.google import GoogleResponse, GoogleBaseConnection API_VERSION = 'v1' DEFAULT_TASK_COMPLETION_TIMEOUT = 180 class GCEResponse(GoogleResponse): pass class GCEConnection(GoogleBaseConnection): """ Connection class for the GCE driver. GCEConnection extends :class:`google.GoogleBaseConnection` for 2 reasons: 1. modify request_path for GCE URI. 2. Implement gce_params functionality described below. If the parameter gce_params is set to a dict prior to calling request(), the URL parameters will be updated to include those key/values FOR A SINGLE REQUEST. If the response contains a nextPageToken, gce_params['pageToken'] will be set to its value. This can be used to implement paging in list: >>> params, more_results = {'maxResults': 2}, True >>> while more_results: ... driver.connection.gce_params=params ... driver.ex_list_urlmaps() ... more_results = 'pageToken' in params ... [, ] [] """ host = 'www.googleapis.com' responseCls = GCEResponse def __init__(self, user_id, key, secure, auth_type=None, credential_file=None, project=None, **kwargs): super(GCEConnection, self).__init__(user_id, key, secure=secure, auth_type=auth_type, credential_file=credential_file, **kwargs) self.request_path = '/compute/%s/projects/%s' % (API_VERSION, project) self.gce_params = None def pre_connect_hook(self, params, headers): """ Update URL parameters with values from self.gce_params. @inherits: :class:`GoogleBaseConnection.pre_connect_hook` """ params, headers = super(GCEConnection, self).pre_connect_hook(params, headers) if self.gce_params: params.update(self.gce_params) return params, headers def request(self, *args, **kwargs): """ Perform request then do GCE-specific processing of URL params. @inherits: :class:`GoogleBaseConnection.request` """ response = super(GCEConnection, self).request(*args, **kwargs) # If gce_params has been set, then update the pageToken with the # nextPageToken so it can be used in the next request. if self.gce_params: if 'nextPageToken' in response.object: self.gce_params['pageToken'] = response.object['nextPageToken'] elif 'pageToken' in self.gce_params: del self.gce_params['pageToken'] self.gce_params = None return response class GCEBackupDriver(BackupDriver): name = 'Google Compute Engine Backup Driver' website = 'http://cloud.google.com/' connectionCls = GCEConnection def __init__(self, user_id, key=None, project=None, auth_type=None, scopes=None, credential_file=None, **kwargs): """ :param user_id: The email address (for service accounts) or Client ID (for installed apps) to be used for authentication. :type user_id: ``str`` :param key: The RSA Key (for service accounts) or file path containing key or Client Secret (for installed apps) to be used for authentication. :type key: ``str`` :keyword project: Your GCE project name. (required) :type project: ``str`` :keyword auth_type: Accepted values are "SA" or "IA" or "GCE" ("Service Account" or "Installed Application" or "GCE" if libcloud is being used on a GCE instance with service account enabled). If not supplied, auth_type will be guessed based on value of user_id or if the code is being executed in a GCE instance. :type auth_type: ``str`` :keyword scopes: List of authorization URLs. Default is empty and grants read/write to Compute, Storage, DNS. :type scopes: ``list`` :keyword credential_file: Path to file for caching authentication information used by GCEConnection. :type credential_file: ``str`` """ if not project: raise ValueError('Project name must be specified using ' '"project" keyword.') self.auth_type = auth_type self.project = project self.scopes = scopes self.credential_file = credential_file or \ '~/.gce_libcloud_auth' + '.' + self.project super(GCEBackupDriver, self).__init__(user_id, key, **kwargs) # Cache Zone and Region information to reduce API calls and # increase speed self.base_path = '/compute/%s/projects/%s' % (API_VERSION, self.project) def get_supported_target_types(self): """ Get a list of backup target types this driver supports :return: ``list`` of :class:``BackupTargetType`` """ return [BackupTargetType.VOLUME] def list_targets(self): """ List all backuptargets :rtype: ``list`` of :class:`BackupTarget` """ raise NotImplementedError( 'list_targets not implemented for this driver') def create_target(self, name, address, type=BackupTargetType.VOLUME, extra=None): """ Creates a new backup target :param name: Name of the target :type name: ``str`` :param address: The volume ID. :type address: ``str`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ # Does nothing since any volume can be snapped at anytime. return self.ex_get_target_by_source(address) def create_target_from_node(self, node, type=BackupTargetType.VIRTUAL, extra=None): """ Creates a new backup target from an existing node :param node: The Node to backup :type node: ``Node`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ # Get the first persistent disk disks = node.extra['disks'] if disks is not None: return self.create_target( name=node.name, address=disks[0]['source'], type=BackupTargetType.VOLUME, extra=None) else: raise RuntimeError("Node does not have any block devices") def create_target_from_container(self, container, type=BackupTargetType.OBJECT, extra=None): """ Creates a new backup target from an existing storage container :param node: The Container to backup :type node: ``Container`` :param type: Backup target type (Physical, Virtual, ...). :type type: :class:`BackupTargetType` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ raise NotImplementedError( 'create_target_from_container not implemented for this driver') def update_target(self, target, name, address, extra): """ Update the properties of a backup target :param target: Backup target to update :type target: Instance of :class:`BackupTarget` :param name: Name of the target :type name: ``str`` :param address: Hostname, FQDN, IP, file path etc. :type address: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTarget` """ # Does nothing since any volume can be snapped at anytime. return self.ex_get_target_by_source(address) def delete_target(self, target): """ Delete a backup target :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` """ raise NotImplementedError( 'delete_target not implemented for this driver') def list_recovery_points(self, target, start_date=None, end_date=None): """ List the recovery points available for a target :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` :param start_date: The start date to show jobs between (optional) :type start_date: :class:`datetime.datetime` :param end_date: The end date to show jobs between (optional) :type end_date: :class:`datetime.datetime`` :rtype: ``list`` of :class:`BackupTargetRecoveryPoint` """ request = '/global/snapshots' response = self.connection.request(request, method='GET').object return self._to_recovery_points(response, target) def recover_target(self, target, recovery_point, path=None): """ Recover a backup target to a recovery point :param target: Backup target to delete :type target: Instance of :class:`BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'recover_target not implemented for this driver') def recover_target_out_of_place(self, target, recovery_point, recovery_target, path=None): """ Recover a backup target to a recovery point out-of-place :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param recovery_point: Backup target with the backup data :type recovery_point: Instance of :class:`BackupTarget` :param recovery_target: Backup target with to recover the data to :type recovery_target: Instance of :class:`BackupTarget` :param path: The part of the recovery point to recover (optional) :type path: ``str`` :rtype: Instance of :class:`BackupTargetJob` """ raise NotImplementedError( 'recover_target_out_of_place not implemented for this driver') def get_target_job(self, target, id): """ Get a specific backup job by ID :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param id: Backup target with the backup data :type id: Instance of :class:`BackupTarget` :rtype: :class:`BackupTargetJob` """ jobs = self.list_target_jobs(target) return list(filter(lambda x: x.id == id, jobs))[0] def list_target_jobs(self, target): """ List the backup jobs on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :rtype: ``list`` of :class:`BackupTargetJob` """ return [] def create_target_job(self, target, extra=None): """ Create a new backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: Instance of :class:`BackupTargetJob` """ name = target.name request = '/zones/%s/disks/%s/createSnapshot' % ( target.extra['zone'].name, target.name) snapshot_data = { 'source': target.extra['source'] } self.connection.async_request(request, method='POST', data=snapshot_data) return self._to_job(self.ex_get_snapshot(name), target) def resume_target_job(self, target, job): """ Resume a suspended backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param job: Backup target job to resume :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'resume_target_job not supported for this driver') def suspend_target_job(self, target, job): """ Suspend a running backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param job: Backup target job to suspend :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'suspend_target_job not supported for this driver') def cancel_target_job(self, target, job): """ Cancel a backup job on a target :param target: Backup target with the backup data :type target: Instance of :class:`BackupTarget` :param job: Backup target job to cancel :type job: Instance of :class:`BackupTargetJob` :rtype: ``bool`` """ raise NotImplementedError( 'cancel_target_job not supported for this driver') def _to_recovery_points(self, data, target): return [self._to_recovery_point(item, target) for item in data.items] def _to_recovery_point(self, item, target): id = item.id date = parse_date(item.creationTimestamp) point = BackupTargetRecoveryPoint( id=id, date=date, target=target, driver=self.connection.driver, extra={ 'snapshot-id': id, }, ) return point def _to_jobs(self, data, target): return [self._to_job(item, target) for item in data.items] def _to_job(self, item, target): id = item.id job = BackupTargetJob( id=id, status=BackupTargetJobStatusType.PENDING, progress=0, target=target, driver=self.connection.driver, extra={ }, ) return job def ex_get_snapshot(self, name): request = '/global/snapshots/%s' % (name) response = self.connection.request(request, method='GET').object return response def ex_get_target_by_source(self, source): return BackupTarget( id=source, name=source, address=source, type=BackupTargetType.VOLUME, driver=self.connection.driver, extra={ "source": source } ) apache-libcloud-2.8.0/libcloud/backup/providers.py0000664000175000017500000000306113535474530022065 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.backup.types import Provider from libcloud.common.providers import get_driver as _get_provider_driver from libcloud.common.providers import set_driver as _set_provider_driver DRIVERS = { Provider.DUMMY: ('libcloud.backup.drivers.dummy', 'DummyBackupDriver'), Provider.EBS: ('libcloud.backup.drivers.ebs', 'EBSBackupDriver'), Provider.GCE: ('libcloud.backup.drivers.gce', 'GCEBackupDriver'), Provider.DIMENSIONDATA: ('libcloud.backup.drivers.dimensiondata', 'DimensionDataBackupDriver'), } def get_driver(provider): return _get_provider_driver(drivers=DRIVERS, provider=provider) def set_driver(provider, module, klass): return _set_provider_driver(drivers=DRIVERS, provider=provider, module=module, klass=klass) apache-libcloud-2.8.0/libcloud/backup/types.py0000664000175000017500000000350513535474530021217 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'Provider', 'BackupTargetType', 'BackupTargetJobStatusType' ] class Provider(object): """ Defines for each of the supported providers Non-Dummy drivers are sorted in alphabetical order. Please preserve this ordering when adding new drivers. """ DUMMY = 'dummy' DIMENSIONDATA = 'dimensiondata' EBS = 'ebs' GCE = 'gce' class BackupTargetType(object): """ Backup Target type. """ VIRTUAL = 'Virtual' """ Denotes a virtual host """ PHYSICAL = 'Physical' """ Denotes a physical host """ FILESYSTEM = 'Filesystem' """ Denotes a file system (e.g. NAS) """ DATABASE = 'Database' """ Denotes a database target """ OBJECT = 'Object' """ Denotes an object based file system """ VOLUME = 'Volume' """ Denotes a block storage volume """ class BackupTargetJobStatusType(object): """ The status of a backup target job """ RUNNING = 'Running' CANCELLED = 'Cancelled' FAILED = 'Failed' COMPLETED = 'Completed' PENDING = 'Pending' apache-libcloud-2.8.0/libcloud/base.py0000664000175000017500000000532213535474530017517 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.backup.providers import Provider as BackupProvider from libcloud.backup.providers import get_driver as get_backup_driver from libcloud.compute.providers import Provider as ComputeProvider from libcloud.compute.providers import get_driver as get_compute_driver from libcloud.container.providers import Provider as ContainerProvider from libcloud.container.providers import get_driver as get_container_driver from libcloud.dns.providers import Provider as DnsProvider from libcloud.dns.providers import get_driver as get_dns_driver from libcloud.loadbalancer.providers import Provider as LoadBalancerProvider from libcloud.loadbalancer.providers import get_driver as \ get_loadbalancer_driver from libcloud.storage.providers import Provider as StorageProvider from libcloud.storage.providers import get_driver as get_storage_driver class DriverType(object): """ Backup-as-a-service driver """ BACKUP = BackupProvider """ Compute-as-a-Service driver """ COMPUTE = ComputeProvider """ Container-as-a-Service driver """ CONTAINER = ContainerProvider """ DNS service provider driver """ DNS = DnsProvider """ Load balancer provider-driver """ LOADBALANCER = LoadBalancerProvider """ Storage-as-a-Service driver """ STORAGE = StorageProvider DriverTypeFactoryMap = { DriverType.BACKUP: get_backup_driver, DriverType.COMPUTE: get_compute_driver, DriverType.CONTAINER: get_container_driver, DriverType.DNS: get_dns_driver, DriverType.LOADBALANCER: get_loadbalancer_driver, DriverType.STORAGE: get_storage_driver } class DriverTypeNotFoundError(KeyError): def __init__(self, type): self.message = "Driver type '%s' not found." % type def __repr__(self): return self.message def get_driver(type, provider): """ Get a driver """ try: return DriverTypeFactoryMap[type](provider) except KeyError: raise DriverTypeNotFoundError(type) apache-libcloud-2.8.0/libcloud/common/0000775000175000017500000000000013600223624017506 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/common/__init__.py0000664000175000017500000000000013535474530021620 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/common/abiquo.py0000664000175000017500000002411313535474530021354 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Abiquo Utilities Module for the Abiquo Driver. Common utilities needed by the :class:`AbiquoNodeDriver`. """ import base64 from libcloud.common.base import ConnectionUserAndKey, PollingConnection from libcloud.common.base import XmlResponse from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import b from libcloud.compute.base import NodeState def get_href(element, rel): """ Search a RESTLink element in the :class:`AbiquoResponse`. Abiquo, as a REST API, it offers self-discovering functionality. That means that you could walk through the whole API only navigating from the links offered by the entities. This is a basic method to find the 'relations' of an entity searching into its links. For instance, a Rack entity serialized as XML as the following:: false 1 racacaca 10 4094 2 1 offers link to datacenters (rel='datacenter'), to itself (rel='edit') and to the machines defined in it (rel='machines') A call to this method with the 'rack' element using 'datacenter' as 'rel' will return: 'http://10.60.12.7:80/api/admin/datacenters/1' :type element: :class:`xml.etree.ElementTree` :param element: Xml Entity returned by Abiquo API (required) :type rel: ``str`` :param rel: relation link name :rtype: ``str`` :return: the 'href' value according to the 'rel' input parameter """ links = element.findall('link') for link in links: if link.attrib['rel'] == rel: href = link.attrib['href'] # href is something like: # # 'http://localhost:80/api/admin/enterprises' # # we are only interested in '/admin/enterprises/' part needle = '/api/' url_path = urlparse.urlparse(href).path index = url_path.find(needle) result = url_path[index + len(needle) - 1:] return result class AbiquoResponse(XmlResponse): """ Abiquo XML Response. Wraps the response in XML bodies or extract the error data in case of error. """ # Map between abiquo state and Libcloud State NODE_STATE_MAP = { 'NOT_ALLOCATED': NodeState.TERMINATED, 'ALLOCATED': NodeState.PENDING, 'CONFIGURED': NodeState.PENDING, 'ON': NodeState.RUNNING, 'PAUSED': NodeState.PENDING, 'OFF': NodeState.PENDING, 'LOCKED': NodeState.PENDING, 'UNKNOWN': NodeState.UNKNOWN } def parse_error(self): """ Parse the error messages. Response body can easily be handled by this class parent :class:`XmlResponse`, but there are use cases which Abiquo API does not respond an XML but an HTML. So we need to handle these special cases. """ if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError(driver=self.connection.driver) elif self.status == httplib.FORBIDDEN: raise ForbiddenError(self.connection.driver) elif self.status == httplib.NOT_ACCEPTABLE: raise LibcloudError('Not Acceptable') else: parsebody = self.parse_body() if parsebody is not None and hasattr(parsebody, 'findall'): errors = self.parse_body().findall('error') # Most of the exceptions only have one error raise LibcloudError(errors[0].findtext('message')) else: raise LibcloudError(self.body) def success(self): """ Determine if the request was successful. Any of the 2XX HTTP response codes are accepted as successful requests :rtype: ``bool`` :return: successful request or not. """ return self.status in [httplib.OK, httplib.CREATED, httplib.NO_CONTENT, httplib.ACCEPTED] def async_success(self): """ Determinate if async request was successful. An async_request retrieves for a task object that can be successfully retrieved (self.status == OK), but the asynchronous task (the body of the HTTP response) which we are asking for has finished with an error. So this method checks if the status code is 'OK' and if the task has finished successfully. :rtype: ``bool`` :return: successful asynchronous request or not """ if self.success(): # So we have a 'task' object in the body task = self.parse_body() return task.findtext('state') == 'FINISHED_SUCCESSFULLY' else: return False class AbiquoConnection(ConnectionUserAndKey, PollingConnection): """ A Connection to Abiquo API. Basic :class:`ConnectionUserAndKey` connection with :class:`PollingConnection` features for asynchronous tasks. """ responseCls = AbiquoResponse def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, retry_delay=None, backoff=None, proxy_url=None): super(AbiquoConnection, self).__init__(user_id=user_id, key=key, secure=secure, host=host, port=port, url=url, timeout=timeout, retry_delay=retry_delay, backoff=backoff, proxy_url=proxy_url) # This attribute stores data cached across multiple request self.cache = {} def add_default_headers(self, headers): """ Add Basic Authentication header to all the requests. It injects the 'Authorization: Basic Base64String===' header in each request :type headers: ``dict`` :param headers: Default input headers :rtype: ``dict`` :return: Default input headers with the 'Authorization' header """ b64string = b('%s:%s' % (self.user_id, self.key)) encoded = base64.b64encode(b64string).decode('utf-8') authorization = 'Basic ' + encoded headers['Authorization'] = authorization return headers def get_poll_request_kwargs(self, response, context, request_kwargs): """ Manage polling request arguments. Return keyword arguments which are passed to the :class:`NodeDriver.request` method when polling for the job status. The Abiquo Asynchronous Response returns and 'acceptedrequest' XmlElement as the following:: You can follow the progress in the link We need to extract the href URI to poll. :type response: :class:`xml.etree.ElementTree` :keyword response: Object returned by poll request. :type request_kwargs: ``dict`` :keyword request_kwargs: Default request arguments and headers :rtype: ``dict`` :return: Modified keyword arguments """ accepted_request_obj = response.object link_poll = get_href(accepted_request_obj, 'status') hdr_poll = {'Accept': 'application/vnd.abiquo.task+xml'} # Override the 'action', 'method' and 'headers' # keys of the previous dict request_kwargs['action'] = link_poll request_kwargs['method'] = 'GET' request_kwargs['headers'] = hdr_poll return request_kwargs def has_completed(self, response): """ Decide if the asynchronous job has ended. :type response: :class:`xml.etree.ElementTree` :param response: Response object returned by poll request :rtype: ``bool`` :return: Whether the job has completed """ task = response.object task_state = task.findtext('state') return task_state in ['FINISHED_SUCCESSFULLY', 'ABORTED', 'FINISHED_UNSUCCESSFULLY'] class ForbiddenError(LibcloudError): """ Exception used when credentials are ok but user has not permissions. """ def __init__(self, driver): message = 'User has not permission to perform this task.' super(ForbiddenError, self).__init__(message, driver) apache-libcloud-2.8.0/libcloud/common/aliyun.py0000664000175000017500000002114013535474530021372 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import hashlib import hmac import sys import time import uuid from libcloud.utils.py3 import ET from libcloud.common.base import ConnectionUserAndKey, XmlResponse from libcloud.common.types import MalformedResponseError from libcloud.utils.py3 import b, u, urlquote, PY3 from libcloud.utils.xml import findtext __all__ = [ 'AliyunXmlResponse', 'AliyunRequestSigner', 'AliyunRequestSignerAlgorithmV1_0', 'SignedAliyunConnection', 'AliyunConnection', 'SIGNATURE_VERSION_1_0', 'DEFAULT_SIGNATURE_VERSION' ] SIGNATURE_VERSION_1_0 = '1.0' DEFAULT_SIGNATURE_VERSION = SIGNATURE_VERSION_1_0 class AliyunXmlResponse(XmlResponse): namespace = None def success(self): return 200 <= self.status < 300 def parse_body(self): """ Each response from Aliyun contains a request id and a host id. The response body is in utf-8 encoding. """ if len(self.body) == 0 and not self.parse_zero_length_body: return self.body try: if PY3: parser = ET.XMLParser(encoding='utf-8') body = ET.XML(self.body.encode('utf-8'), parser=parser) else: try: body = ET.XML(self.body) except ValueError: body = ET.XML(self.body.encode('utf-8')) except Exception: raise MalformedResponseError('Failed to parse XML', body=self.body, driver=self.connection.driver) self.request_id = findtext(element=body, xpath='RequestId', namespace=self.namespace) self.host_id = findtext(element=body, xpath='HostId', namespace=self.namespace) return body def parse_error(self): """ Parse error responses from Aliyun. """ body = super(AliyunXmlResponse, self).parse_error() code, message = self._parse_error_details(element=body) request_id = findtext(element=body, xpath='RequestId', namespace=self.namespace) host_id = findtext(element=body, xpath='HostId', namespace=self.namespace) error = {'code': code, 'message': message, 'request_id': request_id, 'host_id': host_id} return u(error) def _parse_error_details(self, element): """ Parse error code and message from the provided error element. :return: ``tuple`` with two elements: (code, message) :rtype: ``tuple`` """ code = findtext(element=element, xpath='Code', namespace=self.namespace) message = findtext(element=element, xpath='Message', namespace=self.namespace) return (code, message) class AliyunRequestSigner(object): """ Class handles signing the outgoing Aliyun requests. """ def __init__(self, access_key, access_secret, version): """ :param access_key: Access key. :type access_key: ``str`` :param access_secret: Access secret. :type access_secret: ``str`` :param version: API version. :type version: ``str`` """ self.access_key = access_key self.access_secret = access_secret self.version = version def get_request_params(self, params, method='GET', path='/'): return params def get_request_headers(self, params, headers, method='GET', path='/'): return params, headers class AliyunRequestSignerAlgorithmV1_0(AliyunRequestSigner): """Aliyun request signer using signature version 1.0.""" def get_request_params(self, params, method='GET', path='/'): params['Format'] = 'XML' params['Version'] = self.version params['AccessKeyId'] = self.access_key params['SignatureMethod'] = 'HMAC-SHA1' params['SignatureVersion'] = SIGNATURE_VERSION_1_0 params['SignatureNonce'] = _get_signature_nonce() # TODO: Support 'ResourceOwnerAccount' params['Timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) params['Signature'] = self._sign_request(params, method, path) return params def _sign_request(self, params, method, path): """ Sign Aliyun requests parameters and get the signature. StringToSign = HTTPMethod + '&' + percentEncode('/') + '&' + percentEncode(CanonicalizedQueryString) """ keys = list(params.keys()) keys.sort() pairs = [] for key in keys: pairs.append('%s=%s' % (_percent_encode(key), _percent_encode(params[key]))) qs = urlquote('&'.join(pairs), safe='-_.~') string_to_sign = '&'.join((method, urlquote(path, safe=''), qs)) b64_hmac = base64.b64encode( hmac.new(b(self._get_access_secret()), b(string_to_sign), digestmod=hashlib.sha1).digest() ) return b64_hmac.decode('utf8') def _get_access_secret(self): return '%s&' % self.access_secret class AliyunConnection(ConnectionUserAndKey): pass class SignedAliyunConnection(AliyunConnection): api_version = None def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, retry_delay=None, backoff=None, api_version=None, signature_version=DEFAULT_SIGNATURE_VERSION): super(SignedAliyunConnection, self).__init__(user_id=user_id, key=key, secure=secure, host=host, port=port, url=url, timeout=timeout, proxy_url=proxy_url, retry_delay=retry_delay, backoff=backoff) self.signature_version = str(signature_version) if self.signature_version == '1.0': signer_cls = AliyunRequestSignerAlgorithmV1_0 else: raise ValueError('Unsupported signature_version: %s' % signature_version) if api_version is not None: self.api_version = str(api_version) else: if self.api_version is None: raise ValueError('Unsupported null api_version') self.signer = signer_cls(access_key=self.user_id, access_secret=self.key, version=self.api_version) def add_default_params(self, params): params = self.signer.get_request_params(params=params, method=self.method, path=self.action) return params def _percent_encode(encode_str): """ Encode string to utf8, quote for url and replace '+' with %20, '*' with %2A and keep '~' not converted. :param src_str: ``str`` in the same encoding with sys.stdin, default to encoding cp936. :return: ``str`` represents the encoded result :rtype: ``str`` """ encoding = sys.stdin.encoding or 'cp936' decoded = str(encode_str) if PY3: if isinstance(encode_str, bytes): decoded = encode_str.decode(encoding) else: decoded = str(encode_str).decode(encoding) res = urlquote( decoded.encode('utf8'), '') res = res.replace('+', '%20') res = res.replace('*', '%2A') res = res.replace('%7E', '~') return res def _get_signature_nonce(): return str(uuid.uuid4()) apache-libcloud-2.8.0/libcloud/common/aws.py0000664000175000017500000004206313576514553020677 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import Dict from typing import Type import base64 from datetime import datetime import hashlib import hmac import time from hashlib import sha256 try: import simplejson as json except ImportError: import json # type: ignore from libcloud.utils.py3 import ET from libcloud.utils.py3 import _real_unicode from libcloud.utils.py3 import basestring from libcloud.common.base import ConnectionUserAndKey, XmlResponse, BaseDriver from libcloud.common.base import JsonResponse from libcloud.common.types import InvalidCredsError, MalformedResponseError from libcloud.utils.py3 import b, httplib, urlquote from libcloud.utils.xml import findtext, findall __all__ = [ 'AWSBaseResponse', 'AWSGenericResponse', 'AWSTokenConnection', 'SignedAWSConnection', 'AWSRequestSignerAlgorithmV2', 'AWSRequestSignerAlgorithmV4', 'AWSDriver' ] DEFAULT_SIGNATURE_VERSION = '2' UNSIGNED_PAYLOAD = 'UNSIGNED-PAYLOAD' PARAMS_NOT_STRING_ERROR_MSG = """ "params" dictionary contains an attribute "%s" which value (%s, %s) is not a string. Parameters are sent via query parameters and not via request body and as such, all the values need to be of a simple type (string, int, bool). For arrays and other complex types, you should use notation similar to this one: params['TagSpecification.1.Tag.Value'] = 'foo' params['TagSpecification.2.Tag.Value'] = 'bar' See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/Query-Requests.html for details. """.strip() class AWSBaseResponse(XmlResponse): namespace = None def _parse_error_details(self, element): """ Parse code and message from the provided error element. :return: ``tuple`` with two elements: (code, message) :rtype: ``tuple`` """ code = findtext(element=element, xpath='Code', namespace=self.namespace) message = findtext(element=element, xpath='Message', namespace=self.namespace) return code, message class AWSGenericResponse(AWSBaseResponse): # There are multiple error messages in AWS, but they all have an Error node # with Code and Message child nodes. Xpath to select them # None if the root node *is* the Error node xpath = None # This dict maps CodeName to a specific # exception class that is raised immediately. # If a custom exception class is not defined, errors are accumulated and # returned from the parse_error method. exceptions = {} # type: Dict[str, Type[Exception]] def success(self): return self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def parse_error(self): context = self.connection.context status = int(self.status) # FIXME: Probably ditch this as the forbidden message will have # corresponding XML. if status == httplib.FORBIDDEN: if not self.body: raise InvalidCredsError(str(self.status) + ': ' + self.error) else: raise InvalidCredsError(self.body) try: body = ET.XML(self.body) except Exception: raise MalformedResponseError('Failed to parse XML', body=self.body, driver=self.connection.driver) if self.xpath: errs = findall(element=body, xpath=self.xpath, namespace=self.namespace) else: errs = [body] msgs = [] for err in errs: code, message = self._parse_error_details(element=err) exceptionCls = self.exceptions.get(code, None) if exceptionCls is None: msgs.append('%s: %s' % (code, message)) continue # Custom exception class is defined, immediately throw an exception params = {} if hasattr(exceptionCls, 'kwargs'): for key in exceptionCls.kwargs: if key in context: params[key] = context[key] raise exceptionCls(value=message, driver=self.connection.driver, **params) return "\n".join(msgs) class AWSTokenConnection(ConnectionUserAndKey): def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, token=None, retry_delay=None, backoff=None): self.token = token super(AWSTokenConnection, self).__init__(user_id, key, secure=secure, host=host, port=port, url=url, timeout=timeout, retry_delay=retry_delay, backoff=backoff, proxy_url=proxy_url) def add_default_params(self, params): # Even though we are adding it to the headers, we need it here too # so that the token is added to the signature. if self.token: params['x-amz-security-token'] = self.token return super(AWSTokenConnection, self).add_default_params(params) def add_default_headers(self, headers): if self.token: headers['x-amz-security-token'] = self.token return super(AWSTokenConnection, self).add_default_headers(headers) class AWSRequestSigner(object): """ Class which handles signing the outgoing AWS requests. """ def __init__(self, access_key, access_secret, version, connection): """ :param access_key: Access key. :type access_key: ``str`` :param access_secret: Access secret. :type access_secret: ``str`` :param version: API version. :type version: ``str`` :param connection: Connection instance. :type connection: :class:`Connection` """ self.access_key = access_key self.access_secret = access_secret self.version = version # TODO: Remove cycling dependency between connection and signer self.connection = connection def get_request_params(self, params, method='GET', path='/'): return params def get_request_headers(self, params, headers, method='GET', path='/', data=None): return params, headers class AWSRequestSignerAlgorithmV2(AWSRequestSigner): def get_request_params(self, params, method='GET', path='/'): params['SignatureVersion'] = '2' params['SignatureMethod'] = 'HmacSHA256' params['AWSAccessKeyId'] = self.access_key params['Version'] = self.version params['Timestamp'] = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) params['Signature'] = self._get_aws_auth_param( params=params, secret_key=self.access_secret, path=path) return params def _get_aws_auth_param(self, params, secret_key, path='/'): """ Creates the signature required for AWS, per http://bit.ly/aR7GaQ [docs.amazonwebservices.com]: StringToSign = HTTPVerb + "\n" + ValueOfHostHeaderInLowercase + "\n" + HTTPRequestURI + "\n" + CanonicalizedQueryString """ connection = self.connection keys = list(params.keys()) keys.sort() pairs = [] for key in keys: value = str(params[key]) pairs.append(urlquote(key, safe='') + '=' + urlquote(value, safe='-_~')) qs = '&'.join(pairs) hostname = connection.host if (connection.secure and connection.port != 443) or \ (not connection.secure and connection.port != 80): hostname += ':' + str(connection.port) string_to_sign = '\n'.join(('GET', hostname, path, qs)) b64_hmac = base64.b64encode( hmac.new(b(secret_key), b(string_to_sign), digestmod=sha256).digest() ) return b64_hmac.decode('utf-8') class AWSRequestSignerAlgorithmV4(AWSRequestSigner): def get_request_params(self, params, method='GET', path='/'): if method == 'GET': params['Version'] = self.version return params def get_request_headers(self, params, headers, method='GET', path='/', data=None): now = datetime.utcnow() headers['X-AMZ-Date'] = now.strftime('%Y%m%dT%H%M%SZ') headers['X-AMZ-Content-SHA256'] = self._get_payload_hash(method, data) headers['Authorization'] = \ self._get_authorization_v4_header(params=params, headers=headers, dt=now, method=method, path=path, data=data) return params, headers def _get_authorization_v4_header(self, params, headers, dt, method='GET', path='/', data=None): credentials_scope = self._get_credential_scope(dt=dt) signed_headers = self._get_signed_headers(headers=headers) signature = self._get_signature(params=params, headers=headers, dt=dt, method=method, path=path, data=data) return 'AWS4-HMAC-SHA256 Credential=%(u)s/%(c)s, ' \ 'SignedHeaders=%(sh)s, Signature=%(s)s' % { 'u': self.access_key, 'c': credentials_scope, 'sh': signed_headers, 's': signature } def _get_signature(self, params, headers, dt, method, path, data): key = self._get_key_to_sign_with(dt) string_to_sign = self._get_string_to_sign(params=params, headers=headers, dt=dt, method=method, path=path, data=data) return _sign(key=key, msg=string_to_sign, hex=True) def _get_key_to_sign_with(self, dt): return _sign( _sign( _sign( _sign(('AWS4' + self.access_secret), dt.strftime('%Y%m%d')), self.connection.driver.region_name), self.connection.service_name), 'aws4_request') def _get_string_to_sign(self, params, headers, dt, method, path, data): canonical_request = self._get_canonical_request(params=params, headers=headers, method=method, path=path, data=data) return '\n'.join(['AWS4-HMAC-SHA256', dt.strftime('%Y%m%dT%H%M%SZ'), self._get_credential_scope(dt), _hash(canonical_request)]) def _get_credential_scope(self, dt): return '/'.join([dt.strftime('%Y%m%d'), self.connection.driver.region_name, self.connection.service_name, 'aws4_request']) def _get_signed_headers(self, headers): return ';'.join([k.lower() for k in sorted(headers.keys())]) def _get_canonical_headers(self, headers): return '\n'.join([':'.join([k.lower(), str(v).strip()]) for k, v in sorted(headers.items())]) + '\n' def _get_payload_hash(self, method, data=None): if method in ('POST', 'PUT'): if data: if hasattr(data, 'next') or hasattr(data, '__next__'): # File upload; don't try to read the entire payload return UNSIGNED_PAYLOAD return _hash(data) else: return UNSIGNED_PAYLOAD else: return _hash('') def _get_request_params(self, params): # For self.method == GET return '&'.join(["%s=%s" % (urlquote(k, safe=''), urlquote(str(v), safe='~')) for k, v in sorted(params.items())]) def _get_canonical_request(self, params, headers, method, path, data): return '\n'.join([ method, path, self._get_request_params(params), self._get_canonical_headers(headers), self._get_signed_headers(headers), self._get_payload_hash(method, data) ]) class SignedAWSConnection(AWSTokenConnection): version = None def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, token=None, retry_delay=None, backoff=None, signature_version=DEFAULT_SIGNATURE_VERSION): super(SignedAWSConnection, self).__init__(user_id=user_id, key=key, secure=secure, host=host, port=port, url=url, timeout=timeout, token=token, retry_delay=retry_delay, backoff=backoff, proxy_url=proxy_url) self.signature_version = str(signature_version) if self.signature_version == '2': signer_cls = AWSRequestSignerAlgorithmV2 elif self.signature_version == '4': signer_cls = AWSRequestSignerAlgorithmV4 else: raise ValueError('Unsupported signature_version: %s' % (signature_version)) self.signer = signer_cls(access_key=self.user_id, access_secret=self.key, version=self.version, connection=self) def add_default_params(self, params): params = self.signer.get_request_params(params=params, method=self.method, path=self.action) # Verify that params only contain simple types and no nested # dictionaries. # params are sent via query params so only strings are supported for key, value in params.items(): if not isinstance(value, (_real_unicode, basestring, int, bool)): msg = PARAMS_NOT_STRING_ERROR_MSG % (key, value, type(value)) raise ValueError(msg) return params def pre_connect_hook(self, params, headers): params, headers = self.signer.get_request_headers(params=params, headers=headers, method=self.method, path=self.action, data=self.data) return params, headers class AWSJsonResponse(JsonResponse): """ Amazon ECS response class. ECS API uses JSON unlike the s3, elb drivers """ def parse_error(self): response = json.loads(self.body) code = response['__type'] message = response.get('Message', response['message']) return ('%s: %s' % (code, message)) def _sign(key, msg, hex=False): if hex: return hmac.new(b(key), b(msg), hashlib.sha256).hexdigest() else: return hmac.new(b(key), b(msg), hashlib.sha256).digest() def _hash(msg): return hashlib.sha256(b(msg)).hexdigest() class AWSDriver(BaseDriver): def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=None, token=None, **kwargs): self.token = token super(AWSDriver, self).__init__(key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, token=token, **kwargs) def _ex_connection_class_kwargs(self): kwargs = super(AWSDriver, self)._ex_connection_class_kwargs() kwargs['token'] = self.token return kwargs apache-libcloud-2.8.0/libcloud/common/azure.py0000664000175000017500000002405313576514553021232 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import copy import os import time import base64 import hmac from hashlib import sha256 from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.utils.xml import fixxpath from libcloud.utils.py3 import ET from libcloud.common.types import InvalidCredsError from libcloud.common.types import LibcloudError, MalformedResponseError from libcloud.common.base import ConnectionUserAndKey, RawResponse from libcloud.common.base import CertificateConnection from libcloud.common.base import XmlResponse from libcloud.common.base import BaseDriver # The time format for headers in Azure requests AZURE_TIME_FORMAT = '%a, %d %b %Y %H:%M:%S GMT' class AzureRedirectException(Exception): def __init__(self, response): self.location = response.headers['location'] class AzureResponse(XmlResponse): valid_response_codes = [ httplib.NOT_FOUND, httplib.CONFLICT, httplib.BAD_REQUEST, httplib.TEMPORARY_REDIRECT # added TEMPORARY_REDIRECT as this can sometimes be # sent by azure instead of a success or fail response ] def success(self): i = int(self.status) return 200 <= i <= 299 or i in self.valid_response_codes def parse_error(self, msg=None): error_msg = 'Unknown error' try: # Azure does give some meaningful errors, but is inconsistent # Some APIs respond with an XML error. Others just dump HTML body = self.parse_body() # pylint: disable=no-member if type(body) == ET.Element: code = body.findtext(fixxpath(xpath='Code')) message = body.findtext(fixxpath(xpath='Message')) message = message.split('\n')[0] error_msg = '%s: %s' % (code, message) except MalformedResponseError: pass if msg: error_msg = '%s - %s' % (msg, error_msg) if self.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]: raise InvalidCredsError(error_msg) raise LibcloudError( '%s Status code: %d.' % (error_msg, self.status), driver=self ) def parse_body(self): is_redirect = int(self.status) == httplib.TEMPORARY_REDIRECT if is_redirect and self.connection.driver.follow_redirects: raise AzureRedirectException(self) else: return super(AzureResponse, self).parse_body() class AzureRawResponse(RawResponse): pass class AzureConnection(ConnectionUserAndKey): """ Represents a single connection to Azure """ responseCls = AzureResponse rawResponseCls = AzureRawResponse API_VERSION = '2012-02-12' def add_default_params(self, params): return params def pre_connect_hook(self, params, headers): headers = copy.deepcopy(headers) # We have to add a date header in GMT headers['x-ms-date'] = time.strftime(AZURE_TIME_FORMAT, time.gmtime()) headers['x-ms-version'] = self.API_VERSION # Add the authorization header headers['Authorization'] = self._get_azure_auth_signature( method=self.method, headers=headers, params=params, account=self.user_id, secret_key=self.key, path=self.action ) # Azure cribs about this in 'raw' connections headers.pop('Host', None) return params, headers def _get_azure_auth_signature(self, method, headers, params, account, secret_key, path='/'): """ Signature = Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) ) ); StringToSign = HTTP-VERB + "\n" + Content-Encoding + "\n" + Content-Language + "\n" + Content-Length + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + If-Modified-Since + "\n" + If-Match + "\n" + If-None-Match + "\n" + If-Unmodified-Since + "\n" + Range + "\n" + CanonicalizedHeaders + CanonicalizedResource; """ xms_header_values = [] param_list = [] # Split the x-ms headers and normal headers and make everything # lower case headers_copy = {} for header, value in headers.items(): header = header.lower() value = str(value).strip() if header.startswith('x-ms-'): xms_header_values.append((header, value)) else: headers_copy[header] = value # Get the values for the headers in the specific order special_header_values = self._format_special_header_values( headers_copy, method) # Prepare the first section of the string to be signed values_to_sign = [method] + special_header_values # string_to_sign = '\n'.join([method] + special_header_values) # The x-ms-* headers have to be in lower case and sorted xms_header_values.sort() for header, value in xms_header_values: values_to_sign.append('%s:%s' % (header, value)) # Add the canonicalized path values_to_sign.append('/%s%s' % (account, path)) # URL query parameters (sorted and lower case) for key, value in params.items(): param_list.append((key.lower(), str(value).strip())) param_list.sort() for key, value in param_list: values_to_sign.append('%s:%s' % (key, value)) string_to_sign = b('\n'.join(values_to_sign)) secret_key = b(secret_key) b64_hmac = base64.b64encode( hmac.new(secret_key, string_to_sign, digestmod=sha256).digest() ) return 'SharedKey %s:%s' % (self.user_id, b64_hmac.decode('utf-8')) def _format_special_header_values(self, headers, method): is_change = method not in ('GET', 'HEAD') is_old_api = self.API_VERSION <= '2014-02-14' special_header_keys = [ 'content-encoding', 'content-language', 'content-length', 'content-md5', 'content-type', 'date', 'if-modified-since', 'if-match', 'if-none-match', 'if-unmodified-since', 'range' ] special_header_values = [] for header in special_header_keys: header = header.lower() # Just for safety if header in headers: special_header_values.append(headers[header]) elif header == 'content-length' and is_change and is_old_api: # For old API versions, the Content-Length header must be '0' # https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key#content-length-header-in-version-2014-02-14-and-earlier special_header_values.append('0') else: special_header_values.append('') return special_header_values class AzureBaseDriver(BaseDriver): name = "Microsoft Azure Service Management API" class AzureServiceManagementConnection(CertificateConnection): # This needs the following approach - # 1. Make request using LibcloudHTTPSConnection which is a overloaded # class which takes in a client certificate # 2. Depending on the type of operation use a PollingConnection # when the response id is returned # 3. The Response can be used in an AzureServiceManagementResponse """ Authentication class for "Service Account" authentication. """ driver = AzureBaseDriver responseCls = AzureResponse rawResponseCls = AzureRawResponse name = 'Azure Service Management API Connection' host = 'management.core.windows.net' keyfile = "" def __init__(self, subscription_id, key_file, *args, **kwargs): """ Check to see if PyCrypto is available, and convert key file path into a key string if the key is in a file. :param subscription_id: Azure subscription ID. :type subscription_id: ``str`` :param key_file: The PEM file used to authenticate with the service. :type key_file: ``str`` """ super(AzureServiceManagementConnection, self).__init__( key_file, *args, **kwargs ) self.subscription_id = subscription_id keypath = os.path.expanduser(key_file) self.keyfile = keypath is_file_path = os.path.exists(keypath) and os.path.isfile(keypath) if not is_file_path: raise InvalidCredsError( 'You need an certificate PEM file to authenticate with ' 'Microsoft Azure. This can be found in the portal.' ) self.key_file = key_file def add_default_headers(self, headers): """ @inherits: :class:`Connection.add_default_headers` TODO: move to constant.. """ headers['x-ms-version'] = "2014-05-01" headers['x-ms-date'] = time.strftime(AZURE_TIME_FORMAT, time.gmtime()) # headers['host'] = self.host return headers apache-libcloud-2.8.0/libcloud/common/azure_arm.py0000664000175000017500000002351213576514553022070 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. try: import simplejson as json except ImportError: import json # type: ignore import time from libcloud.utils.py3 import urlparse from libcloud.common.base import (ConnectionUserAndKey, JsonResponse, RawResponse) from libcloud.common.base import BaseDriver from libcloud.http import LibcloudConnection from libcloud.utils.py3 import basestring, urlencode class AzureBaseDriver(BaseDriver): name = "Microsoft Azure Resource Management API" class AzureJsonResponse(JsonResponse): def parse_error(self): b = self.parse_body() if isinstance(b, basestring): return b elif isinstance(b, dict) and "error" in b: return "[%s] %s" % (b["error"].get("code"), b["error"].get("message")) else: return str(b) class AzureAuthJsonResponse(JsonResponse): def parse_error(self): b = self.parse_body() if isinstance(b, basestring): return b elif isinstance(b, dict) and "error_description" in b: return b["error_description"] else: return str(b) # Based on # https://github.com/Azure/azure-xplat-cli/blob/master/lib/util/profile/environment.js publicEnvironments = { "default": { 'name': 'default', 'portalUrl': 'http://go.microsoft.com/fwlink/?LinkId=254433', 'publishingProfileUrl': 'http://go.microsoft.com/fwlink/?LinkId=254432', 'managementEndpointUrl': 'https://management.core.windows.net', 'resourceManagerEndpointUrl': 'https://management.azure.com/', 'sqlManagementEndpointUrl': 'https://management.core.windows.net:8443/', 'sqlServerHostnameSuffix': '.database.windows.net', 'galleryEndpointUrl': 'https://gallery.azure.com/', 'activeDirectoryEndpointUrl': 'https://login.microsoftonline.com', 'activeDirectoryResourceId': 'https://management.core.windows.net/', 'activeDirectoryGraphResourceId': 'https://graph.windows.net/', 'activeDirectoryGraphApiVersion': '2013-04-05', 'storageEndpointSuffix': '.core.windows.net', 'keyVaultDnsSuffix': '.vault.azure.net', 'azureDataLakeStoreFileSystemEndpointSuffix': 'azuredatalakestore.net', 'azureDataLakeAnalyticsCatalogAndJobEndpointSuffix': 'azuredatalakeanalytics.net' }, "AzureChinaCloud": { 'name': 'AzureChinaCloud', 'portalUrl': 'http://go.microsoft.com/fwlink/?LinkId=301902', 'publishingProfileUrl': 'http://go.microsoft.com/fwlink/?LinkID=301774', 'managementEndpointUrl': 'https://management.core.chinacloudapi.cn', 'resourceManagerEndpointUrl': 'https://management.chinacloudapi.cn', 'sqlManagementEndpointUrl': 'https://management.core.chinacloudapi.cn:8443/', 'sqlServerHostnameSuffix': '.database.chinacloudapi.cn', 'galleryEndpointUrl': 'https://gallery.chinacloudapi.cn/', 'activeDirectoryEndpointUrl': 'https://login.chinacloudapi.cn', 'activeDirectoryResourceId': 'https://management.core.chinacloudapi.cn/', 'activeDirectoryGraphResourceId': 'https://graph.chinacloudapi.cn/', 'activeDirectoryGraphApiVersion': '2013-04-05', 'storageEndpointSuffix': '.core.chinacloudapi.cn', 'keyVaultDnsSuffix': '.vault.azure.cn', 'azureDataLakeStoreFileSystemEndpointSuffix': 'N/A', 'azureDataLakeAnalyticsCatalogAndJobEndpointSuffix': 'N/A' }, "AzureUSGovernment": { 'name': 'AzureUSGovernment', 'portalUrl': 'https://manage.windowsazure.us', 'publishingProfileUrl': 'https://manage.windowsazure.us/publishsettings/index', 'managementEndpointUrl': 'https://management.core.usgovcloudapi.net', 'resourceManagerEndpointUrl': 'https://management.usgovcloudapi.net', 'sqlManagementEndpointUrl': 'https://management.core.usgovcloudapi.net:8443/', 'sqlServerHostnameSuffix': '.database.usgovcloudapi.net', 'galleryEndpointUrl': 'https://gallery.usgovcloudapi.net/', 'activeDirectoryEndpointUrl': 'https://login-us.microsoftonline.com', 'activeDirectoryResourceId': 'https://management.core.usgovcloudapi.net/', 'activeDirectoryGraphResourceId': 'https://graph.windows.net/', 'activeDirectoryGraphApiVersion': '2013-04-05', 'storageEndpointSuffix': '.core.usgovcloudapi.net', 'keyVaultDnsSuffix': '.vault.usgovcloudapi.net', 'azureDataLakeStoreFileSystemEndpointSuffix': 'N/A', 'azureDataLakeAnalyticsCatalogAndJobEndpointSuffix': 'N/A' }, "AzureGermanCloud": { 'name': 'AzureGermanCloud', 'portalUrl': 'http://portal.microsoftazure.de/', 'publishingProfileUrl': 'https://manage.microsoftazure.de/publishsettings/index', 'managementEndpointUrl': 'https://management.core.cloudapi.de', 'resourceManagerEndpointUrl': 'https://management.microsoftazure.de', 'sqlManagementEndpointUrl': 'https://management.core.cloudapi.de:8443/', 'sqlServerHostnameSuffix': '.database.cloudapi.de', 'galleryEndpointUrl': 'https://gallery.cloudapi.de/', 'activeDirectoryEndpointUrl': 'https://login.microsoftonline.de', 'activeDirectoryResourceId': 'https://management.core.cloudapi.de/', 'activeDirectoryGraphResourceId': 'https://graph.cloudapi.de/', 'activeDirectoryGraphApiVersion': '2013-04-05', 'storageEndpointSuffix': '.core.cloudapi.de', 'keyVaultDnsSuffix': '.vault.microsoftazure.de', 'azureDataLakeStoreFileSystemEndpointSuffix': 'N/A', 'azureDataLakeAnalyticsCatalogAndJobEndpointSuffix': 'N/A' } } class AzureResourceManagementConnection(ConnectionUserAndKey): """ Represents a single connection to Azure """ conn_class = LibcloudConnection driver = AzureBaseDriver name = 'Azure AD Auth' responseCls = AzureJsonResponse rawResponseCls = RawResponse def __init__(self, key, secret, secure=True, tenant_id=None, subscription_id=None, cloud_environment=None, **kwargs): super(AzureResourceManagementConnection, self) \ .__init__(key, secret, **kwargs) if not cloud_environment: cloud_environment = "default" if isinstance(cloud_environment, basestring): cloud_environment = publicEnvironments[cloud_environment] if not isinstance(cloud_environment, dict): raise Exception("cloud_environment must be one of '%s' or a dict " "containing keys 'resourceManagerEndpointUrl', " "'activeDirectoryEndpointUrl', " "'activeDirectoryResourceId', " "'storageEndpointSuffix'" % ( "', '".join(publicEnvironments.keys()))) self.host = urlparse.urlparse( cloud_environment['resourceManagerEndpointUrl']).hostname self.login_host = urlparse.urlparse( cloud_environment['activeDirectoryEndpointUrl']).hostname self.login_resource = cloud_environment['activeDirectoryResourceId'] self.storage_suffix = cloud_environment['storageEndpointSuffix'] self.tenant_id = tenant_id self.subscription_id = subscription_id def add_default_headers(self, headers): headers['Content-Type'] = "application/json" headers['Authorization'] = "Bearer %s" % self.access_token return headers def encode_data(self, data): """Encode data to JSON""" return json.dumps(data) def get_token_from_credentials(self): """ Log in and get bearer token used to authorize API requests. """ conn = self.conn_class(self.login_host, 443, timeout=self.timeout) conn.connect() params = urlencode({ "grant_type": "client_credentials", "client_id": self.user_id, "client_secret": self.key, "resource": self.login_resource }) headers = {"Content-type": "application/x-www-form-urlencoded"} conn.request("POST", "/%s/oauth2/token" % self.tenant_id, params, headers) js = AzureAuthJsonResponse(conn.getresponse(), conn) self.access_token = js.object["access_token"] self.expires_on = js.object["expires_on"] def connect(self, **kwargs): self.get_token_from_credentials() return super(AzureResourceManagementConnection, self).connect(**kwargs) def request(self, action, params=None, data=None, headers=None, method='GET', raw=False): # Log in again if the token has expired or is going to expire soon # (next 5 minutes). if (time.time() + 300) >= int(self.expires_on): self.get_token_from_credentials() return super(AzureResourceManagementConnection, self) \ .request(action, params=params, data=data, headers=headers, method=method, raw=raw) apache-libcloud-2.8.0/libcloud/common/base.py0000664000175000017500000010061013576514553021010 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import Union from typing import Type from typing import Optional import json import os import ssl import socket import copy import binascii import time from libcloud.utils.py3 import ET import libcloud from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import urlencode from libcloud.utils.misc import lowercase_keys, retry from libcloud.common.exceptions import exception_from_message from libcloud.common.types import LibcloudError, MalformedResponseError from libcloud.http import LibcloudConnection, HttpLibResponseProxy __all__ = [ 'RETRY_FAILED_HTTP_REQUESTS', 'BaseDriver', 'Connection', 'PollingConnection', 'ConnectionKey', 'ConnectionUserAndKey', 'CertificateConnection', 'Response', 'HTTPResponse', 'JsonResponse', 'XmlResponse', 'RawResponse' ] # Module level variable indicates if the failed HTTP requests should be retried RETRY_FAILED_HTTP_REQUESTS = False class LazyObject(object): """An object that doesn't get initialized until accessed.""" @classmethod def _proxy(cls, *lazy_init_args, **lazy_init_kwargs): class Proxy(cls, object): _lazy_obj = None def __init__(self): # Must override the lazy_cls __init__ pass def __getattribute__(self, attr): lazy_obj = object.__getattribute__(self, '_get_lazy_obj')() return getattr(lazy_obj, attr) def __setattr__(self, attr, value): lazy_obj = object.__getattribute__(self, '_get_lazy_obj')() setattr(lazy_obj, attr, value) def _get_lazy_obj(self): lazy_obj = object.__getattribute__(self, '_lazy_obj') if lazy_obj is None: lazy_obj = cls(*lazy_init_args, **lazy_init_kwargs) object.__setattr__(self, '_lazy_obj', lazy_obj) return lazy_obj return Proxy() @classmethod def lazy(cls, *lazy_init_args, **lazy_init_kwargs): """Create a lazily instantiated instance of the subclass, cls.""" return cls._proxy(*lazy_init_args, **lazy_init_kwargs) class HTTPResponse(httplib.HTTPResponse): # On python 2.6 some calls can hang because HEAD isn't quite properly # supported. # In particular this happens on S3 when calls are made to get_object to # objects that don't exist. # This applies the behaviour from 2.7, fixing the hangs. def read(self, amt=None): if self.fp is None: return '' if self._method == 'HEAD': self.close() return '' return httplib.HTTPResponse.read(self, amt) class Response(object): """ A base Response class to derive from. """ # Response status code status = httplib.OK # type: int # Response headers headers = {} # type: dict # Raw response body body = None # Parsed response body object = None error = None # Reason returned by the server. connection = None # Parent connection class parse_zero_length_body = False def __init__(self, response, connection): """ :param response: HTTP response object. (optional) :type response: :class:`httplib.HTTPResponse` :param connection: Parent connection object. :type connection: :class:`.Connection` """ self.connection = connection # http.client In Python 3 doesn't automatically lowercase the header # names self.headers = lowercase_keys(dict(response.headers)) self.error = response.reason self.status = response.status_code self.request = response.request self.iter_content = response.iter_content self.body = response.text.strip() \ if response.text is not None and hasattr(response.text, 'strip') \ else '' if not self.success(): raise exception_from_message(code=self.status, message=self.parse_error(), headers=self.headers) self.object = self.parse_body() def parse_body(self): """ Parse response body. Override in a provider's subclass. :return: Parsed body. :rtype: ``str`` """ return self.body if self.body is not None else '' def parse_error(self): """ Parse the error messages. Override in a provider's subclass. :return: Parsed error. :rtype: ``str`` """ return self.body def success(self): """ Determine if our request was successful. The meaning of this can be arbitrary; did we receive OK status? Did the node get created? Were we authenticated? :rtype: ``bool`` :return: ``True`` or ``False`` """ # pylint: disable=E1101 import requests return self.status in [requests.codes.ok, requests.codes.created, httplib.OK, httplib.CREATED, httplib.ACCEPTED] class JsonResponse(Response): """ A Base JSON Response class to derive from. """ def parse_body(self): if len(self.body) == 0 and not self.parse_zero_length_body: return self.body try: body = json.loads(self.body) except Exception: raise MalformedResponseError( 'Failed to parse JSON', body=self.body, driver=self.connection.driver) return body parse_error = parse_body class XmlResponse(Response): """ A Base XML Response class to derive from. """ def parse_body(self): if len(self.body) == 0 and not self.parse_zero_length_body: return self.body try: try: body = ET.XML(self.body) except ValueError: # lxml wants a bytes and tests are basically hard-coded to str body = ET.XML(self.body.encode('utf-8')) except Exception: raise MalformedResponseError('Failed to parse XML', body=self.body, driver=self.connection.driver) return body parse_error = parse_body class RawResponse(Response): def __init__(self, connection, response=None): """ :param connection: Parent connection object. :type connection: :class:`.Connection` """ self._status = None self._response = None self._headers = {} self._error = None self._reason = None self.connection = connection if response is not None: self.headers = lowercase_keys(dict(response.headers)) self.error = response.reason self.status = response.status_code self.request = response.request self.iter_content = response.iter_content def success(self): """ Determine if our request was successful. The meaning of this can be arbitrary; did we receive OK status? Did the node get created? Were we authenticated? :rtype: ``bool`` :return: ``True`` or ``False`` """ # pylint: disable=E1101 import requests return self.status in [requests.codes.ok, requests.codes.created, httplib.OK, httplib.CREATED, httplib.ACCEPTED] @property def response(self): if not self._response: response = self.connection.connection.getresponse() self._response = HttpLibResponseProxy(response) if not self.success(): self.parse_error() return self._response @property def body(self): # Note: We use property to avoid saving whole response body into RAM # See https://github.com/apache/libcloud/pull/1132 for details return self.response.body @property def reason(self): if not self._reason: self._reason = self.response.reason return self._reason class Connection(object): """ A Base Connection class to derive from. """ conn_class = LibcloudConnection responseCls = Response rawResponseCls = RawResponse connection = None host = '127.0.0.1' # type: str port = 443 timeout = None # type: Optional[Union[int, float]] secure = 1 driver = None # type: Type[BaseDriver] action = None cache_busting = False backoff = None retry_delay = None allow_insecure = True def __init__(self, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, retry_delay=None, backoff=None): self.secure = secure and 1 or 0 self.ua = [] self.context = {} if not self.allow_insecure and not secure: # TODO: We should eventually switch to whitelist instead of # blacklist approach raise ValueError('Non https connections are not allowed (use ' 'secure=True)') self.request_path = '' if host: self.host = host if port is not None: self.port = port else: if self.secure == 1: self.port = 443 else: self.port = 80 if url: (self.host, self.port, self.secure, self.request_path) = self._tuple_from_url(url) self.timeout = timeout or self.timeout self.retry_delay = retry_delay self.backoff = backoff self.proxy_url = proxy_url def set_http_proxy(self, proxy_url): """ Set a HTTP / HTTPS proxy which will be used with this connection. :param proxy_url: Proxy URL (e.g. http://: without authentication and ://:@: for basic auth authentication information. :type proxy_url: ``str`` """ self.proxy_url = proxy_url # NOTE: Because of the way connection instantion works, we need to call # self.connection.set_http_proxy() here. Just setting "self.proxy_url" # won't work. self.connection.set_http_proxy(proxy_url=proxy_url) def set_context(self, context): if not isinstance(context, dict): raise TypeError('context needs to be a dictionary') self.context = context def reset_context(self): self.context = {} def _tuple_from_url(self, url): secure = 1 port = None (scheme, netloc, request_path, param, query, fragment) = urlparse.urlparse(url) if scheme not in ['http', 'https']: raise LibcloudError('Invalid scheme: %s in url %s' % (scheme, url)) if scheme == "http": secure = 0 if ":" in netloc: netloc, port = netloc.rsplit(":") port = int(port) if not port: if scheme == "http": port = 80 else: port = 443 host = netloc port = int(port) return (host, port, secure, request_path) def connect(self, host=None, port=None, base_url=None, **kwargs): """ Establish a connection with the API server. :type host: ``str`` :param host: Optional host to override our default :type port: ``int`` :param port: Optional port to override our default :returns: A connection """ # prefer the attribute base_url if its set or sent connection = None secure = self.secure if getattr(self, 'base_url', None) and base_url is None: (host, port, secure, request_path) = \ self._tuple_from_url(getattr(self, 'base_url')) elif base_url is not None: (host, port, secure, request_path) = self._tuple_from_url(base_url) else: host = host or self.host port = port or self.port # Make sure port is an int port = int(port) if not hasattr(kwargs, 'host'): kwargs.update({'host': host}) if not hasattr(kwargs, 'port'): kwargs.update({'port': port}) if not hasattr(kwargs, 'secure'): kwargs.update({'secure': self.secure}) if not hasattr(kwargs, 'key_file') and hasattr(self, 'key_file'): kwargs.update({'key_file': getattr(self, 'key_file')}) if not hasattr(kwargs, 'cert_file') and hasattr(self, 'cert_file'): kwargs.update({'cert_file': getattr(self, 'cert_file')}) if self.timeout: kwargs.update({'timeout': self.timeout}) if self.proxy_url: kwargs.update({'proxy_url': self.proxy_url}) connection = self.conn_class(**kwargs) # You can uncoment this line, if you setup a reverse proxy server # which proxies to your endpoint, and lets you easily capture # connections in cleartext when you setup the proxy to do SSL # for you # connection = self.conn_class("127.0.0.1", 8080) self.connection = connection def _user_agent(self): user_agent_suffix = ' '.join(['(%s)' % x for x in self.ua]) if self.driver: user_agent = 'libcloud/%s (%s) %s' % ( libcloud.__version__, self.driver.name, user_agent_suffix) else: user_agent = 'libcloud/%s %s' % ( libcloud.__version__, user_agent_suffix) return user_agent def user_agent_append(self, token): """ Append a token to a user agent string. Users of the library should call this to uniquely identify their requests to a provider. :type token: ``str`` :param token: Token to add to the user agent. """ self.ua.append(token) def request(self, action, params=None, data=None, headers=None, method='GET', raw=False, stream=False): """ Request a given `action`. Basically a wrapper around the connection object's `request` that does some helpful pre-processing. :type action: ``str`` :param action: A path. This can include arguments. If included, any extra parameters are appended to the existing ones. :type params: ``dict`` :param params: Optional mapping of additional parameters to send. If None, leave as an empty ``dict``. :type data: ``unicode`` :param data: A body of data to send with the request. :type headers: ``dict`` :param headers: Extra headers to add to the request None, leave as an empty ``dict``. :type method: ``str`` :param method: An HTTP method such as "GET" or "POST". :type raw: ``bool`` :param raw: True to perform a "raw" request aka only send the headers and use the rawResponseCls class. This is used with storage API when uploading a file. :type stream: ``bool`` :param stream: True to return an iterator in Response.iter_content and allow streaming of the response data (for downloading large files) :return: An :class:`Response` instance. :rtype: :class:`Response` instance """ if params is None: params = {} else: params = copy.copy(params) if headers is None: headers = {} else: headers = copy.copy(headers) retry_enabled = os.environ.get('LIBCLOUD_RETRY_FAILED_HTTP_REQUESTS', False) or RETRY_FAILED_HTTP_REQUESTS action = self.morph_action_hook(action) self.action = action self.method = method self.data = data # Extend default parameters params = self.add_default_params(params) # Add cache busting parameters (if enabled) if self.cache_busting and method == 'GET': params = self._add_cache_busting_to_params(params=params) # Extend default headers headers = self.add_default_headers(headers) # We always send a user-agent header headers.update({'User-Agent': self._user_agent()}) # Indicate that we support gzip and deflate compression headers.update({'Accept-Encoding': 'gzip,deflate'}) port = int(self.port) if port not in (80, 443): headers.update({'Host': "%s:%d" % (self.host, port)}) else: headers.update({'Host': self.host}) if data: data = self.encode_data(data) params, headers = self.pre_connect_hook(params, headers) if params: if '?' in action: url = '&'.join((action, urlencode(params, doseq=True))) else: url = '?'.join((action, urlencode(params, doseq=True))) else: url = action # IF connection has not yet been established if self.connection is None: self.connect() try: # @TODO: Should we just pass File object as body to request method # instead of dealing with splitting and sending the file ourselves? if raw: self.connection.prepared_request( method=method, url=url, body=data, headers=headers, raw=raw, stream=stream) else: if retry_enabled: retry_request = retry(timeout=self.timeout, retry_delay=self.retry_delay, backoff=self.backoff) retry_request(self.connection.request)(method=method, url=url, body=data, headers=headers, stream=stream) else: self.connection.request(method=method, url=url, body=data, headers=headers, stream=stream) except socket.gaierror as e: message = str(e) errno = getattr(e, 'errno', None) if errno == -5: # Throw a more-friendly exception on "no address associated # with hostname" error. This error could simpli indicate that # "host" Connection class attribute is set to an incorrect # value class_name = self.__class__.__name__ msg = ('%s. Perhaps "host" Connection class attribute ' '(%s.connection) is set to an invalid, non-hostname ' 'value (%s)?' % (message, class_name, self.host)) raise socket.gaierror(msg) self.reset_context() raise e except ssl.SSLError as e: self.reset_context() raise ssl.SSLError(str(e)) if raw: responseCls = self.rawResponseCls kwargs = {'connection': self, 'response': self.connection.getresponse()} else: responseCls = self.responseCls kwargs = {'connection': self, 'response': self.connection.getresponse()} try: response = responseCls(**kwargs) finally: # Always reset the context after the request has completed self.reset_context() return response def morph_action_hook(self, action): url = urlparse.urljoin(self.request_path.lstrip('/').rstrip('/') + '/', action.lstrip('/')) if not url.startswith('/'): return '/' + url else: return url def add_default_params(self, params): """ Adds default parameters (such as API key, version, etc.) to the passed `params` Should return a dictionary. """ return params def add_default_headers(self, headers): """ Adds default headers (such as Authorization, X-Foo-Bar) to the passed `headers` Should return a dictionary. """ return headers def pre_connect_hook(self, params, headers): """ A hook which is called before connecting to the remote server. This hook can perform a final manipulation on the params, headers and url parameters. :type params: ``dict`` :param params: Request parameters. :type headers: ``dict`` :param headers: Request headers. """ return params, headers def encode_data(self, data): """ Encode body data. Override in a provider's subclass. """ return data def _add_cache_busting_to_params(self, params): """ Add cache busting parameter to the query parameters of a GET request. Parameters are only added if "cache_busting" class attribute is set to True. Note: This should only be used with *naughty* providers which use excessive caching of responses. """ cache_busting_value = binascii.hexlify(os.urandom(8)).decode('ascii') if isinstance(params, dict): params['cache-busting'] = cache_busting_value else: params.append(('cache-busting', cache_busting_value)) return params class PollingConnection(Connection): """ Connection class which can also work with the async APIs. After initial requests, this class periodically polls for jobs status and waits until the job has finished. If job doesn't finish in timeout seconds, an Exception thrown. """ poll_interval = 0.5 timeout = 200 request_method = 'request' def async_request(self, action, params=None, data=None, headers=None, method='GET', context=None): """ Perform an 'async' request to the specified path. Keep in mind that this function is *blocking* and 'async' in this case means that the hit URL only returns a job ID which is the periodically polled until the job has completed. This function works like this: - Perform a request to the specified path. Response should contain a 'job_id'. - Returned 'job_id' is then used to construct a URL which is used for retrieving job status. Constructed URL is then periodically polled until the response indicates that the job has completed or the timeout of 'self.timeout' seconds has been reached. :type action: ``str`` :param action: A path :type params: ``dict`` :param params: Optional mapping of additional parameters to send. If None, leave as an empty ``dict``. :type data: ``unicode`` :param data: A body of data to send with the request. :type headers: ``dict`` :param headers: Extra headers to add to the request None, leave as an empty ``dict``. :type method: ``str`` :param method: An HTTP method such as "GET" or "POST". :type context: ``dict`` :param context: Context dictionary which is passed to the functions which construct initial and poll URL. :return: An :class:`Response` instance. :rtype: :class:`Response` instance """ request = getattr(self, self.request_method) kwargs = self.get_request_kwargs(action=action, params=params, data=data, headers=headers, method=method, context=context) response = request(**kwargs) kwargs = self.get_poll_request_kwargs(response=response, context=context, request_kwargs=kwargs) end = time.time() + self.timeout completed = False while time.time() < end and not completed: response = request(**kwargs) completed = self.has_completed(response=response) if not completed: time.sleep(self.poll_interval) if not completed: raise LibcloudError('Job did not complete in %s seconds' % (self.timeout)) return response def get_request_kwargs(self, action, params=None, data=None, headers=None, method='GET', context=None): """ Arguments which are passed to the initial request() call inside async_request. """ kwargs = {'action': action, 'params': params, 'data': data, 'headers': headers, 'method': method} return kwargs def get_poll_request_kwargs(self, response, context, request_kwargs): """ Return keyword arguments which are passed to the request() method when polling for the job status. :param response: Response object returned by poll request. :type response: :class:`HTTPResponse` :param request_kwargs: Kwargs previously used to initiate the poll request. :type response: ``dict`` :return ``dict`` Keyword arguments """ raise NotImplementedError('get_poll_request_kwargs not implemented') def has_completed(self, response): """ Return job completion status. :param response: Response object returned by poll request. :type response: :class:`HTTPResponse` :return ``bool`` True if the job has completed, False otherwise. """ raise NotImplementedError('has_completed not implemented') class ConnectionKey(Connection): """ Base connection class which accepts a single ``key`` argument. """ def __init__(self, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, backoff=None, retry_delay=None): """ Initialize `user_id` and `key`; set `secure` to an ``int`` based on passed value. """ super(ConnectionKey, self).__init__(secure=secure, host=host, port=port, url=url, timeout=timeout, proxy_url=proxy_url, backoff=backoff, retry_delay=retry_delay) self.key = key class CertificateConnection(Connection): """ Base connection class which accepts a single ``cert_file`` argument. """ def __init__(self, cert_file, secure=True, host=None, port=None, url=None, proxy_url=None, timeout=None, backoff=None, retry_delay=None): """ Initialize `cert_file`; set `secure` to an ``int`` based on passed value. """ super(CertificateConnection, self).__init__(secure=secure, host=host, port=port, url=url, timeout=timeout, backoff=backoff, retry_delay=retry_delay, proxy_url=proxy_url) self.cert_file = cert_file class KeyCertificateConnection(CertificateConnection): """ Base connection class which accepts both ``key_file`` and ``cert_file`` argument. """ key_file = None def __init__(self, key_file, cert_file, secure=True, host=None, port=None, url=None, proxy_url=None, timeout=None, backoff=None, retry_delay=None): """ Initialize `cert_file`; set `secure` to an ``int`` based on passed value. """ super(KeyCertificateConnection, self).__init__(cert_file, secure=secure, host=host, port=port, url=url, timeout=timeout, backoff=backoff, retry_delay=retry_delay, proxy_url=proxy_url) self.key_file = key_file class ConnectionUserAndKey(ConnectionKey): """ Base connection class which accepts a ``user_id`` and ``key`` argument. """ user_id = None # type: int def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, backoff=None, retry_delay=None): super(ConnectionUserAndKey, self).__init__(key, secure=secure, host=host, port=port, url=url, timeout=timeout, backoff=backoff, retry_delay=retry_delay, proxy_url=proxy_url) self.user_id = user_id class BaseDriver(object): """ Base driver class from which other classes can inherit from. """ connectionCls = ConnectionKey # type: Type[Connection] def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=None, **kwargs): """ :param key: API key or username to be used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Some providers only support HTTPS, and it is on by default. :type secure: ``bool`` :param host: Override hostname used for connections. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :param api_version: Optional API version. Only used by drivers which support multiple API versions. :type api_version: ``str`` :param region: Optional driver region. Only used by drivers which support multiple regions. :type region: ``str`` :rtype: ``None`` """ self.key = key self.secret = secret self.secure = secure args = [self.key] if self.secret is not None: args.append(self.secret) args.append(secure) if host is not None: args.append(host) if port is not None: args.append(port) self.api_version = api_version self.region = region conn_kwargs = self._ex_connection_class_kwargs() conn_kwargs.update({'timeout': kwargs.pop('timeout', None), 'retry_delay': kwargs.pop('retry_delay', None), 'backoff': kwargs.pop('backoff', None), 'proxy_url': kwargs.pop('proxy_url', None)}) self.connection = self.connectionCls(*args, **conn_kwargs) self.connection.driver = self self.connection.connect() def _ex_connection_class_kwargs(self): """ Return extra connection keyword arguments which are passed to the Connection class constructor. """ return {} apache-libcloud-2.8.0/libcloud/common/brightbox.py0000664000175000017500000000655013600144066022060 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.compute.types import InvalidCredsError from libcloud.utils.py3 import b from libcloud.utils.py3 import httplib from libcloud.utils.py3 import base64_encode_string try: import simplejson as json except ImportError: import json # type: ignore class BrightboxResponse(JsonResponse): def success(self): return httplib.OK <= self.status < httplib.BAD_REQUEST def parse_body(self): if self.headers['content-type'].split(';')[0] == 'application/json': return super(BrightboxResponse, self).parse_body() else: return self.body def parse_error(self): response = super(BrightboxResponse, self).parse_body() if 'error' in response: if response['error'] in ['invalid_client', 'unauthorized_client']: raise InvalidCredsError(response['error']) return response['error'] elif 'error_name' in response: return '%s: %s' % (response['error_name'], response['errors'][0]) return self.body class BrightboxConnection(ConnectionUserAndKey): """ Connection class for the Brightbox driver """ host = 'api.gb1.brightbox.com' responseCls = BrightboxResponse def _fetch_oauth_token(self): body = json.dumps({'client_id': self.user_id, 'grant_type': 'none'}) authorization = 'Basic ' + str(base64_encode_string(b('%s:%s' % (self.user_id, self.key)))).rstrip() self.connect() headers = { 'Host': self.host, 'User-Agent': self._user_agent(), 'Authorization': authorization, 'Content-Type': 'application/json', 'Content-Length': str(len(body)) } response = self.connection.request(method='POST', url='/token', body=body, headers=headers) if response.status == httplib.OK: return json.loads(response.read())['access_token'] else: responseCls = BrightboxResponse( response=response.getresponse(), connection=self) message = responseCls.parse_error() raise InvalidCredsError(message) def add_default_headers(self, headers): try: headers['Authorization'] = 'OAuth ' + self.token except AttributeError: self.token = self._fetch_oauth_token() headers['Authorization'] = 'OAuth ' + self.token return headers def encode_data(self, data): return json.dumps(data) apache-libcloud-2.8.0/libcloud/common/buddyns.py0000664000175000017500000000467113576514553021560 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import List from typing import Dict from libcloud.common.base import ConnectionKey, JsonResponse __all__ = [ 'API_HOST', 'BuddyNSException', 'BuddyNSResponse', 'BuddyNSConnection' ] # Endpoint for buddyns api API_HOST = 'www.buddyns.com' class BuddyNSResponse(JsonResponse): errors = [] # type: List[Dict] objects = [] # type: List[Dict] def __init__(self, response, connection): super(BuddyNSResponse, self).__init__(response=response, connection=connection) self.errors, self.objects = self.parse_body_and_errors() if not self.success(): raise BuddyNSException(code=self.status, message=self.errors.pop()['detail']) def parse_body_and_errors(self): js = super(BuddyNSResponse, self).parse_body() if 'detail' in js: self.errors.append(js) else: self.objects.append(js) return self.errors, self.objects def success(self): return len(self.errors) == 0 class BuddyNSConnection(ConnectionKey): host = API_HOST responseCls = BuddyNSResponse def add_default_headers(self, headers): headers['content-type'] = 'application/json' headers['Authorization'] = 'Token' + ' ' + self.key return headers class BuddyNSException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "BuddyNSException %s %s" % (self.code, self.message) apache-libcloud-2.8.0/libcloud/common/cloudsigma.py0000664000175000017500000001044513535474530022226 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'API_ENDPOINTS_1_0', 'API_ENDPOINTS_2_0', 'API_VERSIONS', 'INSTANCE_TYPES' ] # API end-points API_ENDPOINTS_1_0 = { 'zrh': { 'name': 'Zurich', 'country': 'Switzerland', 'host': 'api.zrh.cloudsigma.com' }, 'lvs': { 'name': 'Las Vegas', 'country': 'United States', 'host': 'api.lvs.cloudsigma.com' } } API_ENDPOINTS_2_0 = { 'zrh': { 'name': 'Zurich', 'country': 'Switzerland', 'host': 'zrh.cloudsigma.com' }, 'sjc': { 'name': 'San Jose, CA', 'country': 'United States', 'host': 'sjc.cloudsigma.com' }, 'mia': { 'name': 'Miami, FL', 'country': 'United States', 'host': 'mia.cloudsigma.com' }, 'wdc': { 'name': 'Washington, DC', 'country': 'United States', 'host': 'wdc.cloudsigma.com' }, 'hnl': { 'name': 'Honolulu, HI', 'country': 'United States', 'host': 'hnl.cloudsigma.com' }, 'per': { 'name': 'Perth, Australia', 'country': 'Australia', 'host': 'per.cloudsigma.com' }, 'mnl': { 'name': 'Manila, Philippines', 'country': 'Philippines', 'host': 'mnl.cloudsigma.com' }, 'waw': { 'name': 'Warsaw, Poland', 'country': 'Poland', 'host': 'waw.cloudsigma.com' } } DEFAULT_REGION = 'zrh' # Supported API versions. API_VERSIONS = [ '1.0' # old and deprecated '2.0' ] DEFAULT_API_VERSION = '2.0' # CloudSigma doesn't specify special instance types. # Basically for CPU any value between 0.5 GHz and 20.0 GHz should work, # 500 MB to 32000 MB for ram # and 1 GB to 1024 GB for hard drive size. # Plans in this file are based on examples listed on http://www.cloudsigma # .com/en/pricing/price-schedules INSTANCE_TYPES = [ { 'id': 'micro-regular', 'name': 'Micro/Regular instance', 'cpu': 1100, 'memory': 640, 'disk': 10 + 3, 'bandwidth': None, }, { 'id': 'micro-high-cpu', 'name': 'Micro/High CPU instance', 'cpu': 2200, 'memory': 640, 'disk': 80, 'bandwidth': None, }, { 'id': 'standard-small', 'name': 'Standard/Small instance', 'cpu': 1100, 'memory': 1741, 'disk': 50, 'bandwidth': None, }, { 'id': 'standard-large', 'name': 'Standard/Large instance', 'cpu': 4400, 'memory': 7680, 'disk': 250, 'bandwidth': None, }, { 'id': 'standard-extra-large', 'name': 'Standard/Extra Large instance', 'cpu': 8800, 'memory': 15360, 'disk': 500, 'bandwidth': None, }, { 'id': 'high-memory-extra-large', 'name': 'High Memory/Extra Large instance', 'cpu': 7150, 'memory': 17510, 'disk': 250, 'bandwidth': None, }, { 'id': 'high-memory-double-extra-large', 'name': 'High Memory/Double Extra Large instance', 'cpu': 14300, 'memory': 32768, 'disk': 500, 'bandwidth': None, }, { 'id': 'high-cpu-medium', 'name': 'High CPU/Medium instance', 'cpu': 5500, 'memory': 1741, 'disk': 150, 'bandwidth': None, }, { 'id': 'high-cpu-extra-large', 'name': 'High CPU/Extra Large instance', 'cpu': 20000, 'memory': 7168, 'disk': 500, 'bandwidth': None, } ] apache-libcloud-2.8.0/libcloud/common/cloudstack.py0000664000175000017500000001662413535474530022240 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import hashlib import copy import hmac from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlencode from libcloud.utils.py3 import urlquote from libcloud.utils.py3 import b from libcloud.common.types import ProviderError from libcloud.common.base import ConnectionUserAndKey, PollingConnection from libcloud.common.base import JsonResponse from libcloud.common.types import MalformedResponseError from libcloud.compute.types import InvalidCredsError class CloudStackResponse(JsonResponse): def parse_error(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError('Invalid provider credentials') value = None body = self.parse_body() if hasattr(body, 'values'): values = list(body.values())[0] if 'errortext' in values: value = values['errortext'] if value is None: value = self.body if not value: value = 'WARNING: error message text sent by provider was empty.' error = ProviderError(value=value, http_code=self.status, driver=self.connection.driver) raise error class CloudStackConnection(ConnectionUserAndKey, PollingConnection): responseCls = CloudStackResponse poll_interval = 1 request_method = '_sync_request' timeout = 600 ASYNC_PENDING = 0 ASYNC_SUCCESS = 1 ASYNC_FAILURE = 2 def encode_data(self, data): """ Must of the data is sent as part of query params (eeww), but in newer versions, userdata argument can be sent as a urlencoded data in the request body. """ if data: data = urlencode(data) return data def _make_signature(self, params): signature = [(k.lower(), v) for k, v in list(params.items())] signature.sort(key=lambda x: x[0]) pairs = [] for pair in signature: key = urlquote(str(pair[0]), safe='[]') value = urlquote(str(pair[1]), safe='[]*') item = '%s=%s' % (key, value) pairs .append(item) signature = '&'.join(pairs) signature = signature.lower().replace('+', '%20') signature = hmac.new(b(self.key), msg=b(signature), digestmod=hashlib.sha1) return base64.b64encode(b(signature.digest())) def add_default_params(self, params): params['apiKey'] = self.user_id params['response'] = 'json' return params def pre_connect_hook(self, params, headers): params['signature'] = self._make_signature(params) return params, headers def _async_request(self, command, action=None, params=None, data=None, headers=None, method='GET', context=None): if params: context = copy.deepcopy(params) else: context = {} # Command is specified as part of GET call context['command'] = command result = super(CloudStackConnection, self).async_request( action=action, params=params, data=data, headers=headers, method=method, context=context) return result['jobresult'] def get_request_kwargs(self, action, params=None, data='', headers=None, method='GET', context=None): command = context['command'] request_kwargs = {'command': command, 'action': action, 'params': params, 'data': data, 'headers': headers, 'method': method} return request_kwargs def get_poll_request_kwargs(self, response, context, request_kwargs): job_id = response['jobid'] params = {'jobid': job_id} kwargs = {'command': 'queryAsyncJobResult', 'params': params} return kwargs def has_completed(self, response): status = response.get('jobstatus', self.ASYNC_PENDING) if status == self.ASYNC_FAILURE: msg = response.get('jobresult', {}).get('errortext', status) raise Exception(msg) return status == self.ASYNC_SUCCESS def _sync_request(self, command, action=None, params=None, data=None, headers=None, method='GET'): """ This method handles synchronous calls which are generally fast information retrieval requests and thus return 'quickly'. """ # command is always sent as part of "command" query parameter if params: params = copy.deepcopy(params) else: params = {} params['command'] = command # pylint: disable=maybe-no-member result = self.request(action=self.driver.path, params=params, data=data, headers=headers, method=method) command = command.lower() # Work around for older verions which don't return "response" suffix # in delete ingress rule response command name if (command == 'revokesecuritygroupingress' and 'revokesecuritygroupingressresponse' not in result.object): command = command elif (command == 'restorevirtualmachine' and 'restorevmresponse' in result.object): command = "restorevmresponse" else: command = command + 'response' if command not in result.object: raise MalformedResponseError( "Unknown response format {}".format(command), body=result.body, driver=self.driver) result = result.object[command] return result class CloudStackDriverMixIn(object): host = None path = None connectionCls = CloudStackConnection def __init__(self, key, secret=None, secure=True, host=None, port=None): host = host or self.host super(CloudStackDriverMixIn, self).__init__(key, secret, secure, host, port) def _sync_request(self, command, action=None, params=None, data=None, headers=None, method='GET'): return self.connection._sync_request(command=command, action=action, params=params, data=data, headers=headers, method=method) def _async_request(self, command, action=None, params=None, data=None, headers=None, method='GET', context=None): return self.connection._async_request(command=command, action=action, params=params, data=data, headers=headers, method=method, context=context) apache-libcloud-2.8.0/libcloud/common/digitalocean.py0000664000175000017500000001557513535474530022533 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Common settings and connection objects for DigitalOcean Cloud """ from libcloud.utils.py3 import httplib, parse_qs, urlparse from libcloud.common.base import BaseDriver from libcloud.common.base import ConnectionKey from libcloud.common.base import JsonResponse from libcloud.common.types import LibcloudError, InvalidCredsError __all__ = [ 'DigitalOcean_v2_Response', 'DigitalOcean_v2_Connection', 'DigitalOceanBaseDriver' ] class DigitalOcean_v1_Error(LibcloudError): """ Exception for when attempting to use version 1 of the DigitalOcean API which is no longer supported. """ def __init__(self, value=('Driver no longer supported: Version 1 of the ' 'DigitalOcean API reached end of life on November 9, ' '2015. Use the v2 driver. Please visit: ' 'https://developers.digitalocean.com/documentation/changelog/api-v1/sunsetting-api-v1/'), # noqa: E501 driver=None): super(DigitalOcean_v1_Error, self).__init__(value, driver=driver) class DigitalOcean_v2_Response(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_error(self): if self.status == httplib.UNAUTHORIZED: body = self.parse_body() raise InvalidCredsError(body['message']) else: body = self.parse_body() if 'message' in body: error = '%s (code: %s)' % (body['message'], self.status) else: error = body return error def success(self): return self.status in self.valid_response_codes class DigitalOcean_v2_Connection(ConnectionKey): """ Connection class for the DigitalOcean (v2) driver. """ host = 'api.digitalocean.com' responseCls = DigitalOcean_v2_Response def add_default_headers(self, headers): """ Add headers that are necessary for every request This method adds ``token`` to the request. """ headers['Authorization'] = 'Bearer %s' % (self.key) headers['Content-Type'] = 'application/json' return headers def add_default_params(self, params): """ Add parameters that are necessary for every request This method adds ``per_page`` to the request to reduce the total number of paginated requests to the API. """ # pylint: disable=maybe-no-member params['per_page'] = self.driver.ex_per_page return params class DigitalOceanConnection(DigitalOcean_v2_Connection): """ Connection class for the DigitalOcean driver. """ pass class DigitalOceanResponse(DigitalOcean_v2_Response): pass class DigitalOceanBaseDriver(BaseDriver): """ DigitalOcean BaseDriver """ name = 'DigitalOcean' website = 'https://www.digitalocean.com' def __new__(cls, key, secret=None, api_version='v2', **kwargs): if cls is DigitalOceanBaseDriver: if api_version == 'v1' or secret is not None: raise DigitalOcean_v1_Error() elif api_version == 'v2': cls = DigitalOcean_v2_BaseDriver else: raise NotImplementedError('Unsupported API version: %s' % (api_version)) return super(DigitalOceanBaseDriver, cls).__new__(cls, **kwargs) def ex_account_info(self): raise NotImplementedError( 'ex_account_info not implemented for this driver') def ex_list_events(self): raise NotImplementedError( 'ex_list_events not implemented for this driver') def ex_get_event(self, event_id): raise NotImplementedError( 'ex_get_event not implemented for this driver') def _paginated_request(self, url, obj): raise NotImplementedError( '_paginated_requests not implemented for this driver') class DigitalOcean_v2_BaseDriver(DigitalOceanBaseDriver): """ DigitalOcean BaseDriver using v2 of the API. Supports `ex_per_page` ``int`` value keyword parameter to adjust per page requests against the API. """ connectionCls = DigitalOcean_v2_Connection def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=None, ex_per_page=200, **kwargs): self.ex_per_page = ex_per_page super(DigitalOcean_v2_BaseDriver, self).__init__(key, **kwargs) def ex_account_info(self): return self.connection.request('/v2/account').object['account'] def ex_list_events(self): return self._paginated_request('/v2/actions', 'actions') def ex_get_event(self, event_id): """ Get an event object :param event_id: Event id (required) :type event_id: ``str`` """ params = {} return self.connection.request('/v2/actions/%s' % event_id, params=params).object['action'] def _paginated_request(self, url, obj): """ Perform multiple calls in order to have a full list of elements when the API responses are paginated. :param url: API endpoint :type url: ``str`` :param obj: Result object key :type obj: ``str`` :return: ``list`` of API response objects :rtype: ``list`` """ params = {} data = self.connection.request(url) try: query = urlparse.urlparse(data.object['links']['pages']['last']) # The query[4] references the query parameters from the url pages = parse_qs(query[4])['page'][0] values = data.object[obj] for page in range(2, int(pages) + 1): params.update({'page': page}) new_data = self.connection.request(url, params=params) more_values = new_data.object[obj] for value in more_values: values.append(value) data = values except KeyError: # No pages. data = data.object[obj] return data apache-libcloud-2.8.0/libcloud/common/dimensiondata.py0000664000175000017500000016164213576514553022731 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Dimension Data Common Components """ from base64 import b64encode from time import sleep # TODO: use disutils.version when Travis CI fixed the pylint issue with version # from distutils.version import LooseVersion from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse from libcloud.compute.base import Node from libcloud.utils.py3 import basestring from libcloud.utils.xml import findtext from libcloud.compute.types import LibcloudError, InvalidCredsError # Roadmap / TODO: # # 1.0 - Copied from OpSource API, named provider details. # setup a few variables to represent all of the DimensionData cloud namespaces NAMESPACE_BASE = "http://oec.api.opsource.net/schemas" ORGANIZATION_NS = NAMESPACE_BASE + "/organization" SERVER_NS = NAMESPACE_BASE + "/server" NETWORK_NS = NAMESPACE_BASE + "/network" DIRECTORY_NS = NAMESPACE_BASE + "/directory" GENERAL_NS = NAMESPACE_BASE + "/general" BACKUP_NS = NAMESPACE_BASE + "/backup" # API 2.0 Namespaces and URNs TYPES_URN = "urn:didata.com:api:cloud:types" # API end-points API_ENDPOINTS = { 'dd-na': { 'name': 'North America (NA)', 'host': 'api-na.dimensiondata.com', 'vendor': 'DimensionData' }, 'dd-eu': { 'name': 'Europe (EU)', 'host': 'api-eu.dimensiondata.com', 'vendor': 'DimensionData' }, 'dd-au': { 'name': 'Australia (AU)', 'host': 'api-au.dimensiondata.com', 'vendor': 'DimensionData' }, 'dd-au-gov': { 'name': 'Australia Canberra ACT (AU)', 'host': 'api-canberra.dimensiondata.com', 'vendor': 'DimensionData' }, 'dd-af': { 'name': 'Africa (AF)', 'host': 'api-mea.dimensiondata.com', 'vendor': 'DimensionData' }, 'dd-ap': { 'name': 'Asia Pacific (AP)', 'host': 'api-ap.dimensiondata.com', 'vendor': 'DimensionData' }, 'dd-latam': { 'name': 'South America (LATAM)', 'host': 'api-latam.dimensiondata.com', 'vendor': 'DimensionData' }, 'dd-canada': { 'name': 'Canada (CA)', 'host': 'api-canada.dimensiondata.com', 'vendor': 'DimensionData' }, 'is-na': { 'name': 'North America (NA)', 'host': 'usapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-eu': { 'name': 'Europe (EU)', 'host': 'euapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-au': { 'name': 'Australia (AU)', 'host': 'auapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-af': { 'name': 'Africa (AF)', 'host': 'meaapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-ap': { 'name': 'Asia Pacific (AP)', 'host': 'apapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-latam': { 'name': 'South America (LATAM)', 'host': 'latamapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-canada': { 'name': 'Canada (CA)', 'host': 'canadaapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'ntta-na': { 'name': 'North America (NA)', 'host': 'cloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-eu': { 'name': 'Europe (EU)', 'host': 'eucloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-au': { 'name': 'Australia (AU)', 'host': 'aucloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-af': { 'name': 'Africa (AF)', 'host': 'sacloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-ap': { 'name': 'Asia Pacific (AP)', 'host': 'hkcloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'cisco-na': { 'name': 'North America (NA)', 'host': 'iaas-api-na.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-eu': { 'name': 'Europe (EU)', 'host': 'iaas-api-eu.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-au': { 'name': 'Australia (AU)', 'host': 'iaas-api-au.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-af': { 'name': 'Africa (AF)', 'host': 'iaas-api-mea.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-ap': { 'name': 'Asia Pacific (AP)', 'host': 'iaas-api-ap.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-latam': { 'name': 'South America (LATAM)', 'host': 'iaas-api-sa.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-canada': { 'name': 'Canada (CA)', 'host': 'iaas-api-ca.cisco-ccs.com', 'vendor': 'Cisco' }, 'med1-il': { 'name': 'Israel (IL)', 'host': 'api.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-na': { 'name': 'North America (NA)', 'host': 'api-na.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-eu': { 'name': 'Europe (EU)', 'host': 'api-eu.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-au': { 'name': 'Australia (AU)', 'host': 'api-au.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-af': { 'name': 'Africa (AF)', 'host': 'api-af.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-ap': { 'name': 'Asia Pacific (AP)', 'host': 'api-ap.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-latam': { 'name': 'South America (LATAM)', 'host': 'api-sa.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-canada': { 'name': 'Canada (CA)', 'host': 'api-ca.cloud.med-1.com', 'vendor': 'Med-1' }, 'indosat-id': { 'name': 'Indonesia (ID)', 'host': 'iaas-api.indosat.com', 'vendor': 'Indosat' }, 'indosat-na': { 'name': 'North America (NA)', 'host': 'iaas-usapi.indosat.com', 'vendor': 'Indosat' }, 'indosat-eu': { 'name': 'Europe (EU)', 'host': 'iaas-euapi.indosat.com', 'vendor': 'Indosat' }, 'indosat-au': { 'name': 'Australia (AU)', 'host': 'iaas-auapi.indosat.com', 'vendor': 'Indosat' }, 'indosat-af': { 'name': 'Africa (AF)', 'host': 'iaas-afapi.indosat.com', 'vendor': 'Indosat' }, 'bsnl-in': { 'name': 'India (IN)', 'host': 'api.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-na': { 'name': 'North America (NA)', 'host': 'usapi.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-eu': { 'name': 'Europe (EU)', 'host': 'euapi.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-au': { 'name': 'Australia (AU)', 'host': 'auapi.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-af': { 'name': 'Africa (AF)', 'host': 'afapi.bsnlcloud.com', 'vendor': 'BSNL' } } # Default API end-point for the base connection class. DEFAULT_REGION = 'dd-na' BAD_CODE_XML_ELEMENTS = ( ('responseCode', SERVER_NS), ('responseCode', TYPES_URN), ('result', GENERAL_NS) ) BAD_MESSAGE_XML_ELEMENTS = ( ('message', SERVER_NS), ('message', TYPES_URN), ('resultDetail', GENERAL_NS) ) def dd_object_to_id(obj, obj_type, id_value='id'): """ Takes in a DD object or string and prints out it's id This is a helper method, as many of our functions can take either an object or a string, and we need an easy way of converting them :param obj: The object to get the id for :type obj: ``object`` :param func: The function to call, e.g. ex_get_vlan. Note: This function needs to return an object which has ``status`` attribute. :type func: ``function`` :rtype: ``str`` """ if isinstance(obj, obj_type): return getattr(obj, id_value) elif isinstance(obj, (basestring)): return obj else: raise TypeError( "Invalid type %s looking for basestring or %s" % (type(obj).__name__, obj_type.__name__) ) # TODO: use disutils.version when Travis CI fixed the pylint issue with version # This is a temporary workaround. def LooseVersion(version): return float(version) class NetworkDomainServicePlan(object): ESSENTIALS = "ESSENTIALS" ADVANCED = "ADVANCED" class DimensionDataRawResponse(RawResponse): pass class DimensionDataResponse(XmlResponse): def parse_error(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError(self.body) elif self.status == httplib.FORBIDDEN: raise InvalidCredsError(self.body) body = self.parse_body() if self.status == httplib.BAD_REQUEST: for response_code in BAD_CODE_XML_ELEMENTS: code = findtext(body, response_code[0], response_code[1]) if code is not None: break for message in BAD_MESSAGE_XML_ELEMENTS: message = findtext(body, message[0], message[1]) if message is not None: break raise DimensionDataAPIException(code=code, msg=message, driver=self.connection.driver) if self.status is not httplib.OK: raise DimensionDataAPIException(code=self.status, msg=body, driver=self.connection.driver) return self.body class DimensionDataAPIException(LibcloudError): def __init__(self, code, msg, driver): self.code = code self.msg = msg self.driver = driver def __str__(self): return "%s: %s" % (self.code, self.msg) def __repr__(self): return ("" % (self.code, self.msg)) class DimensionDataConnection(ConnectionUserAndKey): """ Connection class for the DimensionData driver """ api_path_version_1 = '/oec' api_path_version_2 = '/caas' api_version_1 = 0.9 # Earliest version supported oldest_api_version = '2.2' # Latest version supported latest_api_version = '2.4' # Default api version active_api_version = '2.4' _orgId = None responseCls = DimensionDataResponse rawResponseCls = DimensionDataRawResponse allow_insecure = False def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, api_version=None, **conn_kwargs): super(DimensionDataConnection, self).__init__( user_id=user_id, key=key, secure=secure, host=host, port=port, url=url, timeout=timeout, proxy_url=proxy_url) if conn_kwargs['region']: self.host = conn_kwargs['region']['host'] if api_version: if LooseVersion(api_version) < LooseVersion( self.oldest_api_version): msg = 'API Version specified is too old. No longer ' \ 'supported. Please upgrade to the latest version {}' \ .format(self.active_api_version) raise DimensionDataAPIException(code=None, msg=msg, driver=self.driver) elif LooseVersion(api_version) > LooseVersion( self.latest_api_version): msg = 'Unsupported API Version. The version specified is ' \ 'not release yet. Please use the latest supported ' \ 'version {}' \ .format(self.active_api_version) raise DimensionDataAPIException(code=None, msg=msg, driver=self.driver) else: # Overwrite default version using the version user specified self.active_api_version = api_version def add_default_headers(self, headers): headers['Authorization'] = \ ('Basic %s' % b64encode(b('%s:%s' % (self.user_id, self.key))).decode('utf-8')) headers['Content-Type'] = 'application/xml' return headers def request_api_1(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s/%s" % (self.api_path_version_1, self.api_version_1, action) return super(DimensionDataConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def request_api_2(self, path, action, params=None, data='', headers=None, method='GET'): action = "%s/%s/%s/%s" % (self.api_path_version_2, self.active_api_version, path, action) return super(DimensionDataConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def raw_request_with_orgId_api_1(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s" % (self.get_resource_path_api_1(), action) return super(DimensionDataConnection, self).request( action=action, params=params, data=data, method=method, headers=headers, raw=True) def request_with_orgId_api_1(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s" % (self.get_resource_path_api_1(), action) return super(DimensionDataConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def request_with_orgId_api_2(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s" % (self.get_resource_path_api_2(), action) return super(DimensionDataConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def paginated_request_with_orgId_api_2(self, action, params=None, data='', headers=None, method='GET', page_size=250): """ A paginated request to the MCP2.0 API This essentially calls out to request_with_orgId_api_2 for each page and yields the response to make a generator This generator can be looped through to grab all the pages. :param action: The resource to access (i.e. 'network/vlan') :type action: ``str`` :param params: Parameters to give to the action :type params: ``dict`` or ``None`` :param data: The data payload to be added to the request :type data: ``str`` :param headers: Additional header to be added to the request :type headers: ``str`` or ``dict`` or ``None`` :param method: HTTP Method for the request (i.e. 'GET', 'POST') :type method: ``str`` :param page_size: The size of each page to be returned Note: Max page size in MCP2.0 is currently 250 :type page_size: ``int`` """ if params is None: params = {} params['pageSize'] = page_size resp = self.request_with_orgId_api_2(action, params, data, headers, method).object yield resp if len(resp) <= 0: return pcount = resp.get('pageCount') # pylint: disable=no-member psize = resp.get('pageSize') # pylint: disable=no-member pnumber = resp.get('pageNumber') # pylint: disable=no-member while int(pcount) >= int(psize): params['pageNumber'] = int(pnumber) + 1 resp = self.request_with_orgId_api_2(action, params, data, headers, method).object pcount = resp.get('pageCount') # pylint: disable=no-member psize = resp.get('pageSize') # pylint: disable=no-member pnumber = resp.get('pageNumber') # pylint: disable=no-member yield resp def get_resource_path_api_1(self): """ This method returns a resource path which is necessary for referencing resources that require a full path instead of just an ID, such as networks, and customer snapshots. """ return ("%s/%s/%s" % (self.api_path_version_1, self.api_version_1, self._get_orgId())) def get_resource_path_api_2(self): """ This method returns a resource path which is necessary for referencing resources that require a full path instead of just an ID, such as networks, and customer snapshots. """ return ("%s/%s/%s" % (self.api_path_version_2, self.active_api_version, self._get_orgId())) def wait_for_state(self, state, func, poll_interval=2, timeout=60, *args, **kwargs): """ Wait for the function which returns a instance with field status/state to match. Keep polling func until one of the desired states is matched :param state: Either the desired state (`str`) or a `list` of states :type state: ``str`` or ``list`` :param func: The function to call, e.g. ex_get_vlan. Note: This function needs to return an object which has ``status`` attribute. :type func: ``function`` :param poll_interval: The number of seconds to wait between checks :type poll_interval: `int` :param timeout: The total number of seconds to wait to reach a state :type timeout: `int` :param args: The arguments for func :type args: Positional arguments :param kwargs: The arguments for func :type kwargs: Keyword arguments :return: Result from the calling function. """ cnt = 0 result = None object_state = None while cnt < timeout / poll_interval: result = func(*args, **kwargs) if isinstance(result, Node): object_state = result.state else: object_state = result.status if object_state is state or str(object_state) in state: return result sleep(poll_interval) cnt += 1 msg = 'Status check for object %s timed out' % (result) raise DimensionDataAPIException(code=object_state, msg=msg, driver=self.driver) def _get_orgId(self): """ Send the /myaccount API request to DimensionData cloud and parse the 'orgId' from the XML response object. We need the orgId to use most of the other API functions """ if self._orgId is None: body = self.request_api_1('myaccount').object self._orgId = findtext(body, 'orgId', DIRECTORY_NS) return self._orgId def get_account_details(self): """ Get the details of this account :rtype: :class:`DimensionDataAccountDetails` """ body = self.request_api_1('myaccount').object return DimensionDataAccountDetails( user_name=findtext(body, 'userName', DIRECTORY_NS), full_name=findtext(body, 'fullName', DIRECTORY_NS), first_name=findtext(body, 'firstName', DIRECTORY_NS), last_name=findtext(body, 'lastName', DIRECTORY_NS), email=findtext(body, 'emailAddress', DIRECTORY_NS)) class DimensionDataAccountDetails(object): """ Dimension Data account class details """ def __init__(self, user_name, full_name, first_name, last_name, email): self.user_name = user_name self.full_name = full_name self.first_name = first_name self.last_name = last_name self.email = email class DimensionDataStatus(object): """ DimensionData API pending operation status class action, request_time, user_name, number_of_steps, update_time, step.name, step.number, step.percent_complete, failure_reason, """ def __init__(self, action=None, request_time=None, user_name=None, number_of_steps=None, update_time=None, step_name=None, step_number=None, step_percent_complete=None, failure_reason=None): self.action = action self.request_time = request_time self.user_name = user_name self.number_of_steps = number_of_steps self.update_time = update_time self.step_name = step_name self.step_number = step_number self.step_percent_complete = step_percent_complete self.failure_reason = failure_reason def __repr__(self): return (('') % (self.action, self.request_time, self.user_name, self.number_of_steps, self.update_time, self.step_name, self.step_number, self.step_percent_complete, self.failure_reason)) class DimensionDataNetwork(object): """ DimensionData network with location. """ def __init__(self, id, name, description, location, private_net, multicast, status): self.id = str(id) self.name = name self.description = description self.location = location self.private_net = private_net self.multicast = multicast self.status = status def __repr__(self): return (('') % (self.id, self.name, self.description, self.location, self.private_net, self.multicast)) class DimensionDataNetworkDomain(object): """ DimensionData network domain with location. """ def __init__(self, id, name, description, location, status, plan): self.id = str(id) self.name = name self.description = description self.location = location self.status = status self.plan = plan def __repr__(self): return (('') % (self.id, self.name, self.description, self.location, self.status, self.plan)) class DimensionDataPublicIpBlock(object): """ DimensionData Public IP Block with location. """ def __init__(self, id, base_ip, size, location, network_domain, status): self.id = str(id) self.base_ip = base_ip self.size = size self.location = location self.network_domain = network_domain self.status = status def __repr__(self): return (('') % (self.id, self.base_ip, self.size, self.location, self.status)) class DimensionDataServerCpuSpecification(object): """ A class that represents the specification of the CPU(s) for a node """ def __init__(self, cpu_count, cores_per_socket, performance): """ Instantiate a new :class:`DimensionDataServerCpuSpecification` :param cpu_count: The number of CPUs :type cpu_count: ``int`` :param cores_per_socket: The number of cores per socket, the recommendation is 1 :type cores_per_socket: ``int`` :param performance: The performance type, e.g. HIGHPERFORMANCE :type performance: ``str`` """ self.cpu_count = cpu_count self.cores_per_socket = cores_per_socket self.performance = performance def __repr__(self): return (('') % (self.cpu_count, self.cores_per_socket, self.performance)) class DimensionDataServerDisk(object): """ A class that represents the disk on a server """ def __init__(self, id=None, scsi_id=None, size_gb=None, speed=None, state=None): """ Instantiate a new :class:`DimensionDataServerDisk` :param id: The id of the disk :type id: ``str`` :param scsi_id: Representation for scsi :type scsi_id: ``int`` :param size_gb: Size of the disk :type size_gb: ``int`` :param speed: Speed of the disk (i.e. STANDARD) :type speed: ``str`` :param state: State of the disk (i.e. PENDING) :type state: ``str`` """ self.id = id self.scsi_id = scsi_id self.size_gb = size_gb self.speed = speed self.state = state def __repr__(self): return (('') % (self.status, self.version_status, self.api_version)) class DimensionDataFirewallRule(object): """ DimensionData Firewall Rule for a network domain """ def __init__(self, id, name, action, location, network_domain, status, ip_version, protocol, source, destination, enabled): self.id = str(id) self.name = name self.action = action self.location = location self.network_domain = network_domain self.status = status self.ip_version = ip_version self.protocol = protocol self.source = source self.destination = destination self.enabled = enabled def __repr__(self): return (('') % (self.id, self.name, self.action, self.location, self.network_domain, self.status, self.ip_version, self.protocol, self.source, self.destination, self.enabled)) class DimensionDataFirewallAddress(object): """ The source or destination model in a firewall rule """ def __init__(self, any_ip, ip_address, ip_prefix_size, port_begin, port_end, address_list_id, port_list_id): self.any_ip = any_ip self.ip_address = ip_address self.ip_prefix_size = ip_prefix_size self.port_list_id = port_list_id self.port_begin = port_begin self.port_end = port_end self.address_list_id = address_list_id self.port_list_id = port_list_id def __repr__(self): return ( '' % (self.any_ip, self.ip_address, self.ip_prefix_size, self.port_begin, self.port_end, self.address_list_id, self.port_list_id)) class DimensionDataNatRule(object): """ An IP NAT rule in a network domain """ def __init__(self, id, network_domain, internal_ip, external_ip, status): self.id = id self.network_domain = network_domain self.internal_ip = internal_ip self.external_ip = external_ip self.status = status def __repr__(self): return (('') % (self.id, self.status)) class DimensionDataAntiAffinityRule(object): """ Anti-Affinity rule for DimensionData An Anti-Affinity rule ensures that servers in the rule will not reside on the same VMware ESX host. """ def __init__(self, id, node_list): """ Instantiate a new :class:`DimensionDataAntiAffinityRule` :param id: The ID of the Anti-Affinity rule :type id: ``str`` :param node_list: List of node ids that belong in this rule :type node_list: ``list`` of ``str`` """ self.id = id self.node_list = node_list def __repr__(self): return (('') % (self.id)) class DimensionDataVlan(object): """ DimensionData VLAN. """ def __init__(self, id, name, description, location, network_domain, status, private_ipv4_range_address, private_ipv4_range_size, ipv6_range_address, ipv6_range_size, ipv4_gateway, ipv6_gateway): """ Initialize an instance of ``DimensionDataVlan`` :param id: The ID of the VLAN :type id: ``str`` :param name: The name of the VLAN :type name: ``str`` :param description: Plan text description of the VLAN :type description: ``str`` :param location: The location (data center) of the VLAN :type location: ``NodeLocation`` :param network_domain: The Network Domain that owns this VLAN :type network_domain: :class:`DimensionDataNetworkDomain` :param status: The status of the VLAN :type status: :class:`DimensionDataStatus` :param private_ipv4_range_address: The host address of the VLAN IP space :type private_ipv4_range_address: ``str`` :param private_ipv4_range_size: The size (e.g. '24') of the VLAN as a CIDR range size :type private_ipv4_range_size: ``int`` :param ipv6_range_address: The host address of the VLAN IP space :type ipv6_range_address: ``str`` :param ipv6_range_size: The size (e.g. '32') of the VLAN as a CIDR range size :type ipv6_range_size: ``int`` :param ipv4_gateway: The IPv4 default gateway address :type ipv4_gateway: ``str`` :param ipv6_gateway: The IPv6 default gateway address :type ipv6_gateway: ``str`` """ self.id = str(id) self.name = name self.location = location self.description = description self.network_domain = network_domain self.status = status self.private_ipv4_range_address = private_ipv4_range_address self.private_ipv4_range_size = private_ipv4_range_size self.ipv6_range_address = ipv6_range_address self.ipv6_range_size = ipv6_range_size self.ipv4_gateway = ipv4_gateway self.ipv6_gateway = ipv6_gateway def __repr__(self): return (('') % (self.id, self.name, self.description, self.location, self.status)) class DimensionDataPool(object): """ DimensionData VIP Pool. """ def __init__(self, id, name, description, status, load_balance_method, health_monitor_id, service_down_action, slow_ramp_time): """ Initialize an instance of ``DimensionDataPool`` :param id: The ID of the pool :type id: ``str`` :param name: The name of the pool :type name: ``str`` :param description: Plan text description of the pool :type description: ``str`` :param status: The status of the pool :type status: :class:`DimensionDataStatus` :param load_balance_method: The load balancer method :type load_balance_method: ``str`` :param health_monitor_id: The ID of the health monitor :type health_monitor_id: ``str`` :param service_down_action: Action to take when pool is down :type service_down_action: ``str`` :param slow_ramp_time: The ramp-up time for service recovery :type slow_ramp_time: ``int`` """ self.id = str(id) self.name = name self.description = description self.status = status self.load_balance_method = load_balance_method self.health_monitor_id = health_monitor_id self.service_down_action = service_down_action self.slow_ramp_time = slow_ramp_time def __repr__(self): return (('') % (self.id, self.name, self.description, self.status)) class DimensionDataPoolMember(object): """ DimensionData VIP Pool Member. """ def __init__(self, id, name, status, ip, port, node_id): """ Initialize an instance of ``DimensionDataPoolMember`` :param id: The ID of the pool member :type id: ``str`` :param name: The name of the pool member :type name: ``str`` :param status: The status of the pool :type status: :class:`DimensionDataStatus` :param ip: The IP of the pool member :type ip: ``str`` :param port: The port of the pool member :type port: ``int`` :param node_id: The ID of the associated node :type node_id: ``str`` """ self.id = str(id) self.name = name self.status = status self.ip = ip self.port = port self.node_id = node_id def __repr__(self): return (('') % (self.id, self.name, self.ip, self.status, self.port, self.node_id)) class DimensionDataVIPNode(object): def __init__(self, id, name, status, ip, connection_limit='10000', connection_rate_limit='10000'): """ Initialize an instance of :class:`DimensionDataVIPNode` :param id: The ID of the node :type id: ``str`` :param name: The name of the node :type name: ``str`` :param status: The status of the node :type status: :class:`DimensionDataStatus` :param ip: The IP of the node :type ip: ``str`` :param connection_limit: The total connection limit for the node :type connection_limit: ``int`` :param connection_rate_limit: The rate limit for the node :type connection_rate_limit: ``int`` """ self.id = str(id) self.name = name self.status = status self.ip = ip self.connection_limit = connection_limit self.connection_rate_limit = connection_rate_limit def __repr__(self): return (('') % (self.id, self.name, self.status, self.ip)) class DimensionDataVirtualListener(object): """ DimensionData Virtual Listener. """ def __init__(self, id, name, status, ip): """ Initialize an instance of :class:`DimensionDataVirtualListener` :param id: The ID of the listener :type id: ``str`` :param name: The name of the listener :type name: ``str`` :param status: The status of the listener :type status: :class:`DimensionDataStatus` :param ip: The IP of the listener :type ip: ``str`` """ self.id = str(id) self.name = name self.status = status self.ip = ip def __repr__(self): return (('') % (self.id, self.name, self.status, self.ip)) class DimensionDataDefaultHealthMonitor(object): """ A default health monitor for a VIP (node, pool or listener) """ def __init__(self, id, name, node_compatible, pool_compatible): """ Initialize an instance of :class:`DimensionDataDefaultHealthMonitor` :param id: The ID of the monitor :type id: ``str`` :param name: The name of the monitor :type name: ``str`` :param node_compatible: Is a monitor capable of monitoring nodes :type node_compatible: ``bool`` :param pool_compatible: Is a monitor capable of monitoring pools :type pool_compatible: ``bool`` """ self.id = id self.name = name self.node_compatible = node_compatible self.pool_compatible = pool_compatible def __repr__(self): return (('') % (self.id, self.name)) class DimensionDataPersistenceProfile(object): """ Each Persistence Profile declares the combination of Virtual Listener type and protocol with which it is compatible and whether or not it is compatible as a Fallback Persistence Profile. """ def __init__(self, id, name, compatible_listeners, fallback_compatible): """ Initialize an instance of :class:`DimensionDataPersistenceProfile` :param id: The ID of the profile :type id: ``str`` :param name: The name of the profile :type name: ``str`` :param compatible_listeners: List of compatible Virtual Listener types :type compatible_listeners: ``list`` of :class:`DimensionDataVirtualListenerCompatibility` :param fallback_compatible: Is capable as a fallback profile :type fallback_compatible: ``bool`` """ self.id = id self.name = name self.compatible_listeners = compatible_listeners self.fallback_compatible = fallback_compatible def __repr__(self): return (('') % (self.id, self.name)) class DimensionDataDefaultiRule(object): """ A default iRule for a network domain, can be applied to a listener """ def __init__(self, id, name, compatible_listeners): """ Initialize an instance of :class:`DimensionDataDefaultiRule` :param id: The ID of the iRule :type id: ``str`` :param name: The name of the iRule :type name: ``str`` :param compatible_listeners: List of compatible Virtual Listener types :type compatible_listeners: ``list`` of :class:`DimensionDataVirtualListenerCompatibility` """ self.id = id self.name = name self.compatible_listeners = compatible_listeners def __repr__(self): return (('') % (self.id, self.name)) class DimensionDataVirtualListenerCompatibility(object): """ A compatibility preference for a persistence profile or iRule specifies which virtual listener types this profile or iRule can be applied to. """ def __init__(self, type, protocol): self.type = type self.protocol = protocol def __repr__(self): return (('') % (self.type, self.protocol)) class DimensionDataBackupDetails(object): """ Dimension Data Backup Details represents information about a targets backups configuration """ def __init__(self, asset_id, service_plan, status, clients=None): """ Initialize an instance of :class:`DimensionDataBackupDetails` :param asset_id: Asset identification for backups :type asset_id: ``str`` :param service_plan: The service plan for backups. i.e (Essentials) :type service_plan: ``str`` :param status: The overall status this backup target. i.e. (unregistered) :type status: ``str`` :param clients: Backup clients attached to this target :type clients: ``list`` of :class:`DimensionDataBackupClient` """ self.asset_id = asset_id self.service_plan = service_plan self.status = status self.clients = clients def __repr__(self): return (('') % (self.asset_id)) class DimensionDataBackupClient(object): """ An object that represents a backup client """ def __init__(self, id, type, status, schedule_policy, storage_policy, download_url, alert=None, running_job=None): """ Initialize an instance of :class:`DimensionDataBackupClient` :param id: Unique ID for the client :type id: ``str`` :param type: The type of client that this client is :type type: :class:`DimensionDataBackupClientType` :param status: The states of this particular backup client. i.e. (Unregistered) :type status: ``str`` :param schedule_policy: The schedule policy for this client NOTE: Dimension Data only sends back the name of the schedule policy, no further details :type schedule_policy: ``str`` :param storage_policy: The storage policy for this client NOTE: Dimension Data only sends back the name of the storage policy, no further details :type storage_policy: ``str`` :param download_url: The download url for this client :type download_url: ``str`` :param alert: The alert configured for this backup client (optional) :type alert: :class:`DimensionDataBackupClientAlert` :param alert: The running job for the client (optional) :type alert: :class:`DimensionDataBackupClientRunningJob` """ self.id = id self.type = type self.status = status self.schedule_policy = schedule_policy self.storage_policy = storage_policy self.download_url = download_url self.alert = alert self.running_job = running_job def __repr__(self): return (('') % (self.id)) class DimensionDataBackupClientAlert(object): """ An alert for a backup client """ def __init__(self, trigger, notify_list=[]): """ Initialize an instance of :class:`DimensionDataBackupClientAlert` :param trigger: Trigger type for the client i.e. ON_FAILURE :type trigger: ``str`` :param notify_list: List of email addresses that are notified when the alert is fired :type notify_list: ``list`` of ``str`` """ self.trigger = trigger self.notify_list = notify_list def __repr__(self): return (('') % (self.trigger)) class DimensionDataBackupClientRunningJob(object): """ A running job for a given backup client """ def __init__(self, id, status, percentage=0): """ Initialize an instance of :class:`DimensionDataBackupClientRunningJob` :param id: The unqiue ID of the job :type id: ``str`` :param status: The status of the job i.e. Waiting :type status: ``str`` :param percentage: The percentage completion of the job :type percentage: ``int`` """ self.id = id self.percentage = percentage self.status = status def __repr__(self): return (('') % (self.id)) class DimensionDataBackupClientType(object): """ A client type object for backups """ def __init__(self, type, is_file_system, description): """ Initialize an instance of :class:`DimensionDataBackupClientType` :param type: The type of client i.e. (FA.Linux, MySQL, ect.) :type type: ``str`` :param is_file_system: The name of the iRule :type is_file_system: ``bool`` :param description: Description of the client :type description: ``str`` """ self.type = type self.is_file_system = is_file_system self.description = description def __repr__(self): return (('') % (self.type)) class DimensionDataBackupStoragePolicy(object): """ A representation of a storage policy """ def __init__(self, name, retention_period, secondary_location): """ Initialize an instance of :class:`DimensionDataBackupStoragePolicy` :param name: The name of the storage policy i.e. 14 Day Storage Policy :type name: ``str`` :param retention_period: How long to keep the backup in days :type retention_period: ``int`` :param secondary_location: The secondary location i.e. Primary :type secondary_location: ``str`` """ self.name = name self.retention_period = retention_period self.secondary_location = secondary_location def __repr__(self): return (('') % (self.name)) class DimensionDataBackupSchedulePolicy(object): """ A representation of a schedule policy """ def __init__(self, name, description): """ Initialize an instance of :class:`DimensionDataBackupSchedulePolicy` :param name: The name of the policy i.e 12AM - 6AM :type name: ``str`` :param description: Short summary of the details of the policy :type description: ``str`` """ self.name = name self.description = description def __repr__(self): return (('') % (self.name)) class DimensionDataTag(object): """ A representation of a Tag in Dimension Data A Tag first must have a Tag Key, then an asset is tag with a key and an option value. Tags can be queried later to filter assets and also show up on usage report if so desired. """ def __init__(self, asset_type, asset_id, asset_name, datacenter, key, value): """ Initialize an instance of :class:`DimensionDataTag` :param asset_type: The type of asset. Current asset types: SERVER, VLAN, NETWORK_DOMAIN, CUSTOMER_IMAGE, PUBLIC_IP_BLOCK, ACCOUNT :type asset_type: ``str`` :param asset_id: The GUID of the asset that is tagged :type asset_id: ``str`` :param asset_name: The name of the asset that is tagged :type asset_name: ``str`` :param datacenter: The short datacenter name of the tagged asset :type datacenter: ``str`` :param key: The tagged key :type key: :class:`DimensionDataTagKey` :param value: The tagged value :type value: ``None`` or ``str`` """ self.asset_type = asset_type self.asset_id = asset_id self.asset_name = asset_name self.datacenter = datacenter self.key = key self.value = value def __repr__(self): return (('') % (self.asset_name, self.key.name, self.value)) class DimensionDataTagKey(object): """ A representation of a Tag Key in Dimension Data A tag key is required to tag an asset """ def __init__(self, id, name, description, value_required, display_on_report): """ Initialize an instance of :class:`DimensionDataTagKey` :param id: GUID of the tag key :type id: ``str`` :param name: Name of the tag key :type name: ``str`` :param description: Description of the tag key :type description: ``str`` :param value_required: If a value is required for this tag key :type value_required: ``bool`` :param display_on_report: If this tag key should be displayed on usage reports :type display_on_report: ``bool`` """ self.id = id self.name = name self.description = description self.value_required = value_required self.display_on_report = display_on_report def __repr__(self): return (('') % (self.name)) class DimensionDataIpAddressList(object): """ DimensionData IP Address list """ def __init__(self, id, name, description, ip_version, ip_address_collection, state, create_time, child_ip_address_lists=None): """" Initialize an instance of :class:`DimensionDataIpAddressList` :param id: GUID of the IP Address List key :type id: ``str`` :param name: Name of the IP Address List :type name: ``str`` :param description: Description of the IP Address List :type description: ``str`` :param ip_version: IP version. E.g. IPV4, IPV6 :type ip_version: ``str`` :param ip_address_collection: Collection of DimensionDataIpAddress :type ip_address_collection: ``List`` :param state: IP Address list state :type state: ``str`` :param create_time: IP Address List created time :type create_time: ``date time`` :param child_ip_address_lists: List of IP address list to be included :type child_ip_address_lists: List of :class:'DimensionDataIpAddressList' """ self.id = id self.name = name self.description = description self.ip_version = ip_version self.ip_address_collection = ip_address_collection self.state = state self.create_time = create_time self.child_ip_address_lists = child_ip_address_lists def __repr__(self): return ('' % (self.id, self.name, self.description, self.ip_version, self.ip_address_collection, self.state, self.create_time, self.child_ip_address_lists)) class DimensionDataChildIpAddressList(object): """ DimensionData Child IP Address list """ def __init__(self, id, name): """" Initialize an instance of :class:`DimensionDataChildIpAddressList` :param id: GUID of the IP Address List key :type id: ``str`` :param name: Name of the IP Address List :type name: ``str`` """ self.id = id self.name = name def __repr__(self): return ('' % (self.id, self.name)) class DimensionDataIpAddress(object): """ A representation of IP Address in Dimension Data """ def __init__(self, begin, end=None, prefix_size=None): """ Initialize an instance of :class:`DimensionDataIpAddress` :param begin: IP Address Begin :type begin: ``str`` :param end: IP Address end :type end: ``str`` :param prefixSize: IP Address prefix size :type prefixSize: ``int`` """ self.begin = begin self.end = end self.prefix_size = prefix_size def __repr__(self): return ('' % (self.begin, self.end, self.prefix_size)) class DimensionDataPortList(object): """ DimensionData Port list """ def __init__(self, id, name, description, port_collection, child_portlist_list, state, create_time): """" Initialize an instance of :class:`DimensionDataPortList` :param id: GUID of the Port List key :type id: ``str`` :param name: Name of the Port List :type name: ``str`` :param description: Description of the Port List :type description: ``str`` :param port_collection: Collection of DimensionDataPort :type port_collection: ``List`` :param child_portlist_list: Collection of DimensionDataChildPort :type child_portlist_list: ``List`` :param state: Port list state :type state: ``str`` :param create_time: Port List created time :type create_time: ``date time`` """ self.id = id self.name = name self.description = description self.port_collection = port_collection self.child_portlist_list = child_portlist_list self.state = state self.create_time = create_time def __repr__(self): return ( "" % (self.id, self.name, self.description, self.port_collection, self.child_portlist_list, self.state, self.create_time)) class DimensionDataChildPortList(object): """ DimensionData Child Port list """ def __init__(self, id, name): """" Initialize an instance of :class:`DimensionDataChildIpAddressList` :param id: GUID of the child port list key :type id: ``str`` :param name: Name of the child port List :type name: ``str`` """ self.id = id self.name = name def __repr__(self): return ('' % (self.id, self.name)) class DimensionDataPort(object): """ A representation of Port in Dimension Data """ def __init__(self, begin, end=None): """ Initialize an instance of :class:`DimensionDataPort` :param begin: Port Number Begin :type begin: ``str`` :param end: Port Number end :type end: ``str`` """ self.begin = begin self.end = end def __repr__(self): return ('' % (self.begin, self.end)) class DimensionDataNic(object): """ A representation of Network Adapter in Dimension Data """ def __init__(self, private_ip_v4=None, vlan=None, network_adapter_name=None): """ Initialize an instance of :class:`DimensionDataNic` :param private_ip_v4: IPv4 :type private_ip_v4: ``str`` :param vlan: Network VLAN :type vlan: class: DimensionDataVlan or ``str`` :param network_adapter_name: Network Adapter Name :type network_adapter_name: ``str`` """ self.private_ip_v4 = private_ip_v4 self.vlan = vlan self.network_adapter_name = network_adapter_name def __repr__(self): return ('' % (self.private_ip_v4, self.vlan, self.network_adapter_name)) apache-libcloud-2.8.0/libcloud/common/dnsimple.py0000664000175000017500000000375613535474530021721 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import httplib from libcloud.common.base import ConnectionUserAndKey from libcloud.common.base import JsonResponse class DNSimpleDNSResponse(JsonResponse): def success(self): """ Determine if our request was successful. The meaning of this can be arbitrary; did we receive OK status? Did the node get created? Were we authenticated? :rtype: ``bool`` :return: ``True`` or ``False`` """ # response.success() only checks for 200 and 201 codes. Should we # add 204? return self.status in [httplib.OK, httplib.CREATED, httplib.NO_CONTENT] class DNSimpleDNSConnection(ConnectionUserAndKey): host = 'api.dnsimple.com' responseCls = DNSimpleDNSResponse def add_default_headers(self, headers): """ Add headers that are necessary for every request This method adds ``token`` to the request. """ # TODO: fijarse sobre que info se paso como parametro y en base # a esto, fijar el header headers['X-DNSimple-Token'] = '%s:%s' % (self.user_id, self.key) headers['Accept'] = 'application/json' headers['Content-Type'] = 'application/json' return headers apache-libcloud-2.8.0/libcloud/common/dnspod.py0000664000175000017500000000476513576514553021403 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import List from typing import Dict from libcloud.common.base import ConnectionKey, JsonResponse __all__ = [ 'API_HOST', 'DNSPodException', 'DNSPodResponse', 'DNSPodConnection' ] # Endpoint for dnspod api API_HOST = 'api.dnspod.com' class DNSPodResponse(JsonResponse): errors = [] # type: List[Dict] objects = [] # type: List[Dict] def __init__(self, response, connection): super(DNSPodResponse, self).__init__(response=response, connection=connection) self.errors, self.objects = self.parse_body_and_errors() if not self.success(): raise DNSPodException(code=self.status, message=self.errors.pop() ['status']['message']) def parse_body_and_errors(self): js = super(DNSPodResponse, self).parse_body() if 'status' in js and js['status']['code'] != '1': self.errors.append(js) else: self.objects.append(js) return self.errors, self.objects def success(self): return len(self.errors) == 0 class DNSPodConnection(ConnectionKey): host = API_HOST responseCls = DNSPodResponse def add_default_headers(self, headers): headers['Content-Type'] = 'application/x-www-form-urlencoded' headers['Accept'] = 'text/json' return headers class DNSPodException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "DNSPodException %s %s" % (self.code, self.message) apache-libcloud-2.8.0/libcloud/common/durabledns.py0000664000175000017500000002465513576514553022237 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import List from typing import Dict import re from xml.etree import ElementTree as ET # noqa from libcloud.common.base import ConnectionUserAndKey from libcloud.common.base import XmlResponse # API HOST to connect API_HOST = 'durabledns.com' def _schema_builder(urn_nid, method, attributes): """ Return a xml schema used to do an API request. :param urn_nid: API urn namespace id. :type urn_nid: type: ``str`` :param method: API method. :type method: type: ``str`` :param attributes: List of attributes to include. :type attributes: ``list`` of ``str`` rtype: :class:`Element` """ soap = ET.Element( 'soap:Body', {'xmlns:m': "https://durabledns.com/services/dns/%s" % method} ) urn = ET.SubElement(soap, 'urn:%s:%s' % (urn_nid, method)) # Attributes specification for attribute in attributes: ET.SubElement(urn, 'urn:%s:%s' % (urn_nid, attribute)) return soap SCHEMA_BUILDER_MAP = { 'list_zones': { 'urn_nid': 'listZoneswsdl', 'method': 'listZones', 'attributes': ['apiuser', 'apikey'] }, 'list_records': { 'urn_nid': 'listRecordswsdl', 'method': 'listRecords', 'attributes': ['apiuser', 'apikey', 'zonename'] }, 'get_zone': { 'urn_nid': 'getZonewsdl', 'method': 'getZone', 'attributes': ['apiuser', 'apikey', 'zonename'] }, 'get_record': { 'urn_nid': 'getRecordwsdl', 'method': 'getRecord', 'attributes': ['apiuser', 'apikey', 'zonename', 'recordid'] }, 'create_zone': { 'urn_nid': 'createZonewsdl', 'method': 'createZone', 'attributes': ['apiuser', 'apikey', 'zonename', 'ns', 'mbox', 'refresh', 'retry', 'expire', 'minimum', 'ttl', 'xfer', 'update_acl'] }, 'create_record': { 'urn_nid': 'createRecordwsdl', 'method': 'createRecord', 'attributes': ['apiuser', 'apikey', 'zonename', 'name', 'type', 'data', 'aux', 'ttl', 'ddns_enabled'] }, 'update_zone': { 'urn_nid': 'updateZonewsdl', 'method': 'updateZone', 'attributes': ['apiuser', 'apikey', 'zonename', 'ns', 'mbox', 'refresh', 'retry', 'expire', 'minimum', 'ttl', 'xfer', 'update_acl'] }, 'update_record': { 'urn_nid': 'updateRecordwsdl', 'method': 'updateRecord', 'attributes': ['apiuser', 'apikey', 'zonename', 'id', 'name', 'aux', 'data', 'ttl', 'ddns_enabled'] }, 'delete_zone': { 'urn_nid': 'deleteZonewsdl', 'method': 'deleteZone', 'attributes': ['apiuser', 'apikey', 'zonename'] }, 'delete_record': { 'urn_nid': 'deleteRecordwsdl', 'method': 'deleteRecord', 'attributes': ['apiuser', 'apikey', 'zonename', 'id'] } } class DurableDNSException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "DurableDNSException %s %s" % (self.code, self.message) class DurableResponse(XmlResponse): errors = [] # type: List[Dict] objects = [] # type: List[Dict] def __init__(self, response, connection): super(DurableResponse, self).__init__(response=response, connection=connection) self.objects, self.errors = self.parse_body_and_error() if self.errors: raise self._make_excp(self.errors[0]) def parse_body_and_error(self): """ Used to parse body from httplib.HttpResponse object. """ objects = [] errors = [] error_dict = {} extra = {} zone_dict = {} record_dict = {} xml_obj = self.parse_body() # pylint: disable=no-member envelop_body = list(xml_obj)[0] method_resp = list(envelop_body)[0] # parse the xml_obj # handle errors if 'Fault' in method_resp.tag: fault = [fault for fault in list(method_resp) if fault.tag == 'faultstring'][0] error_dict['ERRORMESSAGE'] = fault.text.strip() error_dict['ERRORCODE'] = self.status errors.append(error_dict) # parsing response from listZonesResponse if 'listZonesResponse' in method_resp.tag: answer = list(method_resp)[0] for element in answer: zone_dict['id'] = list(element)[0].text objects.append(zone_dict) # reset the zone_dict zone_dict = {} # parse response from listRecordsResponse if 'listRecordsResponse' in method_resp.tag: answer = list(method_resp)[0] for element in answer: for child in list(element): if child.tag == 'id': record_dict['id'] = child.text.strip() objects.append(record_dict) # reset the record_dict for later usage record_dict = {} # parse response from getZoneResponse if 'getZoneResponse' in method_resp.tag: for child in list(method_resp): if child.tag == 'origin': zone_dict['id'] = child.text.strip() zone_dict['domain'] = child.text.strip() elif child.tag == 'ttl': zone_dict['ttl'] = int(child.text.strip()) elif child.tag == 'retry': extra['retry'] = int(child.text.strip()) elif child.tag == 'expire': extra['expire'] = int(child.text.strip()) elif child.tag == 'minimum': extra['minimum'] = int(child.text.strip()) else: if child.text: extra[child.tag] = child.text.strip() else: extra[child.tag] = '' zone_dict['extra'] = extra objects.append(zone_dict) # parse response from getRecordResponse if 'getRecordResponse' in method_resp.tag: answer = list(method_resp)[0] for child in list(method_resp): if child.tag == 'id' and child.text: record_dict['id'] = child.text.strip() elif child.tag == 'name' and child.text: record_dict['name'] = child.text.strip() elif child.tag == 'type' and child.text: record_dict['type'] = child.text.strip() elif child.tag == 'data' and child.text: record_dict['data'] = child.text.strip() elif child.tag == 'aux' and child.text: record_dict['aux'] = child.text.strip() elif child.tag == 'ttl' and child.text: record_dict['ttl'] = child.text.strip() if not record_dict: error_dict['ERRORMESSAGE'] = 'Record does not exist' error_dict['ERRORCODE'] = 404 errors.append(error_dict) objects.append(record_dict) record_dict = {} if 'createZoneResponse' in method_resp.tag: answer = list(method_resp)[0] if answer.tag == 'return' and answer.text: record_dict['id'] = answer.text.strip() objects.append(record_dict) # catch Record does not exists error when deleting record if 'deleteRecordResponse' in method_resp.tag: answer = list(method_resp)[0] if 'Record does not exists' in answer.text.strip(): errors.append({'ERRORMESSAGE': answer.text.strip(), 'ERRORCODE': self.status}) # parse response in createRecordResponse if 'createRecordResponse' in method_resp.tag: answer = list(method_resp)[0] record_dict['id'] = answer.text.strip() objects.append(record_dict) record_dict = {} return (objects, errors) def parse_body(self): # A problem arise in the api response because there are undeclared # xml namespaces. In order to fix that at the moment, we use the # _fix_response method to clean up since we won't always have lxml # library. self._fix_response() body = super(DurableResponse, self).parse_body() return body def success(self): """ Used to determine if the request was successful. """ return len(self.errors) == 0 def _make_excp(self, error): return DurableDNSException(error['ERRORCODE'], error['ERRORMESSAGE']) def _fix_response(self): items = re.findall('', self.body, flags=0) for item in items: parts = item.split(' ') prefix = parts[0].replace('<', '').split(':')[1] new_item = "<" + prefix + ">" close_tag = "" new_close_tag = "" self.body = self.body.replace(item, new_item) self.body = self.body.replace(close_tag, new_close_tag) class DurableConnection(ConnectionUserAndKey): host = API_HOST responseCls = DurableResponse def add_default_params(self, params): params['user_id'] = self.user_id params['key'] = self.key return params def add_default_headers(self, headers): headers['Content-Type'] = 'text/xml' headers['Content-Encoding'] = 'gzip; charset=ISO-8859-1' return headers apache-libcloud-2.8.0/libcloud/common/exceptions.py0000664000175000017500000000654113535474530022262 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import time from email.utils import parsedate_tz, mktime_tz __all__ = [ 'BaseHTTPError', 'RateLimitReachedError', 'exception_from_message' ] class BaseHTTPError(Exception): """ The base exception class for all HTTP related exceptions. """ def __init__(self, code, message, headers=None): self.code = code self.message = message self.headers = headers # preserve old exception behavior for tests that # look for e.args[0] super(BaseHTTPError, self).__init__(message) def __str__(self): return self.message class RateLimitReachedError(BaseHTTPError): """ HTTP 429 - Rate limit: you've sent too many requests for this time period. """ code = 429 message = '%s Rate limit exceeded' % (code) def __init__(self, *args, **kwargs): headers = kwargs.pop('headers', None) super(RateLimitReachedError, self).__init__(self.code, self.message, headers) if self.headers is not None: self.retry_after = int(self.headers.get('retry-after', 0)) else: self.retry_after = 0 _error_classes = [RateLimitReachedError] _code_map = dict((c.code, c) for c in _error_classes) def exception_from_message(code, message, headers=None): """ Return an instance of BaseHTTPException or subclass based on response code. If headers include Retry-After, RFC 2616 says that its value may be one of two formats: HTTP-date or delta-seconds, for example: Retry-After: Fri, 31 Dec 1999 23:59:59 GMT Retry-After: 120 If Retry-After comes in HTTP-date, it'll be translated to a positive delta-seconds value when passing it to the exception constructor. Also, RFC 2616 says that Retry-After isn't just only applicable to 429 HTTP status, but also to other responses, like 503 and 3xx. Usage:: raise exception_from_message(code=self.status, message=self.parse_error(), headers=self.headers) """ kwargs = { 'code': code, 'message': message, 'headers': headers } if headers and 'retry-after' in headers: http_date = parsedate_tz(headers['retry-after']) if http_date is not None: # Convert HTTP-date to delay-seconds delay = max(0, int(mktime_tz(http_date) - time.time())) headers['retry-after'] = str(delay) cls = _code_map.get(code, BaseHTTPError) return cls(**kwargs) apache-libcloud-2.8.0/libcloud/common/gandi.py0000664000175000017500000001375713600144066021161 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Gandi driver base classes """ import time import hashlib from libcloud.utils.py3 import b from libcloud.common.base import ConnectionKey from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection # Global constants DEFAULT_TIMEOUT = 600 # operation pooling max seconds DEFAULT_INTERVAL = 20 # seconds between 2 operation.info class GandiException(Exception): """ Exception class for Gandi driver """ def __str__(self): return '(%u) %s' % (self.args[0], self.args[1]) def __repr__(self): return '' % (self.args[0], self.args[1]) class GandiResponse(XMLRPCResponse): """ A Base Gandi Response class to derive from. """ class GandiConnection(XMLRPCConnection, ConnectionKey): """ Connection class for the Gandi driver """ responseCls = GandiResponse host = 'rpc.gandi.net' endpoint = '/xmlrpc/' def __init__(self, key, secure=True, timeout=None, retry_delay=None, backoff=None, proxy_url=None): # Note: Method resolution order in this case is # XMLRPCConnection -> Connection and Connection doesn't take key as the # first argument so we specify a keyword argument instead. # Previously it was GandiConnection -> ConnectionKey so it worked fine. super(GandiConnection, self).__init__(key=key, secure=secure, timeout=timeout, retry_delay=retry_delay, backoff=backoff, proxy_url=proxy_url) self.driver = BaseGandiDriver def request(self, method, *args): args = (self.key, ) + args return super(GandiConnection, self).request(method, *args) class BaseGandiDriver(object): """ Gandi base driver """ connectionCls = GandiConnection name = 'Gandi' # Specific methods for gandi def _wait_operation(self, id, timeout=DEFAULT_TIMEOUT, check_interval=DEFAULT_INTERVAL): """ Wait for an operation to succeed""" for i in range(0, timeout, check_interval): try: # pylint: disable=no-member op = self.connection.request('operation.info', int(id)).object if op['step'] == 'DONE': return True if op['step'] in ['ERROR', 'CANCEL']: return False except (KeyError, IndexError): pass except Exception as e: raise GandiException(1002, e) time.sleep(check_interval) return False class BaseObject(object): """Base class for objects not conventional""" uuid_prefix = '' def __init__(self, id, state, driver): self.id = str(id) if id else None self.state = state self.driver = driver self.uuid = self.get_uuid() def get_uuid(self): """Unique hash for this object :return: ``str`` The hash is a function of an SHA1 hash of prefix, the object's ID and its driver which means that it should be unique between all interfaces. TODO : to review >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> vif = driver.create_interface() >>> vif.get_uuid() 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f' Note, for example, that this example will always produce the same UUID! """ hashstring = '%s:%s:%s' % \ (self.uuid_prefix, self.id, self.driver.type) return hashlib.sha1(b(hashstring)).hexdigest() class IPAddress(BaseObject): """ Provide a common interface for ip addresses """ uuid_prefix = 'inet:' def __init__(self, id, state, inet, driver, version=4, extra=None): super(IPAddress, self).__init__(id, state, driver) self.inet = inet self.version = version self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.inet, self.state, self.driver.name)) class NetworkInterface(BaseObject): """ Provide a common interface for network interfaces """ uuid_prefix = 'if:' def __init__(self, id, state, mac_address, driver, ips=None, node_id=None, extra=None): super(NetworkInterface, self).__init__(id, state, driver) self.mac = mac_address self.ips = ips or {} self.node_id = node_id self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.mac, self.state, self.driver.name)) class Disk(BaseObject): """ Gandi disk component """ def __init__(self, id, state, name, driver, size, extra=None): super(Disk, self).__init__(id, state, driver) self.name = name self.size = size self.extra = extra or {} def __repr__(self): return ( ('') % (self.id, self.name, self.state, self.size, self.driver.name)) apache-libcloud-2.8.0/libcloud/common/gandi_live.py0000664000175000017500000001563313570310635022176 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Gandi Live driver base classes """ import json from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.common.types import ProviderError from libcloud.utils.py3 import httplib __all__ = [ 'API_HOST', 'GandiLiveBaseError', 'JsonParseError', 'ResourceNotFoundError', 'InvalidRequestError', 'ResourceConflictError', 'GandiLiveResponse', 'GandiLiveConnection', 'BaseGandiLiveDriver', ] API_HOST = 'dns.api.gandi.net' class GandiLiveBaseError(ProviderError): """ Exception class for Gandi Live driver """ pass class JsonParseError(GandiLiveBaseError): pass # Example: # { # "code": 404, # "message": "Unknown zone", # "object": "LocalizedHTTPNotFound", # "cause": "Not Found" # } class ResourceNotFoundError(GandiLiveBaseError): pass # Example: # { # "code": 400, # "message": "zone or zone_uuid must be set", # "object": "HTTPBadRequest", # "cause": "No zone set.", # "errors": [ # { # "location": "body", # "name": "zone_uuid", # "description": "\"FAKEUUID\" is not a UUID" # } # ] # } class InvalidRequestError(GandiLiveBaseError): pass # Examples: # { # "code": 409, # "message": "Zone Testing already exists", # "object": "HTTPConflict", # "cause": "Duplicate Entry" # } # { # "code": 409, # "message": "The domain example.org already exists", # "object": "HTTPConflict", # "cause": "Duplicate Entry" # } # { # "code": 409, # "message": "This zone is still used by 1 domains", # "object": "HTTPConflict", # "cause": "In use" # } class ResourceConflictError(GandiLiveBaseError): pass class GandiLiveResponse(JsonResponse): """ A Base Gandi Live Response class to derive from. """ def success(self): """ Determine if our request was successful. For the Gandi Live response class, tag all responses as successful and raise appropriate Exceptions from parse_body. :return: C{True} """ return True def parse_body(self): """ Parse the JSON response body, or raise exceptions as appropriate. :return: JSON dictionary :rtype: ``dict`` """ json_error = False try: body = json.loads(self.body) except Exception: # If there is both a JSON parsing error and an unsuccessful http # response (like a 404), we want to raise the http error and not # the JSON one, so don't raise JsonParseError here. body = self.body json_error = True # Service does not appear to return HTTP 202 Accepted for anything. valid_http_codes = [ httplib.OK, httplib.CREATED, httplib.NO_CONTENT ] if self.status in valid_http_codes: if json_error: raise JsonParseError(body, self.status) else: return body elif self.status == httplib.NOT_FOUND: message = self._get_error(body, json_error) raise ResourceNotFoundError(message, self.status) elif self.status == httplib.BAD_REQUEST: message = self._get_error(body, json_error) raise InvalidRequestError(message, self.status) elif self.status == httplib.CONFLICT: message = self._get_error(body, json_error) raise ResourceConflictError(message, self.status) else: message = self._get_error(body, json_error) raise GandiLiveBaseError(message, self.status) # Errors are not described at all in Gandi's official documentation. # It appears when an error arises, a JSON object is returned along with # an HTTP 4xx class code. The object is structured as: # { # code: , # object: , # message: , # cause: , # errors: [ # { # location: , # name: , # description: # } # ] # } # where # is a number equal to the HTTP response status code # is a string with some internal name for the status code # is a string detailing what the problem is # is a string that comes from a set of succinct problem summaries # errors is optional; if present: # is a string for which part of the request to look in # is a string naming the parameter # is a string detailing what the problem is # Here we ignore object and combine message and cause along with an error # if one or more exists. def _get_error(self, body, json_error): """ Get the error code and message from a JSON response. Incorporate the first error if there are multiple errors. :param body: The body of the JSON response dictionary :type body: ``dict`` :return: String containing error message :rtype: ``str`` """ if not json_error and 'cause' in body: message = '%s: %s' % (body['cause'], body['message']) if 'errors' in body: err = body['errors'][0] message = '%s (%s in %s: %s)' % (message, err.get('location'), err.get('name'), err.get('description')) else: message = body return message class GandiLiveConnection(ConnectionKey): """ Connection class for the Gandi Live driver """ responseCls = GandiLiveResponse host = API_HOST def add_default_headers(self, headers): """ Returns default headers as a dictionary. """ headers["Content-Type"] = 'application/json' headers["X-Api-Key"] = self.key return headers def encode_data(self, data): """Encode data to JSON""" return json.dumps(data) class BaseGandiLiveDriver(object): """ Gandi Live base driver """ connectionCls = GandiLiveConnection name = 'GandiLive' apache-libcloud-2.8.0/libcloud/common/gogrid.py0000664000175000017500000001437313535474530021356 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import hashlib import time from libcloud.utils.py3 import b from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.common.types import MalformedResponseError from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.compute.base import NodeLocation HOST = 'api.gogrid.com' PORTS_BY_SECURITY = {True: 443, False: 80} API_VERSION = '1.8' __all__ = [ "GoGridResponse", "GoGridConnection", "GoGridIpAddress", "BaseGoGridDriver", ] class GoGridResponse(JsonResponse): def __init__(self, *args, **kwargs): self.driver = BaseGoGridDriver super(GoGridResponse, self).__init__(*args, **kwargs) def success(self): if self.status == 403: raise InvalidCredsError('Invalid credentials', self.driver) if self.status == 401: raise InvalidCredsError('API Key has insufficient rights', self.driver) if not self.body: return None try: return self.parse_body()['status'] == 'success' except ValueError: raise MalformedResponseError('Malformed reply', body=self.body, driver=self.driver) def parse_error(self): try: return self.parse_body()["list"][0]["message"] except (ValueError, KeyError): return None class GoGridConnection(ConnectionUserAndKey): """ Connection class for the GoGrid driver """ host = HOST responseCls = GoGridResponse def add_default_params(self, params): params["api_key"] = self.user_id params["v"] = API_VERSION params["format"] = 'json' params["sig"] = self.get_signature(self.user_id, self.key) return params def get_signature(self, key, secret): """ create sig from md5 of key + secret + time """ m = hashlib.md5(b(key + secret + str(int(time.time())))) return m.hexdigest() def request(self, action, params=None, data='', headers=None, method='GET', raw=False): return super(GoGridConnection, self).request(action, params, data, headers, method, raw) class GoGridIpAddress(object): """ IP Address """ def __init__(self, id, ip, public, state, subnet): self.id = id self.ip = ip self.public = public self.state = state self.subnet = subnet class BaseGoGridDriver(object): """GoGrid has common object model for services they provide, like locations and IP, so keep handling of these things in a single place.""" name = "GoGrid" def _get_ip(self, element): return element.get('ip').get('ip') def _to_ip(self, element): ip = GoGridIpAddress(id=element['id'], ip=element['ip'], public=element['public'], subnet=element['subnet'], state=element["state"]["name"]) ip.location = self._to_location(element['datacenter']) return ip def _to_ips(self, object): return [self._to_ip(el) for el in object['list']] def _to_location(self, element): # pylint: disable=no-member location = NodeLocation(id=element['id'], name=element['name'], country="US", driver=self.connection.driver) return location def _to_locations(self, object): return [self._to_location(el) for el in object['list']] def ex_list_ips(self, **kwargs): """Return list of IP addresses assigned to the account. :keyword public: set to True to list only public IPs or False to list only private IPs. Set to None or not specify at all not to filter by type :type public: ``bool`` :keyword assigned: set to True to list only addresses assigned to servers, False to list unassigned addresses and set to None or don't set at all not no filter by state :type assigned: ``bool`` :keyword location: filter IP addresses by location :type location: :class:`NodeLocation` :rtype: ``list`` of :class:`GoGridIpAddress` """ params = {} if "public" in kwargs and kwargs["public"] is not None: params["ip.type"] = {True: "Public", False: "Private"}[kwargs["public"]] if "assigned" in kwargs and kwargs["assigned"] is not None: params["ip.state"] = {True: "Assigned", False: "Unassigned"}[kwargs["assigned"]] if "location" in kwargs and kwargs['location'] is not None: params['datacenter'] = kwargs['location'].id # pylint: disable=no-member response = self.connection.request('/api/grid/ip/list', params=params) ips = self._to_ips(response.object) return ips def _get_first_ip(self, location=None): ips = self.ex_list_ips(public=True, assigned=False, location=location) try: return ips[0].ip except IndexError: # pylint: disable=no-member raise LibcloudError('No public unassigned IPs left', self.driver) apache-libcloud-2.8.0/libcloud/common/google.py0000664000175000017500000007422613600144066021351 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Module for Google Connection and Authentication classes. Information about setting up your Google OAUTH2 credentials: For libcloud, there are two basic methods for authenticating to Google using OAUTH2: Service Accounts and Client IDs for Installed Applications. Both are initially set up from the Cloud Console Console - https://cloud.google.com/console Setting up Service Account authentication (note that you need the cryptography package installed to use this): - Go to the Console - Go to your project and then to "APIs & auth" on the left - Click on "Credentials" - Click on "Create New Client ID..." - Select "Service account" and click on "Create Client ID" - Download the Private Key (should happen automatically). The key you download is in JSON format. - Move the .json file to a safe location. - Optionally, you may choose to Generate a PKCS12 key from the Console. It needs to be converted to the PEM format. Please note, the PKCS12 format is deprecated and may be removed in a future release. - Convert the key using OpenSSL (the default password is 'notasecret'). - Move the .pem file to a safe location. - To Authenticate, you will need to pass the Service Account's "Email address" in as the user_id and the path to the .pem file as the key. Setting up Installed Application authentication: - Go to the Console - Go to your project and then to "APIs & auth" on the left - Click on "Credentials" - Select "Installed application" and "Other" then click on "Create Client ID" - To Authenticate, pass in the "Client ID" as the user_id and the "Client secret" as the key - The first time that you do this, the libcloud will give you a URL to visit. Copy and paste the URL into a browser. - When you go to the URL it will ask you to log in (if you aren't already) and ask you if you want to allow the project access to your account. - Click on Accept and you will be given a code. - Paste that code at the prompt given to you by the Google libcloud connection. - At that point, a token & refresh token will be stored in your home directory and will be used for authentication. Please remember to secure your keys and access tokens. """ from __future__ import with_statement try: import simplejson as json except ImportError: import json # type: ignore import logging import base64 import errno import time import datetime import os import socket import sys from libcloud.utils.connection import get_response_object from libcloud.utils.py3 import b, httplib, urlencode, urlparse, PY3 from libcloud.common.base import (ConnectionUserAndKey, JsonResponse, PollingConnection) from libcloud.common.base import BaseDriver from libcloud.common.types import (ProviderError, LibcloudError) try: from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.hashes import SHA256 from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 except ImportError: # The cryptography library is unavailable SHA256 = None UTC_TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%SZ' LOG = logging.getLogger(__name__) def _utcnow(): """ Mocked in libcloud.test.common.google.GoogleTestCase. """ return datetime.datetime.utcnow() def _utc_timestamp(datetime_obj): """ Return string of datetime_obj in the UTC Timestamp Format """ return datetime_obj.strftime(UTC_TIMESTAMP_FORMAT) def _from_utc_timestamp(timestamp): """ Return datetime obj where date and time are pulled from timestamp string. """ return datetime.datetime.strptime(timestamp, UTC_TIMESTAMP_FORMAT) def _get_gce_metadata(path=''): try: url = 'http://metadata/computeMetadata/v1/' + path.lstrip('/') headers = {'Metadata-Flavor': 'Google'} response = get_response_object(url, headers=headers) return response.status, '', response.body except Exception as e: return -1, str(e), None class GoogleAuthError(LibcloudError): """Generic Error class for various authentication errors.""" def __init__(self, value): self.value = value def __repr__(self): return repr(self.value) class GoogleBaseError(ProviderError): def __init__(self, value, http_code, code, driver=None): self.code = code super(GoogleBaseError, self).__init__(value, http_code, driver) class InvalidRequestError(GoogleBaseError): pass class JsonParseError(GoogleBaseError): pass class ResourceNotFoundError(GoogleBaseError): def __init__(self, value, http_code, code, driver=None): self.code = code if isinstance(value, dict) and 'message' in value and \ value['message'].count('/') == 1 and \ value['message'].count('projects/') == 1: value['message'] = value['message'] + ". A missing project " \ "error may be an authentication issue. " \ "Please ensure your auth credentials match " \ "your project. " super(ResourceNotFoundError, self).__init__(value, http_code, driver) class QuotaExceededError(GoogleBaseError): pass class ResourceExistsError(GoogleBaseError): pass class ResourceInUseError(GoogleBaseError): pass class GoogleResponse(JsonResponse): """ Google Base Response class. """ def success(self): """ Determine if the request was successful. For the Google response class, tag all responses as successful and raise appropriate Exceptions from parse_body. :return: C{True} """ return True def _get_error(self, body): """ Get the error code and message from a JSON response. Return just the first error if there are multiple errors. :param body: The body of the JSON response dictionary :type body: ``dict`` :return: Tuple containing error code and message :rtype: ``tuple`` of ``str`` or ``int`` """ if 'errors' in body['error']: err = body['error']['errors'][0] else: err = body['error'] if 'code' in err: code = err.get('code') message = err.get('message') else: code = None if 'reason' in err: code = err.get('reason') message = body.get('error_description', err) return (code, message) def parse_body(self): """ Parse the JSON response body, or raise exceptions as appropriate. :return: JSON dictionary :rtype: ``dict`` """ if len(self.body) == 0 and not self.parse_zero_length_body: return self.body json_error = False try: body = json.loads(self.body) except Exception: # If there is both a JSON parsing error and an unsuccessful http # response (like a 404), we want to raise the http error and not # the JSON one, so don't raise JsonParseError here. body = self.body json_error = True valid_http_codes = [ httplib.OK, httplib.CREATED, httplib.ACCEPTED, httplib.CONFLICT, ] if self.status in valid_http_codes: if json_error: raise JsonParseError(body, self.status, None) elif 'error' in body: (code, message) = self._get_error(body) if code == 'QUOTA_EXCEEDED': raise QuotaExceededError(message, self.status, code) elif code == 'RESOURCE_ALREADY_EXISTS': raise ResourceExistsError(message, self.status, code) elif code == 'alreadyExists': raise ResourceExistsError(message, self.status, code) elif code.startswith('RESOURCE_IN_USE'): raise ResourceInUseError(message, self.status, code) else: raise GoogleBaseError(message, self.status, code) else: return body elif self.status == httplib.NOT_FOUND: if (not json_error) and ('error' in body): (code, message) = self._get_error(body) else: message = body code = None raise ResourceNotFoundError(message, self.status, code) elif self.status == httplib.BAD_REQUEST: if (not json_error) and ('error' in body): (code, message) = self._get_error(body) else: message = body code = None raise InvalidRequestError(message, self.status, code) else: if (not json_error) and ('error' in body): (code, message) = self._get_error(body) else: message = body code = None raise GoogleBaseError(message, self.status, code) class GoogleBaseDriver(BaseDriver): name = "Google API" class GoogleBaseAuthConnection(ConnectionUserAndKey): """ Base class for Google Authentication. Should be subclassed for specific types of authentication. """ driver = GoogleBaseDriver responseCls = GoogleResponse name = 'Google Auth' host = 'accounts.google.com' auth_path = '/o/oauth2/auth' def __init__(self, user_id, key=None, scopes=None, redirect_uri='urn:ietf:wg:oauth:2.0:oob', login_hint=None, **kwargs): """ :param user_id: The email address (for service accounts) or Client ID (for installed apps) to be used for authentication. :type user_id: ``str`` :param key: The RSA Key (for service accounts) or file path containing key or Client Secret (for installed apps) to be used for authentication. :type key: ``str`` :param scopes: A list of urls defining the scope of authentication to grant. :type scopes: ``list`` :keyword redirect_uri: The Redirect URI for the authentication request. See Google OAUTH2 documentation for more info. :type redirect_uri: ``str`` :keyword login_hint: Login hint for authentication request. Useful for Installed Application authentication. :type login_hint: ``str`` """ scopes = scopes or [] self.scopes = " ".join(scopes) self.redirect_uri = redirect_uri self.login_hint = login_hint super(GoogleBaseAuthConnection, self).__init__(user_id, key, **kwargs) def add_default_headers(self, headers): """ Add defaults for 'Content-Type' and 'Host' headers. """ headers['Content-Type'] = "application/x-www-form-urlencoded" headers['Host'] = self.host return headers def _token_request(self, request_body): """ Return an updated token from a token request body. :param request_body: A dictionary of values to send in the body of the token request. :type request_body: ``dict`` :return: A dictionary with updated token information :rtype: ``dict`` """ data = urlencode(request_body) try: response = self.request('/o/oauth2/token', method='POST', data=data) except AttributeError: raise GoogleAuthError('Invalid authorization response, please ' 'check your credentials and time drift.') token_info = response.object if 'expires_in' in token_info: expire_time = _utcnow() + datetime.timedelta( seconds=token_info['expires_in']) token_info['expire_time'] = _utc_timestamp(expire_time) return token_info def refresh_token(self, token_info): """ Refresh the current token. Fetch an updated refresh token from internal metadata service. :param token_info: Dictionary containing token information. (Not used, but here for compatibility) :type token_info: ``dict`` :return: A dictionary containing updated token information. :rtype: ``dict`` """ # pylint: disable=no-member return self.get_new_token() class GoogleInstalledAppAuthConnection(GoogleBaseAuthConnection): """Authentication connection for "Installed Application" authentication.""" def get_code(self): """ Give the user a URL that they can visit to authenticate and obtain a code. This method will ask for that code that the user can paste in. Mocked in libcloud.test.common.google.GoogleTestCase. :return: Code supplied by the user after authenticating :rtype: ``str`` """ auth_params = {'response_type': 'code', 'client_id': self.user_id, 'redirect_uri': self.redirect_uri, 'scope': self.scopes, 'state': 'Libcloud Request'} if self.login_hint: auth_params['login_hint'] = self.login_hint data = urlencode(auth_params) url = 'https://%s%s?%s' % (self.host, self.auth_path, data) print('\nPlease Go to the following URL and sign in:') print(url) if PY3: code = input('Enter Code: ') else: code = raw_input('Enter Code: ') return code def get_new_token(self): """ Get a new token. Generally used when no previous token exists or there is no refresh token :return: Dictionary containing token information :rtype: ``dict`` """ # Ask the user for a code code = self.get_code() token_request = {'code': code, 'client_id': self.user_id, 'client_secret': self.key, 'redirect_uri': self.redirect_uri, 'grant_type': 'authorization_code'} return self._token_request(token_request) def refresh_token(self, token_info): """ Use the refresh token supplied in the token info to get a new token. :param token_info: Dictionary containing current token information :type token_info: ``dict`` :return: A dictionary containing updated token information. :rtype: ``dict`` """ if 'refresh_token' not in token_info: return self.get_new_token() refresh_request = {'refresh_token': token_info['refresh_token'], 'client_id': self.user_id, 'client_secret': self.key, 'grant_type': 'refresh_token'} new_token = self._token_request(refresh_request) if 'refresh_token' not in new_token: new_token['refresh_token'] = token_info['refresh_token'] return new_token class GoogleServiceAcctAuthConnection(GoogleBaseAuthConnection): """Authentication class for "Service Account" authentication.""" def __init__(self, user_id, key, *args, **kwargs): """ Check to see if cryptography is available, and convert key file path into a key string if the key is in a file. :param user_id: Email address to be used for Service Account authentication. :type user_id: ``str`` :param key: The RSA Key or path to file containing the key. :type key: ``str`` """ if SHA256 is None: raise GoogleAuthError('cryptography library required for ' 'Service Account Authentication.') # Check to see if 'key' is a file and read the file if it is. if key.find("PRIVATE KEY---") == -1: # key is a file keypath = os.path.expanduser(key) is_file_path = os.path.exists(keypath) and os.path.isfile(keypath) if not is_file_path: raise ValueError("Missing (or not readable) key " "file: '%s'" % key) with open(keypath, 'r') as f: contents = f.read() try: key = json.loads(contents) key = key['private_key'] except ValueError: key = contents super(GoogleServiceAcctAuthConnection, self).__init__( user_id, key, *args, **kwargs) def get_new_token(self): """ Get a new token using the email address and RSA Key. :return: Dictionary containing token information :rtype: ``dict`` """ # The header is always the same header = {'alg': 'RS256', 'typ': 'JWT'} header_enc = base64.urlsafe_b64encode(b(json.dumps(header))) # Construct a claim set claim_set = {'iss': self.user_id, 'scope': self.scopes, 'aud': 'https://accounts.google.com/o/oauth2/token', 'exp': int(time.time()) + 3600, 'iat': int(time.time())} claim_set_enc = base64.urlsafe_b64encode(b(json.dumps(claim_set))) # The message contains both the header and claim set message = b'.'.join((header_enc, claim_set_enc)) # Then the message is signed using the key supplied key = serialization.load_pem_private_key( b(self.key), password=None, backend=default_backend() ) signature = key.sign( data=b(message), padding=PKCS1v15(), algorithm=SHA256() ) signature = base64.urlsafe_b64encode(signature) # Finally the message and signature are sent to get a token jwt = b'.'.join((message, signature)) request = {'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion': jwt} return self._token_request(request) class GoogleGCEServiceAcctAuthConnection(GoogleBaseAuthConnection): """Authentication class for self-authentication when used with a GCE instance that supports serviceAccounts. """ def get_new_token(self): """ Get a new token from the internal metadata service. :return: Dictionary containing token information :rtype: ``dict`` """ path = '/instance/service-accounts/default/token' http_code, http_reason, token_info = _get_gce_metadata(path) if http_code == httplib.NOT_FOUND: raise ValueError("Service Accounts are not enabled for this " "GCE instance.") if http_code != httplib.OK: raise ValueError("Internal GCE Authorization failed: " "'%s'" % str(http_reason)) token_info = json.loads(token_info) if 'expires_in' in token_info: expire_time = _utcnow() + datetime.timedelta( seconds=token_info['expires_in']) token_info['expire_time'] = _utc_timestamp(expire_time) return token_info class GoogleAuthType(object): """ SA (Service Account), IA (Installed Application), GCE (Auth from a GCE instance with service account enabled) GCS_S3 (Cloud Storage S3 interoperability authentication) """ SA = 'SA' IA = 'IA' GCE = 'GCE' GCS_S3 = 'GCS_S3' ALL_TYPES = [SA, IA, GCE, GCS_S3] OAUTH2_TYPES = [SA, IA, GCE] @classmethod def guess_type(cls, user_id): if cls._is_sa(user_id): return cls.SA elif cls._is_gcs_s3(user_id): return cls.GCS_S3 elif cls._is_gce(): return cls.GCE else: return cls.IA @classmethod def is_oauth2(cls, auth_type): return auth_type in cls.OAUTH2_TYPES @staticmethod def _is_gce(): """ Checks if we can access the GCE metadata server. Mocked in libcloud.test.common.google.GoogleTestCase. """ http_code, http_reason, body = _get_gce_metadata() if http_code == httplib.OK and body: return True return False @staticmethod def _is_gcs_s3(user_id): """ Checks S3 key format: alphanumeric chars starting with GOOG. """ return ( len(user_id) >= 20 and len(user_id) < 30 and user_id .startswith('GOOG') ) @staticmethod def _is_sa(user_id): return user_id.endswith('.gserviceaccount.com') class GoogleOAuth2Credential(object): default_credential_file = '~/.google_libcloud_auth' def __init__(self, user_id, key, auth_type=None, credential_file=None, scopes=None, **kwargs): self.auth_type = auth_type or GoogleAuthType.guess_type(user_id) if self.auth_type not in GoogleAuthType.ALL_TYPES: raise GoogleAuthError('Invalid auth type: %s' % self.auth_type) if not GoogleAuthType.is_oauth2(self.auth_type): raise GoogleAuthError(('Auth type %s cannot be used with OAuth2' % self.auth_type)) self.user_id = user_id self.key = key default_credential_file = '.'.join([self.default_credential_file, user_id]) self.credential_file = credential_file or default_credential_file # Default scopes to read/write for compute, storage, and dns. self.scopes = scopes or [ 'https://www.googleapis.com/auth/compute', 'https://www.googleapis.com/auth/devstorage.full_control', 'https://www.googleapis.com/auth/ndev.clouddns.readwrite', ] self.token = self._get_token_from_file() if self.auth_type == GoogleAuthType.GCE: self.oauth2_conn = GoogleGCEServiceAcctAuthConnection( self.user_id, self.scopes, **kwargs) elif self.auth_type == GoogleAuthType.SA: self.oauth2_conn = GoogleServiceAcctAuthConnection( self.user_id, self.key, self.scopes, **kwargs) elif self.auth_type == GoogleAuthType.IA: self.oauth2_conn = GoogleInstalledAppAuthConnection( self.user_id, self.key, self.scopes, **kwargs) else: raise GoogleAuthError('Invalid auth_type: %s' % str(self.auth_type)) if self.token is None: self.token = self.oauth2_conn.get_new_token() self._write_token_to_file() @property def access_token(self): if self.token_expire_utc_datetime < _utcnow(): self._refresh_token() return self.token['access_token'] @property def token_expire_utc_datetime(self): return _from_utc_timestamp(self.token['expire_time']) def _refresh_token(self): self.token = self.oauth2_conn.refresh_token(self.token) self._write_token_to_file() def _get_token_from_file(self): """ Read credential file and return token information. Mocked in libcloud.test.common.google.GoogleTestCase. :return: Token information dictionary, or None :rtype: ``dict`` or ``None`` """ token = None filename = os.path.realpath(os.path.expanduser(self.credential_file)) try: with open(filename, 'r') as f: data = f.read() token = json.loads(data) except (IOError, ValueError) as e: # Note: File related errors (IOError) and errors related to json # parsing of the data (ValueError) are not fatal. LOG.info('Failed to read cached auth token from file "%s": %s', filename, str(e)) return token def _write_token_to_file(self): """ Write token to credential file. Mocked in libcloud.test.common.google.GoogleTestCase. """ filename = os.path.expanduser(self.credential_file) filename = os.path.realpath(filename) try: data = json.dumps(self.token) write_flags = os.O_CREAT | os.O_WRONLY | os.O_TRUNC with os.fdopen(os.open(filename, write_flags, int('600', 8)), 'w') as f: f.write(data) except Exception as e: # Note: Failure to write (cache) token in a file is not fatal. It # simply means degraded performance since we will need to acquire a # new token each time script runs. LOG.info('Failed to write auth token to file "%s": %s', filename, str(e)) class GoogleBaseConnection(ConnectionUserAndKey, PollingConnection): """Base connection class for interacting with Google APIs.""" driver = GoogleBaseDriver responseCls = GoogleResponse host = 'www.googleapis.com' poll_interval = 2.0 timeout = 180 def __init__(self, user_id, key=None, auth_type=None, credential_file=None, scopes=None, **kwargs): """ Determine authentication type, set up appropriate authentication connection and get initial authentication information. :param user_id: The email address (for service accounts) or Client ID (for installed apps) to be used for authentication. :type user_id: ``str`` :param key: The RSA Key (for service accounts) or file path containing key or Client Secret (for installed apps) to be used for authentication. :type key: ``str`` :keyword auth_type: See GoogleAuthType class for list and description of accepted values. If not supplied, auth_type will be guessed based on value of user_id or if the code is running on a GCE instance. :type auth_type: ``str`` :keyword credential_file: Path to file for caching authentication information. :type credential_file: ``str`` :keyword scopes: List of OAuth2 scope URLs. The empty default sets read/write access to Compute, Storage, and DNS. :type scopes: ``list`` """ super(GoogleBaseConnection, self).__init__(user_id, key, **kwargs) self.oauth2_credential = GoogleOAuth2Credential( user_id, key, auth_type, credential_file, scopes, **kwargs) python_ver = '%s.%s.%s' % (sys.version_info[0], sys.version_info[1], sys.version_info[2]) ver_platform = 'Python %s/%s' % (python_ver, sys.platform) self.user_agent_append(ver_platform) def add_default_headers(self, headers): """ @inherits: :class:`Connection.add_default_headers` """ headers['Content-Type'] = 'application/json' headers['Host'] = self.host return headers def pre_connect_hook(self, params, headers): """ Check to make sure that token hasn't expired. If it has, get an updated token. Also, add the token to the headers. @inherits: :class:`Connection.pre_connect_hook` """ headers['Authorization'] = ('Bearer ' + self.oauth2_credential.access_token) return params, headers def encode_data(self, data): """Encode data to JSON""" return json.dumps(data) def request(self, *args, **kwargs): """ @inherits: :class:`Connection.request` """ # Adds some retry logic for the occasional # "Connection Reset by peer" error. retries = 4 tries = 0 while tries < (retries - 1): try: return super(GoogleBaseConnection, self).request( *args, **kwargs) except socket.error as e: if e.errno == errno.ECONNRESET: tries = tries + 1 else: raise e # One more time, then give up. return super(GoogleBaseConnection, self).request(*args, **kwargs) def has_completed(self, response): """ Determine if operation has completed based on response. :param response: JSON response :type response: I{responseCls} :return: True if complete, False otherwise :rtype: ``bool`` """ if response.object['status'] == 'DONE': return True else: return False def get_poll_request_kwargs(self, response, context, request_kwargs): """ @inherits: :class:`PollingConnection.get_poll_request_kwargs` """ return {'action': response.object['selfLink']} def morph_action_hook(self, action): """ Update action to correct request path. In many places, the Google API returns a full URL to a resource. This will strip the scheme and host off of the path and just return the request. Otherwise, it will prepend the base request_path to the action. :param action: The action to be called in the http request :type action: ``str`` :return: The modified request based on the action :rtype: ``str`` """ if action.startswith('https://'): u = urlparse.urlsplit(action) request = urlparse.urlunsplit(('', '', u[2], u[3], u[4])) else: request = self.request_path + action return request apache-libcloud-2.8.0/libcloud/common/gridscale.py0000664000175000017500000001031013576514553022030 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Common settings and connection objects for gridscale """ try: import simplejson as json except Exception: import json # type: ignore from libcloud.common.base import BaseDriver, PollingConnection from libcloud.common.base import ConnectionUserAndKey from libcloud.common.base import JsonResponse from libcloud.common.types import InvalidCredsError from libcloud.compute.types import NodeState from libcloud.utils.py3 import httplib NODE_STATE_MAP = { 'ACTIVE': NodeState.RUNNING, 'STOPPED': NodeState.STOPPED, 'UNKNOWN': NodeState.UNKNOWN, } class GridscaleResponse(JsonResponse): """ Gridscale API Response """ valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.NO_CONTENT] def parse_error(self): body = self.parse_body() if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError(body['message']) if self.status == httplib.NOT_FOUND: raise Exception( "The resource you are looking for has not been found.") return self.body def success(self): return self.status in self.valid_response_codes class GridscaleConnection(ConnectionUserAndKey, PollingConnection): """ gridscale connection class Authentication using uuid and api token """ host = 'api.gridscale.io' responseCls = GridscaleResponse def encode_data(self, data): return json.dumps(data) def add_default_headers(self, headers): """ add parameters that are necessary for each request to be successful :param headers: Authentification token :type headers: ``str`` :return: None """ headers['X-Auth-UserId'] = self.user_id headers['X-Auth-Token'] = self.key headers['Content-Type'] = 'application/json' return headers def async_request(self, *poargs, **kwargs): self.async_request_counter = 0 self.request_method = '_poll_request_initial' return super(GridscaleConnection, self).async_request(*poargs, **kwargs) def _poll_request_initial(self, **kwargs): if self.async_request_counter == 0: self.poll_response_initial = super(GridscaleConnection, self) \ .request(**kwargs) r = self.poll_response_initial self.async_request_counter += 1 else: r = self.request(**kwargs) return r def get_poll_request_kwargs(self, response, context, request_kwargs): endpoint_url = 'requests/{}'.format(response.object['request_uuid']) kwargs = {'action': endpoint_url} return kwargs def has_completed(self, response): if response.status == 200: request_uuid = self.poll_response_initial.object['request_uuid'] request_status = response.object[request_uuid]['status'] if request_status == 'done': return True return False class GridscaleBaseDriver(BaseDriver): name = 'gridscale' website = 'https://gridscale.io' connectionCls = GridscaleConnection def __init__(self, user_id, key, **kwargs): super(GridscaleBaseDriver, self).__init__(user_id, key, **kwargs) def _sync_request(self, data=None, endpoint=None, method='GET'): raw_result = self.connection.request(endpoint, data=data, method=method) return raw_result apache-libcloud-2.8.0/libcloud/common/hostvirtual.py0000664000175000017500000000473413576514553022474 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. try: import simplejson as json except ImportError: import json # type: ignore from libcloud.utils.py3 import httplib from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.compute.types import InvalidCredsError from libcloud.common.types import LibcloudError API_HOST = 'vapi.vr.org' class HostVirtualException(LibcloudError): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return self.__repr__() def __repr__(self): return '' % (self.code, self.message) class HostVirtualConnection(ConnectionKey): host = API_HOST allow_insecure = False def add_default_params(self, params): params['key'] = self.key return params class HostVirtualResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_body(self): if not self.body: return None data = json.loads(self.body) return data def parse_error(self): data = self.parse_body() if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError('%(code)s:%(message)s' % (data['error'])) elif self.status == httplib.PRECONDITION_FAILED: raise HostVirtualException( data['error']['code'], data['error']['message']) elif self.status == httplib.NOT_FOUND: raise HostVirtualException( data['error']['code'], data['error']['message']) return self.body def success(self): return self.status in self.valid_response_codes apache-libcloud-2.8.0/libcloud/common/linode.py0000664000175000017500000001273613535474530021356 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.common.types import InvalidCredsError __all__ = [ 'API_HOST', 'API_ROOT', 'LinodeException', 'LinodeResponse', 'LinodeConnection' ] # Endpoint for the Linode API API_HOST = 'api.linode.com' API_ROOT = '/' # Constants that map a RAM figure to a PlanID (updated 2014-08-25) LINODE_PLAN_IDS = {1024: '1', 2048: '2', 4096: '4', 8192: '6', 16384: '7', 32768: '8', 49152: '9', 65536: '10', 98304: '12'} # Available filesystems for disk creation LINODE_DISK_FILESYSTEMS = ['ext3', 'ext4', 'swap', 'raw'] class LinodeException(Exception): """Error originating from the Linode API This class wraps a Linode API error, a list of which is available in the API documentation. All Linode API errors are a numeric code and a human-readable description. """ def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "(%u) %s" % (self.code, self.message) def __repr__(self): return "" % (self.code, self.message) class LinodeResponse(JsonResponse): """ Linode API response Wraps the HTTP response returned by the Linode API. libcloud does not take advantage of batching, so a response will always reflect the above format. A few weird quirks are caught here as well. """ objects = None def __init__(self, response, connection): """Instantiate a LinodeResponse from the HTTP response :keyword response: The raw response returned by urllib :return: parsed :class:`LinodeResponse`""" self.errors = [] super(LinodeResponse, self).__init__(response, connection) self.invalid = LinodeException(0xFF, "Invalid JSON received from server") # Move parse_body() to here; we can't be sure of failure until we've # parsed the body into JSON. self.objects, self.errors = self.parse_body() if not self.success(): # Raise the first error, as there will usually only be one raise self.errors[0] def parse_body(self): """Parse the body of the response into JSON objects If the response chokes the parser, action and data will be returned as None and errorarray will indicate an invalid JSON exception. :return: ``list`` of objects and ``list`` of errors""" js = super(LinodeResponse, self).parse_body() try: if isinstance(js, dict): # solitary response - promote to list js = [js] ret = [] errs = [] for obj in js: if ("DATA" not in obj or "ERRORARRAY" not in obj or "ACTION" not in obj): ret.append(None) errs.append(self.invalid) continue ret.append(obj["DATA"]) errs.extend(self._make_excp(e) for e in obj["ERRORARRAY"]) return (ret, errs) except Exception: return (None, [self.invalid]) def success(self): """Check the response for success The way we determine success is by the presence of an error in ERRORARRAY. If one is there, we assume the whole request failed. :return: ``bool`` indicating a successful request""" return len(self.errors) == 0 def _make_excp(self, error): """Convert an API error to a LinodeException instance :keyword error: JSON object containing ``ERRORCODE`` and ``ERRORMESSAGE`` :type error: dict""" if "ERRORCODE" not in error or "ERRORMESSAGE" not in error: return None if error["ERRORCODE"] == 4: return InvalidCredsError(error["ERRORMESSAGE"]) return LinodeException(error["ERRORCODE"], error["ERRORMESSAGE"]) class LinodeConnection(ConnectionKey): """ A connection to the Linode API Wraps SSL connections to the Linode API, automagically injecting the parameters that the API needs for each request. """ host = API_HOST responseCls = LinodeResponse def add_default_params(self, params): """ Add parameters that are necessary for every request This method adds ``api_key`` and ``api_responseFormat`` to the request. """ params["api_key"] = self.key # Be explicit about this in case the default changes. params["api_responseFormat"] = "json" return params apache-libcloud-2.8.0/libcloud/common/liquidweb.py0000664000175000017500000001466613576514553022102 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 from libcloud.common.base import JsonResponse from libcloud.common.base import ConnectionUserAndKey from libcloud.utils.py3 import b from libcloud.common.types import ProviderError __all__ = [ 'API_HOST', 'LiquidWebException', 'LiquidWebResponse', 'LiquidWebConnection', ] # Endpoint for liquidweb api. API_HOST = 'api.stormondemand.com' class LiquidWebException(ProviderError): """The base class for other Liquidweb exceptions""" def __init__(self, value, http_code, extra=None): """ :param value: message contained in error :type value: ``str`` :param http_code: error code :type http_code: ``int`` :param extra: extra fields specific to error type :type extra: ``list`` """ self.extra = extra super(LiquidWebException, self).__init__(value, http_code, driver=None) def __str__(self): return "%s %s" % (self.http_code, self.value) def __repr__(self): return "LiquidWebException %s %s" % (self.http_code, self.value) class APIException(LiquidWebException): def __init__(self, error_class, full_msg, http_code, extra=None): self.error_class = error_class super(APIException, self).__init__(full_msg, http_code, extra=extra) def __str__(self): return "%s: %s" % (self.error_class, self.value) def __repr__(self): return "%s: %s" % (self.error_class, self.value) EXCEPTIONS_FIELDS = { 'LW::Exception::API::Internal': { 'fields': [] }, 'LW::Exception::API::InvalidEncoding': { 'fields': ['encoding'] }, 'LW::Exception::API::InvalidMethod': { 'fields': ['method'] }, 'LW::Exception::API::Maintenance': { 'fields': [] }, 'LW::Exception::API::RateLimit': { 'fields': ['account', 'ip', 'method'] }, 'LW::Exception::Authorization': { 'fields': ['username'] }, 'LW::Exception::DNS::NoResponse': { 'fields': ['nameservers'] }, 'LW::Exception::DNS::Servfail': { 'fields': ['nameservers'] }, 'LW::Exception::Deserialize': { 'fields': ['data', 'encoding'] }, 'LW::Exception::DuplicateRecord': { 'fields': ['field', 'input', 'statement'] }, 'LW::Exception::Forbidden': { 'fields': [] }, 'LW::Exception::Incapable': { 'fields': ['capability', 'thing'] }, 'LW::Exception::Input': { 'fields': ['field'] }, 'LW::Exception::Input::Disallowed': { 'fields': ['field'] }, 'LW::Exception::Input::Multiple': { 'fields': ['errors', 'field', 'type'] }, 'LW::Exception::Input::NotInRealm': { 'fields': ['field', 'valid', 'value'] }, 'LW::Exception::Input::OutOfBounds': { 'fields': ['field', 'max', 'min', 'value'] }, 'LW::Exception::Input::Required': { 'fields': ['field', 'position'] }, 'LW::Exception::Input::Unknown': { 'fields': ['field', 'value'] }, 'LW::Exception::Input::Validation': { 'fields': ['field', 'type', 'value'] }, 'LW::Exception::Permission': { 'fields': ['account', 'identifier'] }, 'LW::Exception::RecordNotFound': { 'fields': ['field', 'input'] }, 'LW::Exception::RemoteService::Authorization': { 'fields': ['url'] }, 'LW::Exception::Resource': { 'fields': ['resource'] }, 'LW::Exception::Resource::Insufficient': { 'fields': ['available', 'requested', 'resource'] }, 'LW::Exception::Resource::Unavailable': { 'fields': ['resource'] }, 'LW::Exception::Serialize': { 'fields': ['data', 'encoding'] }, 'LW::Exception::Workflow::Conflict': { 'fields': ['conflict', 'workflow'] } } class LiquidWebResponse(JsonResponse): objects = None errors = None def __init__(self, response, connection): self.errors = [] super(LiquidWebResponse, self).__init__(response=response, connection=connection) self.objects, self.errors = self.parse_body_and_errors() if self.errors: error = self.errors.pop() raise self._make_excp(error, self.status) def parse_body_and_errors(self): data = [] errors = [] js = super(LiquidWebResponse, self).parse_body() if 'items' in js: data.append(js['items']) if 'name' in js: data.append(js) if 'deleted' in js: data.append(js['deleted']) if 'error_class' in js: errors.append(js) return (data, errors) def success(self): """ Returns ``True`` if our request is successful. """ return (len(self.errors) == 0) def _make_excp(self, error, status): """ Raise LiquidWebException. """ exc_type = error.get('error_class') message = error.get('full_message') try: _type = EXCEPTIONS_FIELDS[exc_type] fields = _type.get('fields') extra = {} except KeyError: fields = [] for field in fields: extra[field] = error.get(field) return APIException(exc_type, message, status, extra=extra) class LiquidWebConnection(ConnectionUserAndKey): host = API_HOST responseCls = LiquidWebResponse def add_default_headers(self, headers): b64string = b('%s:%s' % (self.user_id, self.key)) encoded = base64.b64encode(b64string).decode('utf-8') authorization = 'Basic ' + encoded headers['Authorization'] = authorization headers['Content-Type'] = 'application/json' return headers apache-libcloud-2.8.0/libcloud/common/luadns.py0000664000175000017500000000516313576514553021373 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import List from typing import Dict import base64 from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.utils.py3 import b __all__ = [ 'API_HOST', 'LuadnsException', 'LuadnsResponse', 'LuadnsConnection' ] # Endpoint for luadns api API_HOST = 'api.luadns.com' class LuadnsResponse(JsonResponse): errors = [] # type: List[Dict] objects = [] # type: List[Dict] def __init__(self, response, connection): super(LuadnsResponse, self).__init__(response=response, connection=connection) self.errors, self.objects = self.parse_body_and_errors() if not self.success(): raise LuadnsException(code=self.status, message=self.errors.pop()['message']) def parse_body_and_errors(self): js = super(LuadnsResponse, self).parse_body() if 'message' in js: self.errors.append(js) else: self.objects.append(js) return self.errors, self.objects def success(self): return len(self.errors) == 0 class LuadnsConnection(ConnectionUserAndKey): host = API_HOST responseCls = LuadnsResponse def add_default_headers(self, headers): b64string = b('%s:%s' % (self.user_id, self.key)) encoded = base64.b64encode(b64string).decode('utf-8') authorization = 'Basic ' + encoded headers['Accept'] = 'application/json' headers['Authorization'] = authorization return headers class LuadnsException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "Luadns %s %s" % (self.code, self.message) apache-libcloud-2.8.0/libcloud/common/maxihost.py0000664000175000017500000000415013570310635021721 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import httplib from libcloud.common.types import InvalidCredsError from libcloud.common.base import JsonResponse from libcloud.common.base import ConnectionKey class MaxihostResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_error(self): if self.status == httplib.UNAUTHORIZED: body = self.parse_body() raise InvalidCredsError(body['message']) else: body = self.parse_body() if 'message' in body: error = '%s (code: %s)' % (body['message'], self.status) else: error = body return error def success(self): return self.status in self.valid_response_codes class MaxihostConnection(ConnectionKey): """ Connection class for the Maxihost driver. """ host = 'api.maxihost.com' responseCls = MaxihostResponse def add_default_headers(self, headers): """ Add headers that are necessary for every request This method adds apikey to the request. """ headers['Authorization'] = 'Bearer %s' % (self.key) headers['Content-Type'] = 'application/json' headers['Accept'] = 'application/vnd.maxihost.v1.1+json' return headers apache-libcloud-2.8.0/libcloud/common/nfsn.py0000664000175000017500000001005113535474530021034 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import hashlib import random import string import time from libcloud.common.base import ConnectionUserAndKey from libcloud.common.base import JsonResponse from libcloud.common.types import InvalidCredsError, ProviderError from libcloud.utils.py3 import basestring, httplib, urlencode SALT_CHARACTERS = string.ascii_letters + string.digits class NFSNException(ProviderError): def __init__(self, value, http_code, code, driver=None): self.code = code super(NFSNException, self).__init__(value, http_code, driver) class NFSNResponse(JsonResponse): def parse_error(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError('Invalid provider credentials') body = self.parse_body() if isinstance(body, basestring): return body + ' (HTTP Code: %d)' % self.status error = body.get('error', None) debug = body.get('debug', None) # If we only have one of "error" or "debug", use the one that we have. # If we have both, use both, with a space character in between them. value = 'No message specified' if error is not None: value = error if debug is not None: value = debug if error is not None and value is not None: value = error + ' ' + value value = value + ' (HTTP Code: %d)' % self.status return value class NFSNConnection(ConnectionUserAndKey): host = 'api.nearlyfreespeech.net' responseCls = NFSNResponse allow_insecure = False def _header(self, action, data): """ Build the contents of the X-NFSN-Authentication HTTP header. See https://members.nearlyfreespeech.net/wiki/API/Introduction for more explanation. """ login = self.user_id timestamp = self._timestamp() salt = self._salt() api_key = self.key data = urlencode(data) data_hash = hashlib.sha1(data.encode('utf-8')).hexdigest() string = ';'.join((login, timestamp, salt, api_key, action, data_hash)) string_hash = hashlib.sha1(string.encode('utf-8')).hexdigest() return ';'.join((login, timestamp, salt, string_hash)) def request(self, action, params=None, data='', headers=None, method='GET'): """ Add the X-NFSN-Authentication header to an HTTP request. """ if not headers: headers = {} if not params: params = {} header = self._header(action, data) headers['X-NFSN-Authentication'] = header if method == 'POST': headers['Content-Type'] = 'application/x-www-form-urlencoded' return ConnectionUserAndKey.request(self, action, params, data, headers, method) def encode_data(self, data): """ NFSN expects the body to be regular key-value pairs that are not JSON-encoded. """ if data: data = urlencode(data) return data def _salt(self): """ Return a 16-character alphanumeric string. """ r = random.SystemRandom() return ''.join(r.choice(SALT_CHARACTERS) for _ in range(16)) def _timestamp(self): """ Return the current number of seconds since the Unix epoch, as a string. """ return str(int(time.time())) apache-libcloud-2.8.0/libcloud/common/nsone.py0000664000175000017500000000461313576514553021226 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import List from typing import Dict from libcloud.common.base import ConnectionKey, JsonResponse __all__ = [ 'API_HOST', 'NsOneException', 'NsOneResponse', 'NsOneConnection' ] # Endpoint for nsone api API_HOST = 'api.nsone.net' class NsOneResponse(JsonResponse): errors = [] # type: List[Dict] objects = [] # type: List[Dict] def __init__(self, response, connection): super(NsOneResponse, self).__init__(response=response, connection=connection) self.errors, self.objects = self.parse_body_and_errors() if not self.success(): raise NsOneException(code=self.status, message=self.errors.pop()['message']) def parse_body_and_errors(self): js = super(NsOneResponse, self).parse_body() if 'message' in js: self.errors.append(js) else: self.objects.append(js) return self.errors, self.objects def success(self): return len(self.errors) == 0 class NsOneConnection(ConnectionKey): host = API_HOST responseCls = NsOneResponse def add_default_headers(self, headers): headers['Content-Type'] = 'application/json' headers['X-NSONE-KEY'] = self.key return headers class NsOneException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "NsOneException %s %s" % (self.code, self.message) apache-libcloud-2.8.0/libcloud/common/nttcis.py0000664000175000017500000022061513577507766021423 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ NTTCIS Common Components """ from typing import Dict import xml.etree.ElementTree as etree import re from functools import wraps from copy import deepcopy from base64 import b64encode from time import sleep from io import BytesIO try: from collections.abc import MutableSequence, Mapping except ImportError: from collections import MutableSequence, Mapping # TODO: use disutils.version when Travis CI fixed the pylint issue with version # from distutils.version import LooseVersion from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse from libcloud.compute.base import Node from libcloud.utils.py3 import basestring from libcloud.utils.xml import findtext from libcloud.compute.types import LibcloudError, InvalidCredsError # Roadmap / TODO: # # 1.0 - Copied from OpSource API, named provider details. # setup a few variables to represent all of the NTTC-CIS cloud namespaces NAMESPACE_BASE = "http://oec.api.opsource.net/schemas" ORGANIZATION_NS = NAMESPACE_BASE + "/organization" SERVER_NS = NAMESPACE_BASE + "/server" NETWORK_NS = NAMESPACE_BASE + "/network" DIRECTORY_NS = NAMESPACE_BASE + "/directory" GENERAL_NS = NAMESPACE_BASE + "/general" BACKUP_NS = NAMESPACE_BASE + "/backup" # API 2.0 Namespaces and URNs TYPES_URN = "urn:didata.com:api:cloud:types" # API end-points API_ENDPOINTS = { 'na': { 'name': 'North America (NA)', 'host': 'api-na.dimensiondata.com', 'vendor': 'NTTC-CIS' }, 'eu': { 'name': 'Europe (EU)', 'host': 'api-eu.dimensiondata.com', 'vendor': 'NTTC-CIS' }, 'au': { 'name': 'Australia (AU)', 'host': 'api-au.dimensiondata.com', 'vendor': 'NTTC-CIS' }, 'au-gov': { 'name': 'Australia Canberra ACT (AU)', 'host': 'api-canberra.dimensiondata.com', 'vendor': 'NTTC-CIS' }, 'af': { 'name': 'Africa (AF)', 'host': 'api-mea.dimensiondata.com', 'vendor': 'NTTC-CIS' }, 'ap': { 'name': 'Asia Pacific (AP)', 'host': 'api-ap.dimensiondata.com', 'vendor': 'NTTC-CIS' }, 'ca': { 'name': 'Canada (CA)', 'host': 'api-canada.dimensiondata.com', 'vendor': 'NTTC-CIS' }, 'is-na': { 'name': 'North America (NA)', 'host': 'usapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-eu': { 'name': 'Europe (EU)', 'host': 'euapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-au': { 'name': 'Australia (AU)', 'host': 'auapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-af': { 'name': 'Africa (AF)', 'host': 'meaapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-ap': { 'name': 'Asia Pacific (AP)', 'host': 'apapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-latam': { 'name': 'South America (LATAM)', 'host': 'latamapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'is-canada': { 'name': 'Canada (CA)', 'host': 'canadaapi.cloud.is.co.za', 'vendor': 'InternetSolutions' }, 'ntta-na': { 'name': 'North America (NA)', 'host': 'cloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-eu': { 'name': 'Europe (EU)', 'host': 'eucloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-au': { 'name': 'Australia (AU)', 'host': 'aucloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-af': { 'name': 'Africa (AF)', 'host': 'sacloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'ntta-ap': { 'name': 'Asia Pacific (AP)', 'host': 'hkcloudapi.nttamerica.com', 'vendor': 'NTTNorthAmerica' }, 'cisco-na': { 'name': 'North America (NA)', 'host': 'iaas-api-na.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-eu': { 'name': 'Europe (EU)', 'host': 'iaas-api-eu.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-au': { 'name': 'Australia (AU)', 'host': 'iaas-api-au.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-af': { 'name': 'Africa (AF)', 'host': 'iaas-api-mea.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-ap': { 'name': 'Asia Pacific (AP)', 'host': 'iaas-api-ap.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-latam': { 'name': 'South America (LATAM)', 'host': 'iaas-api-sa.cisco-ccs.com', 'vendor': 'Cisco' }, 'cisco-canada': { 'name': 'Canada (CA)', 'host': 'iaas-api-ca.cisco-ccs.com', 'vendor': 'Cisco' }, 'med1-il': { 'name': 'Israel (IL)', 'host': 'api.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-na': { 'name': 'North America (NA)', 'host': 'api-na.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-eu': { 'name': 'Europe (EU)', 'host': 'api-eu.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-au': { 'name': 'Australia (AU)', 'host': 'api-au.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-af': { 'name': 'Africa (AF)', 'host': 'api-af.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-ap': { 'name': 'Asia Pacific (AP)', 'host': 'api-ap.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-latam': { 'name': 'South America (LATAM)', 'host': 'api-sa.cloud.med-1.com', 'vendor': 'Med-1' }, 'med1-canada': { 'name': 'Canada (CA)', 'host': 'api-ca.cloud.med-1.com', 'vendor': 'Med-1' }, 'indosat-id': { 'name': 'Indonesia (ID)', 'host': 'iaas-api.indosat.com', 'vendor': 'Indosat' }, 'indosat-na': { 'name': 'North America (NA)', 'host': 'iaas-usapi.indosat.com', 'vendor': 'Indosat' }, 'indosat-eu': { 'name': 'Europe (EU)', 'host': 'iaas-euapi.indosat.com', 'vendor': 'Indosat' }, 'indosat-au': { 'name': 'Australia (AU)', 'host': 'iaas-auapi.indosat.com', 'vendor': 'Indosat' }, 'indosat-af': { 'name': 'Africa (AF)', 'host': 'iaas-afapi.indosat.com', 'vendor': 'Indosat' }, 'bsnl-in': { 'name': 'India (IN)', 'host': 'api.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-na': { 'name': 'North America (NA)', 'host': 'usapi.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-eu': { 'name': 'Europe (EU)', 'host': 'euapi.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-au': { 'name': 'Australia (AU)', 'host': 'auapi.bsnlcloud.com', 'vendor': 'BSNL' }, 'bsnl-af': { 'name': 'Africa (AF)', 'host': 'afapi.bsnlcloud.com', 'vendor': 'BSNL' } } # Default API end-point for the base connection class. DEFAULT_REGION = 'na' BAD_CODE_XML_ELEMENTS = ( ('responseCode', SERVER_NS), ('responseCode', TYPES_URN), ('result', GENERAL_NS) ) BAD_MESSAGE_XML_ELEMENTS = ( ('message', SERVER_NS), ('message', TYPES_URN), ('resultDetail', GENERAL_NS) ) def get_params(func): @wraps(func) def paramed(*args, **kwargs): if kwargs: params = {} for k, v in kwargs.items(): matches = re.findall(r'_(\w)', k) for match in matches: k = k.replace('_' + match, match.upper()) params[k] = v result = func(args[0], params) else: result = func(args[0]) return result return paramed def dd_object_to_id(obj, obj_type, id_value='id'): """ Takes in a DD object or string and prints out it's id This is a helper method, as many of our functions can take either an object or a string, and we need an easy way of converting them :param obj: The object to get the id for :type obj: ``object`` :param func: The function to call, e.g. ex_get_vlan. Note: This function needs to return an object which has ``status`` attribute. :type func: ``function`` :rtype: ``str`` """ if isinstance(obj, obj_type): return getattr(obj, id_value) elif isinstance(obj, (basestring)): return obj else: raise TypeError( "Invalid type %s looking for basestring or %s" % (type(obj).__name__, obj_type.__name__) ) # TODO: use disutils.version when Travis CI fixed the pylint issue with version # This is a temporary workaround. def LooseVersion(version): return float(version) class NetworkDomainServicePlan(object): ESSENTIALS = "ESSENTIALS" ADVANCED = "ADVANCED" class NttCisRawResponse(RawResponse): pass class NttCisResponse(XmlResponse): def parse_error(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError(self.body) elif self.status == httplib.FORBIDDEN: raise InvalidCredsError(self.body) body = self.parse_body() if self.status == httplib.BAD_REQUEST: for response_code in BAD_CODE_XML_ELEMENTS: code = findtext(body, response_code[0], response_code[1]) if code is not None: break for message in BAD_MESSAGE_XML_ELEMENTS: message = findtext(body, message[0], message[1]) if message is not None: break raise NttCisAPIException(code=code, msg=message, driver=self.connection.driver) if self.status is not httplib.OK: raise NttCisAPIException(code=self.status, msg=body, driver=self.connection.driver) return self.body class NttCisAPIException(LibcloudError): def __init__(self, code, msg, driver): self.code = code self.msg = msg self.driver = driver def __str__(self): return "%s: %s" % (self.code, self.msg) def __repr__(self): return ("" % (self.code, self.msg)) class NttCisConnection(ConnectionUserAndKey): """ Connection class for the NttCis driver """ api_path_version_1 = '/oec' api_path_version_2 = '/caas' api_version_1 = 0.9 # Earliest version supported oldest_api_version = '2.2' # Latest version supported latest_api_version = '2.7' # Default api version active_api_version = '2.7' _orgId = None responseCls = NttCisResponse rawResponseCls = NttCisRawResponse allow_insecure = False def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, api_version=None, **conn_kwargs): super(NttCisConnection, self).__init__( user_id=user_id, key=key, secure=secure, host=host, port=port, url=url, timeout=timeout, proxy_url=proxy_url) if conn_kwargs['region']: self.host = conn_kwargs['region']['host'] if api_version: if LooseVersion(api_version) < LooseVersion( self.oldest_api_version): msg = 'API Version specified is too old. No longer ' \ 'supported. Please upgrade to the latest version {}' \ .format(self.active_api_version) raise NttCisAPIException(code=None, msg=msg, driver=self.driver) elif LooseVersion(api_version) > LooseVersion( self.latest_api_version): msg = 'Unsupported API Version. The version specified is ' \ 'not release yet. Please use the latest supported ' \ 'version {}' \ .format(self.active_api_version) raise NttCisAPIException(code=None, msg=msg, driver=self.driver) else: # Overwrite default version using the version user specified self.active_api_version = api_version def add_default_headers(self, headers): headers['Authorization'] = \ ('Basic %s' % b64encode(b('%s:%s' % (self.user_id, self.key))).decode('utf-8')) headers['Content-Type'] = 'application/xml' return headers def request_api_1(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s/%s" % (self.api_path_version_1, self.api_version_1, action) return super(NttCisConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def request_api_2(self, path, action, params=None, data='', headers=None, method='GET'): action = "%s/%s/%s/%s" % (self.api_path_version_2, self.active_api_version, path, action) return super(NttCisConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def raw_request_with_orgId_api_1(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s" % (self.get_resource_path_api_1(), action) return super(NttCisConnection, self).request( action=action, params=params, data=data, method=method, headers=headers, raw=True) def request_with_orgId_api_1(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s" % (self.get_resource_path_api_1(), action) return super(NttCisConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def request_with_orgId_api_2(self, action, params=None, data='', headers=None, method='GET'): action = "%s/%s" % (self.get_resource_path_api_2(), action) return super(NttCisConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def paginated_request_with_orgId_api_2(self, action, params=None, data='', headers=None, method='GET', page_size=250): """ A paginated request to the MCP2.0 API This essentially calls out to request_with_orgId_api_2 for each page and yields the response to make a generator This generator can be looped through to grab all the pages. :param action: The resource to access (i.e. 'network/vlan') :type action: ``str`` :param params: Parameters to give to the action :type params: ``dict`` or ``None`` :param data: The data payload to be added to the request :type data: ``str`` :param headers: Additional header to be added to the request :type headers: ``str`` or ``dict`` or ``None`` :param method: HTTP Method for the request (i.e. 'GET', 'POST') :type method: ``str`` :param page_size: The size of each page to be returned Note: Max page size in MCP2.0 is currently 250 :type page_size: ``int`` """ if params is None: params = {} params['pageSize'] = page_size resp = self.request_with_orgId_api_2(action, params, data, headers, method).object yield resp if len(resp) <= 0: return pcount = resp.get('pageCount') # pylint: disable=no-member psize = resp.get('pageSize') # pylint: disable=no-member pnumber = resp.get('pageNumber') # pylint: disable=no-member while int(pcount) >= int(psize): params['pageNumber'] = int(pnumber) + 1 resp = self.request_with_orgId_api_2(action, params, data, headers, method).object pcount = resp.get('pageCount') # pylint: disable=no-member psize = resp.get('pageSize') # pylint: disable=no-member pnumber = resp.get('pageNumber') # pylint: disable=no-member yield resp def get_resource_path_api_1(self): """ This method returns a resource path which is necessary for referencing resources that require a full path instead of just an ID, such as networks, and customer snapshots. """ return ("%s/%s/%s" % (self.api_path_version_1, self.api_version_1, self._get_orgId())) def get_resource_path_api_2(self): """ This method returns a resource path which is necessary for referencing resources that require a full path instead of just an ID, such as networks, and customer snapshots. """ return ("%s/%s/%s" % (self.api_path_version_2, self.active_api_version, self._get_orgId())) def wait_for_state(self, state, func, poll_interval=2, timeout=60, *args, **kwargs): """ Wait for the function which returns a instance with field status/state to match. Keep polling func until one of the desired states is matched :param state: Either the desired state (`str`) or a `list` of states :type state: ``str`` or ``list`` :param func: The function to call, e.g. ex_get_vlan. Note: This function needs to return an object which has ``status`` attribute. :type func: ``function`` :param poll_interval: The number of seconds to wait between checks :type poll_interval: `int` :param timeout: The total number of seconds to wait to reach a state :type timeout: `int` :param args: The arguments for func :type args: Positional arguments :param kwargs: The arguments for func :type kwargs: Keyword arguments :return: Result from the calling function. """ cnt = 0 result = None object_state = None state = state.lower() while cnt < timeout / poll_interval: result = func(*args, **kwargs) if isinstance(result, Node): object_state = result.state.lower() else: # BUG: need to use result.status.lower() or # will never match if client uses lower case object_state = result.status.lower() if object_state is state or object_state in state: return result sleep(poll_interval) cnt += 1 msg = 'Status check for object %s timed out' % (result) raise NttCisAPIException(code=object_state, msg=msg, driver=self.driver) def _get_orgId(self): """ Send the /myaccount API request to NTTC-CIS cloud and parse the 'orgId' from the XML response object. We need the orgId to use most of the other API functions """ if self._orgId is None: body = self.request_api_1('myaccount').object self._orgId = findtext(body, 'orgId', DIRECTORY_NS) return self._orgId def get_account_details(self): """ Get the details of this account :rtype: :class:`DimensionDataAccountDetails` """ body = self.request_api_1('myaccount').object return NttCisAccountDetails( user_name=findtext(body, 'userName', DIRECTORY_NS), full_name=findtext(body, 'fullName', DIRECTORY_NS), first_name=findtext(body, 'firstName', DIRECTORY_NS), last_name=findtext(body, 'lastName', DIRECTORY_NS), email=findtext(body, 'emailAddress', DIRECTORY_NS)) class NttCisAccountDetails(object): """ NTTCIS account class details """ def __init__(self, user_name, full_name, first_name, last_name, email): self.user_name = user_name self.full_name = full_name self.first_name = first_name self.last_name = last_name self.email = email class NttCisStatus(object): """ NTTCIS API pending operation status class action, request_time, user_name, number_of_steps, update_time, step.name, step.number, step.percent_complete, failure_reason, """ def __init__(self, action=None, request_time=None, user_name=None, number_of_steps=None, update_time=None, step_name=None, step_number=None, step_percent_complete=None, failure_reason=None): self.action = action self.request_time = request_time self.user_name = user_name self.number_of_steps = number_of_steps self.update_time = update_time self.step_name = step_name self.step_number = step_number self.step_percent_complete = step_percent_complete self.failure_reason = failure_reason def __repr__(self): return (('') % (self.action, self.request_time, self.user_name, self.number_of_steps, self.update_time, self.step_name, self.step_number, self.step_percent_complete, self.failure_reason)) class NttCisNetwork(object): """ NTTCIS network with location. """ def __init__(self, id, name, description, location, private_net, multicast, status): self.id = str(id) self.name = name self.description = description self.location = location self.private_net = private_net self.multicast = multicast self.status = status def __repr__(self): return (('') % (self.id, self.name, self.description, self.location, self.private_net, self.multicast)) class NttCisNetworkDomain(object): """ NttCis network domain with location. """ def __init__(self, id, name, description, location, status, plan): self.id = str(id) self.name = name self.description = description self.location = location self.status = status self.plan = plan def __repr__(self): return (('') % (self.id, self.name, self.description, self.location, self.status, self.plan)) class NttCisPublicIpBlock(object): """ NTTCIS Public IP Block with location. """ def __init__(self, id, base_ip, size, location, network_domain, status): self.id = str(id) self.base_ip = base_ip self.size = size self.location = location self.network_domain = network_domain self.status = status def __repr__(self): return (('') % (self.id, self.base_ip, self.size, self.location, self.status)) class NttCisServerCpuSpecification(object): """ A class that represents the specification of the CPU(s) for a node """ def __init__(self, cpu_count, cores_per_socket, performance): """ Instantiate a new :class:`NttCisServerCpuSpecification` :param cpu_count: The number of CPUs :type cpu_count: ``int`` :param cores_per_socket: The number of cores per socket, the recommendation is 1 :type cores_per_socket: ``int`` :param performance: The performance type, e.g. HIGHPERFORMANCE :type performance: ``str`` """ self.cpu_count = cpu_count self.cores_per_socket = cores_per_socket self.performance = performance def __repr__(self): return (('') % (self.cpu_count, self.cores_per_socket, self.performance)) class NttCisServerDisk(object): """ A class that represents the disk on a server """ def __init__(self, id=None, scsi_id=None, size_gb=None, speed=None, state=None): """ Instantiate a new :class:`DimensionDataServerDisk` :param id: The id of the disk :type id: ``str`` :param scsi_id: Representation for scsi :type scsi_id: ``int`` :param size_gb: Size of the disk :type size_gb: ``int`` :param speed: Speed of the disk (i.e. STANDARD) :type speed: ``str`` :param state: State of the disk (i.e. PENDING) :type state: ``str`` """ self.id = id self.scsi_id = scsi_id self.size_gb = size_gb self.speed = speed self.state = state def __repr__(self): return (('') % (self.status, self.version_status, self.api_version)) class NttCisSnapshot(object): """ NTTCIS Class representing server snapshots """ def __init__(self, server_id, service_plan, id=None, window_id=None, start_time=None, state=None, end_time=None, type=None, expiry_time=None, action=None): self.server_id = server_id self.service_plan = service_plan self.id = id self.window_id = window_id self.start_time = start_time self.end_time = end_time self.state = state self.end_time = end_time self.type = type self.expiry_time = expiry_time self.action = action def __repr__(self): return (('') % (self.id, self.start_time, self.end_time, self.type, self.expiry_time, self.state)) class NttCisReservedIpAddress(object): """ NTTCIS Rerverse IPv4 address """ def __init__(self, datacenter_id, exclusive, vlan_id, ip, description=None): self.datacenter_id = datacenter_id self.exclusive = exclusive self.vlan_id = vlan_id self.ip = ip self.description = description def __repr__(self): return (('') % (self.id, self.name, self.action, self.location, self.network_domain, self.status, self.ip_version, self.protocol, self.source, self.destination, self.enabled)) """ class NttCisFirewallAddress(object): The source or destination model in a firewall rule def __init__(self, any_ip, ip_address, ip_prefix_size, port_begin, port_end, address_list_id, port_list_id): self.any_ip = any_ip self.ip_address = ip_address self.ip_prefix_size = ip_prefix_size self.port_list_id = port_list_id self.port_begin = port_begin self.port_end = port_end self.address_list_id = address_list_id self.port_list_id = port_list_id def __repr__(self): return ( '' % (self.any_ip, self.ip_address, self.ip_prefix_size, self.port_begin, self.port_end, self.address_list_id, self.port_list_id)) """ class NttCisFirewallAddress(object): """ The source or destination model in a firewall rule 9/4/18: Editing Class to use with ex_create_firewall_rtule method. Will haved to circle back and test for any other uses. """ def __init__(self, any_ip=None, ip_address=None, ip_prefix_size=None, port_begin=None, port_end=None, address_list_id=None, port_list_id=None): """ :param any_ip: used to set ip address to "ANY" :param ip_address: Optional, an ip address of either IPv4 decimal notation or an IPv6 address :type ``str`` :param ip_prefix_size: An integer denoting prefix size. :type ``int`` :param port_begin: integer for an individual port or start of a list of ports if not using a port list :type ``int`` :param port_end: integer required if using a list of ports (NOT a port list but a list starting with port begin) :type ``int`` :param address_list_id: An id identifying an address list :type ``str`` :param port_list_id: An id identifying a port list :type ``str`` """ self.any_ip = any_ip self.ip_address = ip_address self.ip_prefix_size = ip_prefix_size self.port_list_id = port_list_id self.port_begin = port_begin self.port_end = port_end self.address_list_id = address_list_id self.port_list_id = port_list_id def __repr__(self): return ( '' % (self.any_ip, self.ip_address, self.ip_prefix_size, self.port_begin, self.port_end, self.address_list_id, self.port_list_id)) class NttCisNatRule(object): """ An IP NAT rule in a network domain """ def __init__(self, id, network_domain, internal_ip, external_ip, status): self.id = id self.network_domain = network_domain self.internal_ip = internal_ip self.external_ip = external_ip self.status = status def __repr__(self): return (('') % (self.id, self.status)) class NttCisAntiAffinityRule(object): """ Anti-Affinity rule for NTTCIS An Anti-Affinity rule ensures that servers in the rule will not reside on the same VMware ESX host. """ def __init__(self, id, node_list): """ Instantiate a new :class:`NttCisDataAntiAffinityRule` :param id: The ID of the Anti-Affinity rule :type id: ``str`` :param node_list: List of node ids that belong in this rule :type node_list: ``list`` of ``str`` """ self.id = id self.node_list = node_list def __repr__(self): return (('') % (self.id)) class NttCisVlan(object): """ NTTCIS VLAN. """ def __init__(self, id, name, description, location, network_domain, status, private_ipv4_range_address, private_ipv4_range_size, ipv6_range_address, ipv6_range_size, ipv4_gateway, ipv6_gateway): """ Initialize an instance of ``DimensionDataVlan`` :param id: The ID of the VLAN :type id: ``str`` :param name: The name of the VLAN :type name: ``str`` :param description: Plan text description of the VLAN :type description: ``str`` :param location: The location (data center) of the VLAN :type location: ``NodeLocation`` :param network_domain: The Network Domain that owns this VLAN :type network_domain: :class:`DimensionDataNetworkDomain` :param status: The status of the VLAN :type status: :class:`DimensionDataStatus` :param private_ipv4_range_address: The host address of the VLAN IP space :type private_ipv4_range_address: ``str`` :param private_ipv4_range_size: The size (e.g. '24') of the VLAN as a CIDR range size :type private_ipv4_range_size: ``int`` :param ipv6_range_address: The host address of the VLAN IP space :type ipv6_range_address: ``str`` :param ipv6_range_size: The size (e.g. '32') of the VLAN as a CIDR range size :type ipv6_range_size: ``int`` :param ipv4_gateway: The IPv4 default gateway address :type ipv4_gateway: ``str`` :param ipv6_gateway: The IPv6 default gateway address :type ipv6_gateway: ``str`` """ self.id = str(id) self.name = name self.location = location self.description = description self.network_domain = network_domain self.status = status self.private_ipv4_range_address = private_ipv4_range_address self.private_ipv4_range_size = private_ipv4_range_size self.ipv6_range_address = ipv6_range_address self.ipv6_range_size = ipv6_range_size self.ipv4_gateway = ipv4_gateway self.ipv6_gateway = ipv6_gateway def __repr__(self): return (('') % (self.id, self.name, self.description, self.location, self.status)) class NttCisPool(object): """ NttCis VIP Pool. """ def __init__(self, id, name, description, status, load_balance_method, health_monitor_id, service_down_action, slow_ramp_time): """ Initialize an instance of ``NttCisPool`` :param id: The ID of the pool :type id: ``str`` :param name: The name of the pool :type name: ``str`` :param description: Plan text description of the pool :type description: ``str`` :param status: The status of the pool :type status: :class:NttCisStatus` :param load_balance_method: The load balancer method :type load_balance_method: ``str`` :param health_monitor_id: The ID of the health monitor :type health_monitor_id: ``str`` :param service_down_action: Action to take when pool is down :type service_down_action: ``str`` :param slow_ramp_time: The ramp-up time for service recovery :type slow_ramp_time: ``int`` """ self.id = str(id) self.name = name self.description = description self.status = status self.load_balance_method = load_balance_method self.health_monitor_id = health_monitor_id self.service_down_action = service_down_action self.slow_ramp_time = slow_ramp_time def __repr__(self): return (('') % (self.id, self.name, self.description, self.status)) class NttCisPoolMember(object): """ NTTCIS VIP Pool Member. """ def __init__(self, id, name, status, ip, port, node_id): """ Initialize an instance of ``NttCisPoolMember`` :param id: The ID of the pool member :type id: ``str`` :param name: The name of the pool member :type name: ``str`` :param status: The status of the pool :type status: :class:`NttCisStatus` :param ip: The IP of the pool member :type ip: ``str`` :param port: The port of the pool member :type port: ``int`` :param node_id: The ID of the associated node :type node_id: ``str`` """ self.id = str(id) self.name = name self.status = status self.ip = ip self.port = port self.node_id = node_id def __repr__(self): return (('NttCisPoolMember: id=%s, name=%s, ' 'ip=%s, status=%s, port=%s, node_id=%s>') % (self.id, self.name, self.ip, self.status, self.port, self.node_id)) class NttCisVIPNode(object): def __init__(self, id, name, status, ip, connection_limit='10000', connection_rate_limit='10000', health_monitor=None): """ Initialize an instance of :class:`NttCisVIPNode` :param id: The ID of the node :type id: ``str`` :param name: The name of the node :type name: ``str`` :param status: The status of the node :type status: :class:`NttCisStatus` :param ip: The IP of the node :type ip: ``str`` :param connection_limit: The total connection limit for the node :type connection_limit: ``int`` :param connection_rate_limit: The rate limit for the node :type connection_rate_limit: ``int`` """ self.id = str(id) self.name = name self.status = status self.ip = ip self.connection_limit = connection_limit self.connection_rate_limit = connection_rate_limit if health_monitor is not None: self.health_monitor_id = health_monitor def __repr__(self): return (('') % (self.id, self.name, self.status, self.ip)) class NttCisVirtualListener(object): """ NTTCIS Virtual Listener. """ def __init__(self, id, name, status, ip): """ Initialize an instance of :class:`NttCisVirtualListener` :param id: The ID of the listener :type id: ``str`` :param name: The name of the listener :type name: ``str`` :param status: The status of the listener :type status: :class:`NttCisStatus` :param ip: The IP of the listener :type ip: ``str`` """ self.id = str(id) self.name = name self.status = status self.ip = ip def __repr__(self): return (('') % (self.id, self.name, self.status, self.ip)) class NttCisDefaultHealthMonitor(object): """ A default health monitor for a VIP (node, pool or listener) """ def __init__(self, id, name, node_compatible, pool_compatible): """ Initialize an instance of :class:`NttCisDefaultHealthMonitor` :param id: The ID of the monitor :type id: ``str`` :param name: The name of the monitor :type name: ``str`` :param node_compatible: Is a monitor capable of monitoring nodes :type node_compatible: ``bool`` :param pool_compatible: Is a monitor capable of monitoring pools :type pool_compatible: ``bool`` """ self.id = id self.name = name self.node_compatible = node_compatible self.pool_compatible = pool_compatible def __repr__(self): return (('') % (self.id, self.name)) class NttCisPersistenceProfile(object): """ Each Persistence Profile declares the combination of Virtual Listener type and protocol with which it is compatible and whether or not it is compatible as a Fallback Persistence Profile. """ def __init__(self, id, name, compatible_listeners, fallback_compatible): """ Initialize an instance of :class:`NttCisPersistenceProfile` :param id: The ID of the profile :type id: ``str`` :param name: The name of the profile :type name: ``str`` :param compatible_listeners: List of compatible Virtual Listener types :type compatible_listeners: ``list`` of :class:`NttCisVirtualListenerCompatibility` :param fallback_compatible: Is capable as a fallback profile :type fallback_compatible: ``bool`` """ self.id = id self.name = name self.compatible_listeners = compatible_listeners self.fallback_compatible = fallback_compatible def __repr__(self): return (('NttCisPersistenceProfile: id=%s, name=%s>') % (self.id, self.name)) class NttCisDefaultiRule(object): """ A default iRule for a network domain, can be applied to a listener """ def __init__(self, id, name, compatible_listeners): """ Initialize an instance of :class:`NttCisefaultiRule` :param id: The ID of the iRule :type id: ``str`` :param name: The name of the iRule :type name: ``str`` :param compatible_listeners: List of compatible Virtual Listener types :type compatible_listeners: ``list`` of :class:`NttCisVirtualListenerCompatibility` """ self.id = id self.name = name self.compatible_listeners = compatible_listeners def __repr__(self): return (('') % (self.id, self.name)) class NttCisVirtualListenerCompatibility(object): """ A compatibility preference for a persistence profile or iRule specifies which virtual listener types this profile or iRule can be applied to. """ def __init__(self, type, protocol): self.type = type self.protocol = protocol def __repr__(self): return (('') % (self.type, self.protocol)) class NttCisBackupDetails(object): """ NTTCIS Backup Details represents information about a targets backups configuration """ def __init__(self, asset_id, service_plan, status, clients=None): """ Initialize an instance of :class:`NttCisBackupDetails` :param asset_id: Asset identification for backups :type asset_id: ``str`` :param service_plan: The service plan for backups. i.e (Essentials) :type service_plan: ``str`` :param status: The overall status this backup target. i.e. (unregistered) :type status: ``str`` :param clients: Backup clients attached to this target :type clients: ``list`` of :class:`NttCisBackupClient` """ self.asset_id = asset_id self.service_plan = service_plan self.status = status self.clients = clients def __repr__(self): return (('') % (self.asset_id)) class NttCisBackupClient(object): """ An object that represents a backup client """ def __init__(self, id, type, status, schedule_policy, storage_policy, download_url, alert=None, running_job=None): """ Initialize an instance of this class. :param id: Unique ID for the client :type id: ``str`` :param type: The type of client that this client is :type type: :class:`NttCisBackupClientType` :param status: The states of this particular backup client. i.e. (Unregistered) :type status: ``str`` :param schedule_policy: The schedule policy for this client NOTE: NTTCIS only sends back the name of the schedule policy, no further details :type schedule_policy: ``str`` :param storage_policy: The storage policy for this client NOTE: NTTCIS only sends back the name of the storage policy, no further details :type storage_policy: ``str`` :param download_url: The download url for this client :type download_url: ``str`` :param alert: The alert configured for this backup client (optional) :type alert: :class:`NttCisBackupClientAlert` :param alert: The running job for the client (optional) :type alert: :class:`NttCisBackupClientRunningJob` """ self.id = id self.type = type self.status = status self.schedule_policy = schedule_policy self.storage_policy = storage_policy self.download_url = download_url self.alert = alert self.running_job = running_job def __repr__(self): return (('') % (self.id)) class NttCisBackupClientAlert(object): """ An alert for a backup client """ def __init__(self, trigger, notify_list=[]): """ Initialize an instance of :class:`NttCisBackupClientAlert` :param trigger: Trigger type for the client i.e. ON_FAILURE :type trigger: ``str`` :param notify_list: List of email addresses that are notified when the alert is fired :type notify_list: ``list`` of ``str`` """ self.trigger = trigger self.notify_list = notify_list def __repr__(self): return (('') % (self.trigger)) class NttCisBackupClientRunningJob(object): """ A running job for a given backup client """ def __init__(self, id, status, percentage=0): """ Initialize an instance of :class:`NttCisBackupClientRunningJob` :param id: The unqiue ID of the job :type id: ``str`` :param status: The status of the job i.e. Waiting :type status: ``str`` :param percentage: The percentage completion of the job :type percentage: ``int`` """ self.id = id self.percentage = percentage self.status = status def __repr__(self): return (('') % (self.id)) class NttCisBackupClientType(object): """ A client type object for backups """ def __init__(self, type, is_file_system, description): """ Initialize an instance of :class:`NttCisBackupClientType` :param type: The type of client i.e. (FA.Linux, MySQL, ect.) :type type: ``str`` :param is_file_system: The name of the iRule :type is_file_system: ``bool`` :param description: Description of the client :type description: ``str`` """ self.type = type self.is_file_system = is_file_system self.description = description def __repr__(self): return (('') % (self.type)) class NttCisBackupStoragePolicy(object): """ A representation of a storage policy """ def __init__(self, name, retention_period, secondary_location): """ Initialize an instance of :class:`NttCisBackupStoragePolicy` :param name: The name of the storage policy i.e. 14 Day Storage Policy :type name: ``str`` :param retention_period: How long to keep the backup in days :type retention_period: ``int`` :param secondary_location: The secondary location i.e. Primary :type secondary_location: ``str`` """ self.name = name self.retention_period = retention_period self.secondary_location = secondary_location def __repr__(self): return (('') % (self.name)) class NttCisBackupSchedulePolicy(object): """ A representation of a schedule policy """ def __init__(self, name, description): """ Initialize an instance of :class:`NttCisBackupSchedulePolicy` :param name: The name of the policy i.e 12AM - 6AM :type name: ``str`` :param description: Short summary of the details of the policy :type description: ``str`` """ self.name = name self.description = description def __repr__(self): return (('') % (self.name)) class NttCisTag(object): """ A representation of a Tag in NTTCIS A Tag first must have a Tag Key, then an asset is tag with a key and an option value. Tags can be queried later to filter assets and also show up on usage report if so desired. """ def __init__(self, asset_type, asset_id, asset_name, datacenter, key, value): """ Initialize an instance of :class:`NttCisTag` :param asset_type: The type of asset. Current asset types: SERVER, VLAN, NETWORK_DOMAIN, CUSTOMER_IMAGE, PUBLIC_IP_BLOCK, ACCOUNT :type asset_type: ``str`` :param asset_id: The GUID of the asset that is tagged :type asset_id: ``str`` :param asset_name: The name of the asset that is tagged :type asset_name: ``str`` :param datacenter: The short datacenter name of the tagged asset :type datacenter: ``str`` :param key: The tagged key :type key: :class:`NttCisTagKey` :param value: The tagged value :type value: ``None`` or ``str`` """ self.asset_type = asset_type self.asset_id = asset_id self.asset_name = asset_name self.datacenter = datacenter self.key = key self.value = value def __repr__(self): return (('') % (self.asset_name, self.key.name, self.value)) class NttCisTagKey(object): """ A representation of a Tag Key in NTTCIS A tag key is required to tag an asset """ def __init__(self, id, name, description, value_required, display_on_report): """ Initialize an instance of :class:`NttCisTagKey` :param id: GUID of the tag key :type id: ``str`` :param name: Name of the tag key :type name: ``str`` :param description: Description of the tag key :type description: ``str`` :param value_required: If a value is required for this tag key :type value_required: ``bool`` :param display_on_report: If this tag key should be displayed on usage reports :type display_on_report: ``bool`` """ self.id = id self.name = name self.description = description self.value_required = value_required self.display_on_report = display_on_report def __repr__(self): return (('NttCisTagKey: id=%s name=%s>') % (self.id, self.name)) class NttCisIpAddressList(object): """ NttCis IP Address list """ def __init__(self, id, name, description, ip_version, ip_address_collection, state, create_time, child_ip_address_lists=None): """" Initialize an instance of :class:`NttCisIpAddressList` :param id: GUID of the IP Address List key :type id: ``str`` :param name: Name of the IP Address List :type name: ``str`` :param description: Description of the IP Address List :type description: ``str`` :param ip_version: IP version. E.g. IPV4, IPV6 :type ip_version: ``str`` :param ip_address_collection: Collection of NttCisIpAddress :type ip_address_collection: ``List`` :param state: IP Address list state :type state: ``str`` :param create_time: IP Address List created time :type create_time: ``date time`` :param child_ip_address_lists: List of IP address list to be included :type child_ip_address_lists: List of :class:'NttCisIpAddressList' """ self.id = id self.name = name self.description = description self.ip_version = ip_version self.ip_address_collection = ip_address_collection self.state = state self.create_time = create_time self.child_ip_address_lists = child_ip_address_lists def __repr__(self): return ('' % (self.id, self.name, self.description, self.ip_version, self.ip_address_collection, self.state, self.create_time, self.child_ip_address_lists)) class NttCisChildIpAddressList(object): """ NttCis Child IP Address list """ def __init__(self, id, name): """" Initialize an instance of :class:`NttCisDataChildIpAddressList` :param id: GUID of the IP Address List key :type id: ``str`` :param name: Name of the IP Address List :type name: ``str`` """ self.id = id self.name = name def __repr__(self): return ('' % (self.id, self.name)) class NttCisIpAddress(object): """ A representation of IP Address in NttCis """ def __init__(self, begin, end=None, prefix_size=None): """ Initialize an instance of :class:`NttCisIpAddress` :param begin: IP Address Begin :type begin: ``str`` :param end: IP Address end :type end: ``str`` :param prefixSize: IP Address prefix size :type prefixSize: ``int`` """ self.begin = begin self.end = end self.prefix_size = prefix_size def __repr__(self): return ('' % (self.begin, self.end, self.prefix_size)) class NttCisPortList(object): """ NttCis Port list """ def __init__(self, id, name, description, port_collection, child_portlist_list, state, create_time): """" Initialize an instance of :class:`DNttCisPortList` :param id: GUID of the Port List key :type id: ``str`` :param name: Name of the Port List :type name: ``str`` :param description: Description of the Port List :type description: ``str`` :param port_collection: Collection of NttCisPort :type port_collection: ``List`` :param child_portlist_list: Collection of NttCisChildPort :type child_portlist_list: ``List`` :param state: Port list state :type state: ``str`` :param create_time: Port List created time :type create_time: ``date time`` """ self.id = id self.name = name self.description = description self.port_collection = port_collection self.child_portlist_list = child_portlist_list self.state = state self.create_time = create_time def __repr__(self): return ( "" % (self.id, self.name, self.description, self.port_collection, self.child_portlist_list, self.state, self.create_time)) class NttCisChildPortList(object): """ NttCis Child Port list """ def __init__(self, id, name): """" Initialize an instance of :class:`NttCisChildIpAddressList` :param id: GUID of the child port list key :type id: ``str`` :param name: Name of the child port List :type name: ``str`` """ self.id = id self.name = name def __repr__(self): return ('' % (self.id, self.name)) class NttCisPort(object): """ A representation of Port in NTTCIS """ def __init__(self, begin, end=None): """ Initialize an instance of :class:`NttCisPort` :param begin: Port Number Begin :type begin: ``str`` :param end: Port Number end :type end: ``str`` """ self.begin = begin self.end = end def __repr__(self): return ('' % (self.begin, self.end)) class NttCisNic(object): """ A representation of Network Adapter in NTTCIS """ def __init__(self, private_ip_v4=None, vlan=None, network_adapter_name=None): """ Initialize an instance of :class:`NttCisNic` :param private_ip_v4: IPv4 :type private_ip_v4: ``str`` :param vlan: Network VLAN :type vlan: class: NttCisVlan or ``str`` :param network_adapter_name: Network Adapter Name :type network_adapter_name: ``str`` """ self.private_ip_v4 = private_ip_v4 self.vlan = vlan self.network_adapter_name = network_adapter_name def __repr__(self): return ('' % (self.private_ip_v4, self.vlan, self.network_adapter_name)) # Dynamically create classes from returned XML. Leaves the API as the # single authoritative source. class ClassFactory(object): pass attrs = {} # type: Dict[str, str] def processor(mapping, name=None): """ Closure that keeps the deepcopy of the original dict converted to XML current. :param mapping: The converted XML to dict/lists :type mapping: ``dict`` :param name: (Optional) what becomes the class name if provided :type: ``str`` :return: Nothing """ mapping = mapping # the map_copy will have keys deleted after the key and value are processed map_copy = deepcopy(mapping) def add_items(key, value, name=None): """ Add items to the global attr dict, then delete key, value from map copy :param key: from the process function becomes the attribute name :type key: ``str`` :param value: The value of the property and may be a dict :type value: ``str`` :param name: Name of class, often same as key :type: name" ``str`` """ if name in attrs: attrs[name].update({key: value}) elif name is not None: attrs[name] = value else: attrs.update({key: value}) # trim the copy of the mapping if key in map_copy: del map_copy[key] elif key in map_copy[name]: del map_copy[name][key] if len(map_copy[name]) == 0: del map_copy[name] def handle_map(map, name): tmp = {} types = [type(x) for x in map.values()] if XmlListConfig not in types and \ XmlDictConfig not in types and dict not in types: return map elif XmlListConfig in types: result = handle_seq(map, name) return result else: for k, v in map.items(): if isinstance(v, str): tmp.update({k: v}) if isinstance(v, dict): cls = build_class(k.capitalize(), v) tmp.update({k: cls}) elif isinstance(v, XmlDictConfig): cls = build_class(k.capitalize(), v) return (k, cls) return tmp def handle_seq(seq, name): tmp = {} if isinstance(seq, list): tmp = [] for _ in seq: cls = build_class(name.capitalize(), _) tmp.append(cls) return tmp for k, v in seq.items(): if isinstance(v, MutableSequence): for _ in v: if isinstance(_, Mapping): types = [type(x) for x in _.values()] if XmlDictConfig in types: result = handle_map(_, k) if isinstance(result, tuple): tmp.update({result[0]: result[1]}) else: tmp.update({k: result}) else: tmp_list = [build_class(k.capitalize(), i) for i in v] tmp[k] = tmp_list elif isinstance(v, str): tmp.update({k: v}) return tmp def build_class(key, value): klass = class_factory(key.capitalize(), value) return klass(value) def process(mapping): """ This function is recursive, creating attributes for the class factory by taking apart the elements in the dictionary. Thus, the calls to handle_seq or handle_map :param mapping: the dictionary converted from XML :return: itself (recursive) """ for k1, v1 in mapping.items(): if isinstance(v1, Mapping): types = [type(v) for v in v1.values()] if MutableSequence not in types and dict not in types: result = handle_map(v1, k1) cls = build_class(k1.capitalize(), result) add_items(k1, cls) elif XmlListConfig in types: result = handle_seq(v1, k1) cls = build_class(list(v1)[0], result) add_items(k1, cls) elif dict in types: result = handle_map(v1, k1) cls = build_class(k1.capitalize(), result) add_items(k1, cls, k1) elif isinstance(v1, list): tmp1 = {} tmp2 = {} tmp2[k1] = [] for i, j in enumerate(v1): if isinstance(j, dict): key = list(j)[0] result = handle_map(j, key) tmp1[k1 + str(i)] = build_class(k1, result) tmp2[k1].append(tmp1[k1 + str(i)]) if tmp2: add_items(k1, tmp2[k1], k1) elif isinstance(v1, str): add_items(k1, v1) if len(map_copy) == 0: return 1 return process(mapping) def class_factory(cls_name, attrs): """ This class takes a name and a dictionary to create a class. The clkass has an init method, an iter for retrieving properties, and, finally, a repr for returning the instance :param cls_name: The name to be tacked onto the suffix NttCis :type cls_name: ``str`` :param attrs: The attributes and values for an instance :type attrs: ``dict`` :return: a class that inherits from ClassFactory :rtype: ``ClassFactory`` """ def __init__(self, *args, **kwargs): for key in attrs: setattr(self, key, attrs[key]) if cls_name == "NttCisServer": self.state = self._get_state() def __iter__(self): for name in self.__dict__: yield getattr(self, name) def __repr__(self): values = ', '.join('{}={!r}'.format(*i) for i in zip(self.__dict__, self)) return '{}({})'.format(self.__class__.__name__, values) cls_attrs = dict( __init__=__init__, __iter__=__iter__, __repr__=__repr__) return type("NttCis{}".format(cls_name), (ClassFactory,), cls_attrs) class XmlListConfig(list): """ Creates a class from XML elements that make a list. If a list of XML elements with attributes, the attributes are passed to XmlDictConfig. """ def __init__(self, elem_list): for element in elem_list: if element is not None: # treat like dict if len(element) >= 0 or element[0].tag != element[1].tag: self.append(XmlDictConfig(element)) # treat like list elif element[0].tag == element[1].tag: # property refers to an element used repeatedly # in the XML for data centers only if 'property' in element.tag: self.append({element.attrib.get('name'): element.attrib.get('value')}) else: self.append(element.attrib) elif element.text: text = element.text.strip() if text: self.append(text) class XmlDictConfig(dict): """ Inherits from dict. Looks for XML elements, such as attrib, that can be converted to a dictionary. Any XML element that contains other XML elements, will be passed to XmlListConfig """ def __init__(self, parent_element): if parent_element.items(): if 'property' in parent_element.tag: self.update({parent_element.attrib.get('name'): parent_element.attrib.get('value')}) else: self.update(dict(parent_element.items())) for element in parent_element: if len(element) > 0: # treat like dict - we assume that if the first two tags # in a series are different, then they are all different. if len(element) == 1 or element[0].tag != element[1].tag: elem_dict = XmlDictConfig(element) # treat like list - we assume that if the first two tags # in a series are the same, then the rest are the same. else: # here, we put the list in dictionary; the key is the # tag name the list elements all share in common, and # the value is the list itself elem_dict = {element[0].tag.split('}')[1]: XmlListConfig(element)} # if the tag has attributes, add those to the dict if element.items(): elem_dict.update(dict(element.items())) self.update({element.tag.split('}')[1]: elem_dict}) # this assumes that if you've got an attribute in a tag, # you won't be having any text. This may or may not be a # good idea -- time will tell. It works for the way we are # currently doing XML configuration files... elif element.items(): # It is possible to have duplicate element tags. # If so, convert to a dict of lists if element.tag.split('}')[1] in self: if isinstance(self[element.tag.split('}')[1]], list): self[element.tag.split('}')[1]].\ append(dict(element.items())) else: tmp_list = list() tmp_dict = dict() for k, v in self[element.tag.split('}')[1]].items(): if isinstance(k, XmlListConfig): tmp_list.append(k) else: tmp_dict.update({k: v}) tmp_list.append(tmp_dict) tmp_list.append(dict(element.items())) self[element.tag.split('}')[1]] = tmp_list else: self.update({element.tag.split('}')[1]: dict(element.items())}) # finally, if there are no child tags and no attributes, extract # the text else: self.update({element.tag.split('}')[1]: element.text}) def process_xml(xml): """ Take the xml and put it into a dictionary. The process the dictionary recursively. This returns a class based on the XML API. Thus, properties will have the camel case found in the Java XML. This a trade-off to reduce the number of "static" classes that all have to be synchronized with any changes in the API. :param xml: The serialized version of the XML returned from Cloud Control :return: a dynamic class that inherits from ClassFactory :rtype: `ClassFactory` """ global attrs tree = etree.parse(BytesIO(xml)) root = tree.getroot() elem = root.tag.split('}')[1].capitalize() items = dict(root.items()) if 'pageNumber' in items: converted_xml = XmlListConfig(root) processor(converted_xml[0]) else: converted_xml = XmlDictConfig(root) processor(converted_xml) klass = class_factory(elem.capitalize(), attrs) cls = klass(attrs) attrs = {} return cls apache-libcloud-2.8.0/libcloud/common/onapp.py0000664000175000017500000000412413570310635021203 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from base64 import b64encode from libcloud.utils.py3 import b from libcloud.utils.py3 import httplib from libcloud.common.base import ConnectionUserAndKey, JsonResponse class OnAppResponse(JsonResponse): """ OnApp response class """ def success(self): """ Determine if our request was successful. The meaning of this can be arbitrary; did we receive OK status? Did the node get created? Were we authenticated? :rtype: ``bool`` :return: ``True`` or ``False`` """ return self.status in [httplib.OK, httplib.CREATED, httplib.NO_CONTENT] class OnAppConnection(ConnectionUserAndKey): """ OnApp connection class """ responseCls = OnAppResponse def add_default_headers(self, headers): """ Add Basic Authentication header to all the requests. It injects the "Authorization: Basic Base64String===" header in each request :type headers: ``dict`` :param headers: Default input headers :rtype: ``dict`` :return: Default input headers with the "Authorization" header. """ b64string = b("%s:%s" % (self.user_id, self.key)) encoded = b64encode(b64string).decode("utf-8") headers["Authorization"] = "Basic " + encoded return headers apache-libcloud-2.8.0/libcloud/common/openstack.py0000664000175000017500000004445613576514553022104 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Common utilities for OpenStack """ from libcloud.utils.py3 import ET from libcloud.utils.py3 import httplib from libcloud.common.base import ConnectionUserAndKey, Response from libcloud.common.types import ProviderError from libcloud.compute.types import (LibcloudError, MalformedResponseError) from libcloud.compute.types import KeyPairDoesNotExistError from libcloud.common.openstack_identity import get_class_for_auth_version # Imports for backward compatibility reasons from libcloud.common.openstack_identity import (OpenStackServiceCatalog, OpenStackIdentityTokenScope) try: import simplejson as json except ImportError: import json # type: ignore AUTH_API_VERSION = '1.1' # Auth versions which contain token expiration information. AUTH_VERSIONS_WITH_EXPIRES = [ '1.1', '2.0', '2.0_apikey', '2.0_password', '3.x', '3.x_password' ] __all__ = [ 'OpenStackBaseConnection', 'OpenStackResponse', 'OpenStackException', 'OpenStackDriverMixin' ] class OpenStackBaseConnection(ConnectionUserAndKey): """ Base class for OpenStack connections. :param user_id: User name to use when authenticating :type user_id: ``str`` :param key: Secret to use when authenticating. :type key: ``str`` :param secure: Use HTTPS? (True by default.) :type secure: ``bool`` :param ex_force_base_url: Base URL for connection requests. If not specified, this will be determined by authenticating. :type ex_force_base_url: ``str`` :param ex_force_auth_url: Base URL for authentication requests. :type ex_force_auth_url: ``str`` :param ex_force_auth_version: Authentication version to use. If not specified, defaults to AUTH_API_VERSION. :type ex_force_auth_version: ``str`` :param ex_force_auth_token: Authentication token to use for connection requests. If specified, the connection will not attempt to authenticate, and the value of ex_force_base_url will be used to determine the base request URL. If ex_force_auth_token is passed in, ex_force_base_url must also be provided. :type ex_force_auth_token: ``str`` :param token_scope: Whether to scope a token to a "project", a "domain" or "unscoped". :type token_scope: ``str`` :param ex_domain_name: When authenticating, provide this domain name to the identity service. A scoped token will be returned. Some cloud providers require the domain name to be provided at authentication time. Others will use a default domain if none is provided. :type ex_domain_name: ``str`` :param ex_tenant_name: When authenticating, provide this tenant name to the identity service. A scoped token will be returned. Some cloud providers require the tenant name to be provided at authentication time. Others will use a default tenant if none is provided. :type ex_tenant_name: ``str`` :param ex_tenant_domain_id: When authenticating, provide this tenant domain id to the identity service. A scoped token will be returned. Some cloud providers require the tenant domain id to be provided at authentication time. Others will use a default tenant domain id if none is provided. :type ex_tenant_domain_id: ``str`` :param ex_force_service_type: Service type to use when selecting an service. If not specified, a provider specific default will be used. :type ex_force_service_type: ``str`` :param ex_force_service_name: Service name to use when selecting an service. If not specified, a provider specific default will be used. :type ex_force_service_name: ``str`` :param ex_force_service_region: Region to use when selecting an service. If not specified, a provider specific default will be used. :type ex_force_service_region: ``str`` """ auth_url = None # type: str auth_token = None # type: str auth_token_expires = None auth_user_info = None service_catalog = None service_type = None service_name = None service_region = None accept_format = None _auth_version = None def __init__(self, user_id, key, secure=True, host=None, port=None, timeout=None, proxy_url=None, ex_force_base_url=None, ex_force_auth_url=None, ex_force_auth_version=None, ex_force_auth_token=None, ex_token_scope=OpenStackIdentityTokenScope.PROJECT, ex_domain_name='Default', ex_tenant_name=None, ex_tenant_domain_id='default', ex_force_service_type=None, ex_force_service_name=None, ex_force_service_region=None, retry_delay=None, backoff=None): super(OpenStackBaseConnection, self).__init__( user_id, key, secure=secure, timeout=timeout, retry_delay=retry_delay, backoff=backoff, proxy_url=proxy_url) if ex_force_auth_version: self._auth_version = ex_force_auth_version self.base_url = ex_force_base_url self._ex_force_base_url = ex_force_base_url self._ex_force_auth_url = ex_force_auth_url self._ex_force_auth_token = ex_force_auth_token self._ex_token_scope = ex_token_scope self._ex_domain_name = ex_domain_name self._ex_tenant_name = ex_tenant_name self._ex_tenant_domain_id = ex_tenant_domain_id self._ex_force_service_type = ex_force_service_type self._ex_force_service_name = ex_force_service_name self._ex_force_service_region = ex_force_service_region self._osa = None if ex_force_auth_token and not ex_force_base_url: raise LibcloudError( 'Must also provide ex_force_base_url when specifying ' 'ex_force_auth_token.') if ex_force_auth_token: self.auth_token = ex_force_auth_token if not self._auth_version: self._auth_version = AUTH_API_VERSION auth_url = self._get_auth_url() if not auth_url: raise LibcloudError('OpenStack instance must ' + 'have auth_url set') def get_auth_class(self): """ Retrieve identity / authentication class instance. :rtype: :class:`OpenStackIdentityConnection` """ if not self._osa: auth_url = self._get_auth_url() cls = get_class_for_auth_version(auth_version=self._auth_version) self._osa = cls(auth_url=auth_url, user_id=self.user_id, key=self.key, tenant_name=self._ex_tenant_name, tenant_domain_id=self._ex_tenant_domain_id, domain_name=self._ex_domain_name, token_scope=self._ex_token_scope, timeout=self.timeout, proxy_url=self.proxy_url, parent_conn=self) return self._osa def request(self, action, params=None, data='', headers=None, method='GET', raw=False): headers = headers or {} params = params or {} # Include default content-type for POST and PUT request (if available) default_content_type = getattr(self, 'default_content_type', None) if method.upper() in ['POST', 'PUT'] and default_content_type: headers = {'Content-Type': default_content_type} return super(OpenStackBaseConnection, self).request(action=action, params=params, data=data, method=method, headers=headers, raw=raw) def _get_auth_url(self): """ Retrieve auth url for this instance using either "ex_force_auth_url" constructor kwarg of "auth_url" class variable. """ auth_url = self.auth_url if self._ex_force_auth_url is not None: auth_url = self._ex_force_auth_url return auth_url def get_service_catalog(self): if self.service_catalog is None: self._populate_hosts_and_request_paths() return self.service_catalog def get_service_name(self): """ Gets the service name used to look up the endpoint in the service catalog. :return: name of the service in the catalog """ if self._ex_force_service_name: return self._ex_force_service_name return self.service_name def get_endpoint(self): """ Selects the endpoint to use based on provider specific values, or overrides passed in by the user when setting up the driver. :returns: url of the relevant endpoint for the driver """ service_type = self.service_type service_name = self.service_name service_region = self.service_region if self._ex_force_service_type: service_type = self._ex_force_service_type if self._ex_force_service_name: service_name = self._ex_force_service_name if self._ex_force_service_region: service_region = self._ex_force_service_region endpoint = self.service_catalog.get_endpoint(service_type=service_type, name=service_name, region=service_region) url = endpoint.url if not url: raise LibcloudError('Could not find specified endpoint') return url def add_default_headers(self, headers): headers['X-Auth-Token'] = self.auth_token headers['Accept'] = self.accept_format return headers def morph_action_hook(self, action): self._populate_hosts_and_request_paths() return super(OpenStackBaseConnection, self).morph_action_hook(action) def _set_up_connection_info(self, url): result = self._tuple_from_url(url) (self.host, self.port, self.secure, self.request_path) = result self.connect() def _populate_hosts_and_request_paths(self): """ OpenStack uses a separate host for API calls which is only provided after an initial authentication request. """ osa = self.get_auth_class() if self._ex_force_auth_token: # If ex_force_auth_token is provided we always hit the api directly # and never try to authenticate. # # Note: When ex_force_auth_token is provided, ex_force_base_url # must be provided as well. self._set_up_connection_info(url=self._ex_force_base_url) return if not osa.is_token_valid(): # Token is not available or it has expired. Need to retrieve a # new one. if self._auth_version == '2.0_apikey': kwargs = {'auth_type': 'api_key'} elif self._auth_version == '2.0_password': kwargs = {'auth_type': 'password'} else: kwargs = {} osa = osa.authenticate(**kwargs) # may throw InvalidCreds self.auth_token = osa.auth_token self.auth_token_expires = osa.auth_token_expires self.auth_user_info = osa.auth_user_info # Pull out and parse the service catalog osc = OpenStackServiceCatalog(service_catalog=osa.urls, auth_version=self._auth_version) self.service_catalog = osc url = self._ex_force_base_url or self.get_endpoint() self._set_up_connection_info(url=url) class OpenStackException(ProviderError): pass class OpenStackResponse(Response): node_driver = None def success(self): i = int(self.status) return 200 <= i <= 299 def has_content_type(self, content_type): content_type_value = self.headers.get('content-type') or '' content_type_value = content_type_value.lower() return content_type_value.find(content_type.lower()) > -1 def parse_body(self): if self.status == httplib.NO_CONTENT or not self.body: return None if self.has_content_type('application/xml'): try: return ET.XML(self.body) except Exception: raise MalformedResponseError( 'Failed to parse XML', body=self.body, driver=self.node_driver) elif self.has_content_type('application/json'): try: return json.loads(self.body) except Exception: raise MalformedResponseError( 'Failed to parse JSON', body=self.body, driver=self.node_driver) else: return self.body def parse_error(self): body = self.parse_body() if self.has_content_type('application/xml'): text = '; '.join([err.text or '' for err in body.getiterator() if err.text]) elif self.has_content_type('application/json'): values = list(body.values()) context = self.connection.context driver = self.connection.driver key_pair_name = context.get('key_pair_name', None) if len(values) > 0 and 'code' in values[0] and \ values[0]['code'] == 404 and key_pair_name: raise KeyPairDoesNotExistError(name=key_pair_name, driver=driver) elif len(values) > 0 and 'message' in values[0]: text = ';'.join([fault_data['message'] for fault_data in values]) else: text = body else: # while we hope a response is always one of xml or json, we have # seen html or text in the past, its not clear we can really do # something to make it more readable here, so we will just pass # it along as the whole response body in the text variable. text = body return '%s %s %s' % (self.status, self.error, text) class OpenStackDriverMixin(object): def __init__(self, ex_force_base_url=None, ex_force_auth_url=None, ex_force_auth_version=None, ex_force_auth_token=None, ex_token_scope=OpenStackIdentityTokenScope.PROJECT, ex_domain_name='Default', ex_tenant_name=None, ex_tenant_domain_id='default', ex_force_service_type=None, ex_force_service_name=None, ex_force_service_region=None, *args, **kwargs): self._ex_force_base_url = ex_force_base_url self._ex_force_auth_url = ex_force_auth_url self._ex_force_auth_version = ex_force_auth_version self._ex_force_auth_token = ex_force_auth_token self._ex_token_scope = ex_token_scope self._ex_domain_name = ex_domain_name self._ex_tenant_name = ex_tenant_name self._ex_tenant_domain_id = ex_tenant_domain_id self._ex_force_service_type = ex_force_service_type self._ex_force_service_name = ex_force_service_name self._ex_force_service_region = ex_force_service_region def openstack_connection_kwargs(self): """ Returns certain ``ex_*`` parameters for this connection. :rtype: ``dict`` """ rv = {} if self._ex_force_base_url: rv['ex_force_base_url'] = self._ex_force_base_url if self._ex_force_auth_token: rv['ex_force_auth_token'] = self._ex_force_auth_token if self._ex_force_auth_url: rv['ex_force_auth_url'] = self._ex_force_auth_url if self._ex_force_auth_version: rv['ex_force_auth_version'] = self._ex_force_auth_version if self._ex_token_scope: rv['ex_token_scope'] = self._ex_token_scope if self._ex_domain_name: rv['ex_domain_name'] = self._ex_domain_name if self._ex_tenant_name: rv['ex_tenant_name'] = self._ex_tenant_name if self._ex_tenant_domain_id: rv['ex_tenant_domain_id'] = self._ex_tenant_domain_id if self._ex_force_service_type: rv['ex_force_service_type'] = self._ex_force_service_type if self._ex_force_service_name: rv['ex_force_service_name'] = self._ex_force_service_name if self._ex_force_service_region: rv['ex_force_service_region'] = self._ex_force_service_region return rv apache-libcloud-2.8.0/libcloud/common/openstack_identity.py0000664000175000017500000017005313600144066023770 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Common / shared code for handling authentication against OpenStack identity service (Keystone). """ import datetime from libcloud.utils.py3 import httplib from libcloud.utils.iso8601 import parse_date from libcloud.common.base import (ConnectionUserAndKey, Response, CertificateConnection) from libcloud.compute.types import (LibcloudError, InvalidCredsError, MalformedResponseError) try: import simplejson as json except ImportError: import json # type: ignore AUTH_API_VERSION = '1.1' # Auth versions which contain token expiration information. AUTH_VERSIONS_WITH_EXPIRES = [ '1.1', '2.0', '2.0_apikey', '2.0_password', '2.0_voms', '3.0', '3.x_password', '3.x_oidc_access_token' ] # How many seconds to subtract from the auth token expiration time before # testing if the token is still valid. # The time is subtracted to account for the HTTP request latency and prevent # user from getting "InvalidCredsError" if token is about to expire. AUTH_TOKEN_EXPIRES_GRACE_SECONDS = 5 __all__ = [ 'OpenStackIdentityVersion', 'OpenStackIdentityDomain', 'OpenStackIdentityProject', 'OpenStackIdentityUser', 'OpenStackIdentityRole', 'OpenStackServiceCatalog', 'OpenStackServiceCatalogEntry', 'OpenStackServiceCatalogEntryEndpoint', 'OpenStackIdentityEndpointType', 'OpenStackIdentityConnection', 'OpenStackIdentity_1_0_Connection', 'OpenStackIdentity_1_1_Connection', 'OpenStackIdentity_2_0_Connection', 'OpenStackIdentity_2_0_Connection_VOMS', 'OpenStackIdentity_3_0_Connection', 'OpenStackIdentity_3_0_Connection_OIDC_access_token', 'get_class_for_auth_version' ] class OpenStackIdentityEndpointType(object): """ Enum class for openstack identity endpoint type. """ INTERNAL = 'internal' EXTERNAL = 'external' ADMIN = 'admin' class OpenStackIdentityTokenScope(object): """ Enum class for openstack identity token scope. """ PROJECT = 'project' DOMAIN = 'domain' UNSCOPED = 'unscoped' class OpenStackIdentityVersion(object): def __init__(self, version, status, updated, url): self.version = version self.status = status self.updated = updated self.url = url def __repr__(self): return (('' % (self.version, self.status, self.updated, self.url))) class OpenStackIdentityDomain(object): def __init__(self, id, name, enabled): self.id = id self.name = name self.enabled = enabled def __repr__(self): return (('' % (self.id, self.name, self.enabled))) class OpenStackIdentityProject(object): def __init__(self, id, name, description, enabled, domain_id=None): self.id = id self.name = name self.description = description self.enabled = enabled self.domain_id = domain_id def __repr__(self): return (('' % (self.id, self.domain_id, self.name, self.enabled))) class OpenStackIdentityRole(object): def __init__(self, id, name, description, enabled): self.id = id self.name = name self.description = description self.enabled = enabled def __repr__(self): return (('' % (self.id, self.name, self.description, self.enabled))) class OpenStackIdentityUser(object): def __init__(self, id, domain_id, name, email, description, enabled): self.id = id self.domain_id = domain_id self.name = name self.email = email self.description = description self.enabled = enabled def __repr__(self): return (('' % (self.id, self.domain_id, self.name, self.email, self.enabled))) class OpenStackServiceCatalog(object): """ http://docs.openstack.org/api/openstack-identity-service/2.0/content/ This class should be instantiated with the contents of the 'serviceCatalog' in the auth response. This will do the work of figuring out which services actually exist in the catalog as well as split them up by type, name, and region if available """ _auth_version = None _service_catalog = None def __init__(self, service_catalog, auth_version=AUTH_API_VERSION): self._auth_version = auth_version # Check this way because there are a couple of different 2.0_* # auth types. if '3.x' in self._auth_version: entries = self._parse_service_catalog_auth_v3( service_catalog=service_catalog) elif '2.0' in self._auth_version: entries = self._parse_service_catalog_auth_v2( service_catalog=service_catalog) elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version): entries = self._parse_service_catalog_auth_v1( service_catalog=service_catalog) else: raise LibcloudError('auth version "%s" not supported' % (self._auth_version)) # Force consistent ordering by sorting the entries entries = sorted(entries, key=lambda x: x.service_type + (x.service_name or '')) self._entries = entries # stories all the service catalog entries def get_entries(self): """ Return all the entries for this service catalog. :rtype: ``list`` of :class:`.OpenStackServiceCatalogEntry` """ return self._entries def get_catalog(self): """ Deprecated in the favor of ``get_entries`` method. """ return self.get_entries() def get_public_urls(self, service_type=None, name=None): """ Retrieve all the available public (external) URLs for the provided service type and name. """ endpoints = self.get_endpoints(service_type=service_type, name=name) result = [] for endpoint in endpoints: endpoint_type = endpoint.endpoint_type if endpoint_type == OpenStackIdentityEndpointType.EXTERNAL: result.append(endpoint.url) return result def get_endpoints(self, service_type=None, name=None): """ Retrieve all the endpoints for the provided service type and name. :rtype: ``list`` of :class:`.OpenStackServiceCatalogEntryEndpoint` """ endpoints = [] for entry in self._entries: # Note: "if XXX and YYY != XXX" comparison is used to support # partial lookups. # This allows user to pass in only one argument to the method (only # service_type or name), both of them or neither. if service_type and entry.service_type != service_type: continue if name and entry.service_name != name: continue for endpoint in entry.endpoints: endpoints.append(endpoint) return endpoints def get_endpoint(self, service_type=None, name=None, region=None, endpoint_type=OpenStackIdentityEndpointType.EXTERNAL): """ Retrieve a single endpoint using the provided criteria. Note: If no or more than one matching endpoint is found, an exception is thrown. """ endpoints = [] for entry in self._entries: if service_type and entry.service_type != service_type: continue if name and entry.service_name != name: continue for endpoint in entry.endpoints: if region and endpoint.region != region: continue if endpoint_type and endpoint.endpoint_type != endpoint_type: continue endpoints.append(endpoint) if len(endpoints) == 1: return endpoints[0] elif len(endpoints) > 1: raise ValueError('Found more than 1 matching endpoint') else: raise LibcloudError('Could not find specified endpoint') def get_regions(self, service_type=None): """ Retrieve a list of all the available regions. :param service_type: If specified, only return regions for this service type. :type service_type: ``str`` :rtype: ``list`` of ``str`` """ regions = set() for entry in self._entries: if service_type and entry.service_type != service_type: continue for endpoint in entry.endpoints: if endpoint.region: regions.add(endpoint.region) return sorted(list(regions)) def get_service_types(self, region=None): """ Retrieve all the available service types. :param region: Optional region to retrieve service types for. :type region: ``str`` :rtype: ``list`` of ``str`` """ service_types = set() for entry in self._entries: include = True for endpoint in entry.endpoints: if region and endpoint.region != region: include = False break if include: service_types.add(entry.service_type) return sorted(list(service_types)) def get_service_names(self, service_type=None, region=None): """ Retrieve list of service names that match service type and region. :type service_type: ``str`` :type region: ``str`` :rtype: ``list`` of ``str`` """ names = set() if '2.0' not in self._auth_version: raise ValueError('Unsupported version: %s' % (self._auth_version)) for entry in self._entries: if service_type and entry.service_type != service_type: continue include = True for endpoint in entry.endpoints: if region and endpoint.region != region: include = False break if include and entry.service_name: names.add(entry.service_name) return sorted(list(names)) def _parse_service_catalog_auth_v1(self, service_catalog): entries = [] for service, endpoints in service_catalog.items(): entry_endpoints = [] for endpoint in endpoints: region = endpoint.get('region', None) public_url = endpoint.get('publicURL', None) private_url = endpoint.get('internalURL', None) if public_url: entry_endpoint = OpenStackServiceCatalogEntryEndpoint( region=region, url=public_url, endpoint_type=OpenStackIdentityEndpointType.EXTERNAL) entry_endpoints.append(entry_endpoint) if private_url: entry_endpoint = OpenStackServiceCatalogEntryEndpoint( region=region, url=private_url, endpoint_type=OpenStackIdentityEndpointType.INTERNAL) entry_endpoints.append(entry_endpoint) entry = OpenStackServiceCatalogEntry(service_type=service, endpoints=entry_endpoints) entries.append(entry) return entries def _parse_service_catalog_auth_v2(self, service_catalog): entries = [] for service in service_catalog: service_type = service['type'] service_name = service.get('name', None) entry_endpoints = [] for endpoint in service.get('endpoints', []): region = endpoint.get('region', None) public_url = endpoint.get('publicURL', None) private_url = endpoint.get('internalURL', None) if public_url: entry_endpoint = OpenStackServiceCatalogEntryEndpoint( region=region, url=public_url, endpoint_type=OpenStackIdentityEndpointType.EXTERNAL) entry_endpoints.append(entry_endpoint) if private_url: entry_endpoint = OpenStackServiceCatalogEntryEndpoint( region=region, url=private_url, endpoint_type=OpenStackIdentityEndpointType.INTERNAL) entry_endpoints.append(entry_endpoint) entry = OpenStackServiceCatalogEntry(service_type=service_type, endpoints=entry_endpoints, service_name=service_name) entries.append(entry) return entries def _parse_service_catalog_auth_v3(self, service_catalog): entries = [] for item in service_catalog: service_type = item['type'] service_name = item.get('name', None) entry_endpoints = [] for endpoint in item['endpoints']: region = endpoint.get('region', None) url = endpoint['url'] endpoint_type = endpoint['interface'] if endpoint_type == 'internal': endpoint_type = OpenStackIdentityEndpointType.INTERNAL elif endpoint_type == 'public': endpoint_type = OpenStackIdentityEndpointType.EXTERNAL elif endpoint_type == 'admin': endpoint_type = OpenStackIdentityEndpointType.ADMIN entry_endpoint = OpenStackServiceCatalogEntryEndpoint( region=region, url=url, endpoint_type=endpoint_type) entry_endpoints.append(entry_endpoint) entry = OpenStackServiceCatalogEntry(service_type=service_type, service_name=service_name, endpoints=entry_endpoints) entries.append(entry) return entries class OpenStackServiceCatalogEntry(object): def __init__(self, service_type, endpoints=None, service_name=None): """ :param service_type: Service type. :type service_type: ``str`` :param endpoints: Endpoints belonging to this entry. :type endpoints: ``list`` :param service_name: Optional service name. :type service_name: ``str`` """ self.service_type = service_type self.endpoints = endpoints or [] self.service_name = service_name # For consistency, sort the endpoints self.endpoints = sorted(self.endpoints, key=lambda x: x.url or '') def __eq__(self, other): return (self.service_type == other.service_type and self.endpoints == other.endpoints and other.service_name == self.service_name) def __ne__(self, other): return not self.__eq__(other=other) def __repr__(self): return ((' None super(LibcloudError, self).__init__(value) self.value = value self.driver = driver def __str__(self): return self.__repr__() def __repr__(self): return ("") class MalformedResponseError(LibcloudError): """Exception for the cases when a provider returns a malformed response, e.g. you request JSON and provider returns '

something

' due to some error on their side.""" def __init__(self, value, body=None, driver=None): # type: (str, Optional[str], Optional[NodeDriver]) -> None self.value = value self.driver = driver self.body = body def __str__(self): return self.__repr__() def __repr__(self): return (": " + repr(self.body)) class ProviderError(LibcloudError): """ Exception used when provider gives back error response (HTTP 4xx, 5xx) for a request. Specific sub types can be derived for errors like HTTP 401 : InvalidCredsError HTTP 404 : NodeNotFoundError, ContainerDoesNotExistError """ def __init__(self, value, http_code, driver=None): # type: (str, int, Optional[NodeDriver]) -> None super(ProviderError, self).__init__(value=value, driver=driver) self.http_code = http_code def __str__(self): return self.__repr__() def __repr__(self): return repr(self.value) class InvalidCredsError(ProviderError): """Exception used when invalid credentials are used on a provider.""" def __init__(self, value='Invalid credentials with the provider', driver=None): # type: (str, Optional[NodeDriver]) -> None super(InvalidCredsError, self).__init__(value, http_code=httplib.UNAUTHORIZED, driver=driver) # Deprecated alias of :class:`InvalidCredsError` InvalidCredsException = InvalidCredsError class ServiceUnavailableError(ProviderError): """Exception used when a provider returns 503 Service Unavailable.""" def __init__(self, value='Service unavailable at provider', driver=None): # type: (str, Optional[NodeDriver]) -> None super(ServiceUnavailableError, self).__init__( value, http_code=httplib.SERVICE_UNAVAILABLE, driver=driver ) class LazyList(object): def __init__(self, get_more, value_dict=None): # type: (Callable, Optional[dict]) -> None self._data = [] # type: list self._last_key = None self._exhausted = False self._all_loaded = False self._get_more = get_more self._value_dict = value_dict or {} def __iter__(self): if not self._all_loaded: self._load_all() data = self._data for i in data: yield i def __getitem__(self, index): if index >= len(self._data) and not self._all_loaded: self._load_all() return self._data[index] def __len__(self): self._load_all() return len(self._data) def __repr__(self): self._load_all() repr_string = ', ' .join([repr(item) for item in self._data]) repr_string = '[%s]' % (repr_string) return repr_string def _load_all(self): while not self._exhausted: newdata, self._last_key, self._exhausted = \ self._get_more(last_key=self._last_key, value_dict=self._value_dict) self._data.extend(newdata) self._all_loaded = True apache-libcloud-2.8.0/libcloud/common/upcloud.py0000664000175000017500000002137413577507766021573 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json import time from libcloud.common.exceptions import BaseHTTPError from libcloud.common.types import LibcloudError class UpcloudTimeoutException(LibcloudError): pass class UpcloudCreateNodeRequestBody(object): """ Body of the create_node request Takes the create_node arguments (**kwargs) and constructs the request body :param name: Name of the created server (required) :type name: ``str`` :param size: The size of resources allocated to this node. :type size: :class:`.NodeSize` :param image: OS Image to boot on node. :type image: :class:`.NodeImage` :param location: Which data center to create a node in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param auth: Initial authentication information for the node (optional) :type auth: :class:`.NodeAuthSSHKey` :param ex_hostname: Hostname. Default is 'localhost'. (optional) :type ex_hostname: ``str`` :param ex_username: User's username, which is created. Default is 'root'. (optional) :type ex_username: ``str`` """ def __init__(self, name, size, image, location, auth=None, ex_hostname='localhost', ex_username='root'): self.body = { 'server': { 'title': name, 'hostname': ex_hostname, 'plan': size.id, 'zone': location.id, 'login_user': _LoginUser(ex_username, auth).to_dict(), 'storage_devices': _StorageDevice(image, size).to_dict() } } def to_json(self): """ Serializes the body to json :return: JSON string :rtype: ``str`` """ return json.dumps(self.body) class UpcloudNodeDestroyer(object): """ Helper class for destroying node. Node must be first stopped and then it can be destroyed :param upcloud_node_operations: UpcloudNodeOperations instance :type upcloud_node_operations: :class:`.UpcloudNodeOperations` :param sleep_func: Callable function, which sleeps. Takes int argument to sleep in seconds (optional) :type sleep_func: ``function`` """ WAIT_AMOUNT = 2 SLEEP_COUNT_TO_TIMEOUT = 20 def __init__(self, upcloud_node_operations, sleep_func=None): self._operations = upcloud_node_operations self._sleep_func = sleep_func or time.sleep self._sleep_count = 0 def destroy_node(self, node_id): """ Destroys the given node. :param node_id: Id of the Node. :type node_id: ``int`` """ self._stop_called = False self._sleep_count = 0 return self._do_destroy_node(node_id) def _do_destroy_node(self, node_id): state = self._operations.get_node_state(node_id) if state == 'stopped': self._operations.destroy_node(node_id) return True elif state == 'error': return False elif state == 'started': if not self._stop_called: self._operations.stop_node(node_id) self._stop_called = True else: # Waiting for started state to change and # not calling stop again self._sleep() return self._do_destroy_node(node_id) elif state == 'maintenance': # Lets wait maintenace state to go away and retry destroy self._sleep() return self._do_destroy_node(node_id) elif state is None: # Server not found any more return True def _sleep(self): if self._sleep_count > self.SLEEP_COUNT_TO_TIMEOUT: raise UpcloudTimeoutException("Timeout, could not destroy node") self._sleep_count += 1 self._sleep_func(self.WAIT_AMOUNT) class UpcloudNodeOperations(object): """ Helper class to start and stop node. :param conneciton: Connection instance :type connection: :class:`.UpcloudConnection` """ def __init__(self, connection): self.connection = connection def stop_node(self, node_id): """ Stops the node :param node_id: Id of the Node :type node_id: ``int`` """ body = { 'stop_server': { 'stop_type': 'hard' } } self.connection.request('1.2/server/{0}/stop'.format(node_id), method='POST', data=json.dumps(body)) def get_node_state(self, node_id): """ Get the state of the node. :param node_id: Id of the Node :type node_id: ``int`` :rtype: ``str`` """ action = '1.2/server/{0}'.format(node_id) try: response = self.connection.request(action) return response.object['server']['state'] except BaseHTTPError as e: if e.code == 404: return None raise def destroy_node(self, node_id): """ Destroys the node. :param node_id: Id of the Node :type node_id: ``int`` """ self.connection.request('1.2/server/{0}'.format(node_id), method='DELETE') class PlanPrice(object): """ Helper class to construct plan price in different zones :param zone_prices: List of prices in different zones in UpCloud :type zone_prices: ```list``` """ def __init__(self, zone_prices): self._zone_prices = zone_prices def get_price(self, plan_name, location=None): """ Returns the plan's price in location. If location is not provided returns None :param plan_name: Name of the plan :type plan_name: ```str``` :param location: Location, which price is returned (optional) :type location: :class:`.NodeLocation` rtype: ``float`` """ if location is None: return None server_plan_name = 'server_plan_' + plan_name for zone_price in self._zone_prices: if zone_price['name'] == location.id: return zone_price.get(server_plan_name, {}).get('price') return None class _LoginUser(object): def __init__(self, user_id, auth=None): self.user_id = user_id self.auth = auth def to_dict(self): login_user = {'username': self.user_id} if self.auth is not None: login_user['ssh_keys'] = { 'ssh_key': [self.auth.pubkey] } else: login_user['create_password'] = 'yes' return login_user class _StorageDevice(object): def __init__(self, image, size): self.image = image self.size = size def to_dict(self): extra = self.image.extra if extra['type'] == 'template': return self._storage_device_for_template_image() elif extra['type'] == 'cdrom': return self._storage_device_for_cdrom_image() def _storage_device_for_template_image(self): hdd_device = { 'action': 'clone', 'storage': self.image.id } hdd_device.update(self._common_hdd_device()) return {'storage_device': [hdd_device]} def _storage_device_for_cdrom_image(self): hdd_device = {'action': 'create'} hdd_device.update(self._common_hdd_device()) storage_devices = { 'storage_device': [ hdd_device, { 'action': 'attach', 'storage': self.image.id, 'type': 'cdrom' } ] } return storage_devices def _common_hdd_device(self): return { 'title': self.image.name, 'size': self.size.disk, 'tier': self.size.extra.get('storage_tier', 'maxiops') } apache-libcloud-2.8.0/libcloud/common/vultr.py0000664000175000017500000001010113576514553021245 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import Dict from libcloud.common.base import ConnectionKey, JsonResponse __all__ = [ 'API_HOST', 'VultrConnection', 'VultrException', 'VultrResponse', ] # Endpoint for the Vultr API API_HOST = 'api.vultr.com' class VultrResponse(JsonResponse): objects = None error_dict = {} # type: Dict[str, str] errors = None ERROR_CODE_MAP = { 400: "Invalid API location. Check the URL that you are using.", 403: "Invalid or missing API key. Check that your API key is present" + " and matches your assigned key.", 405: "Invalid HTTP method. Check that the method (POST|GET) matches" + " what the documentation indicates.", 412: "Request failed. Check the response body for a more detailed" + " description.", 500: "Internal server error. Try again at a later time.", 503: "Rate limit hit. API requests are limited to an average of 1/s." + " Try your request again later.", } def __init__(self, response, connection): self.errors = [] super(VultrResponse, self).__init__(response=response, connection=connection) self.objects, self.errors = self.parse_body_and_errors() if not self.success(): raise self._make_excp(self.errors[0]) def parse_body_and_errors(self): """ Returns JSON data in a python list. """ json_objects = [] errors = [] if self.status in self.ERROR_CODE_MAP: self.error_dict['ERRORCODE'] = self.status self.error_dict['ERRORMESSAGE'] = self.ERROR_CODE_MAP[self.status] errors.append(self.error_dict) js = super(VultrResponse, self).parse_body() if isinstance(js, dict): js = [js] json_objects.append(js) return (json_objects, errors) def _make_excp(self, error): """ Convert API error to a VultrException instance """ return VultrException(error['ERRORCODE'], error['ERRORMESSAGE']) def success(self): return len(self.errors) == 0 class VultrConnection(ConnectionKey): """ A connection to the Vultr API """ host = API_HOST responseCls = VultrResponse def add_default_params(self, params): """ Returns default params such as api_key which is needed to perform an action.Returns a dictionary. Example:/v1/server/upgrade_plan?api_key=self.key """ params['api_key'] = self.key return params def add_default_headers(self, headers): """ Returns default headers such as content-type. Returns a dictionary. """ headers["Content-Type"] = "application/x-www-form-urlencoded" headers["Accept"] = "text/plain" return headers def set_path(self): self.path = '/v/' return self.path class VultrException(Exception): """ Error originating from the Vultr API """ def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "(%u) %s" % (self.code, self.message) def __repr__(self): return "VultrException code %u '%s'" % (self.code, self.message) apache-libcloud-2.8.0/libcloud/common/worldwidedns.py0000664000175000017500000001611413535474530022603 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re from libcloud.common.base import ConnectionUserAndKey from libcloud.common.base import Response from libcloud.common.types import ProviderError OK_CODES = ['200', '211', '212', '213'] ERROR_CODES = ['401', '403', '405', '406', '407', '408', '409', '410', '411', '412', '413', '414', '450', '451'] class WorldWideDNSException(ProviderError): def __init__(self, value, http_code, code, driver=None): self.code = code super(WorldWideDNSException, self).__init__(value, http_code, driver) class SuspendedAccount(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Login ID you supplied is SUSPENDED, you need to renew" + \ " your account" super(SuspendedAccount, self).__init__(value, http_code, 401, driver) class LoginOrPasswordNotMatch(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Login ID and/or Password you supplied is not on file or" + \ " does not match" super(LoginOrPasswordNotMatch, self).__init__(value, http_code, 403, driver) class NonExistentDomain(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Domain name supplied is not in your account" super(NonExistentDomain, self).__init__(value, http_code, 405, driver) class CouldntRemoveDomain(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Error occured removing domain from name server, try again" super(CouldntRemoveDomain, self).__init__(value, http_code, 406, driver) class LimitExceeded(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Your limit was exceeded, you need to upgrade your account" super(LimitExceeded, self).__init__(value, http_code, 407, driver) class ExistentDomain(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Domain already exists on our servers" super(ExistentDomain, self).__init__(value, http_code, 408, driver) class DomainBanned(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Domain is listed in DNSBL and is banned from our servers" super(DomainBanned, self).__init__(value, http_code, 409, driver) class InvalidDomainName(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Invalid domain name" super(InvalidDomainName, self).__init__(value, http_code, 410, driver) class ErrorOnReloadInNameServer(WorldWideDNSException): def __init__(self, server, http_code, driver=None): if server == 1: value = "Name server #1 kicked an error on reload, contact support" code = 411 elif server == 2: value = "Name server #2 kicked an error on reload, contact support" code = 412 elif server == 3: value = "Name server #3 kicked an error on reload, contact support" code = 413 super(ErrorOnReloadInNameServer, self).__init__(value, http_code, code, driver) class NewUserNotValid(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "New userid is not valid" super(NewUserNotValid, self).__init__(value, http_code, 414, driver) class CouldntReachNameServer(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "Couldn't reach the name server, try again later" super(CouldntReachNameServer, self).__init__(value, http_code, 450, driver) class NoZoneFile(WorldWideDNSException): def __init__(self, http_code, driver=None): value = "No zone file in the name server queried" super(NoZoneFile, self).__init__(value, http_code, 451, driver) ERROR_CODE_TO_EXCEPTION_CLS = { '401': SuspendedAccount, '403': LoginOrPasswordNotMatch, '405': NonExistentDomain, '406': CouldntRemoveDomain, '407': LimitExceeded, '408': ExistentDomain, '409': DomainBanned, '410': InvalidDomainName, '411': ErrorOnReloadInNameServer, '412': ErrorOnReloadInNameServer, '413': ErrorOnReloadInNameServer, '414': NewUserNotValid, '450': CouldntReachNameServer, '451': NoZoneFile, } class WorldWideDNSResponse(Response): def parse_body(self): """ Parse response body. :return: Parsed body. :rtype: ``str`` """ if self._code_response(self.body): codes = re.split('\r?\n', self.body) for code in codes: if code in OK_CODES: continue elif code in ERROR_CODES: exception = ERROR_CODE_TO_EXCEPTION_CLS.get(code) if code in ['411', '412', '413']: server = int(code[2]) raise exception(server, self.status) raise exception(self.status) return self.body def _code_response(self, body): """ Checks if the response body contains code status. :rtype: ``bool`` """ available_response_codes = OK_CODES + ERROR_CODES codes = re.split('\r?\n', body) if codes[0] in available_response_codes: return True return False class WorldWideDNSConnection(ConnectionUserAndKey): host = 'www.worldwidedns.net' responseCls = WorldWideDNSResponse def add_default_params(self, params): """ Add parameters that are necessary for every request This method adds ``NAME`` and ``PASSWORD`` to the request. """ params["NAME"] = self.user_id params["PASSWORD"] = self.key reseller_id = getattr(self, 'reseller_id', None) if reseller_id: params["ID"] = reseller_id return params apache-libcloud-2.8.0/libcloud/common/xmlrpc.py0000664000175000017500000000754313576514553021416 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Base classes for working with xmlrpc APIs """ from typing import Dict from typing import Type from libcloud.utils.py3 import xmlrpclib from libcloud.utils.py3 import httplib from libcloud.common.base import Response, Connection from libcloud.common.types import LibcloudError class ProtocolError(Exception): pass class ErrorCodeMixin(object): """ This is a helper for API's that have a well defined collection of error codes that are easily parsed out of error messages. It acts as a factory: it finds the right exception for the error code, fetches any parameters it needs from the context and raises it. """ exceptions = {} # type: Dict[str, Type[LibcloudError]] def raise_exception_for_error(self, error_code, message): exceptionCls = self.exceptions.get(error_code, None) if exceptionCls is None: return context = self.connection.context driver = self.connection.driver params = {} if hasattr(exceptionCls, 'kwargs'): for key in exceptionCls.kwargs: if key in context: params[key] = context[key] raise exceptionCls(value=message, driver=driver, **params) class XMLRPCResponse(ErrorCodeMixin, Response): defaultExceptionCls = Exception # type: Type[Exception] def success(self): return self.status == httplib.OK def parse_body(self): try: params, methodname = xmlrpclib.loads(self.body) if len(params) == 1: params = params[0] return params except xmlrpclib.Fault as e: self.raise_exception_for_error(e.faultCode, e.faultString) error_string = '%s: %s' % (e.faultCode, e.faultString) raise self.defaultExceptionCls(error_string) def parse_error(self): msg = 'Server returned an invalid xmlrpc response (%d)' % (self.status) raise ProtocolError(msg) class XMLRPCConnection(Connection): """ Connection class which can call XMLRPC based API's. This class uses the xmlrpclib marshalling and demarshalling code but uses the http transports provided by libcloud giving it better certificate validation and debugging helpers than the core client library. """ responseCls = XMLRPCResponse endpoint = None # type: str def add_default_headers(self, headers): headers['Content-Type'] = 'text/xml' return headers def request(self, method_name, *args, **kwargs): """ Call a given `method_name`. :type method_name: ``str`` :param method_name: A method exposed by the xmlrpc endpoint that you are connecting to. :type args: ``tuple`` :param args: Arguments to invoke with method with. """ endpoint = kwargs.get('endpoint', self.endpoint) data = xmlrpclib.dumps(args, methodname=method_name, allow_none=True) return super(XMLRPCConnection, self).request(endpoint, data=data, method='POST') apache-libcloud-2.8.0/libcloud/common/zonomi.py0000664000175000017500000001050613535474530021410 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.base import XmlResponse from libcloud.common.base import ConnectionKey __all__ = [ 'ZonomiException', 'ZonomiResponse', 'ZonomiConnection' ] # Endpoint for Zonomi API. API_HOST = 'zonomi.com' SPECIAL_ERRORS = [ 'Not found.', 'ERROR: This zone is already in your zone list.', 'Record not deleted.' ] class ZonomiException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "ZonomiException %s %s" % (self.code, self.message) class ZonomiResponse(XmlResponse): errors = None objects = None def __init__(self, response, connection): self.errors = [] super(ZonomiResponse, self).__init__(response=response, connection=connection) self.objects, self.errors = self.parse_body_and_errors() if self.errors: raise self._make_excp(self.errors[0]) def parse_body_and_errors(self): error_dict = {} actions = None result_counts = None action_childrens = None data = [] errors = [] xml_body = super(ZonomiResponse, self).parse_body() # pylint: disable=no-member # Error handling if xml_body.text is not None and xml_body.tag == 'error': error_dict['ERRORCODE'] = self.status if xml_body.text.startswith('ERROR: No zone found for'): error_dict['ERRORCODE'] = '404' error_dict['ERRORMESSAGE'] = 'Not found.' else: error_dict['ERRORMESSAGE'] = xml_body.text errors.append(error_dict) # Data handling childrens = list(xml_body) if len(childrens) == 3: result_counts = childrens[1] actions = childrens[2] if actions is not None: actions_childrens = list(actions) action = actions_childrens[0] action_childrens = list(action) if action_childrens is not None: for child in action_childrens: if child.tag == 'zone' or child.tag == 'record': data.append(child.attrib) if result_counts is not None and \ result_counts.attrib.get('deleted') == '1': data.append('DELETED') if result_counts is not None and \ result_counts.attrib.get('deleted') == '0' and \ action.get('action') == 'DELETE': error_dict['ERRORCODE'] = self.status error_dict['ERRORMESSAGE'] = 'Record not deleted.' errors.append(error_dict) return (data, errors) def success(self): return (len(self.errors) == 0) def _make_excp(self, error): """ :param error: contains error code and error message :type error: dict """ return ZonomiException(error['ERRORCODE'], error['ERRORMESSAGE']) class ZonomiConnection(ConnectionKey): host = API_HOST responseCls = ZonomiResponse def add_default_params(self, params): """ Adds default parameters to perform a request, such as api_key. """ params['api_key'] = self.key return params def add_default_headers(self, headers): """ Adds default headers needed to perform a successful request such as Content-Type, User-Agent. """ headers['Content-Type'] = 'text/xml;charset=UTF-8' return headers apache-libcloud-2.8.0/libcloud/compute/0000775000175000017500000000000013600223624017672 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/compute/__init__.py0000664000175000017500000000147413570310635022016 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Module for working with Cloud Servers """ apache-libcloud-2.8.0/libcloud/compute/base.py0000664000175000017500000017133213577507766021216 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Provides base classes for working with drivers """ from __future__ import with_statement from typing import Dict from typing import List from typing import Tuple from typing import Type from typing import Optional from typing import Any from typing import Union from typing import TYPE_CHECKING import time import hashlib import os import re import socket import random import binascii import datetime from libcloud.utils.py3 import b import libcloud.compute.ssh from libcloud.pricing import get_size_price from libcloud.compute.types import NodeState, StorageVolumeState,\ DeploymentError if TYPE_CHECKING: from libcloud.compute.deployment import Deployment from libcloud.compute.types import Provider from libcloud.compute.types import NodeImageMemberState from libcloud.compute.ssh import SSHClient from libcloud.compute.ssh import BaseSSHClient from libcloud.common.base import Connection from libcloud.common.base import ConnectionKey from libcloud.common.base import BaseDriver from libcloud.common.types import LibcloudError from libcloud.compute.ssh import have_paramiko from libcloud.utils.networking import is_private_subnet from libcloud.utils.networking import is_valid_ip_address if have_paramiko: from paramiko.ssh_exception import SSHException from paramiko.ssh_exception import AuthenticationException SSH_TIMEOUT_EXCEPTION_CLASSES = (AuthenticationException, SSHException, IOError, socket.gaierror, socket.error) else: SSH_TIMEOUT_EXCEPTION_CLASSES = (IOError, socket.gaierror, # type: ignore socket.error) # type: ignore T_Auth = Union['NodeAuthSSHKey', 'NodeAuthPassword'] T_Ssh_key = Union[List[str], str] # How long to wait for the node to come online after creating it NODE_ONLINE_WAIT_TIMEOUT = 10 * 60 # How long to try connecting to a remote SSH server when running a deployment # script. SSH_CONNECT_TIMEOUT = 5 * 60 __all__ = [ 'Node', 'NodeState', 'NodeSize', 'NodeImage', 'NodeImageMember', 'NodeLocation', 'NodeAuthSSHKey', 'NodeAuthPassword', 'NodeDriver', 'StorageVolume', 'StorageVolumeState', 'VolumeSnapshot', # Deprecated, moved to libcloud.utils.networking 'is_private_subnet', 'is_valid_ip_address' ] class UuidMixin(object): """ Mixin class for get_uuid function. """ def __init__(self): self._uuid = None # type: str def get_uuid(self): """ Unique hash for a node, node image, or node size The hash is a function of an SHA1 hash of the node, node image, or node size's ID and its driver which means that it should be unique between all objects of its type. In some subclasses (e.g. GoGridNode) there is no ID available so the public IP address is used. This means that, unlike a properly done system UUID, the same UUID may mean a different system install at a different time >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> node = driver.create_node() >>> node.get_uuid() 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f' Note, for example, that this example will always produce the same UUID! :rtype: ``str`` """ if not self._uuid: self._uuid = hashlib.sha1(b('%s:%s' % (self.id, self.driver.type))).hexdigest() return self._uuid @property def uuid(self): # type: () -> str return self.get_uuid() class Node(UuidMixin): """ Provide a common interface for handling nodes of all types. The Node object provides the interface in libcloud through which we can manipulate nodes in different cloud providers in the same way. Node objects don't actually do much directly themselves, instead the node driver handles the connection to the node. You don't normally create a node object yourself; instead you use a driver and then have that create the node for you. >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> node = driver.create_node() >>> node.public_ips[0] '127.0.0.3' >>> node.name 'dummy-3' You can also get nodes from the driver's list_node function. >>> node = driver.list_nodes()[0] >>> node.name 'dummy-1' The node keeps a reference to its own driver which means that we can work on nodes from different providers without having to know which is which. >>> driver = DummyNodeDriver(72) >>> node2 = driver.create_node() >>> node.driver.creds 0 >>> node2.driver.creds 72 Although Node objects can be subclassed, this isn't normally done. Instead, any driver specific information is stored in the "extra" attribute of the node. >>> node.extra {'foo': 'bar'} """ def __init__(self, id, # type: str name, # type: str state, # type: NodeState public_ips, # type: List[str] private_ips, # type: List[str] driver, size=None, # type: NodeSize image=None, # type: NodeImage extra=None, # type: dict created_at=None # type: datetime.datetime ): """ :param id: Node ID. :type id: ``str`` :param name: Node name. :type name: ``str`` :param state: Node state. :type state: :class:`libcloud.compute.types.NodeState` :param public_ips: Public IP addresses associated with this node. :type public_ips: ``list`` :param private_ips: Private IP addresses associated with this node. :type private_ips: ``list`` :param driver: Driver this node belongs to. :type driver: :class:`.NodeDriver` :param size: Size of this node. (optional) :type size: :class:`.NodeSize` :param image: Image of this node. (optional) :type image: :class:`.NodeImage` :param created_at: The datetime this node was created (optional) :type created_at: :class: `datetime.datetime` :param extra: Optional provider specific attributes associated with this node. :type extra: ``dict`` """ self.id = str(id) if id else None self.name = name self.state = state self.public_ips = public_ips if public_ips else [] self.private_ips = private_ips if private_ips else [] self.driver = driver self.size = size self.created_at = created_at self.image = image self.extra = extra or {} UuidMixin.__init__(self) def reboot(self): # type: () -> bool """ Reboot this node :return: ``bool`` This calls the node's driver and reboots the node >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> node = driver.create_node() >>> node.state == NodeState.RUNNING True >>> node.state == NodeState.REBOOTING False >>> node.reboot() True >>> node.state == NodeState.REBOOTING True """ return self.driver.reboot_node(self) def start(self): # type: () -> bool """ Start this node. :return: ``bool`` """ return self.driver.start_node(self) def stop_node(self): # type: () -> bool """ Stop (shutdown) this node. :return: ``bool`` """ return self.driver.stop_node(self) def destroy(self): # type: () -> bool """ Destroy this node :return: ``bool`` This calls the node's driver and destroys the node >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> from libcloud.compute.types import NodeState >>> node = driver.create_node() >>> node.state == NodeState.RUNNING True >>> node.destroy() True >>> node.state == NodeState.RUNNING False """ return self.driver.destroy_node(self) def __repr__(self): state = NodeState.tostring(self.state) return (('') % (self.uuid, self.name, state, self.public_ips, self.private_ips, self.driver.name)) class NodeSize(UuidMixin): """ A Base NodeSize class to derive from. NodeSizes are objects which are typically returned a driver's list_sizes function. They contain a number of different parameters which define how big an image is. The exact parameters available depends on the provider. N.B. Where a parameter is "unlimited" (for example bandwidth in Amazon) this will be given as 0. >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> size = driver.list_sizes()[0] >>> size.ram 128 >>> size.bandwidth 500 >>> size.price 4 """ def __init__(self, id, # type: str name, # type: str ram, # type: int disk, # type: int bandwidth, # type: Optional[int] price, # type: float driver, # type: Type[NodeDriver] extra=None # type: Optional[dict] ): """ :param id: Size ID. :type id: ``str`` :param name: Size name. :type name: ``str`` :param ram: Amount of memory (in MB) provided by this size. :type ram: ``int`` :param disk: Amount of disk storage (in GB) provided by this image. :type disk: ``int`` :param bandwidth: Amount of bandiwdth included with this size. :type bandwidth: ``int`` :param price: Price (in US dollars) of running this node for an hour. :type price: ``float`` :param driver: Driver this size belongs to. :type driver: :class:`.NodeDriver` :param extra: Optional provider specific attributes associated with this size. :type extra: ``dict`` """ self.id = str(id) self.name = name self.ram = ram self.disk = disk self.bandwidth = bandwidth self.price = price self.driver = driver self.extra = extra or {} UuidMixin.__init__(self) def __repr__(self): return (('') % (self.id, self.name, self.ram, self.disk, self.bandwidth, self.price, self.driver.name)) class NodeImage(UuidMixin): """ An operating system image. NodeImage objects are typically returned by the driver for the cloud provider in response to the list_images function >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> image = driver.list_images()[0] >>> image.name 'Ubuntu 9.10' Apart from name and id, there is no further standard information; other parameters are stored in a driver specific "extra" variable When creating a node, a node image should be given as an argument to the create_node function to decide which OS image to use. >>> node = driver.create_node(image=image) """ def __init__(self, id, # type: str name, # type: str driver, # type: Type[NodeDriver] extra=None # type: Optional[dict] ): """ :param id: Image ID. :type id: ``str`` :param name: Image name. :type name: ``str`` :param driver: Driver this image belongs to. :type driver: :class:`.NodeDriver` :param extra: Optional provided specific attributes associated with this image. :type extra: ``dict`` """ self.id = str(id) self.name = name self.driver = driver self.extra = extra or {} UuidMixin.__init__(self) def __repr__(self): return (('') % (self.id, self.name, self.driver.name)) class NodeImageMember(UuidMixin): """ A member of an image. At some cloud providers there is a mechanism to share images. Once an image is shared with another account that user will be a 'member' of the image. For example, see the image members schema in the OpenStack Image Service API v2 documentation. https://developer.openstack.org/ api-ref/image/v2/index.html#image-members-schema NodeImageMember objects are typically returned by the driver for the cloud provider in response to the list_image_members method """ def __init__(self, id, # type: str image_id, # type: str state, # type: NodeImageMemberState driver, # type: Type[NodeDriver] created=None, # type: datetime.datetime extra=None # type: Optional[dict] ): """ :param id: Image member ID. :type id: ``str`` :param id: The associated image ID. :type id: ``str`` :param state: State of the NodeImageMember. If not provided, will default to UNKNOWN. :type state: :class:`.NodeImageMemberState` :param driver: Driver this image belongs to. :type driver: :class:`.NodeDriver` :param created: A datetime object that represents when the image member was created :type created: ``datetime.datetime`` :param extra: Optional provided specific attributes associated with this image. :type extra: ``dict`` """ self.id = str(id) self.image_id = str(image_id) self.state = state self.driver = driver self.created = created self.extra = extra or {} UuidMixin.__init__(self) def __repr__(self): return (('') % (self.id, self.image_id, self.state, self.driver.name)) class NodeLocation(object): """ A physical location where nodes can be. >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> location = driver.list_locations()[0] >>> location.country 'US' """ def __init__(self, id, # type: str name, # type: str country, # type: str driver, # type: Type[NodeDriver] extra=None # type: Optional[dict] ): """ :param id: Location ID. :type id: ``str`` :param name: Location name. :type name: ``str`` :param country: Location country. :type country: ``str`` :param driver: Driver this location belongs to. :type driver: :class:`.NodeDriver` :param extra: Optional provided specific attributes associated with this location. :type extra: ``dict`` """ self.id = str(id) self.name = name self.country = country self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.name, self.country, self.driver.name)) class NodeAuthSSHKey(object): """ An SSH key to be installed for authentication to a node. This is the actual contents of the users ssh public key which will normally be installed as root's public key on the node. >>> pubkey = '...' # read from file >>> from libcloud.compute.base import NodeAuthSSHKey >>> k = NodeAuthSSHKey(pubkey) >>> k """ def __init__(self, pubkey): # type: (str) -> None """ :param pubkey: Public key material. :type pubkey: ``str`` """ self.pubkey = pubkey def __repr__(self): return '' class NodeAuthPassword(object): """ A password to be used for authentication to a node. """ def __init__(self, password, generated=False): # type: (str, bool) -> None """ :param password: Password. :type password: ``str`` :type generated: ``True`` if this password was automatically generated, ``False`` otherwise. """ self.password = password self.generated = generated def __repr__(self): return '' class StorageVolume(UuidMixin): """ A base StorageVolume class to derive from. """ def __init__(self, id, # type: str name, # type: str size, # type: int driver, # type: NodeDriver state=None, # type: Optional[StorageVolumeState] extra=None # type: Optional[Dict] ): # type: (...) -> None """ :param id: Storage volume ID. :type id: ``str`` :param name: Storage volume name. :type name: ``str`` :param size: Size of this volume (in GB). :type size: ``int`` :param driver: Driver this image belongs to. :type driver: :class:`.NodeDriver` :param state: Optional state of the StorageVolume. If not provided, will default to UNKNOWN. :type state: :class:`.StorageVolumeState` :param extra: Optional provider specific attributes. :type extra: ``dict`` """ self.id = id self.name = name self.size = size self.driver = driver self.extra = extra self.state = state UuidMixin.__init__(self) def list_snapshots(self): # type: () -> List[VolumeSnapshot] """ :rtype: ``list`` of ``VolumeSnapshot`` """ return self.driver.list_volume_snapshots(volume=self) def attach(self, node, device=None): # type: (Node, Optional[str]) -> bool """ Attach this volume to a node. :param node: Node to attach volume to :type node: :class:`.Node` :param device: Where the device is exposed, e.g. '/dev/sdb (optional) :type device: ``str`` :return: ``True`` if attach was successful, ``False`` otherwise. :rtype: ``bool`` """ return self.driver.attach_volume(node=node, volume=self, device=device) def detach(self): # type: () -> bool """ Detach this volume from its node :return: ``True`` if detach was successful, ``False`` otherwise. :rtype: ``bool`` """ return self.driver.detach_volume(volume=self) def snapshot(self, name): # type: (str) -> VolumeSnapshot """ Creates a snapshot of this volume. :return: Created snapshot. :rtype: ``VolumeSnapshot`` """ return self.driver.create_volume_snapshot(volume=self, name=name) def destroy(self): # type: () -> bool """ Destroy this storage volume. :return: ``True`` if destroy was successful, ``False`` otherwise. :rtype: ``bool`` """ return self.driver.destroy_volume(volume=self) def __repr__(self): return '' % ( self.id, self.size, self.driver.name) class VolumeSnapshot(object): """ A base VolumeSnapshot class to derive from. """ def __init__(self, id, # type: str driver, # type: NodeDriver size=None, # type: int extra=None, # type: Optional[Dict] created=None, # type: Optional[datetime.datetime] state=None, # type: StorageVolumeState name=None # type: Optional[str] ): # type: (...) -> None """ VolumeSnapshot constructor. :param id: Snapshot ID. :type id: ``str`` :param driver: The driver that represents a connection to the provider :type driver: `NodeDriver` :param size: A snapshot size in GB. :type size: ``int`` :param extra: Provider depends parameters for snapshot. :type extra: ``dict`` :param created: A datetime object that represents when the snapshot was created :type created: ``datetime.datetime`` :param state: A string representing the state the snapshot is in. See `libcloud.compute.types.StorageVolumeState`. :type state: ``StorageVolumeState`` :param name: A string representing the name of the snapshot :type name: ``str`` """ self.id = id self.driver = driver self.size = size self.extra = extra or {} self.created = created self.state = state self.name = name def destroy(self): # type: () -> bool """ Destroys this snapshot. :rtype: ``bool`` """ return self.driver.destroy_volume_snapshot(snapshot=self) def __repr__(self): return ('' % (self.name, self.id, self.size, self.driver.name, self.state)) class KeyPair(object): """ Represents a SSH key pair. """ def __init__(self, name, # type: str public_key, # type: str fingerprint, # type: str driver, # type: NodeDriver private_key=None, # type: Optional[str] extra=None # type: Optional[Dict] ): # type: (...) -> None """ Constructor. :keyword name: Name of the key pair object. :type name: ``str`` :keyword fingerprint: Key fingerprint. :type fingerprint: ``str`` :keyword public_key: Public key in OpenSSH format. :type public_key: ``str`` :keyword private_key: Private key in PEM format. :type private_key: ``str`` :keyword extra: Provider specific attributes associated with this key pair. (optional) :type extra: ``dict`` """ self.name = name self.fingerprint = fingerprint self.public_key = public_key self.private_key = private_key self.driver = driver self.extra = extra or {} def __repr__(self): return ('' % (self.name, self.fingerprint, self.driver.name)) class NodeDriver(BaseDriver): """ A base NodeDriver class to derive from This class is always subclassed by a specific driver. For examples of base behavior of most functions (except deploy node) see the dummy driver. """ connectionCls = ConnectionKey # type: Type[Connection] name = None # type: str api_name = None # type: str website = None # type: str type = None # type: Provider port = None # type: int features = {'create_node': []} # type: Dict[str, List[str]] """ List of available features for a driver. - :meth:`libcloud.compute.base.NodeDriver.create_node` - ssh_key: Supports :class:`.NodeAuthSSHKey` as an authentication method for nodes. - password: Supports :class:`.NodeAuthPassword` as an authentication method for nodes. - generates_password: Returns a password attribute on the Node object returned from creation. """ NODE_STATE_MAP = {} # type: Dict[str, NodeState] def list_nodes(self, *args, **kwargs): # type: (Any, Any) -> List[Node] """ List all nodes. :return: list of node objects :rtype: ``list`` of :class:`.Node` """ raise NotImplementedError( 'list_nodes not implemented for this driver') def list_sizes(self, location=None): # type: (Optional[NodeLocation]) -> List[NodeSize] """ List sizes on a provider :param location: The location at which to list sizes :type location: :class:`.NodeLocation` :return: list of node size objects :rtype: ``list`` of :class:`.NodeSize` """ raise NotImplementedError( 'list_sizes not implemented for this driver') def list_locations(self): # type: () -> List[NodeLocation] """ List data centers for a provider :return: list of node location objects :rtype: ``list`` of :class:`.NodeLocation` """ raise NotImplementedError( 'list_locations not implemented for this driver') def create_node(self, name, # type: str size, # type: NodeSize image, # type: NodeImage location=None, # type: Optional[NodeLocation] auth=None # type: T_Auth ): # type: (...) -> Node """ Create a new node instance. This instance will be started automatically. Not all hosting API's are created equal and to allow libcloud to support as many as possible there are some standard supported variations of ``create_node``. These are declared using a ``features`` API. You can inspect ``driver.features['create_node']`` to see what variation of the API you are dealing with: ``ssh_key`` You can inject a public key into a new node allows key based SSH authentication. ``password`` You can inject a password into a new node for SSH authentication. If no password is provided libcloud will generated a password. The password will be available as ``return_value.extra['password']``. ``generates_password`` The hosting provider will generate a password. It will be returned to you via ``return_value.extra['password']``. Some drivers allow you to set how you will authenticate with the instance that is created. You can inject this initial authentication information via the ``auth`` parameter. If a driver supports the ``ssh_key`` feature flag for ``created_node`` you can upload a public key into the new instance:: >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> auth = NodeAuthSSHKey('pubkey data here') >>> node = driver.create_node("test_node", auth=auth) If a driver supports the ``password`` feature flag for ``create_node`` you can set a password:: >>> driver = DummyNodeDriver(0) >>> auth = NodeAuthPassword('mysecretpassword') >>> node = driver.create_node("test_node", auth=auth) If a driver supports the ``password`` feature and you don't provide the ``auth`` argument libcloud will assign a password:: >>> driver = DummyNodeDriver(0) >>> node = driver.create_node("test_node") >>> password = node.extra['password'] A password will also be returned in this way for drivers that declare the ``generates_password`` feature, though in that case the password is actually provided to the driver API by the hosting provider rather than generated by libcloud. You can only pass a :class:`.NodeAuthPassword` or :class:`.NodeAuthSSHKey` to ``create_node`` via the auth parameter if has the corresponding feature flag. :param name: String with a name for this new node (required) :type name: ``str`` :param size: The size of resources allocated to this node. (required) :type size: :class:`.NodeSize` :param image: OS Image to boot on node. (required) :type image: :class:`.NodeImage` :param location: Which data center to create a node in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param auth: Initial authentication information for the node (optional) :type auth: :class:`.NodeAuthSSHKey` or :class:`NodeAuthPassword` :return: The newly created node. :rtype: :class:`.Node` """ raise NotImplementedError( 'create_node not implemented for this driver') def deploy_node(self, deploy, # type: Deployment ssh_username='root', # type: str ssh_alternate_usernames=None, # type: Optional[List[str]] ssh_port=22, # type: int ssh_timeout=10, # type: int ssh_key=None, # type: Optional[T_Ssh_key] auth=None, # type: T_Auth timeout=SSH_CONNECT_TIMEOUT, # type: int max_tries=3, # type: int ssh_interface='public_ips', # type: str **create_node_kwargs): # type: (...) -> Node """ Create a new node, and start deployment. In order to be able to SSH into a created node access credentials are required. A user can pass either a :class:`.NodeAuthPassword` or :class:`.NodeAuthSSHKey` to the ``auth`` argument. If the ``create_node`` implementation supports that kind if credential (as declared in ``self.features['create_node']``) then it is passed on to ``create_node``. Otherwise it is not passed on to ``create_node`` and it is only used for authentication. If the ``auth`` parameter is not supplied but the driver declares it supports ``generates_password`` then the password returned by ``create_node`` will be used to SSH into the server. Finally, if the ``ssh_key_file`` is supplied that key will be used to SSH into the server. This function may raise a :class:`DeploymentException`, if a create_node call was successful, but there is a later error (like SSH failing or timing out). This exception includes a Node object which you may want to destroy if incomplete deployments are not desirable. >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> from libcloud.compute.deployment import ScriptDeployment >>> from libcloud.compute.deployment import MultiStepDeployment >>> from libcloud.compute.base import NodeAuthSSHKey >>> driver = DummyNodeDriver(0) >>> key = NodeAuthSSHKey('...') # read from file >>> script = ScriptDeployment("yum -y install emacs strace tcpdump") >>> msd = MultiStepDeployment([key, script]) >>> def d(): ... try: ... driver.deploy_node(deploy=msd) ... except NotImplementedError: ... print ("not implemented for dummy driver") >>> d() not implemented for dummy driver Deploy node is typically not overridden in subclasses. The existing implementation should be able to handle most such. :param deploy: Deployment to run once machine is online and available to SSH. :type deploy: :class:`Deployment` :param ssh_username: Optional name of the account which is used when connecting to SSH server (default is root) :type ssh_username: ``str`` :param ssh_alternate_usernames: Optional list of ssh usernames to try to connect with if using the default one fails :type ssh_alternate_usernames: ``list`` :param ssh_port: Optional SSH server port (default is 22) :type ssh_port: ``int`` :param ssh_timeout: Optional SSH connection timeout in seconds (default is 10) :type ssh_timeout: ``float`` :param auth: Initial authentication information for the node (optional) :type auth: :class:`.NodeAuthSSHKey` or :class:`NodeAuthPassword` :param ssh_key: A path (or paths) to an SSH private key with which to attempt to authenticate. (optional) :type ssh_key: ``str`` or ``list`` of ``str`` :param timeout: How many seconds to wait before timing out. (default is 600) :type timeout: ``int`` :param max_tries: How many times to retry if a deployment fails before giving up (default is 3) :type max_tries: ``int`` :param ssh_interface: The interface to wait for. Default is 'public_ips', other option is 'private_ips'. :type ssh_interface: ``str`` """ if not libcloud.compute.ssh.have_paramiko: raise RuntimeError('paramiko is not installed. You can install ' + 'it using pip: pip install paramiko') if auth: if not isinstance(auth, (NodeAuthSSHKey, NodeAuthPassword)): raise NotImplementedError( 'If providing auth, only NodeAuthSSHKey or' 'NodeAuthPassword is supported') elif ssh_key: # If an ssh_key is provided we can try deploy_node pass elif 'create_node' in self.features: f = self.features['create_node'] if 'generates_password' not in f and "password" not in f: raise NotImplementedError( 'deploy_node not implemented for this driver') else: raise NotImplementedError( 'deploy_node not implemented for this driver') # NOTE 1: This is a workaround for legacy code. Sadly a lot of legacy # code uses **kwargs in "create_node()" method and simply ignores # "deploy_node()" arguments which are passed to it. # That's obviously far from idea that's why we first try to pass only # non-deploy node arguments to the "create_node()" methods and if it # that doesn't work, fall back to the old approach and simply pass in # all the arguments # NOTE 2: Some drivers which use password based SSH authentication # rely on password being stored on the "auth" argument and that's why # we also propagate that argument to "create_node()" method. try: # NOTE: We only pass auth to the method if auth argument is # provided if auth: node = self.create_node(auth=auth, **create_node_kwargs) else: node = self.create_node(**create_node_kwargs) except TypeError as e: msg_1_re = (r'create_node\(\) missing \d+ required ' 'positional arguments.*') msg_2_re = r'create_node\(\) takes at least \d+ arguments.*' if re.match(msg_1_re, str(e)) or re.match(msg_2_re, str(e)): # pylint: disable=unexpected-keyword-arg node = self.create_node( # type: ignore deploy=deploy, ssh_username=ssh_username, ssh_alternate_usernames=ssh_alternate_usernames, ssh_port=ssh_port, ssh_timeout=ssh_timeout, ssh_key=ssh_key, auth=auth, timeout=timeout, max_tries=max_tries, ssh_interface=ssh_interface, **create_node_kwargs) # pylint: enable=unexpected-keyword-arg else: raise e password = None if auth: if isinstance(auth, NodeAuthPassword): password = auth.password elif 'password' in node.extra: password = node.extra['password'] wait_timeout = timeout or NODE_ONLINE_WAIT_TIMEOUT # Wait until node is up and running and has IP assigned try: node, ip_addresses = self.wait_until_running( nodes=[node], wait_period=3, timeout=wait_timeout, ssh_interface=ssh_interface)[0] except Exception as e: raise DeploymentError(node=node, original_exception=e, driver=self) ssh_alternate_usernames = ssh_alternate_usernames or [] deploy_timeout = timeout or SSH_CONNECT_TIMEOUT deploy_error = None for username in ([ssh_username] + ssh_alternate_usernames): try: self._connect_and_run_deployment_script( task=deploy, node=node, ssh_hostname=ip_addresses[0], ssh_port=ssh_port, ssh_username=username, ssh_password=password, ssh_key_file=ssh_key, ssh_timeout=ssh_timeout, timeout=deploy_timeout, max_tries=max_tries) except Exception as e: # Try alternate username # Todo: Need to fix paramiko so we can catch a more specific # exception deploy_error = e else: # Script successfully executed, don't try alternate username deploy_error = None break if deploy_error is not None: raise DeploymentError(node=node, original_exception=deploy_error, driver=self) return node def reboot_node(self, node): # type: (Node) -> bool """ Reboot a node. :param node: The node to be rebooted :type node: :class:`.Node` :return: True if the reboot was successful, otherwise False :rtype: ``bool`` """ raise NotImplementedError( 'reboot_node not implemented for this driver') def start_node(self, node): # type: (Node) -> bool """ Start a node. :param node: The node to be started :type node: :class:`.Node` :return: True if the start was successful, otherwise False :rtype: ``bool`` """ raise NotImplementedError( 'start_node not implemented for this driver') def stop_node(self, node): # type: (Node) -> bool """ Stop a node :param node: The node to be stopped. :type node: :class:`.Node` :return: True if the stop was successful, otherwise False :rtype: ``bool`` """ raise NotImplementedError( 'stop_node not implemented for this driver') def destroy_node(self, node): # type: (Node) -> bool """ Destroy a node. Depending upon the provider, this may destroy all data associated with the node, including backups. :param node: The node to be destroyed :type node: :class:`.Node` :return: True if the destroy was successful, False otherwise. :rtype: ``bool`` """ raise NotImplementedError( 'destroy_node not implemented for this driver') ## # Volume and snapshot management methods ## def list_volumes(self): # type: () -> List[StorageVolume] """ List storage volumes. :rtype: ``list`` of :class:`.StorageVolume` """ raise NotImplementedError( 'list_volumes not implemented for this driver') def list_volume_snapshots(self, volume): # type: (StorageVolume) -> List[VolumeSnapshot] """ List snapshots for a storage volume. :rtype: ``list`` of :class:`VolumeSnapshot` """ raise NotImplementedError( 'list_volume_snapshots not implemented for this driver') def create_volume(self, size, # type: int name, # type: str location=None, # Optional[NodeLocation] snapshot=None # Optional[VolumeSnapshot] ): # type: (...) -> StorageVolume """ Create a new volume. :param size: Size of volume in gigabytes (required) :type size: ``int`` :param name: Name of the volume to be created :type name: ``str`` :param location: Which data center to create a volume in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param snapshot: Snapshot from which to create the new volume. (optional) :type snapshot: :class:`.VolumeSnapshot` :return: The newly created volume. :rtype: :class:`StorageVolume` """ raise NotImplementedError( 'create_volume not implemented for this driver') def create_volume_snapshot(self, volume, name=None): # type: (StorageVolume, Optional[str]) -> VolumeSnapshot """ Creates a snapshot of the storage volume. :param volume: The StorageVolume to create a VolumeSnapshot from :type volume: :class:`.StorageVolume` :param name: Name of created snapshot (optional) :type name: `str` :rtype: :class:`VolumeSnapshot` """ raise NotImplementedError( 'create_volume_snapshot not implemented for this driver') def attach_volume(self, node, volume, device=None): # type: (Node, StorageVolume, Optional[str]) -> bool """ Attaches volume to node. :param node: Node to attach volume to. :type node: :class:`.Node` :param volume: Volume to attach. :type volume: :class:`.StorageVolume` :param device: Where the device is exposed, e.g. '/dev/sdb' :type device: ``str`` :rytpe: ``bool`` """ raise NotImplementedError('attach not implemented for this driver') def detach_volume(self, volume): # type: (StorageVolume) -> bool """ Detaches a volume from a node. :param volume: Volume to be detached :type volume: :class:`.StorageVolume` :rtype: ``bool`` """ raise NotImplementedError('detach not implemented for this driver') def destroy_volume(self, volume): # type: (StorageVolume) -> bool """ Destroys a storage volume. :param volume: Volume to be destroyed :type volume: :class:`StorageVolume` :rtype: ``bool`` """ raise NotImplementedError( 'destroy_volume not implemented for this driver') def destroy_volume_snapshot(self, snapshot): # type: (VolumeSnapshot) -> bool """ Destroys a snapshot. :param snapshot: The snapshot to delete :type snapshot: :class:`VolumeSnapshot` :rtype: :class:`bool` """ raise NotImplementedError( 'destroy_volume_snapshot not implemented for this driver') ## # Image management methods ## def list_images(self, location=None): # type: (Optional[NodeLocation]) -> List[NodeImage] """ List images on a provider. :param location: The location at which to list images. :type location: :class:`.NodeLocation` :return: list of node image objects. :rtype: ``list`` of :class:`.NodeImage` """ raise NotImplementedError( 'list_images not implemented for this driver') def create_image(self, node, name, description=None): # type: (Node, str, Optional[str]) -> List[NodeImage] """ Creates an image from a node object. :param node: Node to run the task on. :type node: :class:`.Node` :param name: name for new image. :type name: ``str`` :param description: description for new image. :type name: ``description`` :rtype: :class:`.NodeImage`: :return: NodeImage instance on success. """ raise NotImplementedError( 'create_image not implemented for this driver') def delete_image(self, node_image): # type: (NodeImage) -> bool """ Deletes a node image from a provider. :param node_image: Node image object. :type node_image: :class:`.NodeImage` :return: ``True`` if delete_image was successful, ``False`` otherwise. :rtype: ``bool`` """ raise NotImplementedError( 'delete_image not implemented for this driver') def get_image(self, image_id): # type: (str) -> NodeImage """ Returns a single node image from a provider. :param image_id: Node to run the task on. :type image_id: ``str`` :rtype :class:`.NodeImage`: :return: NodeImage instance on success. """ raise NotImplementedError( 'get_image not implemented for this driver') def copy_image(self, source_region, node_image, name, description=None): # type: (str, NodeImage, str, Optional[str]) -> NodeImage """ Copies an image from a source region to the current region. :param source_region: Region to copy the node from. :type source_region: ``str`` :param node_image: NodeImage to copy. :type node_image: :class:`.NodeImage`: :param name: name for new image. :type name: ``str`` :param description: description for new image. :type name: ``str`` :rtype: :class:`.NodeImage`: :return: NodeImage instance on success. """ raise NotImplementedError( 'copy_image not implemented for this driver') ## # SSH key pair management methods ## def list_key_pairs(self): # type: () -> List[KeyPair] """ List all the available key pair objects. :rtype: ``list`` of :class:`.KeyPair` objects """ raise NotImplementedError( 'list_key_pairs not implemented for this driver') def get_key_pair(self, name): # type: (str) -> KeyPair """ Retrieve a single key pair. :param name: Name of the key pair to retrieve. :type name: ``str`` :rtype: :class:`.KeyPair` """ raise NotImplementedError( 'get_key_pair not implemented for this driver') def create_key_pair(self, name): # type: (str) -> KeyPair """ Create a new key pair object. :param name: Key pair name. :type name: ``str`` :rtype: :class:`.KeyPair` object """ raise NotImplementedError( 'create_key_pair not implemented for this driver') def import_key_pair_from_string(self, name, key_material): # type: (str, str) -> KeyPair """ Import a new public key from string. :param name: Key pair name. :type name: ``str`` :param key_material: Public key material. :type key_material: ``str`` :rtype: :class:`.KeyPair` object """ raise NotImplementedError( 'import_key_pair_from_string not implemented for this driver') def import_key_pair_from_file(self, name, key_file_path): # type: (str, str) -> KeyPair """ Import a new public key from string. :param name: Key pair name. :type name: ``str`` :param key_file_path: Path to the public key file. :type key_file_path: ``str`` :rtype: :class:`.KeyPair` object """ key_file_path = os.path.expanduser(key_file_path) with open(key_file_path, 'r') as fp: key_material = fp.read().strip() return self.import_key_pair_from_string(name=name, key_material=key_material) def delete_key_pair(self, key_pair): # type: (KeyPair) -> bool """ Delete an existing key pair. :param key_pair: Key pair object. :type key_pair: :class:`.KeyPair` :rtype: ``bool`` """ raise NotImplementedError( 'delete_key_pair not implemented for this driver') def wait_until_running(self, nodes, # type: List[Node] wait_period=3, # type: float timeout=600, # type: int ssh_interface='public_ips', # type: str force_ipv4=True, # type: bool ex_list_nodes_kwargs=None # type: Optional[Dict] ): # type: (...) -> List[Tuple[Node, List[str]]] """ Block until the provided nodes are considered running. Node is considered running when it's state is "running" and when it has at least one IP address assigned. :param nodes: List of nodes to wait for. :type nodes: ``list`` of :class:`.Node` :param wait_period: How many seconds to wait between each loop iteration. (default is 3) :type wait_period: ``int`` :param timeout: How many seconds to wait before giving up. (default is 600) :type timeout: ``int`` :param ssh_interface: Which attribute on the node to use to obtain an IP address. Valid options: public_ips, private_ips. Default is public_ips. :type ssh_interface: ``str`` :param force_ipv4: Ignore IPv6 addresses (default is True). :type force_ipv4: ``bool`` :param ex_list_nodes_kwargs: Optional driver-specific keyword arguments which are passed to the ``list_nodes`` method. :type ex_list_nodes_kwargs: ``dict`` :return: ``[(Node, ip_addresses)]`` list of tuple of Node instance and list of ip_address on success. :rtype: ``list`` of ``tuple`` """ ex_list_nodes_kwargs = ex_list_nodes_kwargs or {} def is_supported(address): # type: (str) -> bool """ Return True for supported address. """ if force_ipv4 and not is_valid_ip_address(address=address, family=socket.AF_INET): return False return True def filter_addresses(addresses): # type: (List[str]) -> List[str] """ Return list of supported addresses. """ return [address for address in addresses if is_supported(address)] if ssh_interface not in ['public_ips', 'private_ips']: raise ValueError('ssh_interface argument must either be ' + 'public_ips or private_ips') start = time.time() end = start + timeout uuids = set([node.uuid for node in nodes]) while time.time() < end: all_nodes = self.list_nodes(**ex_list_nodes_kwargs) matching_nodes = list([node for node in all_nodes if node.uuid in uuids]) if len(matching_nodes) > len(uuids): found_uuids = [node.uuid for node in matching_nodes] msg = ('Unable to match specified uuids ' + '(%s) with existing nodes. Found ' % (uuids) + 'multiple nodes with same uuid: (%s)' % (found_uuids)) raise LibcloudError(value=msg, driver=self) running_nodes = [node for node in matching_nodes if node.state == NodeState.RUNNING] addresses = [] for node in running_nodes: node_addresses = filter_addresses(getattr(node, ssh_interface)) if len(node_addresses) >= 1: addresses.append(node_addresses) if len(running_nodes) == len(uuids) == len(addresses): return list(zip(running_nodes, addresses)) else: time.sleep(wait_period) continue raise LibcloudError(value='Timed out after %s seconds' % (timeout), driver=self) def _get_and_check_auth(self, auth): # type: (T_Auth) -> T_Auth """ Helper function for providers supporting :class:`.NodeAuthPassword` or :class:`.NodeAuthSSHKey` Validates that only a supported object type is passed to the auth parameter and raises an exception if it is not. If no :class:`.NodeAuthPassword` object is provided but one is expected then a password is automatically generated. """ if isinstance(auth, NodeAuthPassword): if 'password' in self.features['create_node']: return auth raise LibcloudError( 'Password provided as authentication information, but password' 'not supported', driver=self) if isinstance(auth, NodeAuthSSHKey): if 'ssh_key' in self.features['create_node']: return auth raise LibcloudError( 'SSH Key provided as authentication information, but SSH Key' 'not supported', driver=self) if 'password' in self.features['create_node']: value = os.urandom(16) value = binascii.hexlify(value).decode('ascii') # Some providers require password to also include uppercase # characters so convert some characters to uppercase password = '' for char in value: if not char.isdigit() and char.islower(): if random.randint(0, 1) == 1: char = char.upper() password += char return NodeAuthPassword(password, generated=True) if auth: raise LibcloudError( '"auth" argument provided, but it was not a NodeAuthPassword' 'or NodeAuthSSHKey object', driver=self) def _wait_until_running(self, node, wait_period=3, timeout=600, ssh_interface='public_ips', force_ipv4=True): # type: (Node, float, int, str, bool) -> List[Tuple[Node, List[str]]] # This is here for backward compatibility and will be removed in the # next major release return self.wait_until_running(nodes=[node], wait_period=wait_period, timeout=timeout, ssh_interface=ssh_interface, force_ipv4=force_ipv4) def _ssh_client_connect(self, ssh_client, wait_period=1.5, timeout=300): # type: (BaseSSHClient, float, int) -> BaseSSHClient """ Try to connect to the remote SSH server. If a connection times out or is refused it is retried up to timeout number of seconds. :param ssh_client: A configured SSHClient instance :type ssh_client: ``SSHClient`` :param wait_period: How many seconds to wait between each loop iteration. (default is 1.5) :type wait_period: ``int`` :param timeout: How many seconds to wait before giving up. (default is 300) :type timeout: ``int`` :return: ``SSHClient`` on success """ start = time.time() end = start + timeout while time.time() < end: try: ssh_client.connect() except SSH_TIMEOUT_EXCEPTION_CLASSES as e: # Errors which represent fatal invalid key files which should # be propagated to the user message = str(e).lower() invalid_key_msgs = [ 'no such file or directory', 'invalid key', 'not a valid ', ] # Propagate (key) file doesn't exist errors # NOTE: Paramiko only supports PEM private key format # See https://github.com/paramiko/paramiko/issues/1313 # for details for invalid_key_msg in invalid_key_msgs: if invalid_key_msg in message: raise e # Retry if a connection is refused, timeout occurred, # or the connection fails due to failed authentication. ssh_client.close() time.sleep(wait_period) continue else: return ssh_client raise LibcloudError(value='Could not connect to the remote SSH ' + 'server. Giving up.', driver=self) def _connect_and_run_deployment_script( self, task, # type: Deployment node, # type: Node ssh_hostname, # type: str ssh_port, # type: int ssh_username, # type: str ssh_password, # type: Optional[str] ssh_key_file, # type:Optional[T_Ssh_key] ssh_timeout, # type: int timeout, # type: int max_tries # type: int ): """ Establish an SSH connection to the node and run the provided deployment task. :rtype: :class:`.Node`: :return: Node instance on success. """ ssh_client = SSHClient(hostname=ssh_hostname, port=ssh_port, username=ssh_username, password=ssh_password, key_files=ssh_key_file, timeout=ssh_timeout) ssh_client = self._ssh_client_connect(ssh_client=ssh_client, timeout=timeout) # Execute the deployment task node = self._run_deployment_script(task=task, node=node, ssh_client=ssh_client, max_tries=max_tries) return node def _run_deployment_script(self, task, node, ssh_client, max_tries=3): # type: (Deployment, Node, BaseSSHClient, int) -> Node """ Run the deployment script on the provided node. At this point it is assumed that SSH connection has already been established. :param task: Deployment task to run. :type task: :class:`Deployment` :param node: Node to run the task on. :type node: ``Node`` :param ssh_client: A configured and connected SSHClient instance. :type ssh_client: :class:`SSHClient` :param max_tries: How many times to retry if a deployment fails before giving up. (default is 3) :type max_tries: ``int`` :rtype: :class:`.Node` :return: ``Node`` Node instance on success. """ tries = 0 while tries < max_tries: try: node = task.run(node, ssh_client) except Exception as e: tries += 1 if tries >= max_tries: raise LibcloudError(value='Failed after %d tries: %s' % (max_tries, str(e)), driver=self) else: # Deployment succeeded ssh_client.close() return node return node def _get_size_price(self, size_id): # type: (str) -> float """ Return pricing information for the provided size id. """ return get_size_price(driver_type='compute', driver_name=self.api_name, size_id=size_id) if __name__ == '__main__': import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/compute/constants.py0000664000175000017500000132606413600217207022274 0ustar kamikami00000000000000# File generated by script - DO NOT EDIT manually # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. INSTANCE_TYPES = { "a1.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "a1.2xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "AWS Graviton Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "a1.2xlarge", "name": "a1.2xlarge", "ram": 16384 }, "a1.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "a1.4xlarge", "instancesku": "JQK5AH3Y44CQ57AA", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "AWS Graviton Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "a1.4xlarge", "name": "a1.4xlarge", "ram": 32768 }, "a1.large": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "a1.large", "instancesku": "FV7PUC9Y973899CS", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "4 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "AWS Graviton Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "a1.large", "name": "a1.large", "ram": 4096 }, "a1.medium": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "a1.medium", "instancesku": "Q494P4JCZC9KDPCA", "memory": "2 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "2", "physicalProcessor": "AWS Graviton Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "1" }, "id": "a1.medium", "name": "a1.medium", "ram": 2048 }, "a1.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "a1.xlarge", "instancesku": "943GQ4TSWGS354CV", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "AWS Graviton Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "a1.xlarge", "name": "a1.xlarge", "ram": 8192 }, "c1.medium": { "bandwidth": None, "disk": 350, "extra": { "currentGeneration": "No", "ecu": "5", "enhancedNetworkingSupported": "No", "instanceFamily": "Compute optimized", "instanceType": "c1.medium", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "1.7 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "2", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "32-bit or 64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 350 SSD", "vcpu": "2" }, "id": "c1.medium", "name": "c1.medium", "ram": 1740 }, "c1.xlarge": { "bandwidth": None, "disk": 1680, "extra": { "currentGeneration": "No", "ecu": "20", "enhancedNetworkingSupported": "No", "instanceFamily": "Compute optimized", "instanceType": "c1.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "7 GiB", "networkPerformance": "High", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 420 SSD", "vcpu": "8" }, "id": "c1.xlarge", "name": "c1.xlarge", "ram": 7168 }, "c3.2xlarge": { "bandwidth": None, "disk": 160, "extra": { "clockSpeed": "2.8 GHz", "currentGeneration": "No", "ecu": "28", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c3.2xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "15 GiB", "networkPerformance": "High", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2680 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 80 SSD", "vcpu": "8" }, "id": "c3.2xlarge", "name": "c3.2xlarge", "ram": 15360 }, "c3.4xlarge": { "bandwidth": None, "disk": 320, "extra": { "clockSpeed": "2.8 GHz", "currentGeneration": "No", "ecu": "55", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c3.4xlarge", "instancesku": "BPC44EBCFMK4UP3U", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30 GiB", "networkPerformance": "High", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2680 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 160 SSD", "vcpu": "16" }, "id": "c3.4xlarge", "name": "c3.4xlarge", "ram": 30720 }, "c3.8xlarge": { "bandwidth": 10, "disk": 640, "extra": { "clockSpeed": "2.8 GHz", "currentGeneration": "No", "ecu": "108", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c3.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "60 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2680 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 320 SSD", "vcpu": "36" }, "id": "c3.8xlarge", "name": "c3.8xlarge", "ram": 61440 }, "c3.large": { "bandwidth": None, "disk": 32, "extra": { "clockSpeed": "2.8 GHz", "currentGeneration": "No", "ecu": "7", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c3.large", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "3.75 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon E5-2680 v2 (Ivy Bridge)", "processorArchitecture": "32-bit or 64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 16 SSD", "vcpu": "2" }, "id": "c3.large", "name": "c3.large", "ram": 3840 }, "c3.xlarge": { "bandwidth": None, "disk": 80, "extra": { "clockSpeed": "2.8 GHz", "currentGeneration": "No", "ecu": "14", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c3.xlarge", "instancesku": "37H9CQX49KK8KQ2D", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "7.5 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2680 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 40 SSD", "vcpu": "4" }, "id": "c3.xlarge", "name": "c3.xlarge", "ram": 7680 }, "c4.2xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.9 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1000 Mbps", "ecu": "31", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c4.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "15 GiB", "networkPerformance": "High", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2666 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "c4.2xlarge", "name": "c4.2xlarge", "ram": 15360 }, "c4.4xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.9 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2000 Mbps", "ecu": "62", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c4.4xlarge", "instancesku": "DKZ8SVQYPP9QWN2F", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30 GiB", "networkPerformance": "High", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2666 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "c4.4xlarge", "name": "c4.4xlarge", "ram": 30720 }, "c4.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.9 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "4000 Mbps", "ecu": "132", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c4.8xlarge", "instancesku": "AKHXNUBZUVXUQVS4", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "60 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2666 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "36" }, "id": "c4.8xlarge", "name": "c4.8xlarge", "ram": 61440 }, "c4.large": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.9 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "500 Mbps", "ecu": "8", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c4.large", "instancesku": "NJYJAMFEMWY3BC2Y", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "3.75 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon E5-2666 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "c4.large", "name": "c4.large", "ram": 3840 }, "c4.xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.9 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "750 Mbps", "ecu": "16", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c4.xlarge", "instancesku": "KT5H34MYNAZWD4VM", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "7.5 GiB", "networkPerformance": "High", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2666 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "c4.xlarge", "name": "c4.xlarge", "ram": 7680 }, "c5.12xlarge": { "bandwidth": 12, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "188", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.12xlarge", "instancesku": "G88BQ9JNT44CJU5A", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "96 GiB", "networkPerformance": "12 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8275L", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Deep Learning Boost; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "c5.12xlarge", "name": "c5.12xlarge", "ram": 98304 }, "c5.18xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "9000 Mbps", "ecu": "281", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.18xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "144 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "144", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "72" }, "id": "c5.18xlarge", "name": "c5.18xlarge", "ram": 147456 }, "c5.24xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "375", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.24xlarge", "instancesku": "DFU3RR7RPDU5NHP6", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8275L", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Deep Learning Boost; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "c5.24xlarge", "name": "c5.24xlarge", "ram": 196608 }, "c5.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "39", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.2xlarge", "instancesku": "DFH4W5NFFA5EGBVU", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "c5.2xlarge", "name": "c5.2xlarge", "ram": 16384 }, "c5.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "73", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.4xlarge", "instancesku": "ZJCH42UY78N76ZSX", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "c5.4xlarge", "name": "c5.4xlarge", "ram": 32768 }, "c5.9xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "4500 Mbps", "ecu": "139", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.9xlarge", "instancesku": "8UXUVRFUWYET2CA4", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "72 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "72", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "36" }, "id": "c5.9xlarge", "name": "c5.9xlarge", "ram": 73728 }, "c5.large": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "10", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.large", "instancesku": "ZGCJFX4FNDKBY4B4", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "4 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "c5.large", "name": "c5.large", "ram": 4096 }, "c5.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "20", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5.xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "c5.xlarge", "name": "c5.xlarge", "ram": 8192 }, "c5d.12xlarge": { "bandwidth": 12, "disk": 1800, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "188", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.12xlarge", "instancesku": "65HKXNPPQZVPW4JB", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "96 GiB", "networkPerformance": "12 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8275L", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Deep Learning Boost; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "48" }, "id": "c5d.12xlarge", "name": "c5d.12xlarge", "ram": 98304 }, "c5d.18xlarge": { "bandwidth": 25, "disk": 1800, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "9000 Mbps", "ecu": "281", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.18xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "144 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "144", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "72" }, "id": "c5d.18xlarge", "name": "c5d.18xlarge", "ram": 147456 }, "c5d.24xlarge": { "bandwidth": 25, "disk": 3600, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "375", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.24xlarge", "instancesku": "PC4G8JDRGDDX5R8B", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8275L", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Deep Learning Boost; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 900 NVMe SSD", "vcpu": "96" }, "id": "c5d.24xlarge", "name": "c5d.24xlarge", "ram": 196608 }, "c5d.2xlarge": { "bandwidth": 10, "disk": 200, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "39", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 200 NVMe SSD", "vcpu": "8" }, "id": "c5d.2xlarge", "name": "c5d.2xlarge", "ram": 16384 }, "c5d.4xlarge": { "bandwidth": 10, "disk": 400, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "73", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.4xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 400 NVMe SSD", "vcpu": "16" }, "id": "c5d.4xlarge", "name": "c5d.4xlarge", "ram": 32768 }, "c5d.9xlarge": { "bandwidth": 10, "disk": 900, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "4500 Mbps", "ecu": "139", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.9xlarge", "instancesku": "6PPHHXHGC4KS4FD2", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "72 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "72", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 900 NVMe SSD", "vcpu": "36" }, "id": "c5d.9xlarge", "name": "c5d.9xlarge", "ram": 73728 }, "c5d.large": { "bandwidth": 10, "disk": 50, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "10", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.large", "instancesku": "DZ66HJ5ZUN3XZX8X", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "4 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 50 NVMe SSD", "vcpu": "2" }, "id": "c5d.large", "name": "c5d.large", "ram": 4096 }, "c5d.xlarge": { "bandwidth": 10, "disk": 100, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2250 Mbps", "ecu": "20", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5d.xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 100 NVMe SSD", "vcpu": "4" }, "id": "c5d.xlarge", "name": "c5d.xlarge", "ram": 8192 }, "c5n.18xlarge": { "bandwidth": 100, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "281", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5n.18xlarge", "instancesku": "GP9J882PRJR3HFWT", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "144", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "72" }, "id": "c5n.18xlarge", "name": "c5n.18xlarge", "ram": 196608 }, "c5n.2xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "39", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5n.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "21 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "c5n.2xlarge", "name": "c5n.2xlarge", "ram": 21504 }, "c5n.4xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "73", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5n.4xlarge", "instancesku": "RXTSEWTUD8EWJENN", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "42 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "c5n.4xlarge", "name": "c5n.4xlarge", "ram": 43008 }, "c5n.9xlarge": { "bandwidth": 50, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "139", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5n.9xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "96 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "72", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "36" }, "id": "c5n.9xlarge", "name": "c5n.9xlarge", "ram": 98304 }, "c5n.large": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "10", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5n.large", "instancesku": "RGPG564XSTMQEEGT", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "5.25 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "c5n.large", "name": "c5n.large", "ram": 5376 }, "c5n.xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "3.0 Ghz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "20", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Compute optimized", "instanceType": "c5n.xlarge", "instancesku": "XPUQY5QHXK4NZNKG", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "10.5 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8124M", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "c5n.xlarge", "name": "c5n.xlarge", "ram": 10752 }, "cc2.8xlarge": { "bandwidth": 10, "disk": 3360, "extra": { "clockSpeed": "2.6 GHz", "currentGeneration": "No", "ecu": "88", "instanceFamily": "Compute optimized", "instanceType": "cc2.8xlarge", "memory": "60.5 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2670", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 840", "vcpu": "32" }, "id": "cc2.8xlarge", "name": "cc2.8xlarge", "ram": 61952 }, "cr1.8xlarge": { "bandwidth": 10, "disk": 240, "extra": { "currentGeneration": "No", "ecu": "88", "instanceFamily": "Memory optimized", "instanceType": "cr1.8xlarge", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2670", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 120 SSD", "vcpu": "32" }, "id": "cr1.8xlarge", "name": "cr1.8xlarge", "ram": 249856 }, "d2.2xlarge": { "bandwidth": None, "disk": 12000, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1000 Mbps", "ecu": "28", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "d2.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "61 GiB", "networkPerformance": "High", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "6 x 2000 HDD", "vcpu": "8" }, "id": "d2.2xlarge", "name": "d2.2xlarge", "ram": 62464 }, "d2.4xlarge": { "bandwidth": None, "disk": 24000, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2000 Mbps", "ecu": "56", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "d2.4xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "122 GiB", "networkPerformance": "High", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "12 x 2000 HDD", "vcpu": "16" }, "id": "d2.4xlarge", "name": "d2.4xlarge", "ram": 124928 }, "d2.8xlarge": { "bandwidth": 10, "disk": 48000, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "4000 Mbps", "ecu": "116", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "d2.8xlarge", "instancesku": "XP5P8NMSB2W7KP3U", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "24 x 2000 HDD", "vcpu": "36" }, "id": "d2.8xlarge", "name": "d2.8xlarge", "ram": 249856 }, "d2.xlarge": { "bandwidth": None, "disk": 6000, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "750 Mbps", "ecu": "14", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "d2.xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30.5 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "3 x 2000 HDD", "vcpu": "4" }, "id": "d2.xlarge", "name": "d2.xlarge", "ram": 31232 }, "f1.16xlarge": { "bandwidth": 20, "disk": 3760, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "201", "enhancedNetworkingSupported": "Yes", "instanceFamily": "FPGA Instances", "instanceType": "f1.16xlarge", "instancesku": "P4PZ87XYY47FTQT9", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "976 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 940 NVMe SSD", "vcpu": "64" }, "id": "f1.16xlarge", "name": "f1.16xlarge", "ram": 999424 }, "f1.2xlarge": { "bandwidth": 10, "disk": 470, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1700 Mbps", "ecu": "31", "enhancedNetworkingSupported": "Yes", "instanceFamily": "FPGA Instances", "instanceType": "f1.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "122 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 470 NVMe SSD", "vcpu": "8" }, "id": "f1.2xlarge", "name": "f1.2xlarge", "ram": 124928 }, "f1.4xlarge": { "bandwidth": 10, "disk": 940, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "58", "enhancedNetworkingSupported": "Yes", "instanceFamily": "FPGA Instances", "instanceType": "f1.4xlarge", "instancesku": "3294757KFZTHDXMC", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 940 NVMe SSD", "vcpu": "16" }, "id": "f1.4xlarge", "name": "f1.4xlarge", "ram": 249856 }, "g2.2xlarge": { "bandwidth": None, "disk": 60, "extra": { "clockSpeed": "2.6 GHz", "currentGeneration": "No", "ecu": "26", "enhancedNetworkingSupported": "No", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g2.2xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "15 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2670 (Sandy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 60 SSD", "vcpu": "8" }, "id": "g2.2xlarge", "name": "g2.2xlarge", "ram": 15360 }, "g2.8xlarge": { "bandwidth": None, "disk": 240, "extra": { "clockSpeed": "2.6 GHz", "currentGeneration": "No", "ecu": "104", "enhancedNetworkingSupported": "No", "gpu": "4", "instanceFamily": "GPU instance", "instanceType": "g2.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "60 GiB", "networkPerformance": "High", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2670 (Sandy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 120 SSD", "vcpu": "32" }, "id": "g2.8xlarge", "name": "g2.8xlarge", "ram": 61440 }, "g3.16xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "201", "enhancedNetworkingSupported": "Yes", "gpu": "4", "instanceFamily": "GPU instance", "instanceType": "g3.16xlarge", "instancesku": "9JX6W8YKTGAXCFNB", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "488 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "g3.16xlarge", "name": "g3.16xlarge", "ram": 499712 }, "g3.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "58", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g3.4xlarge", "instancesku": "XQVRFGT3HCZ63BJ5", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "122 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "g3.4xlarge", "name": "g3.4xlarge", "ram": 124928 }, "g3.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "97", "enhancedNetworkingSupported": "Yes", "gpu": "2", "instanceFamily": "GPU instance", "instanceType": "g3.8xlarge", "instancesku": "8DQCJ3V7VZPTQK24", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "g3.8xlarge", "name": "g3.8xlarge", "ram": 249856 }, "g3s.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "100 Mbps", "ecu": "13", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g3s.xlarge", "instancesku": "CH4D8VQYKHAT566Q", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "30.5 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "g3s.xlarge", "name": "g3s.xlarge", "ram": 31232 }, "g4dn.12xlarge": { "bandwidth": 50, "disk": 900, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "gpu": "4", "instanceFamily": "GPU instance", "instanceType": "g4dn.12xlarge", "instancesku": "KYG4GJZXW67JH275", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "900 GB NVMe SSD", "vcpu": "48" }, "id": "g4dn.12xlarge", "name": "g4dn.12xlarge", "ram": 196608 }, "g4dn.16xlarge": { "bandwidth": 50, "disk": 900, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g4dn.16xlarge", "instancesku": "EV7U94XE5G2K8RWP", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "256 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "900 GB NVMe SSD", "vcpu": "64" }, "id": "g4dn.16xlarge", "name": "g4dn.16xlarge", "ram": 262144 }, "g4dn.2xlarge": { "bandwidth": 25, "disk": 225, "extra": { "currentGeneration": "Yes", "ecu": "NA", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g4dn.2xlarge", "instancesku": "3W5TQY9NMW3Z6HKV", "memory": "32 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "225 GB NVMe SSD", "vcpu": "8" }, "id": "g4dn.2xlarge", "name": "g4dn.2xlarge", "ram": 32768 }, "g4dn.4xlarge": { "bandwidth": 25, "disk": 225, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g4dn.4xlarge", "instancesku": "P2PYJRR8WRUQQ83N", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "225 GB NVMe SSD", "vcpu": "16" }, "id": "g4dn.4xlarge", "name": "g4dn.4xlarge", "ram": 65536 }, "g4dn.8xlarge": { "bandwidth": 50, "disk": 900, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g4dn.8xlarge", "instancesku": "E4ENVUU4X4C9CA2A", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "128 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "900 GB NVMe SSD", "vcpu": "32" }, "id": "g4dn.8xlarge", "name": "g4dn.8xlarge", "ram": 131072 }, "g4dn.xlarge": { "bandwidth": 25, "disk": 125, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "g4dn.xlarge", "instancesku": "CBN4GYUGRUCDMWNY", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "125 GB NVMe SSD", "vcpu": "4" }, "id": "g4dn.xlarge", "name": "g4dn.xlarge", "ram": 16384 }, "h1.16xlarge": { "bandwidth": 25, "disk": 16000, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "201", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "h1.16xlarge", "instancesku": "95Z3VYWMT3AARF75", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "256 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "8 x 2000 HDD", "vcpu": "64" }, "id": "h1.16xlarge", "name": "h1.16xlarge", "ram": 262144 }, "h1.2xlarge": { "bandwidth": 10, "disk": 2000, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1750 Mbps", "ecu": "31", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "h1.2xlarge", "instancesku": "EDHN83CZXXV35NWH", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 2000 HDD", "vcpu": "8" }, "id": "h1.2xlarge", "name": "h1.2xlarge", "ram": 32768 }, "h1.4xlarge": { "bandwidth": 10, "disk": 4000, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "58", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "h1.4xlarge", "instancesku": "E3W8QW3X5FF55BPW", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 2000 HDD", "vcpu": "16" }, "id": "h1.4xlarge", "name": "h1.4xlarge", "ram": 65536 }, "h1.8xlarge": { "bandwidth": 10, "disk": 8000, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "97", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "h1.8xlarge", "instancesku": "V92EE38S25QMHCHR", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "128 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 2000 HDD", "vcpu": "32" }, "id": "h1.8xlarge", "name": "h1.8xlarge", "ram": 131072 }, "hs1.8xlarge": { "bandwidth": 10, "disk": 48000, "extra": { "clockSpeed": "2 GHz", "currentGeneration": "No", "ecu": "35", "instanceFamily": "Storage optimized", "instanceType": "hs1.8xlarge", "memory": "117 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2650", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "24 x 2000", "vcpu": "17" }, "id": "hs1.8xlarge", "name": "hs1.8xlarge", "ram": 119808 }, "i2.2xlarge": { "bandwidth": None, "disk": 1600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "dedicatedEbsThroughput": "1500 Mbps", "ecu": "27", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i2.2xlarge", "instancesku": "S3CUTS4VY2N7TUAC", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "61 GiB", "networkPerformance": "High", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 800 SSD", "vcpu": "8" }, "id": "i2.2xlarge", "name": "i2.2xlarge", "ram": 62464 }, "i2.4xlarge": { "bandwidth": None, "disk": 3200, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "dedicatedEbsThroughput": "1500 Mbps", "ecu": "53", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i2.4xlarge", "instancesku": "QAS6U8F8Z43CEYDJ", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "122 GiB", "networkPerformance": "High", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 800 SSD", "vcpu": "16" }, "id": "i2.4xlarge", "name": "i2.4xlarge", "ram": 124928 }, "i2.8xlarge": { "bandwidth": 10, "disk": 6400, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "dedicatedEbsThroughput": "1500 Mbps", "ecu": "104", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i2.8xlarge", "instancesku": "GJUYG5H8K4MVD9B2", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "8 x 800 SSD", "vcpu": "32" }, "id": "i2.8xlarge", "name": "i2.8xlarge", "ram": 249856 }, "i2.xlarge": { "bandwidth": None, "disk": 800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "dedicatedEbsThroughput": "750 Mbps", "ecu": "14", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i2.xlarge", "instancesku": "VJV23STC4X8PNAQM", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30.5 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 800 SSD", "vcpu": "4" }, "id": "i2.xlarge", "name": "i2.xlarge", "ram": 31232 }, "i3.16xlarge": { "bandwidth": 20, "disk": 15200, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "201", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3.16xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "488 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "8 x 1900 NVMe SSD", "vcpu": "64" }, "id": "i3.16xlarge", "name": "i3.16xlarge", "ram": 499712 }, "i3.2xlarge": { "bandwidth": 10, "disk": 1900, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1750 Mbps", "ecu": "31", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "61 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 1900 NVMe SSD", "vcpu": "8" }, "id": "i3.2xlarge", "name": "i3.2xlarge", "ram": 62464 }, "i3.4xlarge": { "bandwidth": 10, "disk": 3800, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "53", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3.4xlarge", "memory": "122 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX, Intel AVX2, Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 1900 NVMe SSD", "vcpu": "16" }, "id": "i3.4xlarge", "name": "i3.4xlarge", "ram": 124928 }, "i3.8xlarge": { "bandwidth": 10, "disk": 7600, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "97", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3.8xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 1900 NVMe SSD", "vcpu": "32" }, "id": "i3.8xlarge", "name": "i3.8xlarge", "ram": 249856 }, "i3.large": { "bandwidth": 10, "disk": 475, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "425 Mbps", "ecu": "8", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3.large", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "15.25 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 475 NVMe SSD", "vcpu": "2" }, "id": "i3.large", "name": "i3.large", "ram": 15616 }, "i3.xlarge": { "bandwidth": 10, "disk": 950, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "850 Mbps", "ecu": "16", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3.xlarge", "instancesku": "99QZ9VR3AF2FW3TB", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30.5 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 950 NVMe SSD", "vcpu": "4" }, "id": "i3.xlarge", "name": "i3.xlarge", "ram": 31232 }, "i3en.12xlarge": { "bandwidth": 50, "disk": 30000, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "168", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3en.12xlarge", "instancesku": "GVPZRNHNZPE4JV4G", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 7500 NVMe SSD", "vcpu": "48" }, "id": "i3en.12xlarge", "name": "i3en.12xlarge", "ram": 393216 }, "i3en.24xlarge": { "bandwidth": 100, "disk": 60000, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "337", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3en.24xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "768 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "8 x 7500 NVMe SSD", "vcpu": "96" }, "id": "i3en.24xlarge", "name": "i3en.24xlarge", "ram": 786432 }, "i3en.2xlarge": { "bandwidth": 25, "disk": 5000, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "37", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3en.2xlarge", "instancesku": "KPSBHZJSEURW9AUU", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 2500 NVMe SSD", "vcpu": "8" }, "id": "i3en.2xlarge", "name": "i3en.2xlarge", "ram": 65536 }, "i3en.3xlarge": { "bandwidth": 25, "disk": 7500, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3en.3xlarge", "instancesku": "4M9CWY3DF8ZQRQ2F", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "96 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "24", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 7500 NVMe SSD", "vcpu": "12" }, "id": "i3en.3xlarge", "name": "i3en.3xlarge", "ram": 98304 }, "i3en.6xlarge": { "bandwidth": 25, "disk": 15000, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3en.6xlarge", "instancesku": "8RHN5TZKA9MW3AWW", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "48", "physicalProcessor": "Intel Xeon Platinum 8175", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 7500 NVMe SSD", "vcpu": "24" }, "id": "i3en.6xlarge", "name": "i3en.6xlarge", "ram": 196608 }, "i3en.large": { "bandwidth": 25, "disk": 1250, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "10", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3en.large", "instancesku": "EDC6Z6KEEJ6KENE8", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 1250 NVMe SSD", "vcpu": "2" }, "id": "i3en.large", "name": "i3en.large", "ram": 16384 }, "i3en.xlarge": { "bandwidth": 25, "disk": 2500, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Storage optimized", "instanceType": "i3en.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 2500 NVMe SSD", "vcpu": "4" }, "id": "i3en.xlarge", "name": "i3en.xlarge", "ram": 32768 }, "inf1.24xlarge": { "bandwidth": 100, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Machine Learning ASIC Instances", "instanceType": "inf1.24xlarge", "instancesku": "YKZ73T2PBEWV8HSM", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "192 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Platinum 8275CL (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "inf1.24xlarge", "name": "inf1.24xlarge", "ram": 196608 }, "inf1.2xlarge": { "bandwidth": 25, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "875 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Machine Learning ASIC Instances", "instanceType": "inf1.2xlarge", "instancesku": "66AAM3URQPDCTMXY", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Platinum 8275CL (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "inf1.2xlarge", "name": "inf1.2xlarge", "ram": 16384 }, "inf1.6xlarge": { "bandwidth": 25, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Machine Learning ASIC Instances", "instanceType": "inf1.6xlarge", "instancesku": "CGXS8PYBHFGKES9Z", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "48 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Platinum 8275CL (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "24" }, "id": "inf1.6xlarge", "name": "inf1.6xlarge", "ram": 49152 }, "inf1.xlarge": { "bandwidth": 25, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "875 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Machine Learning ASIC Instances", "instanceType": "inf1.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "NA", "physicalProcessor": "Intel Xeon Platinum 8275CL (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "inf1.xlarge", "name": "inf1.xlarge", "ram": 8192 }, "m1.large": { "bandwidth": None, "disk": 840, "extra": { "currentGeneration": "No", "ecu": "4", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m1.large", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "7.5 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 420 SSD", "vcpu": "2" }, "id": "m1.large", "name": "m1.large", "ram": 7680 }, "m1.medium": { "bandwidth": None, "disk": 410, "extra": { "currentGeneration": "No", "ecu": "2", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m1.medium", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "3.75 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "2", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "32-bit or 64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 410 SSD", "vcpu": "1" }, "id": "m1.medium", "name": "m1.medium", "ram": 3840 }, "m1.small": { "bandwidth": None, "disk": 160, "extra": { "currentGeneration": "No", "ecu": "1", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m1.small", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "1.7 GiB", "networkPerformance": "Low", "normalizationSizeFactor": "1", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "32-bit or 64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 160 SSD", "vcpu": "1" }, "id": "m1.small", "name": "m1.small", "ram": 1740 }, "m1.xlarge": { "bandwidth": None, "disk": 1680, "extra": { "currentGeneration": "No", "ecu": "8", "instanceFamily": "General purpose", "instanceType": "m1.xlarge", "memory": "15 GiB", "networkPerformance": "High", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 420", "vcpu": "4" }, "id": "m1.xlarge", "name": "m1.xlarge", "ram": 15360 }, "m2.2xlarge": { "bandwidth": None, "disk": 850, "extra": { "currentGeneration": "No", "ecu": "13", "instanceFamily": "Memory optimized", "instanceType": "m2.2xlarge", "memory": "34.2 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 850", "vcpu": "4" }, "id": "m2.2xlarge", "name": "m2.2xlarge", "ram": 35020 }, "m2.4xlarge": { "bandwidth": None, "disk": 1680, "extra": { "currentGeneration": "No", "ecu": "26", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "m2.4xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "68.4 GiB", "networkPerformance": "High", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 840 SSD", "vcpu": "8" }, "id": "m2.4xlarge", "name": "m2.4xlarge", "ram": 70041 }, "m2.xlarge": { "bandwidth": None, "disk": 420, "extra": { "currentGeneration": "No", "ecu": "6.5", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "m2.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "17.1 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 420 SSD", "vcpu": "2" }, "id": "m2.xlarge", "name": "m2.xlarge", "ram": 17510 }, "m3.2xlarge": { "bandwidth": None, "disk": 160, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "dedicatedEbsThroughput": "1000 Mbps", "ecu": "26", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m3.2xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30 GiB", "networkPerformance": "High", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge/Sandy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 80 SSD", "vcpu": "8" }, "id": "m3.2xlarge", "name": "m3.2xlarge", "ram": 30720 }, "m3.large": { "bandwidth": None, "disk": 32, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "ecu": "6.5", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m3.large", "instancesku": "8KTQAHWA58GUHDGC", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "7.5 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge/Sandy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 32 SSD", "vcpu": "2" }, "id": "m3.large", "name": "m3.large", "ram": 7680 }, "m3.medium": { "bandwidth": None, "disk": 4, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "ecu": "3", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m3.medium", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "3.75 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "2", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge/Sandy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 4 SSD", "vcpu": "1" }, "id": "m3.medium", "name": "m3.medium", "ram": 3840 }, "m3.xlarge": { "bandwidth": None, "disk": 80, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "dedicatedEbsThroughput": "500 Mbps", "ecu": "13", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m3.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "15 GiB", "networkPerformance": "High", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge/Sandy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 40 SSD", "vcpu": "4" }, "id": "m3.xlarge", "name": "m3.xlarge", "ram": 15360 }, "m4.10xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "4000 Mbps", "ecu": "124.5", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m4.10xlarge", "instancesku": "MDVS9QJ4U4VXR7P6", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "160 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "80", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "40" }, "id": "m4.10xlarge", "name": "m4.10xlarge", "ram": 163840 }, "m4.16xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "188", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m4.16xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "256 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "m4.16xlarge", "name": "m4.16xlarge", "ram": 262144 }, "m4.2xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1000 Mbps", "ecu": "26", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m4.2xlarge", "memory": "32 GiB", "networkPerformance": "High", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "m4.2xlarge", "name": "m4.2xlarge", "ram": 32768 }, "m4.4xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2000 Mbps", "ecu": "53.5", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m4.4xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "High", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "m4.4xlarge", "name": "m4.4xlarge", "ram": 65536 }, "m4.large": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "450 Mbps", "ecu": "6.5", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m4.large", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "8 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "m4.large", "name": "m4.large", "ram": 8192 }, "m4.xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.4 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "750 Mbps", "ecu": "13", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m4.xlarge", "instancesku": "5RFD7HVPT29ZZRJZ", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "High", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2676 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "m4.xlarge", "name": "m4.xlarge", "ram": 16384 }, "m5.12xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "168", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.12xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "m5.12xlarge", "name": "m5.12xlarge", "ram": 196608 }, "m5.16xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "256", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.16xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "256 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "m5.16xlarge", "name": "m5.16xlarge", "ram": 262144 }, "m5.24xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "337", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.24xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "384 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "m5.24xlarge", "name": "m5.24xlarge", "ram": 393216 }, "m5.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "37", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "m5.2xlarge", "name": "m5.2xlarge", "ram": 32768 }, "m5.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2120 Mbps", "ecu": "70", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.4xlarge", "instancesku": "GPN9XWJXU6R7VNVU", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "m5.4xlarge", "name": "m5.4xlarge", "ram": 65536 }, "m5.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "128", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.8xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "128 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "m5.8xlarge", "name": "m5.8xlarge", "ram": 131072 }, "m5.large": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Upto 2120 Mbps", "ecu": "8", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.large", "instancesku": "2WTZUAPYXZ92MPYV", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8175", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX, Intel AVX2, Intel AVX512, Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "m5.large", "name": "m5.large", "ram": 8192 }, "m5.metal": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "345", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.metal", "instancesku": "NEA5ZGBNTVZY47F8", "memory": "384 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8175", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX, Intel AVX2, Intel AVX512, Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "m5.metal", "name": "m5.metal", "ram": 393216 }, "m5.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "16", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5.xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "m5.xlarge", "name": "m5.xlarge", "ram": 16384 }, "m5a.12xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.12xlarge", "instancesku": "NTCQHKBGDWZV9A4S", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "192 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "m5a.12xlarge", "name": "m5a.12xlarge", "ram": 196608 }, "m5a.16xlarge": { "bandwidth": 12, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.16xlarge", "instancesku": "PDTXJ9FD3DSMTAWR", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "12 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "m5a.16xlarge", "name": "m5a.16xlarge", "ram": 262144 }, "m5a.24xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.24xlarge", "instancesku": "3DZQSBC8ACN83U66", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "m5a.24xlarge", "name": "m5a.24xlarge", "ram": 393216 }, "m5a.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.2xlarge", "instancesku": "SQ6QFVBCH7QJN7WE", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "m5a.2xlarge", "name": "m5a.2xlarge", "ram": 32768 }, "m5a.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.4xlarge", "instancesku": "YHV5N59X2JZJT7UF", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "m5a.4xlarge", "name": "m5a.4xlarge", "ram": 65536 }, "m5a.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "m5a.8xlarge", "name": "m5a.8xlarge", "ram": 131072 }, "m5a.large": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.large", "instancesku": "YETHAPD3GP4N3ZNK", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "m5a.large", "name": "m5a.large", "ram": 8192 }, "m5a.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5a.xlarge", "instancesku": "2DC7PA6547H9EQEU", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "m5a.xlarge", "name": "m5a.xlarge", "ram": 16384 }, "m5ad.12xlarge": { "bandwidth": 10, "disk": 1800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.12xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "192 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "48" }, "id": "m5ad.12xlarge", "name": "m5ad.12xlarge", "ram": 196608 }, "m5ad.16xlarge": { "bandwidth": 12, "disk": 2400, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.16xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "12 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 600 NVMe SSD", "vcpu": "64" }, "id": "m5ad.16xlarge", "name": "m5ad.16xlarge", "ram": 262144 }, "m5ad.24xlarge": { "bandwidth": 20, "disk": 3600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.24xlarge", "instancesku": "6QSKH897CEX9D5PD", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 900 NVMe SSD", "vcpu": "96" }, "id": "m5ad.24xlarge", "name": "m5ad.24xlarge", "ram": 393216 }, "m5ad.2xlarge": { "bandwidth": 10, "disk": 300, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.2xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 300 NVMe SSD", "vcpu": "8" }, "id": "m5ad.2xlarge", "name": "m5ad.2xlarge", "ram": 32768 }, "m5ad.4xlarge": { "bandwidth": 10, "disk": 600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.4xlarge", "instancesku": "53D2DUQDA28GP4FA", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 300 NVMe SSD", "vcpu": "16" }, "id": "m5ad.4xlarge", "name": "m5ad.4xlarge", "ram": 65536 }, "m5ad.8xlarge": { "bandwidth": 10, "disk": 1200, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 600 NVMe SSD", "vcpu": "32" }, "id": "m5ad.8xlarge", "name": "m5ad.8xlarge", "ram": 131072 }, "m5ad.large": { "bandwidth": 10, "disk": 75, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.large", "instancesku": "DV2FPCRNYQC737FY", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 75 NVMe SSD", "vcpu": "2" }, "id": "m5ad.large", "name": "m5ad.large", "ram": 8192 }, "m5ad.xlarge": { "bandwidth": 10, "disk": 150, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5ad.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 150 NVMe SSD", "vcpu": "4" }, "id": "m5ad.xlarge", "name": "m5ad.xlarge", "ram": 16384 }, "m5d.12xlarge": { "bandwidth": 10, "disk": 1800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "6000 Mbps", "ecu": "168", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.12xlarge", "instancesku": "GMGGY8H6FE639R7J", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "48" }, "id": "m5d.12xlarge", "name": "m5d.12xlarge", "ram": 196608 }, "m5d.16xlarge": { "bandwidth": 20, "disk": 2400, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "256", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.16xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "256 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 600 NVMe SSD", "vcpu": "64" }, "id": "m5d.16xlarge", "name": "m5d.16xlarge", "ram": 262144 }, "m5d.24xlarge": { "bandwidth": 25, "disk": 3600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "337", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.24xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "384 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 900 NVMe SSD", "vcpu": "96" }, "id": "m5d.24xlarge", "name": "m5d.24xlarge", "ram": 393216 }, "m5d.2xlarge": { "bandwidth": 10, "disk": 300, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "37", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 300 NVMe SSD", "vcpu": "8" }, "id": "m5d.2xlarge", "name": "m5d.2xlarge", "ram": 32768 }, "m5d.4xlarge": { "bandwidth": 10, "disk": 600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2120 Mbps", "ecu": "70", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.4xlarge", "instancesku": "SJTJT7YB2TAKEFUZ", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 300 NVMe SSD", "vcpu": "16" }, "id": "m5d.4xlarge", "name": "m5d.4xlarge", "ram": 65536 }, "m5d.8xlarge": { "bandwidth": 10, "disk": 1200, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "128", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.8xlarge", "instancesku": "7WTXDDTKVDX74SRU", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "128 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 600 NVMe SSD", "vcpu": "32" }, "id": "m5d.8xlarge", "name": "m5d.8xlarge", "ram": 131072 }, "m5d.large": { "bandwidth": 10, "disk": 75, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "10", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.large", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 75 NVMe SSD", "vcpu": "2" }, "id": "m5d.large", "name": "m5d.large", "ram": 8192 }, "m5d.xlarge": { "bandwidth": 10, "disk": 150, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Upto 2120 Mbps", "ecu": "16", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "m5d.xlarge", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8175", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX, Intel AVX2, Intel AVX512, Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 150 NVMe SSD", "vcpu": "4" }, "id": "m5d.xlarge", "name": "m5d.xlarge", "ram": 16384 }, "m5dn.12xlarge": { "bandwidth": 50, "disk": 1800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.12xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "192 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 GB NVMe SSD", "vcpu": "48" }, "id": "m5dn.12xlarge", "name": "m5dn.12xlarge", "ram": 196608 }, "m5dn.16xlarge": { "bandwidth": 75, "disk": 2400, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.16xlarge", "instancesku": "2UXZVUW3AW4RWSVK", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "75 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 600 NVMe SSD", "vcpu": "64" }, "id": "m5dn.16xlarge", "name": "m5dn.16xlarge", "ram": 262144 }, "m5dn.24xlarge": { "bandwidth": 100, "disk": 3600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.24xlarge", "instancesku": "3CSFMMFP6H6R4C8N", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 900 NVMe SSD", "vcpu": "96" }, "id": "m5dn.24xlarge", "name": "m5dn.24xlarge", "ram": 393216 }, "m5dn.2xlarge": { "bandwidth": 25, "disk": 300, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.2xlarge", "instancesku": "EFERZJ2267U6HKKN", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 300 NVMe SSD", "vcpu": "8" }, "id": "m5dn.2xlarge", "name": "m5dn.2xlarge", "ram": 32768 }, "m5dn.4xlarge": { "bandwidth": 25, "disk": 600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.4xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 300 NVMe SSD", "vcpu": "16" }, "id": "m5dn.4xlarge", "name": "m5dn.4xlarge", "ram": 65536 }, "m5dn.8xlarge": { "bandwidth": 25, "disk": 1200, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 600 NVMe SSD", "vcpu": "32" }, "id": "m5dn.8xlarge", "name": "m5dn.8xlarge", "ram": 131072 }, "m5dn.large": { "bandwidth": 25, "disk": 75, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.large", "instancesku": "TP3PAHR3346GJ67W", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 75 NVMe SSD", "vcpu": "2" }, "id": "m5dn.large", "name": "m5dn.large", "ram": 8192 }, "m5dn.xlarge": { "bandwidth": 25, "disk": 150, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5dn.xlarge", "instancesku": "SHVB6RBA3NZZ9V4Z", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 150 NVMe SSD", "vcpu": "4" }, "id": "m5dn.xlarge", "name": "m5dn.xlarge", "ram": 16384 }, "m5n.12xlarge": { "bandwidth": 50, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.12xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "192 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "m5n.12xlarge", "name": "m5n.12xlarge", "ram": 196608 }, "m5n.16xlarge": { "bandwidth": 75, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.16xlarge", "instancesku": "EA8S423TQADF5CY2", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "75 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "m5n.16xlarge", "name": "m5n.16xlarge", "ram": 262144 }, "m5n.24xlarge": { "bandwidth": 100, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.24xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "m5n.24xlarge", "name": "m5n.24xlarge", "ram": 393216 }, "m5n.2xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.2xlarge", "instancesku": "UYEPHYDEF5R5EBP5", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "m5n.2xlarge", "name": "m5n.2xlarge", "ram": 32768 }, "m5n.4xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.4xlarge", "instancesku": "ZH4K42CV65578MRJ", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "m5n.4xlarge", "name": "m5n.4xlarge", "ram": 65536 }, "m5n.8xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.8xlarge", "instancesku": "ATZJ9KFTKYZZMGEJ", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "m5n.8xlarge", "name": "m5n.8xlarge", "ram": 131072 }, "m5n.large": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.large", "instancesku": "2FNJS8YA6UBP65EW", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "m5n.large", "name": "m5n.large", "ram": 8192 }, "m5n.xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m5n.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "m5n.xlarge", "name": "m5n.xlarge", "ram": 16384 }, "m6g.12xlarge": { "bandwidth": 12, "disk": 0, "extra": { "currentGeneration": "Yes", "ecu": "NA", "instanceFamily": "General purpose", "instanceType": "m6g.12xlarge", "instancesku": "WW7AYBVNX4P6DKEG", "memory": "192 GiB", "networkPerformance": "12 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "m6g.12xlarge", "name": "m6g.12xlarge", "ram": 196608 }, "m6g.16xlarge": { "bandwidth": 25, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "18000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m6g.16xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "m6g.16xlarge", "name": "m6g.16xlarge", "ram": 262144 }, "m6g.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "2250 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m6g.2xlarge", "instancesku": "275QHDMHEFGAB9QZ", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "m6g.2xlarge", "name": "m6g.2xlarge", "ram": 32768 }, "m6g.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "4500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m6g.4xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "m6g.4xlarge", "name": "m6g.4xlarge", "ram": 65536 }, "m6g.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "9000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m6g.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "m6g.8xlarge", "name": "m6g.8xlarge", "ram": 131072 }, "m6g.large": { "bandwidth": 10, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "600 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m6g.large", "instancesku": "WKZUYUTMHZP7PGQS", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "m6g.large", "name": "m6g.large", "ram": 8192 }, "m6g.medium": { "bandwidth": 10, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "300 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m6g.medium", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "4 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "2", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "1" }, "id": "m6g.medium", "name": "m6g.medium", "ram": 4096 }, "m6g.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "currentGeneration": "Yes", "dedicatedEbsThroughput": "1125 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "m6g.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "AWS Graviton2 Processor", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "m6g.xlarge", "name": "m6g.xlarge", "ram": 16384 }, "p2.16xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "201", "enhancedNetworkingSupported": "Yes", "gpu": "16", "instanceFamily": "GPU instance", "instanceType": "p2.16xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "732 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "p2.16xlarge", "name": "p2.16xlarge", "ram": 749568 }, "p2.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "97", "enhancedNetworkingSupported": "Yes", "gpu": "8", "instanceFamily": "GPU instance", "instanceType": "p2.8xlarge", "instancesku": "CJQFCM483GYMQ4H7", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "488 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "p2.8xlarge", "name": "p2.8xlarge", "ram": 499712 }, "p2.xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "750 Mbps", "ecu": "16", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "p2.xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "61 GiB", "networkPerformance": "High", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "p2.xlarge", "name": "p2.xlarge", "ram": 62464 }, "p3.16xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "201", "enhancedNetworkingSupported": "Yes", "gpu": "8", "instanceFamily": "GPU instance", "instanceType": "p3.16xlarge", "instancesku": "23X4DDDYPQ4U9WXE", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "488 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "p3.16xlarge", "name": "p3.16xlarge", "ram": 499712 }, "p3.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1750 Mbps", "ecu": "31", "enhancedNetworkingSupported": "Yes", "gpu": "1", "instanceFamily": "GPU instance", "instanceType": "p3.2xlarge", "instancesku": "BQCBF2WYFFDEDXN7", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "61 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "p3.2xlarge", "name": "p3.2xlarge", "ram": 62464 }, "p3.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "97", "enhancedNetworkingSupported": "Yes", "gpu": "4", "instanceFamily": "GPU instance", "instanceType": "p3.8xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "p3.8xlarge", "name": "p3.8xlarge", "ram": 249856 }, "p3dn.24xlarge": { "bandwidth": 100, "disk": 1800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "337", "enhancedNetworkingSupported": "Yes", "gpu": "8", "instanceFamily": "GPU instance", "instanceType": "p3dn.24xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "768 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "96" }, "id": "p3dn.24xlarge", "name": "p3dn.24xlarge", "ram": 786432 }, "r3.2xlarge": { "bandwidth": None, "disk": 160, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "ecu": "26", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r3.2xlarge", "instancesku": "QPBU35XRU5BNBBFE", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "61 GiB", "networkPerformance": "High", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 160 SSD", "vcpu": "8" }, "id": "r3.2xlarge", "name": "r3.2xlarge", "ram": 62464 }, "r3.4xlarge": { "bandwidth": None, "disk": 320, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "ecu": "52", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r3.4xlarge", "instancesku": "Y9WDY7HG6S2NXFSP", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "122 GiB", "networkPerformance": "High", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 320 SSD", "vcpu": "16" }, "id": "r3.4xlarge", "name": "r3.4xlarge", "ram": 124928 }, "r3.8xlarge": { "bandwidth": 10, "disk": 640, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "ecu": "104", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r3.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 320 SSD", "vcpu": "32" }, "id": "r3.8xlarge", "name": "r3.8xlarge", "ram": 249856 }, "r3.large": { "bandwidth": None, "disk": 32, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "ecu": "6.5", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r3.large", "memory": "15.25 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 32 SSD", "vcpu": "2" }, "id": "r3.large", "name": "r3.large", "ram": 15616 }, "r3.xlarge": { "bandwidth": None, "disk": 80, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "No", "ecu": "13", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r3.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30.5 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2670 v2 (Ivy Bridge)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 80 SSD", "vcpu": "4" }, "id": "r3.xlarge", "name": "r3.xlarge", "ram": 31232 }, "r4.16xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "195", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r4.16xlarge", "instancesku": "M3PF8AJDMYE8CTHJ", "memory": "488 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX, Intel AVX2, Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "r4.16xlarge", "name": "r4.16xlarge", "ram": 499712 }, "r4.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1600 Mbps", "ecu": "31", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r4.2xlarge", "instancesku": "T73VEGF6Z7U2FM2E", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "61 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "r4.2xlarge", "name": "r4.2xlarge", "ram": 62464 }, "r4.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3000 Mbps", "ecu": "58", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r4.4xlarge", "instancesku": "Q4JYWMFXQ9MM3WYP", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "122 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "r4.4xlarge", "name": "r4.4xlarge", "ram": 124928 }, "r4.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "6000 Mbps", "ecu": "97", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r4.8xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "244 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "r4.8xlarge", "name": "r4.8xlarge", "ram": 249856 }, "r4.large": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "400 Mbps", "ecu": "7", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r4.large", "instancesku": "EMEXNPTCFPMK9SZ6", "memory": "15.25 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX, Intel AVX2, Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "r4.large", "name": "r4.large", "ram": 15616 }, "r4.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "800 Mbps", "ecu": "16", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r4.xlarge", "instancesku": "Q985NTC5RUN6W6FN", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "30.5 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon E5-2686 v4 (Broadwell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "r4.xlarge", "name": "r4.xlarge", "ram": 31232 }, "r5.12xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "6000 Mbps", "ecu": "168", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.12xlarge", "instancesku": "DEBR9WT8ZEH5SVYY", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "384 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "r5.12xlarge", "name": "r5.12xlarge", "ram": 393216 }, "r5.16xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "256", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.16xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "512 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "r5.16xlarge", "name": "r5.16xlarge", "ram": 524288 }, "r5.24xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "337", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.24xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "768 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "r5.24xlarge", "name": "r5.24xlarge", "ram": 786432 }, "r5.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "37", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.2xlarge", "instancesku": "TX6VCU4AX7SURS3R", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "r5.2xlarge", "name": "r5.2xlarge", "ram": 65536 }, "r5.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2120 Mbps", "ecu": "70", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.4xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "128 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "r5.4xlarge", "name": "r5.4xlarge", "ram": 131072 }, "r5.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "128", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.8xlarge", "instancesku": "8J9E8648XRY8KRTV", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "256 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "r5.8xlarge", "name": "r5.8xlarge", "ram": 262144 }, "r5.large": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "10", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.large", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "r5.large", "name": "r5.large", "ram": 16384 }, "r5.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "3.1 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "19", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5.xlarge", "instancesku": "RYY8KJSCAHAJ2S2N", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "r5.xlarge", "name": "r5.xlarge", "ram": 32768 }, "r5a.12xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.12xlarge", "instancesku": "K4WF4MUAD8NH6F85", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "r5a.12xlarge", "name": "r5a.12xlarge", "ram": 393216 }, "r5a.16xlarge": { "bandwidth": 12, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.16xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "512 GiB", "networkPerformance": "12 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "64" }, "id": "r5a.16xlarge", "name": "r5a.16xlarge", "ram": 524288 }, "r5a.24xlarge": { "bandwidth": 20, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.24xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "768 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "r5a.24xlarge", "name": "r5a.24xlarge", "ram": 786432 }, "r5a.2xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.2xlarge", "instancesku": "P7S4KAQ9D4GAFR54", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "r5a.2xlarge", "name": "r5a.2xlarge", "ram": 65536 }, "r5a.4xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.4xlarge", "instancesku": "SDQK54UK2HRQTUXV", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "16" }, "id": "r5a.4xlarge", "name": "r5a.4xlarge", "ram": 131072 }, "r5a.8xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.8xlarge", "instancesku": "6B56HCXAHSRM98ZB", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "r5a.8xlarge", "name": "r5a.8xlarge", "ram": 262144 }, "r5a.large": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.large", "instancesku": "UG5A9S2YU4GDQ6VS", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "r5a.large", "name": "r5a.large", "ram": 16384 }, "r5a.xlarge": { "bandwidth": 10, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5a.xlarge", "instancesku": "3QM2JUUU3729P3XF", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "r5a.xlarge", "name": "r5a.xlarge", "ram": 32768 }, "r5ad.12xlarge": { "bandwidth": 10, "disk": 1800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.12xlarge", "instancesku": "CVGPBG74JXGXFUPZ", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "48" }, "id": "r5ad.12xlarge", "name": "r5ad.12xlarge", "ram": 393216 }, "r5ad.16xlarge": { "bandwidth": 12, "disk": 2400, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.16xlarge", "instancesku": "5ECTGJZ54PJWVXSR", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "512 GiB", "networkPerformance": "12 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 600 NVMe SSD", "vcpu": "64" }, "id": "r5ad.16xlarge", "name": "r5ad.16xlarge", "ram": 524288 }, "r5ad.24xlarge": { "bandwidth": 20, "disk": 3600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.24xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "768 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 900 NVMe SSD", "vcpu": "96" }, "id": "r5ad.24xlarge", "name": "r5ad.24xlarge", "ram": 786432 }, "r5ad.2xlarge": { "bandwidth": 10, "disk": 300, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.2xlarge", "instancesku": "GUVRRZUCEA4W2NA2", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 300 NVMe SSD", "vcpu": "8" }, "id": "r5ad.2xlarge", "name": "r5ad.2xlarge", "ram": 65536 }, "r5ad.4xlarge": { "bandwidth": 10, "disk": 600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.4xlarge", "instancesku": "VT3PC6G59VCVCDVN", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 300 NVMe SSD", "vcpu": "16" }, "id": "r5ad.4xlarge", "name": "r5ad.4xlarge", "ram": 131072 }, "r5ad.8xlarge": { "bandwidth": 10, "disk": 1200, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.8xlarge", "instancesku": "Y7ZUMCMQMBHWWD67", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 600 NVMe SSD", "vcpu": "32" }, "id": "r5ad.8xlarge", "name": "r5ad.8xlarge", "ram": 262144 }, "r5ad.large": { "bandwidth": 10, "disk": 75, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.large", "instancesku": "DZNY4VEMMSVRTR73", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 75 NVMe SSD", "vcpu": "2" }, "id": "r5ad.large", "name": "r5ad.large", "ram": 16384 }, "r5ad.xlarge": { "bandwidth": 10, "disk": 150, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5ad.xlarge", "instancesku": "X9QQDFJ8MS8FB32D", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 150 NVMe SSD", "vcpu": "4" }, "id": "r5ad.xlarge", "name": "r5ad.xlarge", "ram": 32768 }, "r5d.12xlarge": { "bandwidth": 10, "disk": 1800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "6000 Mbps", "ecu": "168", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.12xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "384 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "48" }, "id": "r5d.12xlarge", "name": "r5d.12xlarge", "ram": 393216 }, "r5d.16xlarge": { "bandwidth": 20, "disk": 2400, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "256", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.16xlarge", "instancesku": "7A8KJ5V5P6RMFWQ8", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "512 GiB", "networkPerformance": "20 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 600 NVMe SSD", "vcpu": "64" }, "id": "r5d.16xlarge", "name": "r5d.16xlarge", "ram": 524288 }, "r5d.24xlarge": { "bandwidth": 25, "disk": 3600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "337", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.24xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "768 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 900 NVMe SSD", "vcpu": "96" }, "id": "r5d.24xlarge", "name": "r5d.24xlarge", "ram": 786432 }, "r5d.2xlarge": { "bandwidth": 10, "disk": 300, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "37", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 300 NVMe SSD", "vcpu": "8" }, "id": "r5d.2xlarge", "name": "r5d.2xlarge", "ram": 65536 }, "r5d.4xlarge": { "bandwidth": 10, "disk": 600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2120 Mbps", "ecu": "70", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.4xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "128 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 300 NVMe SSD", "vcpu": "16" }, "id": "r5d.4xlarge", "name": "r5d.4xlarge", "ram": 131072 }, "r5d.8xlarge": { "bandwidth": 10, "disk": 1200, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "128", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.8xlarge", "instancesku": "KDH339PT4BZYF4KZ", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "256 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 600 NVMe SSD", "vcpu": "32" }, "id": "r5d.8xlarge", "name": "r5d.8xlarge", "ram": 262144 }, "r5d.large": { "bandwidth": 10, "disk": 75, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "10", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.large", "instancesku": "GGDAM58JTEWKNJHM", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 75 NVMe SSD", "vcpu": "2" }, "id": "r5d.large", "name": "r5d.large", "ram": 16384 }, "r5d.xlarge": { "bandwidth": 10, "disk": 150, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "19", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "r5d.xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8175 (Skylake)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 150 NVMe SSD", "vcpu": "4" }, "id": "r5d.xlarge", "name": "r5d.xlarge", "ram": 32768 }, "r5dn.12xlarge": { "bandwidth": 50, "disk": 1800, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "6000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.12xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 GB NVMe SSD", "vcpu": "48" }, "id": "r5dn.12xlarge", "name": "r5dn.12xlarge", "ram": 393216 }, "r5dn.16xlarge": { "bandwidth": 75, "disk": 2400, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "10000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.16xlarge", "instancesku": "7V498XTUEEHCJRGZ", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "512 GiB", "networkPerformance": "75 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 600 NVMe SSD", "vcpu": "64" }, "id": "r5dn.16xlarge", "name": "r5dn.16xlarge", "ram": 524288 }, "r5dn.24xlarge": { "bandwidth": 100, "disk": 3600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.24xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "768 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "4 x 900 NVMe SSD", "vcpu": "96" }, "id": "r5dn.24xlarge", "name": "r5dn.24xlarge", "ram": 786432 }, "r5dn.2xlarge": { "bandwidth": 25, "disk": 300, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.2xlarge", "instancesku": "SV48KRP8HM2DH2UC", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 300 NVMe SSD", "vcpu": "8" }, "id": "r5dn.2xlarge", "name": "r5dn.2xlarge", "ram": 65536 }, "r5dn.4xlarge": { "bandwidth": 25, "disk": 600, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.4xlarge", "instancesku": "KFFG95QS5WUKQP8D", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "128 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 300 NVMe SSD", "vcpu": "16" }, "id": "r5dn.4xlarge", "name": "r5dn.4xlarge", "ram": 131072 }, "r5dn.8xlarge": { "bandwidth": 25, "disk": 1200, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.8xlarge", "instancesku": "WJB3V98YXM2CZ9US", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 600 NVMe SSD", "vcpu": "32" }, "id": "r5dn.8xlarge", "name": "r5dn.8xlarge", "ram": 262144 }, "r5dn.large": { "bandwidth": 25, "disk": 75, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.large", "instancesku": "5SM96WH3QZND6QG9", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 75 NVMe SSD", "vcpu": "2" }, "id": "r5dn.large", "name": "r5dn.large", "ram": 16384 }, "r5dn.xlarge": { "bandwidth": 25, "disk": 150, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5dn.xlarge", "instancesku": "KW4K9UDQ493ER24R", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 150 NVMe SSD", "vcpu": "4" }, "id": "r5dn.xlarge", "name": "r5dn.xlarge", "ram": 32768 }, "r5n.12xlarge": { "bandwidth": 50, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "6000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5n.12xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "384 GiB", "networkPerformance": "50 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "48" }, "id": "r5n.12xlarge", "name": "r5n.12xlarge", "ram": 393216 }, "r5n.16xlarge": { "bandwidth": 75, "disk": 0, "extra": { "currentGeneration": "Yes", "ecu": "NA", "instanceFamily": "Memory optimized", "instanceType": "r5n.16xlarge", "instancesku": "8V7ZBPH5MUDT6TF5", "memory": "512 GiB", "networkPerformance": "75 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "NA", "vcpu": "64" }, "id": "r5n.16xlarge", "name": "r5n.16xlarge", "ram": 524288 }, "r5n.24xlarge": { "bandwidth": 100, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "12000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5n.24xlarge", "instancesku": "84XC4EP5DDTNC8ZA", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "768 GiB", "networkPerformance": "100 Gigabit", "normalizationSizeFactor": "192", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "96" }, "id": "r5n.24xlarge", "name": "r5n.24xlarge", "ram": 786432 }, "r5n.2xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5n.2xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "64 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "r5n.2xlarge", "name": "r5n.2xlarge", "ram": 65536 }, "r5n.4xlarge": { "bandwidth": 25, "disk": 0, "extra": { "currentGeneration": "Yes", "ecu": "NA", "instanceFamily": "Memory optimized", "instanceType": "r5n.4xlarge", "instancesku": "QDCRSRKZM3MX7XAG", "memory": "128 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "NA", "vcpu": "16" }, "id": "r5n.4xlarge", "name": "r5n.4xlarge", "ram": 131072 }, "r5n.8xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "5000 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5n.8xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "256 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "32" }, "id": "r5n.8xlarge", "name": "r5n.8xlarge", "ram": 262144 }, "r5n.large": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5n.large", "instancesku": "KN56TRZD3CM72VXU", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "r5n.large", "name": "r5n.large", "ram": 16384 }, "r5n.xlarge": { "bandwidth": 25, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "NA", "enhancedNetworkingSupported": "No", "instanceFamily": "Memory optimized", "instanceType": "r5n.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Up to 25 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8259 (Cascade Lake)", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "r5n.xlarge", "name": "r5n.xlarge", "ram": 32768 }, "t1.micro": { "bandwidth": None, "disk": 0, "extra": { "currentGeneration": "No", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "Micro instances", "instanceType": "t1.micro", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "0.613 GiB", "networkPerformance": "Very Low", "normalizationSizeFactor": "0.5", "physicalProcessor": "Variable", "processorArchitecture": "32-bit or 64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "1" }, "id": "t1.micro", "name": "t1.micro", "ram": 627 }, "t2.2xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "Up to 3.3 GHz", "currentGeneration": "Yes", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t2.2xlarge", "instancesku": "WKK3DC7GCMFXGGYP", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "t2.2xlarge", "name": "t2.2xlarge", "ram": 32768 }, "t2.large": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "Up to 3.3 GHz", "currentGeneration": "Yes", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t2.large", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "8 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t2.large", "name": "t2.large", "ram": 8192 }, "t2.medium": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "Up to 3.3 GHz", "currentGeneration": "Yes", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t2.medium", "instancesku": "HSW33TU9JRSFYRKF", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "4 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "2", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "32-bit or 64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t2.medium", "name": "t2.medium", "ram": 4096 }, "t2.micro": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "Up to 3.3 GHz", "currentGeneration": "Yes", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t2.micro", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "1 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "0.5", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "32-bit or 64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "1" }, "id": "t2.micro", "name": "t2.micro", "ram": 1024 }, "t2.nano": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "Up to 3.3 GHz", "currentGeneration": "Yes", "ecu": "Variable", "instanceFamily": "General purpose", "instanceType": "t2.nano", "memory": "0.5 GiB", "networkPerformance": "Low", "normalizationSizeFactor": "0.25", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "32-bit or 64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "1" }, "id": "t2.nano", "name": "t2.nano", "ram": 512 }, "t2.small": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "Up to 3.3 GHz", "currentGeneration": "Yes", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t2.small", "instancesku": "XQ8FKG65FR9Z4ZPR", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "2 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "1", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "32-bit or 64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "1" }, "id": "t2.small", "name": "t2.small", "ram": 2048 }, "t2.xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "Up to 3.3 GHz", "currentGeneration": "Yes", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t2.xlarge", "intelAvx2Available": "No", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Family", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "t2.xlarge", "name": "t2.xlarge", "ram": 16384 }, "t3.2xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2048 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t3.2xlarge", "instancesku": "56TSPRQERU8CAJ43", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Skylake E5 2686 v5", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "t3.2xlarge", "name": "t3.2xlarge", "ram": 32768 }, "t3.large": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2048 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t3.large", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "8 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Skylake E5 2686 v5", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3.large", "name": "t3.large", "ram": 8192 }, "t3.medium": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 1536 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t3.medium", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "4 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "2", "physicalProcessor": "Intel Skylake E5 2686 v5", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3.medium", "name": "t3.medium", "ram": 4096 }, "t3.micro": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 1536 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t3.micro", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "1 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "0.5", "physicalProcessor": "Intel Skylake E5 2686 v5", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3.micro", "name": "t3.micro", "ram": 1024 }, "t3.nano": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 1536 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t3.nano", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "0.5 GiB", "networkPerformance": "Low", "normalizationSizeFactor": "0.25", "physicalProcessor": "Intel Skylake E5 2686 v5", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3.nano", "name": "t3.nano", "ram": 512 }, "t3.small": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 1536 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t3.small", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "2 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "1", "physicalProcessor": "Intel Skylake E5 2686 v5", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3.small", "name": "t3.small", "ram": 2048 }, "t3.xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2048 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "No", "instanceFamily": "General purpose", "instanceType": "t3.xlarge", "instancesku": "6YPUHM9X2FGUB8D2", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "16 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Skylake E5 2686 v5", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "t3.xlarge", "name": "t3.xlarge", "ram": 16384 }, "t3a.2xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "t3a.2xlarge", "instancesku": "FSP74JWHB79FDG9T", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "32 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "16", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "8" }, "id": "t3a.2xlarge", "name": "t3a.2xlarge", "ram": 32768 }, "t3a.large": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Upto 2120 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "t3a.large", "instancesku": "QE64UKF9H7MH4QTP", "memory": "8 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "4", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX, AVX2, AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3a.large", "name": "t3a.large", "ram": 8192 }, "t3a.medium": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2120 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "t3a.medium", "instancesku": "F5K4DYDG9JZ549EQ", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "4 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "2", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3a.medium", "name": "t3a.medium", "ram": 4096 }, "t3a.micro": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 1500 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "t3a.micro", "instancesku": "C92KHZUPSGNAZA8G", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "1 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "0.5", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3a.micro", "name": "t3a.micro", "ram": 1024 }, "t3a.nano": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 1500 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "t3a.nano", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "0.5 GiB", "networkPerformance": "Low", "normalizationSizeFactor": "0.25", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3a.nano", "name": "t3a.nano", "ram": 512 }, "t3a.small": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 1500 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "t3a.small", "instancesku": "JE8UDWJG8MPPHAZZ", "intelAvx2Available": "No", "intelAvxAvailable": "No", "intelTurboAvailable": "No", "memory": "2 GiB", "networkPerformance": "Low to Moderate", "normalizationSizeFactor": "1", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX; AVX2; AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "2" }, "id": "t3a.small", "name": "t3a.small", "ram": 2048 }, "t3a.xlarge": { "bandwidth": None, "disk": 0, "extra": { "clockSpeed": "2.5 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Upto 2120 Mbps", "ecu": "Variable", "enhancedNetworkingSupported": "Yes", "instanceFamily": "General purpose", "instanceType": "t3a.xlarge", "instancesku": "TBV6C3VKSXKFHHSC", "memory": "16 GiB", "networkPerformance": "Moderate", "normalizationSizeFactor": "8", "physicalProcessor": "AMD EPYC 7571", "processorArchitecture": "64-bit", "processorFeatures": "AVX, AVX2, AMD Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "EBS only", "vcpu": "4" }, "id": "t3a.xlarge", "name": "t3a.xlarge", "ram": 16384 }, "x1.16xlarge": { "bandwidth": None, "disk": 1920, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "174.5", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1.16xlarge", "instancesku": "PCDN4738CD5856G7", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "976 GiB", "networkPerformance": "High", "normalizationSizeFactor": "128", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 1920 SSD", "vcpu": "64" }, "id": "x1.16xlarge", "name": "x1.16xlarge", "ram": 999424 }, "x1.32xlarge": { "bandwidth": None, "disk": 3840, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "349", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1.32xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "1952 GiB", "networkPerformance": "High", "normalizationSizeFactor": "256", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 1920 SSD", "vcpu": "128" }, "id": "x1.32xlarge", "name": "x1.32xlarge", "ram": 1998848 }, "x1e.16xlarge": { "bandwidth": 10, "disk": 1920, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "179", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1e.16xlarge", "instancesku": "WGPFFCGF4UHBGVDH", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "No", "memory": "1952 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "128", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 1920 SSD", "vcpu": "64" }, "id": "x1e.16xlarge", "name": "x1e.16xlarge", "ram": 1998848 }, "x1e.2xlarge": { "bandwidth": 10, "disk": 240, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1000 Mbps", "ecu": "23", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1e.2xlarge", "instancesku": "UA4QBJUCBNHDQX2B", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "No", "memory": "244 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 240 SSD", "vcpu": "8" }, "id": "x1e.2xlarge", "name": "x1e.2xlarge", "ram": 249856 }, "x1e.32xlarge": { "bandwidth": 25, "disk": 3840, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "340", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1e.32xlarge", "instancesku": "A52J7F6ERS7NFNBK", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "No", "memory": "3904 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "256", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 1920 SSD", "vcpu": "128" }, "id": "x1e.32xlarge", "name": "x1e.32xlarge", "ram": 3997696 }, "x1e.4xlarge": { "bandwidth": 10, "disk": 480, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "1750 Mbps", "ecu": "47", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1e.4xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "No", "memory": "488 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "32", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 480 SSD", "vcpu": "16" }, "id": "x1e.4xlarge", "name": "x1e.4xlarge", "ram": 499712 }, "x1e.8xlarge": { "bandwidth": 10, "disk": 960, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "3500 Mbps", "ecu": "91", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1e.8xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "No", "memory": "976 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "64", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 960 SSD", "vcpu": "32" }, "id": "x1e.8xlarge", "name": "x1e.8xlarge", "ram": 999424 }, "x1e.xlarge": { "bandwidth": 10, "disk": 120, "extra": { "clockSpeed": "2.3 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "500 Mbps", "ecu": "12", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "x1e.xlarge", "instancesku": "F4FMFRXVW3TMHF72", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "No", "memory": "122 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "High Frequency Intel Xeon E7-8880 v3 (Haswell)", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 120 SSD", "vcpu": "4" }, "id": "x1e.xlarge", "name": "x1e.xlarge", "ram": 124928 }, "z1d.12xlarge": { "bandwidth": 25, "disk": 1800, "extra": { "clockSpeed": "4.0 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "14000 Mbps", "ecu": "235", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "z1d.12xlarge", "instancesku": "3NPW8NJBUPE5PHWG", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "384 GiB", "networkPerformance": "25 Gigabit", "normalizationSizeFactor": "96", "physicalProcessor": "Intel Xeon Platinum 8151", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "2 x 900 NVMe SSD", "vcpu": "48" }, "id": "z1d.12xlarge", "name": "z1d.12xlarge", "ram": 393216 }, "z1d.2xlarge": { "bandwidth": 10, "disk": 300, "extra": { "clockSpeed": "4.0 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "2333 Mbps", "ecu": "45", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "z1d.2xlarge", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "64 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "16", "physicalProcessor": "Intel Xeon Platinum 8151", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 300 NVMe SSD", "vcpu": "8" }, "id": "z1d.2xlarge", "name": "z1d.2xlarge", "ram": 65536 }, "z1d.3xlarge": { "bandwidth": 10, "disk": 450, "extra": { "currentGeneration": "Yes", "ecu": "75", "instanceFamily": "Memory optimized", "instanceType": "z1d.3xlarge", "memory": "96 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "24", "physicalProcessor": "Intel Xeon Platinum 8151", "processorArchitecture": "64-bit", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 450 NVMe SSD", "vcpu": "12" }, "id": "z1d.3xlarge", "name": "z1d.3xlarge", "ram": 98304 }, "z1d.6xlarge": { "bandwidth": 10, "disk": 900, "extra": { "clockSpeed": "4.0 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "7000 Mbps", "ecu": "116", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "z1d.6xlarge", "instancesku": "6KCEGJ35VRAHEDVX", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "192 GiB", "networkPerformance": "10 Gigabit", "normalizationSizeFactor": "48", "physicalProcessor": "Intel Xeon Platinum 8151", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 900 NVMe SSD", "vcpu": "24" }, "id": "z1d.6xlarge", "name": "z1d.6xlarge", "ram": 196608 }, "z1d.large": { "bandwidth": 10, "disk": 75, "extra": { "clockSpeed": "4.0 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2333 Mbps", "ecu": "12", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "z1d.large", "instancesku": "A7FTGGDM8KVFNGQB", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "16 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "4", "physicalProcessor": "Intel Xeon Platinum 8151", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 75 NVMe SSD", "vcpu": "2" }, "id": "z1d.large", "name": "z1d.large", "ram": 16384 }, "z1d.xlarge": { "bandwidth": 10, "disk": 150, "extra": { "clockSpeed": "4.0 GHz", "currentGeneration": "Yes", "dedicatedEbsThroughput": "Up to 2333 Mbps", "ecu": "23", "enhancedNetworkingSupported": "Yes", "instanceFamily": "Memory optimized", "instanceType": "z1d.xlarge", "instancesku": "DAVJWHZW3NM7TCJW", "intelAvx2Available": "Yes", "intelAvxAvailable": "Yes", "intelTurboAvailable": "Yes", "memory": "32 GiB", "networkPerformance": "Up to 10 Gigabit", "normalizationSizeFactor": "8", "physicalProcessor": "Intel Xeon Platinum 8151", "processorArchitecture": "64-bit", "processorFeatures": "Intel AVX; Intel AVX2; Intel AVX512; Intel Turbo", "servicecode": "AmazonEC2", "servicename": "Amazon Elastic Compute Cloud", "storage": "1 x 150 NVMe SSD", "vcpu": "4" }, "id": "z1d.xlarge", "name": "z1d.xlarge", "ram": 32768 } } REGION_DETAILS = { "ap-northeast-1": { "api_name": "ec2_ap_northeast", "country": "Japan", "endpoint": "ec2.ap-northeast-1.amazonaws.com", "id": "ap-northeast-1", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "cc2.8xlarge", "cr1.8xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "hs1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "m5dn.12xlarge", "m5dn.16xlarge", "m5dn.24xlarge", "m5dn.2xlarge", "m5dn.4xlarge", "m5dn.8xlarge", "m5dn.large", "m5dn.xlarge", "m5n.12xlarge", "m5n.16xlarge", "m5n.24xlarge", "m5n.2xlarge", "m5n.4xlarge", "m5n.8xlarge", "m5n.large", "m5n.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "p3dn.24xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "r5dn.12xlarge", "r5dn.16xlarge", "r5dn.24xlarge", "r5dn.2xlarge", "r5dn.4xlarge", "r5dn.8xlarge", "r5dn.large", "r5dn.xlarge", "r5n.12xlarge", "r5n.16xlarge", "r5n.24xlarge", "r5n.2xlarge", "r5n.4xlarge", "r5n.8xlarge", "r5n.large", "r5n.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "2" }, "ap-northeast-2": { "api_name": "ec2_ap_northeast", "country": "South Korea", "endpoint": "ec2.ap-northeast-2.amazonaws.com", "id": "ap-northeast-2", "instance_types": [ "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "4" }, "ap-northeast-3": { "api_name": "ec2_ap_northeast", "country": "Japan", "endpoint": "ec2.ap-northeast-3.amazonaws.com", "id": "ap-northeast-3", "instance_types": [ "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.18xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.18xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge" ], "signature_version": "4" }, "ap-south-1": { "api_name": "ec2_ap_south_1", "country": "India", "endpoint": "ec2.ap-south-1.amazonaws.com", "id": "ap-south-1", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.18xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "4" }, "ap-southeast-1": { "api_name": "ec2_ap_southeast", "country": "Singapore", "endpoint": "ec2.ap-southeast-1.amazonaws.com", "id": "ap-southeast-1", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "hs1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.metal", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "m5dn.12xlarge", "m5dn.16xlarge", "m5dn.24xlarge", "m5dn.2xlarge", "m5dn.4xlarge", "m5dn.8xlarge", "m5dn.large", "m5dn.xlarge", "m5n.12xlarge", "m5n.16xlarge", "m5n.24xlarge", "m5n.2xlarge", "m5n.4xlarge", "m5n.8xlarge", "m5n.large", "m5n.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "r5dn.12xlarge", "r5dn.16xlarge", "r5dn.24xlarge", "r5dn.2xlarge", "r5dn.4xlarge", "r5dn.8xlarge", "r5dn.large", "r5dn.xlarge", "r5n.12xlarge", "r5n.16xlarge", "r5n.24xlarge", "r5n.2xlarge", "r5n.4xlarge", "r5n.8xlarge", "r5n.large", "r5n.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "2" }, "ap-southeast-2": { "api_name": "ec2_ap_southeast_2", "country": "Australia", "endpoint": "ec2.ap-southeast-2.amazonaws.com", "id": "ap-southeast-2", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "f1.16xlarge", "f1.2xlarge", "f1.4xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "hs1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "2" }, "ca-central-1": { "api_name": "ec2_ca_central_1", "country": "Canada", "endpoint": "ec2.ca-central-1.amazonaws.com", "id": "ca-central-1", "instance_types": [ "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge" ], "signature_version": "4" }, "cn-north-1": { "api_name": "ec2_cn_north", "country": "China", "endpoint": "ec2.cn-north-1.amazonaws.com.cn", "id": "cn-north-1", "instance_types": [], "signature_version": "4" }, "cn-northwest-1": { "api_name": "ec2_cn_northwest", "country": "China", "endpoint": "ec2.cn-northwest-1.amazonaws.com.cn", "id": "cn-northwest-1", "instance_types": [], "signature_version": "4" }, "eu-central-1": { "api_name": "ec2_eu_central", "country": "Frankfurt", "endpoint": "ec2.eu-central-1.amazonaws.com", "id": "eu-central-1", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "m5dn.12xlarge", "m5dn.16xlarge", "m5dn.24xlarge", "m5dn.2xlarge", "m5dn.4xlarge", "m5dn.8xlarge", "m5dn.large", "m5dn.xlarge", "m5n.12xlarge", "m5n.16xlarge", "m5n.24xlarge", "m5n.2xlarge", "m5n.4xlarge", "m5n.8xlarge", "m5n.large", "m5n.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "r5dn.12xlarge", "r5dn.16xlarge", "r5dn.24xlarge", "r5dn.2xlarge", "r5dn.4xlarge", "r5dn.8xlarge", "r5dn.large", "r5dn.xlarge", "r5n.12xlarge", "r5n.16xlarge", "r5n.24xlarge", "r5n.2xlarge", "r5n.4xlarge", "r5n.8xlarge", "r5n.large", "r5n.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "4" }, "eu-west-1": { "api_name": "ec2_eu_west", "country": "Ireland", "endpoint": "ec2.eu-west-1.amazonaws.com", "id": "eu-west-1", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "cc2.8xlarge", "cr1.8xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "f1.16xlarge", "f1.2xlarge", "f1.4xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "h1.16xlarge", "h1.2xlarge", "h1.4xlarge", "h1.8xlarge", "hs1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "m5dn.12xlarge", "m5dn.16xlarge", "m5dn.24xlarge", "m5dn.2xlarge", "m5dn.4xlarge", "m5dn.8xlarge", "m5dn.large", "m5dn.xlarge", "m5n.12xlarge", "m5n.16xlarge", "m5n.24xlarge", "m5n.2xlarge", "m5n.4xlarge", "m5n.8xlarge", "m5n.large", "m5n.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "p3dn.24xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "r5dn.12xlarge", "r5dn.16xlarge", "r5dn.24xlarge", "r5dn.2xlarge", "r5dn.4xlarge", "r5dn.8xlarge", "r5dn.large", "r5dn.xlarge", "r5n.12xlarge", "r5n.16xlarge", "r5n.24xlarge", "r5n.2xlarge", "r5n.4xlarge", "r5n.8xlarge", "r5n.large", "r5n.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "2" }, "eu-west-2": { "api_name": "ec2_eu_west_london", "country": "United Kingdom", "endpoint": "ec2.eu-west-2.amazonaws.com", "id": "eu-west-2", "instance_types": [ "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "4" }, "eu-west-3": { "api_name": "ec2_eu_west_paris", "country": "France", "endpoint": "ec2.eu-west-3.amazonaws.com", "id": "eu-west-3", "instance_types": [ "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.18xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge" ], "signature_version": "4" }, "sa-east-1": { "api_name": "ec2_sa_east", "country": "Brazil", "endpoint": "ec2.sa-east-1.amazonaws.com", "id": "sa-east-1", "instance_types": [ "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g2.2xlarge", "g2.8xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge" ], "signature_version": "2" }, "us-east-1": { "api_name": "ec2_us_east", "country": "USA", "endpoint": "ec2.us-east-1.amazonaws.com", "id": "us-east-1", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "cc2.8xlarge", "cr1.8xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "f1.16xlarge", "f1.2xlarge", "f1.4xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "h1.16xlarge", "h1.2xlarge", "h1.4xlarge", "h1.8xlarge", "hs1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "inf1.24xlarge", "inf1.2xlarge", "inf1.6xlarge", "inf1.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "m5dn.12xlarge", "m5dn.16xlarge", "m5dn.24xlarge", "m5dn.2xlarge", "m5dn.4xlarge", "m5dn.8xlarge", "m5dn.large", "m5dn.xlarge", "m5n.12xlarge", "m5n.16xlarge", "m5n.24xlarge", "m5n.2xlarge", "m5n.4xlarge", "m5n.8xlarge", "m5n.large", "m5n.xlarge", "m6g.12xlarge", "m6g.16xlarge", "m6g.2xlarge", "m6g.4xlarge", "m6g.8xlarge", "m6g.large", "m6g.medium", "m6g.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "p3dn.24xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "r5dn.12xlarge", "r5dn.16xlarge", "r5dn.24xlarge", "r5dn.2xlarge", "r5dn.4xlarge", "r5dn.8xlarge", "r5dn.large", "r5dn.xlarge", "r5n.12xlarge", "r5n.16xlarge", "r5n.24xlarge", "r5n.2xlarge", "r5n.4xlarge", "r5n.8xlarge", "r5n.large", "r5n.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "2" }, "us-east-2": { "api_name": "ec2_us_east_ohio", "country": "USA", "endpoint": "ec2.us-east-2.amazonaws.com", "id": "us-east-2", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "h1.16xlarge", "h1.2xlarge", "h1.4xlarge", "h1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.metal", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "m5dn.12xlarge", "m5dn.16xlarge", "m5dn.24xlarge", "m5dn.2xlarge", "m5dn.4xlarge", "m5dn.8xlarge", "m5dn.large", "m5dn.xlarge", "m5n.12xlarge", "m5n.16xlarge", "m5n.24xlarge", "m5n.2xlarge", "m5n.4xlarge", "m5n.8xlarge", "m5n.large", "m5n.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "r5dn.12xlarge", "r5dn.16xlarge", "r5dn.24xlarge", "r5dn.2xlarge", "r5dn.4xlarge", "r5dn.8xlarge", "r5dn.large", "r5dn.xlarge", "r5n.12xlarge", "r5n.16xlarge", "r5n.24xlarge", "r5n.2xlarge", "r5n.4xlarge", "r5n.8xlarge", "r5n.large", "r5n.xlarge", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "4" }, "us-gov-west-1": { "api_name": "ec2_us_govwest", "country": "US", "endpoint": "ec2.us-gov-west-1.amazonaws.com", "id": "us-gov-west-1", "instance_types": [ "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "cc2.8xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "f1.16xlarge", "f1.2xlarge", "f1.4xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "hs1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "p3dn.24xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge" ], "signature_version": "2" }, "us-west-1": { "api_name": "ec2_us_west", "country": "USA", "endpoint": "ec2.us-west-1.amazonaws.com", "id": "us-west-1", "instance_types": [ "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "f1.16xlarge", "f1.2xlarge", "f1.4xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "2" }, "us-west-2": { "api_name": "ec2_us_west_oregon", "country": "US", "endpoint": "ec2.us-west-2.amazonaws.com", "id": "us-west-2", "instance_types": [ "a1.2xlarge", "a1.4xlarge", "a1.large", "a1.medium", "a1.xlarge", "c1.medium", "c1.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c3.large", "c3.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c4.large", "c4.xlarge", "c5.12xlarge", "c5.18xlarge", "c5.24xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.large", "c5.xlarge", "c5d.12xlarge", "c5d.18xlarge", "c5d.24xlarge", "c5d.2xlarge", "c5d.4xlarge", "c5d.9xlarge", "c5d.large", "c5d.xlarge", "c5n.18xlarge", "c5n.2xlarge", "c5n.4xlarge", "c5n.9xlarge", "c5n.large", "c5n.xlarge", "cc2.8xlarge", "cr1.8xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "d2.xlarge", "f1.16xlarge", "f1.2xlarge", "f1.4xlarge", "g2.2xlarge", "g2.8xlarge", "g3.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3s.xlarge", "g4dn.12xlarge", "g4dn.16xlarge", "g4dn.2xlarge", "g4dn.4xlarge", "g4dn.8xlarge", "g4dn.xlarge", "h1.16xlarge", "h1.2xlarge", "h1.4xlarge", "h1.8xlarge", "hs1.8xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "i2.xlarge", "i3.16xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge", "i3.large", "i3.xlarge", "i3en.12xlarge", "i3en.24xlarge", "i3en.2xlarge", "i3en.3xlarge", "i3en.6xlarge", "i3en.large", "i3en.xlarge", "inf1.24xlarge", "inf1.2xlarge", "inf1.6xlarge", "inf1.xlarge", "m1.large", "m1.medium", "m1.small", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.2xlarge", "m3.large", "m3.medium", "m3.xlarge", "m4.10xlarge", "m4.16xlarge", "m4.2xlarge", "m4.4xlarge", "m4.large", "m4.xlarge", "m5.12xlarge", "m5.16xlarge", "m5.24xlarge", "m5.2xlarge", "m5.4xlarge", "m5.8xlarge", "m5.large", "m5.metal", "m5.xlarge", "m5a.12xlarge", "m5a.16xlarge", "m5a.24xlarge", "m5a.2xlarge", "m5a.4xlarge", "m5a.8xlarge", "m5a.large", "m5a.xlarge", "m5ad.12xlarge", "m5ad.16xlarge", "m5ad.24xlarge", "m5ad.2xlarge", "m5ad.4xlarge", "m5ad.8xlarge", "m5ad.large", "m5ad.xlarge", "m5d.12xlarge", "m5d.16xlarge", "m5d.24xlarge", "m5d.2xlarge", "m5d.4xlarge", "m5d.8xlarge", "m5d.large", "m5d.xlarge", "m5dn.12xlarge", "m5dn.16xlarge", "m5dn.24xlarge", "m5dn.2xlarge", "m5dn.4xlarge", "m5dn.8xlarge", "m5dn.large", "m5dn.xlarge", "m5n.12xlarge", "m5n.16xlarge", "m5n.24xlarge", "m5n.2xlarge", "m5n.4xlarge", "m5n.8xlarge", "m5n.large", "m5n.xlarge", "p2.16xlarge", "p2.8xlarge", "p2.xlarge", "p3.16xlarge", "p3.2xlarge", "p3.8xlarge", "p3dn.24xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r3.large", "r3.xlarge", "r4.16xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge", "r4.large", "r4.xlarge", "r5.12xlarge", "r5.16xlarge", "r5.24xlarge", "r5.2xlarge", "r5.4xlarge", "r5.8xlarge", "r5.large", "r5.xlarge", "r5a.12xlarge", "r5a.16xlarge", "r5a.24xlarge", "r5a.2xlarge", "r5a.4xlarge", "r5a.8xlarge", "r5a.large", "r5a.xlarge", "r5ad.12xlarge", "r5ad.16xlarge", "r5ad.24xlarge", "r5ad.2xlarge", "r5ad.4xlarge", "r5ad.8xlarge", "r5ad.large", "r5ad.xlarge", "r5d.12xlarge", "r5d.16xlarge", "r5d.24xlarge", "r5d.2xlarge", "r5d.4xlarge", "r5d.8xlarge", "r5d.large", "r5d.xlarge", "r5dn.12xlarge", "r5dn.16xlarge", "r5dn.24xlarge", "r5dn.2xlarge", "r5dn.4xlarge", "r5dn.8xlarge", "r5dn.large", "r5dn.xlarge", "r5n.12xlarge", "r5n.16xlarge", "r5n.24xlarge", "r5n.2xlarge", "r5n.4xlarge", "r5n.8xlarge", "r5n.large", "r5n.xlarge", "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge", "t3a.2xlarge", "t3a.large", "t3a.medium", "t3a.micro", "t3a.nano", "t3a.small", "t3a.xlarge", "x1.16xlarge", "x1.32xlarge", "x1e.16xlarge", "x1e.2xlarge", "x1e.32xlarge", "x1e.4xlarge", "x1e.8xlarge", "x1e.xlarge", "z1d.12xlarge", "z1d.2xlarge", "z1d.3xlarge", "z1d.6xlarge", "z1d.large", "z1d.xlarge" ], "signature_version": "2" } } apache-libcloud-2.8.0/libcloud/compute/deployment.py0000664000175000017500000002323413577507766022461 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Provides generic deployment steps for machines post boot. """ from __future__ import with_statement from typing import Union from typing import Optional from typing import List from typing import IO from typing import cast import os import binascii from libcloud.utils.py3 import basestring, PY3 from libcloud.compute.base import Node from libcloud.compute.ssh import BaseSSHClient class Deployment(object): """ Base class for deployment tasks. """ def run(self, node, client): # type: (Node, BaseSSHClient) -> Node """ Runs this deployment task on node using the client provided. :type node: :class:`Node` :keyword node: Node to operate one :type client: :class:`BaseSSHClient` :keyword client: Connected SSH client to use. :return: :class:`Node` """ raise NotImplementedError( 'run not implemented for this deployment') def _get_string_value(self, argument_name, argument_value): if not isinstance(argument_value, basestring) and \ not hasattr(argument_value, 'read'): raise TypeError('%s argument must be a string or a file-like ' 'object' % (argument_name)) if hasattr(argument_value, 'read'): argument_value = argument_value.read() return argument_value class SSHKeyDeployment(Deployment): """ Installs a public SSH Key onto a server. """ def __init__(self, key): # type: (Union[str, IO]) -> None """ :type key: ``str`` or :class:`File` object :keyword key: Contents of the public key write or a file object which can be read. """ self.key = self._get_string_value(argument_name='key', argument_value=key) def run(self, node, client): # type: (Node, BaseSSHClient) -> Node """ Installs SSH key into ``.ssh/authorized_keys`` See also :class:`Deployment.run` """ client.put(".ssh/authorized_keys", contents=self.key, mode='a') return node class FileDeployment(Deployment): """ Installs a file on the server. """ def __init__(self, source, target): # type: (str, str) -> None """ :type source: ``str`` :keyword source: Local path of file to be installed :type target: ``str`` :keyword target: Path to install file on node """ self.source = source self.target = target def run(self, node, client): # type: (Node, BaseSSHClient) -> Node """ Upload the file, retaining permissions. See also :class:`Deployment.run` """ perms = int(oct(os.stat(self.source).st_mode)[4:], 8) with open(self.source, 'rb') as fp: content = fp.read() client.put(path=self.target, chmod=perms, contents=content) return node class ScriptDeployment(Deployment): """ Runs an arbitrary shell script on the server. This step works by first writing the content of the shell script (script argument) in a *.sh file on a remote server and then running that file. If you are running a non-shell script, make sure to put the appropriate shebang to the top of the script. You are also advised to do that even if you are running a plan shell script. """ def __init__(self, script, args=None, name=None, delete=False): # type: (str, Optional[List[str]], Optional[str], bool) -> None """ :type script: ``str`` :keyword script: Contents of the script to run. :type args: ``list`` :keyword args: Optional command line arguments which get passed to the deployment script file. :type name: ``str`` :keyword name: Name of the script to upload it as, if not specified, a random name will be chosen. :type delete: ``bool`` :keyword delete: Whether to delete the script on completion. """ script = self._get_string_value(argument_name='script', argument_value=script) self.script = script self.args = args or [] self.stdout = None # type: Optional[str] self.stderr = None # type: Optional[str] self.exit_status = None # type: Optional[int] self.delete = delete self.name = name # type: Optional[str] if self.name is None: # File is put under user's home directory # (~/libcloud_deployment_.sh) random_string = '' # type: Union[str, bytes] random_string = binascii.hexlify(os.urandom(4)) random_string = cast(bytes, random_string) random_string = random_string.decode('ascii') self.name = 'libcloud_deployment_%s.sh' % (random_string) def run(self, node, client): # type: (Node, BaseSSHClient) -> Node """ Uploads the shell script and then executes it. See also :class:`Deployment.run` """ self.name = cast(str, self.name) file_path = client.put(path=self.name, chmod=int('755', 8), contents=self.script) # Pre-pend cwd if user specified a relative path if self.name and self.name[0] != '/': base_path = os.path.dirname(file_path) name = os.path.join(base_path, self.name) else: self.name = cast(str, self.name) name = self.name cmd = name if self.args: # Append arguments to the command cmd = '%s %s' % (name, ' '.join(self.args)) else: cmd = name self.stdout, self.stderr, self.exit_status = client.run(cmd) if self.delete: client.delete(self.name) return node def __str__(self): return self.__repr__() def __repr__(self): script = self.script[:15] + '...' exit_status = self.exit_status if exit_status is not None: stdout = self.stdout[:30] + '...' stderr = self.stderr[:30] + '...' else: exit_status = 'script didn\'t run yet' stdout = None stderr = None return ("" % (script, exit_status, stdout, stderr)) class ScriptFileDeployment(ScriptDeployment): """ Runs an arbitrary shell script from a local file on the server. Same as ScriptDeployment, except that you can pass in a path to the file instead of the script content. """ def __init__(self, script_file, args=None, name=None, delete=False): # type: (str, Optional[List[str]], Optional[str], bool) -> None """ :type script_file: ``str`` :keyword script_file: Path to a file containing the script to run. :type args: ``list`` :keyword args: Optional command line arguments which get passed to the deployment script file. :type name: ``str`` :keyword name: Name of the script to upload it as, if not specified, a random name will be chosen. :type delete: ``bool`` :keyword delete: Whether to delete the script on completion. """ with open(script_file, 'rb') as fp: content = fp.read() # type: Union[bytes, str] if PY3: content = cast(bytes, content) content = content.decode('utf-8') super(ScriptFileDeployment, self).__init__(script=content, args=args, name=name, delete=delete) class MultiStepDeployment(Deployment): """ Runs a chain of Deployment steps. """ def __init__(self, add=None): # type: (Optional[Union[Deployment, List[Deployment]]]) -> None """ :type add: ``list`` :keyword add: Deployment steps to add. """ self.steps = [] # type: list if add: self.add(add) def add(self, add): # type: (Union[Deployment, List[Deployment]]) -> None """ Add a deployment to this chain. :type add: Single :class:`Deployment` or a ``list`` of :class:`Deployment` :keyword add: Adds this deployment to the others already in this object. """ if add is not None: add = add if isinstance(add, (list, tuple)) else [add] self.steps.extend(add) def run(self, node, client): # type: (Node, BaseSSHClient) -> Node """ Run each deployment that has been added. See also :class:`Deployment.run` """ for s in self.steps: node = s.run(node, client) return node apache-libcloud-2.8.0/libcloud/compute/deprecated.py0000664000175000017500000000447713535474530022373 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Database of deprecated drivers """ from libcloud.compute.types import Provider DEPRECATED_DRIVERS = { Provider.OPSOURCE: { 'reason': 'OpSource cloud is now part of Dimension Data, ' 'use the DIMENSIONDATA provider instead.', 'url': 'http://www.ntt.co.jp/news2011/1107e/110701a.html' }, Provider.NINEFOLD: { 'reason': 'We will shortly notify our customers that we ' 'will be sunsetting our Public Cloud Computing ' '(Server) platform, the last day of operation ' 'being January 30, 2016', 'url': 'https://ninefold.com/news/' }, Provider.IBM: { 'reason': 'IBM SmartCloud Enterprise has been deprecated ' 'in favour of IBM SoftLayer Public Cloud, please' ' use the SOFTLAYER provider.', 'url': 'http://www.ibm.com/midmarket/us/en/article_cloud6_1310.html' }, Provider.HPCLOUD: { 'reason': 'HP Helion Public Cloud was shut down in January 2016.', 'url': 'http://libcloud.apache.org/blog/' '2016/02/16/new-drivers-deprecated-drivers.html' }, Provider.CLOUDFRAMES: { 'reason': 'The CloudFrames Provider is no longer supported', 'url': 'http://libcloud.apache.org/blog/2016/02/16/new-drivers-' 'deprecated-drivers.html' }, Provider.RUNABOVE: { 'reason': 'The RunAbove compute is no longer supported. ' 'Use the OVH one instead.', 'url': 'https://www.runabove.com/cloud-instance.xml' } } apache-libcloud-2.8.0/libcloud/compute/drivers/0000775000175000017500000000000013600223624021350 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/compute/drivers/__init__.py0000664000175000017500000000226713570310635023475 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Drivers for working with different providers """ __all__ = [ 'abiquo', 'brightbox', 'bluebox', 'dimensiondata', 'dummy', 'ec2', 'ecp', 'elasticstack', 'elastichosts', 'cloudsigma', 'gce', 'gogrid', 'hostvirtual', 'linode', 'nttcis', 'opennebula', 'rackspace', 'rimuhosting', 'softlayer', 'vcloud', 'voxel', 'vpsnet', 'onapp', ] apache-libcloud-2.8.0/libcloud/compute/drivers/abiquo.py0000664000175000017500000007545113577507766023247 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Abiquo Compute Driver The driver implements the compute Abiquo functionality for the Abiquo API. This version is compatible with the following versions of Abiquo: * Abiquo 3.4 (http://wiki.abiquo.com/display/ABI34/The+Abiquo+API) """ from libcloud.utils.py3 import ET from libcloud.compute.base import NodeDriver, NodeSize from libcloud.compute.types import Provider, LibcloudError from libcloud.common.abiquo import (AbiquoConnection, get_href, AbiquoResponse) from libcloud.compute.base import NodeLocation, NodeImage, Node from libcloud.utils.py3 import tostring class AbiquoNodeDriver(NodeDriver): """ Implements the :class:`NodeDriver`'s for the Abiquo Compute Provider """ type = Provider.ABIQUO name = 'Abiquo' website = 'http://www.abiquo.com/' connectionCls = AbiquoConnection timeout = 2000 # some images take a lot of time! # Media Types NODES_MIME_TYPE = 'application/vnd.abiquo.virtualmachines+xml' NODE_MIME_TYPE = 'application/vnd.abiquo.virtualmachine+xml' VAPPS_MIME_TYPE = 'application/vnd.abiquo.virtualappliances+xml' VAPP_MIME_TYPE = 'application/vnd.abiquo.virtualappliance+xml' VM_TASK_MIME_TYPE = 'application/vnd.abiquo.virtualmachinetask+xml' USER_MIME_TYPE = 'application/vnd.abiquo.user+xml' ENT_MIME_TYPE = 'application/vnd.abiquo.enterprise+xml' VDCS_MIME_TYPE = 'application/vnd.abiquo.virtualdatacenters+xml' VDC_MIME_TYPE = 'application/vnd.abiquo.virtualdatacenter+xml' DCS_MIME_TYPE = 'application/vnd.abiquo.datacenters+xml' VMTPLS_MIME_TYPE = 'application/vnd.abiquo.virtualmachinetemplates+xml' VMTPL_MIME_TYPE = 'application/vnd.abiquo.virtualmachinetemplate+xml' NICS_MIME_TYPE = 'application/vnd.abiquo.nics+xml' DCRS_MIME_TYPE = 'application/vnd.abiquo.datacenterrepositories+xml' DCR_MIME_TYPE = 'application/vnd.abiquo.datacenterrepository+xml' AR_MIME_TYPE = 'application/vnd.abiquo.acceptedrequest+xml' # Others constants GIGABYTE = 1073741824 def __init__(self, user_id, secret, endpoint, **kwargs): """ Initializes Abiquo Driver Initializes the :class:`NodeDriver` object and populate the cache. :param user_id: identifier of Abiquo user (required) :type user_id: ``str`` :param secret: password of the Abiquo user (required) :type secret: ``str`` :param endpoint: Abiquo API endpoint (required) :type endpoint: ``str`` that can be parsed as URL """ self.endpoint = endpoint super(AbiquoNodeDriver, self).__init__(key=user_id, secret=secret, secure=False, host=None, port=None, **kwargs) self.ex_populate_cache() def create_node(self, image, name=None, size=None, location=None, ex_group_name=None): """ Create a new node instance in Abiquo All the :class:`Node`s need to be defined inside a VirtualAppliance (called :class:`NodeGroup` here). If there is no group name defined, 'libcloud' name will be used instead. This method wraps these Abiquo actions: 1. Create a group if it does not exist. 2. Register a new node in the group. 3. Deploy the node and boot it. 4. Retrieves it again to get schedule-time attributes (such as ips and vnc ports). The rest of the driver methods has been created in a way that, if any of these actions fail, the user can not reach an inconsistent state :keyword name: The name for this new node (required) :type name: ``str`` :keyword size: The size of resources allocated to this node. :type size: :class:`NodeSize` :keyword image: OS Image to boot on node. (required) :type image: :class:`NodeImage` :keyword location: Which data center to create a node in. If empty, undefined behavior will be selected. (optional) :type location: :class:`NodeLocation` :keyword ex_group_name: Which group this node belongs to. If empty, it will be created into 'libcloud' group. If it does not found any group in the target location (random location if you have not set the parameter), then it will create a new group with this name. :type ex_group_name: c{str} :return: The newly created node. :rtype: :class:`Node` """ # Define the location # To be clear: # 'xml_loc' is the xml element we navigate into (we need links) # 'loc' is the :class:`NodeLocation` entity xml_loc, loc = self._define_create_node_location(image=image, location=location) # Define the Group group = self._define_create_node_group(xml_loc, loc, ex_group_name) # Register the Node vm = self._define_create_node_node(group, name=name, size=size, image=image) # Execute the 'create' in hypervisor action self._deploy_remote(vm) # Retrieve it again, to get some schedule-time defined values edit_vm = get_href(vm, 'edit') headers = {'Accept': self.NODE_MIME_TYPE} vm = self.connection.request(edit_vm, headers=headers).object return self._to_node(vm, self) def destroy_node(self, node): """ Destroy a node Depending on the provider, this may destroy all data associated with the node, including backups. :param node: The node to be destroyed :type node: :class:`Node` :return: True if the destroy was successful, otherwise False :rtype: ``bool`` """ # Refresh node state headers = {'Accept': self.NODE_MIME_TYPE} e_vm = self.connection.request(node.extra['uri_id'], headers=headers).object state = e_vm.findtext('state') if state in ['ALLOCATED', 'CONFIGURED', 'LOCKED', 'UNKNOWN']: raise LibcloudError('Invalid Node state', self) if state != 'NOT_ALLOCATED': # prepare the element that forces the undeploy vm_task = ET.Element('virtualmachinetask') force_undeploy = ET.SubElement(vm_task, 'forceUndeploy') force_undeploy.text = 'True' # Set the URI destroy_uri = node.extra['uri_id'] + '/action/undeploy' # Prepare the headers headers = {'Accept': self.AR_MIME_TYPE, 'Content-type': self.VM_TASK_MIME_TYPE} res = self.connection.async_request(action=destroy_uri, method='POST', data=tostring(vm_task), headers=headers) if state == 'NOT_ALLOCATED' or res.async_success(): self.connection.request(action=node.extra['uri_id'], method='DELETE') return True else: return False def ex_run_node(self, node): """ Runs a node Here there is a bit difference between Abiquo states and libcloud states, so this method is created to have better compatibility. In libcloud, if the node is not running, then it does not exist (avoiding UNKNOWN and temporal states). In Abiquo, you can define a node, and then deploy it. If the node is in :class:`NodeState.TERMINATED` libcloud's state and in 'NOT_DEPLOYED' Abiquo state, there is a way to run and recover it for libcloud using this method. There is no way to reach this state if you are using only libcloud, but you may have used another Abiquo client and now you want to recover your node to be used by libcloud. :param node: The node to run :type node: :class:`Node` :return: The node itself, but with the new state :rtype: :class:`Node` """ # Refresh node state e_vm = self.connection.request(node.extra['uri_id']).object state = e_vm.findtext('state') if state != 'NOT_ALLOCATED': raise LibcloudError('Invalid Node state', self) # -------------------------------------------------------- # Deploy the Node # -------------------------------------------------------- self._deploy_remote(e_vm) # -------------------------------------------------------- # Retrieve it again, to get some schedule-defined # values. # -------------------------------------------------------- edit_vm = get_href(e_vm, 'edit') headers = {'Accept': self.NODE_MIME_TYPE} e_vm = self.connection.request(edit_vm, headers=headers).object return self._to_node(e_vm, self) def ex_populate_cache(self): """ Populate the cache. For each connection, it is good to store some objects that will be useful for further requests, such as the 'user' and the 'enterprise' objects. Executes the 'login' resource after setting the connection parameters and, if the execution is successful, it sets the 'user' object into cache. After that, it also requests for the 'enterprise' and 'locations' data. List of locations should remain the same for a single libcloud connection. However, this method is public and you are able to refresh the list of locations any time. """ user_headers = {'Accept': self.USER_MIME_TYPE} user = self.connection.request('/login', headers=user_headers).object self.connection.cache['user'] = user e_ent = get_href(self.connection.cache['user'], 'enterprise') ent_headers = {'Accept': self.ENT_MIME_TYPE} ent = self.connection.request(e_ent, headers=ent_headers).object self.connection.cache['enterprise'] = ent vdcs_headers = {'Accept': self.VDCS_MIME_TYPE} uri_vdcs = '/cloud/virtualdatacenters' e_vdcs = self.connection.request(uri_vdcs, headers=vdcs_headers).object params = {"idEnterprise": self._get_enterprise_id()} dcs_headers = {'Accept': self.DCS_MIME_TYPE} e_dcs = self.connection.request('/admin/datacenters', headers=dcs_headers, params=params).object dc_dict = {} for dc in e_dcs.findall('datacenter'): key = get_href(dc, 'self') dc_dict[key] = dc # Populate locations name cache self.connection.cache['locations'] = {} for e_vdc in e_vdcs.findall('virtualDatacenter'): loc = get_href(e_vdc, 'location') if loc is not None: self.connection.cache['locations'][loc] = get_href(e_vdc, 'edit') def ex_create_group(self, name, location=None): """ Create an empty group. You can specify the location as well. :param group: name of the group (required) :type group: ``str`` :param location: location were to create the group :type location: :class:`NodeLocation` :returns: the created group :rtype: :class:`NodeGroup` """ # prepare the element vapp = ET.Element('virtualAppliance') vapp_name = ET.SubElement(vapp, 'name') vapp_name.text = name if location is None: location = self.list_locations()[0] elif location not in self.list_locations(): raise LibcloudError('Location does not exist') link_vdc = self.connection.cache['locations'][location] hdr_vdc = {'Accept': self.VDC_MIME_TYPE} e_vdc = self.connection.request(link_vdc, headers=hdr_vdc).object creation_link = get_href(e_vdc, 'virtualappliances') headers = {'Accept': self.VAPP_MIME_TYPE, 'Content-type': self.VAPP_MIME_TYPE} vapp = self.connection.request(creation_link, data=tostring(vapp), headers=headers, method='POST').object uri_vapp = get_href(vapp, 'edit') return NodeGroup(self, vapp.findtext('name'), uri=uri_vapp) def ex_destroy_group(self, group): """ Destroy a group. Be careful! Destroying a group means destroying all the :class:`Node` instances there and the group itself! If there is currently any action over any :class:`Node` of the :class:`NodeGroup`, then the method will raise an exception. :param name: The group (required) :type name: :class:`NodeGroup` :return: If the group was destroyed successfully :rtype: ``bool`` """ # Refresh group state e_group = self.connection.request(group.uri).object state = e_group.findtext('state') if state not in ['NOT_DEPLOYED', 'DEPLOYED']: error = 'Can not destroy group because of current state' raise LibcloudError(error, self) if state == 'DEPLOYED': # prepare the element that forces the undeploy vm_task = ET.Element('virtualmachinetask') force_undeploy = ET.SubElement(vm_task, 'forceUndeploy') force_undeploy.text = 'True' # Set the URI undeploy_uri = group.uri + '/action/undeploy' # Prepare the headers headers = {'Accept': self.AR_MIME_TYPE, 'Content-type': self.VM_TASK_MIME_TYPE} res = self.connection.async_request(action=undeploy_uri, method='POST', data=tostring(vm_task), headers=headers) if state == 'NOT_DEPLOYED' or res.async_success(): # The node is no longer deployed. Unregister it. self.connection.request(action=group.uri, method='DELETE') return True else: return False def ex_list_groups(self, location=None): """ List all groups. :param location: filter the groups by location (optional) :type location: a :class:`NodeLocation` instance. :return: the list of :class:`NodeGroup` """ groups = [] for vdc in self._get_locations(location): link_vdc = self.connection.cache['locations'][vdc] hdr_vdc = {'Accept': self.VDC_MIME_TYPE} e_vdc = self.connection.request(link_vdc, headers=hdr_vdc).object apps_link = get_href(e_vdc, 'virtualappliances') hdr_vapps = {'Accept': self.VAPPS_MIME_TYPE} vapps = self.connection.request(apps_link, headers=hdr_vapps).object for vapp in vapps.findall('virtualAppliance'): nodes = [] vms_link = get_href(vapp, 'virtualmachines') headers = {'Accept': self.NODES_MIME_TYPE} vms = self.connection.request(vms_link, headers=headers).object for vm in vms.findall('virtualMachine'): nodes.append(self._to_node(vm, self)) group = NodeGroup(self, vapp.findtext('name'), nodes, get_href(vapp, 'edit')) groups.append(group) return groups def list_images(self, location=None): """ List images on Abiquo Repositories :keyword location: The location to list images for. :type location: :class:`NodeLocation` :return: list of node image objects :rtype: ``list`` of :class:`NodeImage` """ enterprise_id = self._get_enterprise_id() uri = '/admin/enterprises/%s/datacenterrepositories/' % (enterprise_id) repos_hdr = {'Accept': self.DCRS_MIME_TYPE} repos = self.connection.request(uri, headers=repos_hdr).object images = [] for repo in repos.findall('datacenterRepository'): # filter by location. Skips when the name of the location # is different from the 'datacenterRepository' element for vdc in self._get_locations(location): # Check if the virtual datacenter belongs to this repo link_vdc = self.connection.cache['locations'][vdc] hdr_vdc = {'Accept': self.VDC_MIME_TYPE} e_vdc = self.connection.request(link_vdc, headers=hdr_vdc).object dc_link_vdc = get_href(e_vdc, 'location') dc_link_repo = get_href(repo, 'datacenter') if dc_link_vdc.split("/")[-1] == dc_link_repo.split("/")[-1]: # Filter the template in case we don't have it yet url_templates = get_href(repo, 'virtualmachinetemplates') hypervisor_type = e_vdc.findtext('hypervisorType') params = {'hypervisorTypeName': hypervisor_type} headers = {'Accept': self.VMTPLS_MIME_TYPE} templates = self.connection.request(url_templates, params, headers=headers).object for templ in templates.findall('virtualMachineTemplate'): # Avoid duplicated templates id_template = templ.findtext('id') ids = [image.id for image in images] if id_template not in ids: images.append(self._to_nodeimage(templ, self, get_href(repo, 'edit'))) return images def list_locations(self): """ Return list of locations where the user has access to. :return: the list of :class:`NodeLocation` available for the current user :rtype: ``list`` of :class:`NodeLocation` """ return list(self.connection.cache['locations'].keys()) def list_nodes(self, location=None): """ List all nodes. :param location: Filter the groups by location (optional) :type location: a :class:`NodeLocation` instance. :return: List of node objects :rtype: ``list`` of :class:`Node` """ nodes = [] for group in self.ex_list_groups(location): nodes.extend(group.nodes) return nodes def list_sizes(self, location=None): """ List sizes on a provider. Abiquo does not work with sizes. However, this method returns a list of predefined ones (copied from :class:`DummyNodeDriver` but without price neither bandwidth) to help the users to create their own. If you call the method :class:`AbiquoNodeDriver.create_node` with the size informed, it will just override the 'ram' value of the 'image' template. So it is no too much usefull work with sizes... :return: The list of sizes :rtype: ``list`` of :class:`NodeSizes` """ return [ NodeSize(id=1, name='Small', ram=128, disk=4, bandwidth=None, price=None, driver=self), NodeSize(id=2, name='Medium', ram=512, disk=16, bandwidth=None, price=None, driver=self), NodeSize(id=3, name='Big', ram=4096, disk=32, bandwidth=None, price=None, driver=self), NodeSize(id=4, name="XXL Big", ram=4096 * 2, disk=32 * 4, bandwidth=None, price=None, driver=self) ] def reboot_node(self, node): """ Reboot a node. :param node: The node to be rebooted :type node: :class:`Node` :return: True if the reboot was successful, otherwise False :rtype: ``bool`` """ reboot_uri = node.extra['uri_id'] + '/action/reset' reboot_hdr = {'Accept': self.AR_MIME_TYPE} res = self.connection.async_request(action=reboot_uri, method='POST', headers=reboot_hdr) return res.async_success() # ------------------------- # Extenstion methods # ------------------------- def _ex_connection_class_kwargs(self): """ Set the endpoint as an extra :class:`AbiquoConnection` argument. According to Connection code, the "url" argument should be parsed properly to connection. :return: ``dict`` of :class:`AbiquoConnection` input arguments """ return {'url': self.endpoint} def _deploy_remote(self, e_vm): """ Asynchronous call to create the node. """ # -------------------------------------------------------- # Deploy the Node # -------------------------------------------------------- # prepare the element that forces the deploy vm_task = ET.Element('virtualmachinetask') force_deploy = ET.SubElement(vm_task, 'forceEnterpriseSoftLimits') force_deploy.text = 'True' # Prepare the headers headers = {'Accept': self.AR_MIME_TYPE, 'Content-type': self.VM_TASK_MIME_TYPE} link_deploy = get_href(e_vm, 'deploy') res = self.connection.async_request(action=link_deploy, method='POST', data=tostring(vm_task), headers=headers) if not res.async_success(): raise LibcloudError('Could not run the node', self) def _to_location(self, vdc, dc, driver): """ Generates the :class:`NodeLocation` class. """ identifier = vdc.findtext('id') name = vdc.findtext('name') country = dc.findtext('name') return NodeLocation(identifier, name, country, driver) def _to_node(self, vm, driver): """ Generates the :class:`Node` class. """ identifier = vm.findtext('id') name = vm.findtext('label') state = AbiquoResponse.NODE_STATE_MAP[vm.findtext('state')] link_image = get_href(vm, 'virtualmachinetemplate') link_hdr = {'Accept': self.VMTPL_MIME_TYPE} image_element = self.connection.request(link_image, headers=link_hdr).object repo_link = get_href(image_element, 'datacenterrepository') image = self._to_nodeimage(image_element, self, repo_link) # Fill the 'ips' data private_ips = [] public_ips = [] nics_hdr = {'Accept': self.NICS_MIME_TYPE} nics_element = self.connection.request(get_href(vm, 'nics'), headers=nics_hdr).object for nic in nics_element.findall('nic'): ip = nic.findtext('ip') for link in nic.findall('link'): rel = link.attrib['rel'] if rel == 'privatenetwork': private_ips.append(ip) elif rel in ['publicnetwork', 'externalnetwork', 'unmanagednetwork']: public_ips.append(ip) extra = {'uri_id': get_href(vm, 'edit')} if vm.find('vdrpIp') is not None: extra['vdrp_ip'] = vm.findtext('vdrpIP') extra['vdrp_port'] = vm.findtext('vdrpPort') return Node(identifier, name, state, public_ips, private_ips, driver, image=image, extra=extra) def _to_nodeimage(self, template, driver, repo): """ Generates the :class:`NodeImage` class. """ identifier = template.findtext('id') name = template.findtext('name') url = get_href(template, 'edit') hdreqd = template.findtext('hdRequired') extra = {'repo': repo, 'url': url, 'hdrequired': hdreqd} return NodeImage(identifier, name, driver, extra) def _get_locations(self, location=None): """ Returns the locations as a generator. """ if location is not None: yield location else: for loc in self.list_locations(): yield loc def _get_enterprise_id(self): """ Returns the identifier of the logged user's enterprise. """ return self.connection.cache['enterprise'].findtext('id') def _define_create_node_location(self, image, location): """ Search for a location where to create the node. Based on 'create_node' **kwargs argument, decide in which location will be created. """ # First, get image location if not image: error = "'image' parameter is mandatory" raise LibcloudError(error, self) # Get the location argument if location: if location not in self.list_locations(): raise LibcloudError('Location does not exist') # Check if the image is compatible with any of the locations or # the input location loc = None target_loc = None for candidate_loc in self._get_locations(location): link_vdc = self.connection.cache['locations'][candidate_loc] hdr_vdc = {'Accept': self.VDC_MIME_TYPE} e_vdc = self.connection.request(link_vdc, headers=hdr_vdc).object for img in self.list_images(candidate_loc): if img.id == image.id: loc = e_vdc target_loc = candidate_loc break if loc is None: error = 'The image can not be used in any location' raise LibcloudError(error, self) return loc, target_loc def _define_create_node_group(self, xml_loc, loc, group_name=None): """ Search for a group where to create the node. If we can not find any group, create it into argument 'location' """ if not group_name: group_name = NodeGroup.DEFAULT_GROUP_NAME # We search if the group is already defined into the location groups_link = get_href(xml_loc, 'virtualappliances') groups_hdr = {'Accept': self.VAPPS_MIME_TYPE} vapps_element = self.connection.request(groups_link, headers=groups_hdr).object target_group = None for vapp in vapps_element.findall('virtualAppliance'): if vapp.findtext('name') == group_name: uri_vapp = get_href(vapp, 'edit') return NodeGroup(self, vapp.findtext('name'), uri=uri_vapp) # target group not found: create it. Since it is an extension of # the basic 'libcloud' functionality, we try to be as flexible as # possible. if target_group is None: return self.ex_create_group(group_name, loc) def _define_create_node_node(self, group, name=None, size=None, image=None): """ Defines the node before to create. In Abiquo, you first need to 'register' or 'define' the node in the API before to create it into the target hypervisor. """ vm = ET.Element('virtualMachine') if name: vmname = ET.SubElement(vm, 'label') vmname.text = name attrib = {'type': self.VMTPL_MIME_TYPE, 'rel': 'virtualmachinetemplate', 'href': image.extra['url']} ET.SubElement(vm, 'link', attrib=attrib) headers = {'Accept': self.NODE_MIME_TYPE, 'Content-type': self.NODE_MIME_TYPE} if size: # Override the 'NodeSize' data ram = ET.SubElement(vm, 'ram') ram.text = str(size.ram) # Create the virtual machine nodes_link = group.uri + '/virtualmachines' vm = self.connection.request(nodes_link, data=tostring(vm), headers=headers, method='POST').object edit_vm = get_href(vm, 'edit') headers = {'Accept': self.NODE_MIME_TYPE} return self.connection.request(edit_vm, headers=headers).object class NodeGroup(object): """ Group of virtual machines that can be managed together All :class:`Node`s in Abiquo must be defined inside a Virtual Appliance. We offer a way to handle virtual appliances (called NodeGroup to maintain some kind of name conventions here) inside the :class:`AbiquoNodeDriver` without breaking compatibility of the rest of libcloud API. If the user does not want to handle groups, all the virtual machines will be created inside a group named 'libcloud' """ DEFAULT_GROUP_NAME = 'libcloud' def __init__(self, driver, name=DEFAULT_GROUP_NAME, nodes=[], uri=''): """ Initialize a new group object. """ self.driver = driver self.name = name self.nodes = nodes self.uri = uri def __repr__(self): return (('') % (self.name, ",".join(map(str, self.nodes)))) def destroy(self): """ Destroys the group delegating the execution to :class:`AbiquoNodeDriver`. """ return self.driver.ex_destroy_group(self) apache-libcloud-2.8.0/libcloud/compute/drivers/auroracompute.py0000664000175000017500000000377013535474530024632 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.providers import Provider from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver __all__ = [ 'AuroraComputeRegion', 'AuroraComputeNodeDriver' ] class AuroraComputeRegion(object): AMS = 'Amsterdam' RTD = 'Rotterdam' MIA = 'Miami' LAX = 'Los Angeles' TYO = 'Tokyo' BCN = 'Barcelona' REGION_ENDPOINT_MAP = { AuroraComputeRegion.AMS: '/ams', AuroraComputeRegion.RTD: '/rtd', AuroraComputeRegion.MIA: '/mia', AuroraComputeRegion.LAX: '/lax', AuroraComputeRegion.TYO: '/tyo', AuroraComputeRegion.BCN: '/bcn' } class AuroraComputeNodeDriver(CloudStackNodeDriver): type = Provider.AURORACOMPUTE name = 'PCextreme AuroraCompute' website = 'https://www.pcextreme.com/aurora/compute' def __init__(self, key, secret, path=None, host=None, url=None, region=None): if host is None: host = 'api.auroracompute.eu' if path is None: path = REGION_ENDPOINT_MAP.get(region, '/ams') super(AuroraComputeNodeDriver, self).__init__(key=key, secret=secret, host=host, path=path, secure=True) apache-libcloud-2.8.0/libcloud/compute/drivers/azure.py0000664000175000017500000033467713600144066023076 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Driver for Microsoft Azure Virtual Machines service. http://azure.microsoft.com/en-us/services/virtual-machines/ """ import re import time import collections import random import sys import copy import base64 from datetime import datetime from xml.dom import minidom from xml.sax.saxutils import escape as xml_escape from libcloud.utils.py3 import ET from libcloud.common.azure import AzureServiceManagementConnection from libcloud.common.azure import AzureRedirectException from libcloud.compute.providers import Provider from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize from libcloud.compute.base import NodeImage, StorageVolume from libcloud.compute.types import NodeState from libcloud.common.types import LibcloudError from libcloud.utils.py3 import _real_unicode from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import ensure_string from libcloud.utils.py3 import urlquote as url_quote from libcloud.utils.misc import ReprMixin HTTPSConnection = httplib.HTTPSConnection if sys.version_info < (3,): _unicode_type = unicode def _str(value): if isinstance(value, unicode): return value.encode('utf-8') return str(value) else: _str = str _unicode_type = str AZURE_SERVICE_MANAGEMENT_HOST = 'management.core.windows.net' X_MS_VERSION = '2013-08-01' WINDOWS_SERVER_REGEX = re.compile( r'Win|SQL|SharePoint|Visual|Dynamics|DynGP|BizTalk' ) """ Sizes must be hardcoded because Microsoft doesn't provide an API to fetch them From http://msdn.microsoft.com/en-us/library/windowsazure/dn197896.aspx Prices are for Linux instances in East US data center. To see what pricing will actually be, visit: http://azure.microsoft.com/en-gb/pricing/details/virtual-machines/ """ AZURE_COMPUTE_INSTANCE_TYPES = { 'A0': { 'id': 'ExtraSmall', 'name': 'Extra Small Instance', 'ram': 768, 'disk': 127, 'bandwidth': None, 'price': '0.0211', 'max_data_disks': 1, 'cores': 'Shared' }, 'A1': { 'id': 'Small', 'name': 'Small Instance', 'ram': 1792, 'disk': 127, 'bandwidth': None, 'price': '0.0633', 'max_data_disks': 2, 'cores': 1 }, 'A2': { 'id': 'Medium', 'name': 'Medium Instance', 'ram': 3584, 'disk': 127, 'bandwidth': None, 'price': '0.1266', 'max_data_disks': 4, 'cores': 2 }, 'A3': { 'id': 'Large', 'name': 'Large Instance', 'ram': 7168, 'disk': 127, 'bandwidth': None, 'price': '0.2531', 'max_data_disks': 8, 'cores': 4 }, 'A4': { 'id': 'ExtraLarge', 'name': 'Extra Large Instance', 'ram': 14336, 'disk': 127, 'bandwidth': None, 'price': '0.5062', 'max_data_disks': 16, 'cores': 8 }, 'A5': { 'id': 'A5', 'name': 'Memory Intensive Instance', 'ram': 14336, 'disk': 127, 'bandwidth': None, 'price': '0.2637', 'max_data_disks': 4, 'cores': 2 }, 'A6': { 'id': 'A6', 'name': 'A6 Instance', 'ram': 28672, 'disk': 127, 'bandwidth': None, 'price': '0.5273', 'max_data_disks': 8, 'cores': 4 }, 'A7': { 'id': 'A7', 'name': 'A7 Instance', 'ram': 57344, 'disk': 127, 'bandwidth': None, 'price': '1.0545', 'max_data_disks': 16, 'cores': 8 }, 'A8': { 'id': 'A8', 'name': 'A8 Instance', 'ram': 57344, 'disk': 127, 'bandwidth': None, 'price': '2.0774', 'max_data_disks': 16, 'cores': 8 }, 'A9': { 'id': 'A9', 'name': 'A9 Instance', 'ram': 114688, 'disk': 127, 'bandwidth': None, 'price': '4.7137', 'max_data_disks': 16, 'cores': 16 }, 'A10': { 'id': 'A10', 'name': 'A10 Instance', 'ram': 57344, 'disk': 127, 'bandwidth': None, 'price': '1.2233', 'max_data_disks': 16, 'cores': 8 }, 'A11': { 'id': 'A11', 'name': 'A11 Instance', 'ram': 114688, 'disk': 127, 'bandwidth': None, 'price': '2.1934', 'max_data_disks': 16, 'cores': 16 }, 'D1': { 'id': 'Standard_D1', 'name': 'D1 Faster Compute Instance', 'ram': 3584, 'disk': 127, 'bandwidth': None, 'price': '0.0992', 'max_data_disks': 2, 'cores': 1 }, 'D2': { 'id': 'Standard_D2', 'name': 'D2 Faster Compute Instance', 'ram': 7168, 'disk': 127, 'bandwidth': None, 'price': '0.1983', 'max_data_disks': 4, 'cores': 2 }, 'D3': { 'id': 'Standard_D3', 'name': 'D3 Faster Compute Instance', 'ram': 14336, 'disk': 127, 'bandwidth': None, 'price': '0.3965', 'max_data_disks': 8, 'cores': 4 }, 'D4': { 'id': 'Standard_D4', 'name': 'D4 Faster Compute Instance', 'ram': 28672, 'disk': 127, 'bandwidth': None, 'price': '0.793', 'max_data_disks': 16, 'cores': 8 }, 'D11': { 'id': 'Standard_D11', 'name': 'D11 Faster Compute Instance', 'ram': 14336, 'disk': 127, 'bandwidth': None, 'price': '0.251', 'max_data_disks': 4, 'cores': 2 }, 'D12': { 'id': 'Standard_D12', 'name': 'D12 Faster Compute Instance', 'ram': 28672, 'disk': 127, 'bandwidth': None, 'price': '0.502', 'max_data_disks': 8, 'cores': 4 }, 'D13': { 'id': 'Standard_D13', 'name': 'D13 Faster Compute Instance', 'ram': 57344, 'disk': 127, 'bandwidth': None, 'price': '0.9038', 'max_data_disks': 16, 'cores': 8 }, 'D14': { 'id': 'Standard_D14', 'name': 'D14 Faster Compute Instance', 'ram': 114688, 'disk': 127, 'bandwidth': None, 'price': '1.6261', 'max_data_disks': 32, 'cores': 16 } } _KNOWN_SERIALIZATION_XFORMS = { 'include_apis': 'IncludeAPIs', 'message_id': 'MessageId', 'content_md5': 'Content-MD5', 'last_modified': 'Last-Modified', 'cache_control': 'Cache-Control', 'account_admin_live_email_id': 'AccountAdminLiveEmailId', 'service_admin_live_email_id': 'ServiceAdminLiveEmailId', 'subscription_id': 'SubscriptionID', 'fqdn': 'FQDN', 'private_id': 'PrivateID', 'os_virtual_hard_disk': 'OSVirtualHardDisk', 'logical_disk_size_in_gb': 'LogicalDiskSizeInGB', 'logical_size_in_gb': 'LogicalSizeInGB', 'os': 'OS', 'persistent_vm_downtime_info': 'PersistentVMDowntimeInfo', 'copy_id': 'CopyId', 'os_disk_configuration': 'OSDiskConfiguration', 'is_dns_programmed': 'IsDnsProgrammed' } class AzureNodeDriver(NodeDriver): connectionCls = AzureServiceManagementConnection name = 'Azure Virtual machines' website = 'http://azure.microsoft.com/en-us/services/virtual-machines/' type = Provider.AZURE _instance_types = AZURE_COMPUTE_INSTANCE_TYPES _blob_url = ".blob.core.windows.net" features = {'create_node': ['password']} service_location = collections.namedtuple( 'service_location', ['is_affinity_group', 'service_location'] ) NODE_STATE_MAP = { 'RoleStateUnknown': NodeState.UNKNOWN, 'CreatingVM': NodeState.PENDING, 'StartingVM': NodeState.PENDING, 'Provisioning': NodeState.PENDING, 'CreatingRole': NodeState.PENDING, 'StartingRole': NodeState.PENDING, 'ReadyRole': NodeState.RUNNING, 'BusyRole': NodeState.PENDING, 'StoppingRole': NodeState.PENDING, 'StoppingVM': NodeState.PENDING, 'DeletingVM': NodeState.PENDING, 'StoppedVM': NodeState.STOPPED, 'RestartingRole': NodeState.REBOOTING, 'CyclingRole': NodeState.TERMINATED, 'FailedStartingRole': NodeState.TERMINATED, 'FailedStartingVM': NodeState.TERMINATED, 'UnresponsiveRole': NodeState.TERMINATED, 'StoppedDeallocated': NodeState.TERMINATED, } def __init__(self, subscription_id=None, key_file=None, **kwargs): """ subscription_id contains the Azure subscription id in the form of GUID key_file contains the Azure X509 certificate in .pem form """ self.subscription_id = subscription_id self.key_file = key_file self.follow_redirects = kwargs.get('follow_redirects', True) super(AzureNodeDriver, self).__init__( self.subscription_id, self.key_file, secure=True, **kwargs ) def list_sizes(self): """ Lists all sizes :rtype: ``list`` of :class:`NodeSize` """ sizes = [] for _, values in self._instance_types.items(): node_size = self._to_node_size(copy.deepcopy(values)) sizes.append(node_size) return sizes def list_images(self, location=None): """ Lists all images :rtype: ``list`` of :class:`NodeImage` """ data = self._perform_get(self._get_image_path(), Images) custom_image_data = self._perform_get( self._get_vmimage_path(), VMImages ) images = [self._to_image(i) for i in data] images.extend(self._vm_to_image(j) for j in custom_image_data) if location is not None: images = [ image for image in images if location in image.extra["location"] ] return images def list_locations(self): """ Lists all locations :rtype: ``list`` of :class:`NodeLocation` """ data = self._perform_get( '/' + self.subscription_id + '/locations', Locations ) return [self._to_location(l) for l in data] def list_nodes(self, ex_cloud_service_name): """ List all nodes ex_cloud_service_name parameter is used to scope the request to a specific Cloud Service. This is a required parameter as nodes cannot exist outside of a Cloud Service nor be shared between a Cloud Service within Azure. :param ex_cloud_service_name: Cloud Service name :type ex_cloud_service_name: ``str`` :rtype: ``list`` of :class:`Node` """ response = self._perform_get( self._get_hosted_service_path(ex_cloud_service_name) + '?embed-detail=True', None ) self.raise_for_response(response, 200) data = self._parse_response(response, HostedService) vips = None if (len(data.deployments) > 0 and data.deployments[0].virtual_ips is not None): vips = [vip.address for vip in data.deployments[0].virtual_ips] try: return [ self._to_node(n, ex_cloud_service_name, vips) for n in data.deployments[0].role_instance_list ] except IndexError: return [] def reboot_node(self, node, ex_cloud_service_name=None, ex_deployment_slot=None): """ Reboots a node. ex_cloud_service_name parameter is used to scope the request to a specific Cloud Service. This is a required parameter as nodes cannot exist outside of a Cloud Service nor be shared between a Cloud Service within Azure. :param ex_cloud_service_name: Cloud Service name :type ex_cloud_service_name: ``str`` :param ex_deployment_slot: Options are "production" (default) or "Staging". (Optional) :type ex_deployment_slot: ``str`` :rtype: ``bool`` """ if ex_cloud_service_name is None: if node.extra is not None: ex_cloud_service_name = node.extra.get( 'ex_cloud_service_name' ) if not ex_cloud_service_name: raise ValueError("ex_cloud_service_name is required.") if not ex_deployment_slot: ex_deployment_slot = "Production" _deployment_name = self._get_deployment( service_name=ex_cloud_service_name, deployment_slot=ex_deployment_slot ).name try: response = self._perform_post( self._get_deployment_path_using_name( ex_cloud_service_name, _deployment_name ) + '/roleinstances/' + _str(node.id) + '?comp=reboot', '' ) self.raise_for_response(response, 202) if self._parse_response_for_async_op(response): return True else: return False except Exception: return False def list_volumes(self, node=None): """ Lists volumes of the disks in the image repository that are associated with the specified subscription. Pass Node object to scope the list of volumes to a single instance. :rtype: ``list`` of :class:`StorageVolume` """ data = self._perform_get(self._get_disk_path(), Disks) volumes = [self._to_volume(volume=v, node=node) for v in data] return volumes def create_node(self, name, size, image, ex_cloud_service_name, ex_storage_service_name=None, ex_new_deployment=False, ex_deployment_slot="Production", ex_deployment_name=None, ex_admin_user_id="azureuser", ex_custom_data=None, ex_virtual_network_name=None, ex_network_config=None, auth=None, **kwargs): """ Create Azure Virtual Machine Reference: http://bit.ly/1fIsCb7 [www.windowsazure.com/en-us/documentation/] We default to: + 3389/TCP - RDP - 1st Microsoft instance. + RANDOM/TCP - RDP - All succeeding Microsoft instances. + 22/TCP - SSH - 1st Linux instance + RANDOM/TCP - SSH - All succeeding Linux instances. The above replicates the standard behavior of the Azure UI. You can retrieve the assigned ports to each instance by using the following private function: _get_endpoint_ports(service_name) Returns public,private port key pair. @inherits: :class:`NodeDriver.create_node` :keyword image: The image to use when creating this node :type image: `NodeImage` :keyword size: The size of the instance to create :type size: `NodeSize` :keyword ex_cloud_service_name: Required. Name of the Azure Cloud Service. :type ex_cloud_service_name: ``str`` :keyword ex_storage_service_name: Optional: Name of the Azure Storage Service. :type ex_storage_service_name: ``str`` :keyword ex_new_deployment: Optional. Tells azure to create a new deployment rather than add to an existing one. :type ex_new_deployment: ``boolean`` :keyword ex_deployment_slot: Optional: Valid values: production| staging. Defaults to production. :type ex_deployment_slot: ``str`` :keyword ex_deployment_name: Optional. The name of the deployment. If this is not passed in we default to using the Cloud Service name. :type ex_deployment_name: ``str`` :type ex_custom_data: ``str`` :keyword ex_custom_data: Optional script or other data which is injected into the VM when it's beginning provisioned. :keyword ex_admin_user_id: Optional. Defaults to 'azureuser'. :type ex_admin_user_id: ``str`` :keyword ex_virtual_network_name: Optional. If this is not passed in no virtual network is used. :type ex_virtual_network_name: ``str`` :keyword ex_network_config: Optional. The ConfigurationSet to use for network configuration :type ex_network_config: `ConfigurationSet` """ # TODO: Refactor this method to make it more readable, split it into # multiple smaller methods auth = self._get_and_check_auth(auth) password = auth.password if not isinstance(size, NodeSize): raise ValueError('Size must be an instance of NodeSize') if not isinstance(image, NodeImage): raise ValueError( "Image must be an instance of NodeImage, " "produced by list_images()" ) # Retrieve a list of currently available nodes for the provided cloud # service node_list = self.list_nodes( ex_cloud_service_name=ex_cloud_service_name ) if ex_network_config is None: network_config = ConfigurationSet() else: network_config = ex_network_config network_config.configuration_set_type = 'NetworkConfiguration' # Base64 encode custom data if provided if ex_custom_data: ex_custom_data = self._encode_base64(data=ex_custom_data) # We do this because we need to pass a Configuration to the # method. This will be either Linux or Windows. if WINDOWS_SERVER_REGEX.search(image.id, re.I): machine_config = WindowsConfigurationSet( computer_name=name, admin_password=password, admin_user_name=ex_admin_user_id ) machine_config.domain_join = None if not node_list or ex_new_deployment: port = "3389" else: port = random.randint(41952, 65535) endpoints = self._get_deployment( service_name=ex_cloud_service_name, deployment_slot=ex_deployment_slot ) for instances in endpoints.role_instance_list: ports = [ep.public_port for ep in instances.instance_endpoints] while port in ports: port = random.randint(41952, 65535) endpoint = ConfigurationSetInputEndpoint( name='Remote Desktop', protocol='tcp', port=port, local_port='3389', load_balanced_endpoint_set_name=None, enable_direct_server_return=False ) else: if not node_list or ex_new_deployment: port = "22" else: port = random.randint(41952, 65535) endpoints = self._get_deployment( service_name=ex_cloud_service_name, deployment_slot=ex_deployment_slot ) for instances in endpoints.role_instance_list: ports = [] if instances.instance_endpoints is not None: for ep in instances.instance_endpoints: ports += [ep.public_port] while port in ports: port = random.randint(41952, 65535) endpoint = ConfigurationSetInputEndpoint( name='SSH', protocol='tcp', port=port, local_port='22', load_balanced_endpoint_set_name=None, enable_direct_server_return=False ) machine_config = LinuxConfigurationSet( name, ex_admin_user_id, password, False, ex_custom_data ) network_config.input_endpoints.items.append(endpoint) _storage_location = self._get_cloud_service_location( service_name=ex_cloud_service_name ) if ex_storage_service_name is None: ex_storage_service_name = ex_cloud_service_name ex_storage_service_name = re.sub( r'[\W_-]+', '', ex_storage_service_name.lower(), flags=re.UNICODE ) if self._is_storage_service_unique( service_name=ex_storage_service_name): self._create_storage_account( service_name=ex_storage_service_name, location=_storage_location.service_location, is_affinity_group=_storage_location.is_affinity_group ) # OK, bit annoying here. You must create a deployment before # you can create an instance; however, the deployment function # creates the first instance, but all subsequent instances # must be created using the add_role function. # # So, yeah, annoying. if not node_list or ex_new_deployment: # This is the first node in this cloud service. if not ex_deployment_name: ex_deployment_name = ex_cloud_service_name vm_image_id = None disk_config = None if image.extra.get('vm_image', False): vm_image_id = image.id # network_config = None else: blob_url = "http://%s.blob.core.windows.net" % ( ex_storage_service_name) # Azure's pattern in the UI. disk_name = "%s-%s-%s.vhd" % ( ex_cloud_service_name, name, time.strftime("%Y-%m-%d") ) media_link = "%s/vhds/%s" % (blob_url, disk_name) disk_config = OSVirtualHardDisk(image.id, media_link) response = self._perform_post( self._get_deployment_path_using_name(ex_cloud_service_name), AzureXmlSerializer.virtual_machine_deployment_to_xml( ex_deployment_name, ex_deployment_slot, name, name, machine_config, disk_config, 'PersistentVMRole', network_config, None, None, size.id, ex_virtual_network_name, vm_image_id ) ) self.raise_for_response(response, 202) self._ex_complete_async_azure_operation(response) else: _deployment_name = self._get_deployment( service_name=ex_cloud_service_name, deployment_slot=ex_deployment_slot ).name vm_image_id = None disk_config = None if image.extra.get('vm_image', False): vm_image_id = image.id # network_config = None else: blob_url = "http://%s.blob.core.windows.net" % ( ex_storage_service_name ) disk_name = "%s-%s-%s.vhd" % ( ex_cloud_service_name, name, time.strftime("%Y-%m-%d") ) media_link = "%s/vhds/%s" % (blob_url, disk_name) disk_config = OSVirtualHardDisk(image.id, media_link) path = self._get_role_path(ex_cloud_service_name, _deployment_name) body = AzureXmlSerializer.add_role_to_xml( name, # role_name machine_config, # system_config disk_config, # os_virtual_hard_disk 'PersistentVMRole', # role_type network_config, # network_config None, # availability_set_name None, # data_virtual_hard_disks vm_image_id, # vm_image size.id # role_size ) response = self._perform_post(path, body) self.raise_for_response(response, 202) self._ex_complete_async_azure_operation(response) return Node( id=name, name=name, state=NodeState.PENDING, public_ips=[], private_ips=[], driver=self.connection.driver, extra={ 'ex_cloud_service_name': ex_cloud_service_name } ) def destroy_node(self, node, ex_cloud_service_name=None, ex_deployment_slot="Production"): """ Remove Azure Virtual Machine This removes the instance, but does not remove the disk. You will need to use destroy_volume. Azure sometimes has an issue where it will hold onto a blob lease for an extended amount of time. :keyword ex_cloud_service_name: Required. Name of the Azure Cloud Service. :type ex_cloud_service_name: ``str`` :keyword ex_deployment_slot: Optional: The name of the deployment slot. If this is not passed in we default to production. :type ex_deployment_slot: ``str`` """ if not isinstance(node, Node): raise ValueError("A libcloud Node object is required.") if ex_cloud_service_name is None and node.extra is not None: ex_cloud_service_name = node.extra.get('ex_cloud_service_name') if not ex_cloud_service_name: raise ValueError("Unable to get ex_cloud_service_name from Node.") _deployment = self._get_deployment( service_name=ex_cloud_service_name, deployment_slot=ex_deployment_slot ) _deployment_name = _deployment.name _server_deployment_count = len(_deployment.role_instance_list) if _server_deployment_count > 1: path = self._get_role_path( ex_cloud_service_name, _deployment_name, node.id ) else: path = self._get_deployment_path_using_name( ex_cloud_service_name, _deployment_name ) path += '?comp=media' self._perform_delete(path) return True def ex_list_cloud_services(self): return self._perform_get( self._get_hosted_service_path(), HostedServices ) def ex_create_cloud_service(self, name, location, description=None, extended_properties=None): """ Create an azure cloud service. :param name: Name of the service to create :type name: ``str`` :param location: Standard azure location string :type location: ``str`` :param description: Optional description :type description: ``str`` :param extended_properties: Optional extended_properties :type extended_properties: ``dict`` :rtype: ``bool`` """ response = self._perform_cloud_service_create( self._get_hosted_service_path(), AzureXmlSerializer.create_hosted_service_to_xml( name, self._encode_base64(name), description, location, None, extended_properties ) ) self.raise_for_response(response, 201) return True def ex_destroy_cloud_service(self, name): """ Delete an azure cloud service. :param name: Name of the cloud service to destroy. :type name: ``str`` :rtype: ``bool`` """ response = self._perform_cloud_service_delete( self._get_hosted_service_path(name) ) self.raise_for_response(response, 200) return True def ex_add_instance_endpoints(self, node, endpoints, ex_deployment_slot="Production"): all_endpoints = [ { "name": endpoint.name, "protocol": endpoint.protocol, "port": endpoint.public_port, "local_port": endpoint.local_port, } for endpoint in node.extra['instance_endpoints'] ] all_endpoints.extend(endpoints) result = self.ex_set_instance_endpoints(node, all_endpoints, ex_deployment_slot) return result def ex_set_instance_endpoints(self, node, endpoints, ex_deployment_slot="Production"): """ For example:: endpoint = ConfigurationSetInputEndpoint( name='SSH', protocol='tcp', port=port, local_port='22', load_balanced_endpoint_set_name=None, enable_direct_server_return=False ) { 'name': 'SSH', 'protocol': 'tcp', 'port': port, 'local_port': '22' } """ ex_cloud_service_name = node.extra['ex_cloud_service_name'] vm_role_name = node.name network_config = ConfigurationSet() network_config.configuration_set_type = 'NetworkConfiguration' for endpoint in endpoints: new_endpoint = ConfigurationSetInputEndpoint(**endpoint) network_config.input_endpoints.items.append(new_endpoint) _deployment_name = self._get_deployment( service_name=ex_cloud_service_name, deployment_slot=ex_deployment_slot ).name response = self._perform_put( self._get_role_path( ex_cloud_service_name, _deployment_name, vm_role_name ), AzureXmlSerializer.add_role_to_xml( None, # role_name None, # system_config None, # os_virtual_hard_disk 'PersistentVMRole', # role_type network_config, # network_config None, # availability_set_name None, # data_virtual_hard_disks None, # vm_image None # role_size ) ) self.raise_for_response(response, 202) def ex_create_storage_service(self, name, location, description=None, affinity_group=None, extended_properties=None): """ Create an azure storage service. :param name: Name of the service to create :type name: ``str`` :param location: Standard azure location string :type location: ``str`` :param description: (Optional) Description of storage service. :type description: ``str`` :param affinity_group: (Optional) Azure affinity group. :type affinity_group: ``str`` :param extended_properties: (Optional) Additional configuration options support by Azure. :type extended_properties: ``dict`` :rtype: ``bool`` """ response = self._perform_storage_service_create( self._get_storage_service_path(), AzureXmlSerializer.create_storage_service_to_xml( service_name=name, label=self._encode_base64(name), description=description, location=location, affinity_group=affinity_group, extended_properties=extended_properties ) ) self.raise_for_response(response, 202) return True def ex_destroy_storage_service(self, name): """ Destroy storage service. Storage service must not have any active blobs. Sometimes Azure likes to hold onto volumes after they are deleted for an inordinate amount of time, so sleep before calling this method after volume deletion. :param name: Name of storage service. :type name: ``str`` :rtype: ``bool`` """ response = self._perform_storage_service_delete( self._get_storage_service_path(name) ) self.raise_for_response(response, 200) return True """ Functions not implemented """ def create_volume_snapshot(self): raise NotImplementedError( 'You cannot create snapshots of ' 'Azure VMs at this time.' ) def attach_volume(self): raise NotImplementedError( 'attach_volume is not supported ' 'at this time.' ) def create_volume(self): raise NotImplementedError( 'create_volume is not supported ' 'at this time.' ) def detach_volume(self): raise NotImplementedError( 'detach_volume is not supported ' 'at this time.' ) def destroy_volume(self): raise NotImplementedError( 'destroy_volume is not supported ' 'at this time.' ) """ Private Functions """ def _perform_cloud_service_create(self, path, data): request = AzureHTTPRequest() request.method = 'POST' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.body = data request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) return response def _perform_cloud_service_delete(self, path): request = AzureHTTPRequest() request.method = 'DELETE' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) return response def _perform_storage_service_create(self, path, data): request = AzureHTTPRequest() request.method = 'POST' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.body = data request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) return response def _perform_storage_service_delete(self, path): request = AzureHTTPRequest() request.method = 'DELETE' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) return response def _to_node(self, data, ex_cloud_service_name=None, virtual_ips=None): """ Convert the data from a Azure response object into a Node """ remote_desktop_port = '' ssh_port = '' public_ips = virtual_ips or [] if data.instance_endpoints is not None: if len(data.instance_endpoints) >= 1: public_ips = [data.instance_endpoints[0].vip] for port in data.instance_endpoints: if port.name == 'Remote Desktop': remote_desktop_port = port.public_port if port.name == "SSH": ssh_port = port.public_port return Node( id=data.role_name, name=data.role_name, state=self.NODE_STATE_MAP.get( data.instance_status, NodeState.UNKNOWN ), public_ips=public_ips, private_ips=[data.ip_address], driver=self.connection.driver, extra={ 'instance_endpoints': data.instance_endpoints, 'remote_desktop_port': remote_desktop_port, 'ssh_port': ssh_port, 'power_state': data.power_state, 'instance_size': data.instance_size, 'ex_cloud_service_name': ex_cloud_service_name } ) def _to_location(self, data): """ Convert the data from a Azure response object into a location """ country = data.display_name if "Asia" in data.display_name: country = "Asia" if "Europe" in data.display_name: country = "Europe" if "US" in data.display_name: country = "US" if "Japan" in data.display_name: country = "Japan" if "Brazil" in data.display_name: country = "Brazil" vm_role_sizes = data.compute_capabilities.virtual_machines_role_sizes return AzureNodeLocation( id=data.name, name=data.display_name, country=country, driver=self.connection.driver, available_services=data.available_services, virtual_machine_role_sizes=vm_role_sizes ) def _to_node_size(self, data): """ Convert the AZURE_COMPUTE_INSTANCE_TYPES into NodeSize """ return NodeSize( id=data["id"], name=data["name"], ram=data["ram"], disk=data["disk"], bandwidth=data["bandwidth"], price=data["price"], driver=self.connection.driver, extra={ 'max_data_disks': data["max_data_disks"], 'cores': data["cores"] } ) def _to_image(self, data): return NodeImage( id=data.name, name=data.label, driver=self.connection.driver, extra={ 'os': data.os, 'category': data.category, 'description': data.description, 'location': data.location, 'affinity_group': data.affinity_group, 'media_link': data.media_link, 'vm_image': False } ) def _vm_to_image(self, data): return NodeImage( id=data.name, name=data.label, driver=self.connection.driver, extra={ 'os': data.os_disk_configuration.os, 'category': data.category, 'location': data.location, 'media_link': data.os_disk_configuration.media_link, 'affinity_group': data.affinity_group, 'deployment_name': data.deployment_name, 'vm_image': True } ) def _to_volume(self, volume, node): extra = { 'affinity_group': volume.affinity_group, 'os': volume.os, 'location': volume.location, 'media_link': volume.media_link, 'source_image_name': volume.source_image_name } role_name = getattr(volume.attached_to, 'role_name', None) hosted_service_name = getattr( volume.attached_to, 'hosted_service_name', None ) deployment_name = getattr( volume.attached_to, 'deployment_name', None ) if role_name is not None: extra['role_name'] = role_name if hosted_service_name is not None: extra['hosted_service_name'] = hosted_service_name if deployment_name is not None: extra['deployment_name'] = deployment_name if node: if role_name is not None and role_name == node.id: return StorageVolume( id=volume.name, name=volume.name, size=int(volume.logical_disk_size_in_gb), driver=self.connection.driver, extra=extra ) else: return StorageVolume( id=volume.name, name=volume.name, size=int(volume.logical_disk_size_in_gb), driver=self.connection.driver, extra=extra ) def _get_deployment(self, **kwargs): _service_name = kwargs['service_name'] _deployment_slot = kwargs['deployment_slot'] response = self._perform_get( self._get_deployment_path_using_slot( _service_name, _deployment_slot ), None ) self.raise_for_response(response, 200) return self._parse_response(response, Deployment) def _get_cloud_service_location(self, service_name=None): if not service_name: raise ValueError("service_name is required.") res = self._perform_get( '%s?embed-detail=False' % ( self._get_hosted_service_path(service_name) ), HostedService ) _affinity_group = res.hosted_service_properties.affinity_group _cloud_service_location = res.hosted_service_properties.location if _affinity_group is not None and _affinity_group != '': return self.service_location(True, _affinity_group) elif _cloud_service_location is not None: return self.service_location(False, _cloud_service_location) else: return None def _is_storage_service_unique(self, service_name=None): if not service_name: raise ValueError("service_name is required.") _check_availability = self._perform_get( '%s/operations/isavailable/%s%s' % ( self._get_storage_service_path(), _str(service_name), '' ), AvailabilityResponse ) self.raise_for_response(_check_availability, 200) return _check_availability.result def _create_storage_account(self, **kwargs): if kwargs['is_affinity_group'] is True: response = self._perform_post( self._get_storage_service_path(), AzureXmlSerializer.create_storage_service_input_to_xml( kwargs['service_name'], kwargs['service_name'], self._encode_base64(kwargs['service_name']), kwargs['location'], None, # Location True, # geo_replication_enabled None # extended_properties ) ) self.raise_for_response(response, 202) else: response = self._perform_post( self._get_storage_service_path(), AzureXmlSerializer.create_storage_service_input_to_xml( kwargs['service_name'], kwargs['service_name'], self._encode_base64(kwargs['service_name']), None, # Affinity Group kwargs['location'], # Location True, # geo_replication_enabled None # extended_properties ) ) self.raise_for_response(response, 202) # We need to wait for this to be created before we can # create the storage container and the instance. self._ex_complete_async_azure_operation( response, "create_storage_account" ) def _get_operation_status(self, request_id): return self._perform_get( '/' + self.subscription_id + '/operations/' + _str(request_id), Operation ) def _perform_get(self, path, response_type): request = AzureHTTPRequest() request.method = 'GET' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) if response_type is not None: return self._parse_response(response, response_type) return response def _perform_post(self, path, body, response_type=None): request = AzureHTTPRequest() request.method = 'POST' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.body = ensure_string(self._get_request_body(body)) request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) return response def _perform_put(self, path, body, response_type=None): request = AzureHTTPRequest() request.method = 'PUT' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.body = ensure_string(self._get_request_body(body)) request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) return response def _perform_delete(self, path): request = AzureHTTPRequest() request.method = 'DELETE' request.host = AZURE_SERVICE_MANAGEMENT_HOST request.path = path request.path, request.query = self._update_request_uri_query(request) request.headers = self._update_management_header(request) response = self._perform_request(request) self.raise_for_response(response, 202) def _perform_request(self, request): try: return self.connection.request( action=request.path, data=request.body, headers=request.headers, method=request.method ) except AzureRedirectException as e: parsed_url = urlparse.urlparse(e.location) request.host = parsed_url.netloc return self._perform_request(request) except Exception as e: raise e def _update_request_uri_query(self, request): """ pulls the query string out of the URI and moves it into the query portion of the request object. If there are already query parameters on the request the parameters in the URI will appear after the existing parameters """ if '?' in request.path: request.path, _, query_string = request.path.partition('?') if query_string: query_params = query_string.split('&') for query in query_params: if '=' in query: name, _, value = query.partition('=') request.query.append((name, value)) request.path = url_quote(request.path, '/()$=\',') # add encoded queries to request.path. if request.query: request.path += '?' for name, value in request.query: if value is not None: request.path += '%s=%s%s' % ( name, url_quote(value, '/()$=\','), '&' ) request.path = request.path[:-1] return request.path, request.query def _update_management_header(self, request): """ Add additional headers for management. """ if request.method in ['PUT', 'POST', 'MERGE', 'DELETE']: request.headers['Content-Length'] = str(len(request.body)) # append additional headers base on the service # request.headers.append(('x-ms-version', X_MS_VERSION)) # if it is not GET or HEAD request, must set content-type. if request.method not in ['GET', 'HEAD']: for key in request.headers: if 'content-type' == key.lower(): break else: request.headers['Content-Type'] = 'application/xml' return request.headers def _parse_response(self, response, return_type): """ Parse the HTTPResponse's body and fill all the data into a class of return_type. """ return self._parse_response_body_from_xml_text( response=response, return_type=return_type ) def _parse_response_body_from_xml_text(self, response, return_type): """ parse the xml and fill all the data into a class of return_type """ respbody = response.body doc = minidom.parseString(respbody) return_obj = return_type() for node in self._get_child_nodes(doc, return_type.__name__): self._fill_data_to_return_object(node, return_obj) # Note: We always explicitly assign status code to the custom return # type object return_obj.status = response.status return return_obj def _get_child_nodes(self, node, tag_name): return [childNode for childNode in node.getElementsByTagName(tag_name) if childNode.parentNode == node] def _fill_data_to_return_object(self, node, return_obj): members = dict(vars(return_obj)) for name, value in members.items(): if isinstance(value, _ListOf): setattr( return_obj, name, self._fill_list_of( node, value.list_type, value.xml_element_name ) ) elif isinstance(value, ScalarListOf): setattr( return_obj, name, self._fill_scalar_list_of( node, value.list_type, self._get_serialization_name(name), value.xml_element_name ) ) elif isinstance(value, _DictOf): setattr( return_obj, name, self._fill_dict_of( node, self._get_serialization_name(name), value.pair_xml_element_name, value.key_xml_element_name, value.value_xml_element_name ) ) elif isinstance(value, WindowsAzureData): setattr( return_obj, name, self._fill_instance_child(node, name, value.__class__) ) elif isinstance(value, dict): setattr( return_obj, name, self._fill_dict( node, self._get_serialization_name(name) ) ) elif isinstance(value, _Base64String): value = self._fill_data_minidom(node, name, '') if value is not None: value = self._decode_base64_to_text(value) # always set the attribute, # so we don't end up returning an object # with type _Base64String setattr(return_obj, name, value) else: value = self._fill_data_minidom(node, name, value) if value is not None: setattr(return_obj, name, value) def _fill_list_of(self, xmldoc, element_type, xml_element_name): xmlelements = self._get_child_nodes(xmldoc, xml_element_name) return [ self._parse_response_body_from_xml_node(xmlelement, element_type) for xmlelement in xmlelements ] def _parse_response_body_from_xml_node(self, node, return_type): """ parse the xml and fill all the data into a class of return_type """ return_obj = return_type() self._fill_data_to_return_object(node, return_obj) return return_obj def _fill_scalar_list_of(self, xmldoc, element_type, parent_xml_element_name, xml_element_name): xmlelements = self._get_child_nodes(xmldoc, parent_xml_element_name) if xmlelements: xmlelements = self._get_child_nodes( xmlelements[0], xml_element_name ) return [ self._get_node_value(xmlelement, element_type) for xmlelement in xmlelements ] def _get_node_value(self, xmlelement, data_type): value = xmlelement.firstChild.nodeValue if data_type is datetime: return self._to_datetime(value) elif data_type is bool: return value.lower() != 'false' else: return data_type(value) def _get_serialization_name(self, element_name): """ Converts a Python name into a serializable name. """ known = _KNOWN_SERIALIZATION_XFORMS.get(element_name) if known is not None: return known if element_name.startswith('x_ms_'): return element_name.replace('_', '-') if element_name.endswith('_id'): element_name = element_name.replace('_id', 'ID') for name in ['content_', 'last_modified', 'if_', 'cache_control']: if element_name.startswith(name): element_name = element_name.replace('_', '-_') return ''.join(name.capitalize() for name in element_name.split('_')) def _fill_dict_of(self, xmldoc, parent_xml_element_name, pair_xml_element_name, key_xml_element_name, value_xml_element_name): return_obj = {} xmlelements = self._get_child_nodes(xmldoc, parent_xml_element_name) if xmlelements: xmlelements = self._get_child_nodes( xmlelements[0], pair_xml_element_name ) for pair in xmlelements: keys = self._get_child_nodes(pair, key_xml_element_name) values = self._get_child_nodes(pair, value_xml_element_name) if keys and values: key = keys[0].firstChild.nodeValue value = values[0].firstChild.nodeValue return_obj[key] = value return return_obj def _fill_instance_child(self, xmldoc, element_name, return_type): """ Converts a child of the current dom element to the specified type. """ xmlelements = self._get_child_nodes( xmldoc, self._get_serialization_name(element_name) ) if not xmlelements: return None return_obj = return_type() self._fill_data_to_return_object(xmlelements[0], return_obj) return return_obj def _fill_dict(self, xmldoc, element_name): xmlelements = self._get_child_nodes(xmldoc, element_name) if xmlelements: return_obj = {} for child in xmlelements[0].childNodes: if child.firstChild: return_obj[child.nodeName] = child.firstChild.nodeValue return return_obj def _encode_base64(self, data): if isinstance(data, _unicode_type): data = data.encode('utf-8') encoded = base64.b64encode(data) return encoded.decode('utf-8') def _decode_base64_to_bytes(self, data): if isinstance(data, _unicode_type): data = data.encode('utf-8') return base64.b64decode(data) def _decode_base64_to_text(self, data): decoded_bytes = self._decode_base64_to_bytes(data) return decoded_bytes.decode('utf-8') def _fill_data_minidom(self, xmldoc, element_name, data_member): xmlelements = self._get_child_nodes( xmldoc, self._get_serialization_name(element_name) ) if not xmlelements or not xmlelements[0].childNodes: return None value = xmlelements[0].firstChild.nodeValue if data_member is None: return value elif isinstance(data_member, datetime): return self._to_datetime(value) elif type(data_member) is bool: return value.lower() != 'false' elif type(data_member) is str: return _real_unicode(value) else: return type(data_member)(value) def _to_datetime(self, strtime): return datetime.strptime(strtime, "%Y-%m-%dT%H:%M:%S.%f") def _get_request_body(self, request_body): if request_body is None: return b'' if isinstance(request_body, WindowsAzureData): request_body = self._convert_class_to_xml(request_body) if isinstance(request_body, bytes): return request_body if isinstance(request_body, _unicode_type): return request_body.encode('utf-8') request_body = str(request_body) if isinstance(request_body, _unicode_type): return request_body.encode('utf-8') return request_body def _convert_class_to_xml(self, source, xml_prefix=True): root = ET.Element() doc = self._construct_element_tree(source, root) result = ensure_string(ET.tostring(doc, encoding='utf-8', method='xml')) return result def _construct_element_tree(self, source, etree): if source is None: return ET.Element() if isinstance(source, list): for value in source: etree.append(self._construct_element_tree(value, etree)) elif isinstance(source, WindowsAzureData): class_name = source.__class__.__name__ etree.append(ET.Element(class_name)) for name, value in vars(source).items(): if value is not None: if (isinstance(value, list) or isinstance(value, WindowsAzureData)): etree.append( self._construct_element_tree(value, etree) ) else: ele = ET.Element(self._get_serialization_name(name)) ele.text = xml_escape(str(value)) etree.append(ele) etree.append(ET.Element(class_name)) return etree def _parse_response_for_async_op(self, response): if response is None: return None result = AsynchronousOperationResult() if response.headers: for name, value in response.headers.items(): if name.lower() == 'x-ms-request-id': result.request_id = value return result def _get_deployment_path_using_name(self, service_name, deployment_name=None): components = [ 'services/hostedservices/', _str(service_name), '/deployments' ] resource = ''.join(components) return self._get_path(resource, deployment_name) def _get_path(self, resource, name): path = '/' + self.subscription_id + '/' + resource if name is not None: path += '/' + _str(name) return path def _get_image_path(self, image_name=None): return self._get_path('services/images', image_name) def _get_vmimage_path(self, image_name=None): return self._get_path('services/vmimages', image_name) def _get_hosted_service_path(self, service_name=None): return self._get_path('services/hostedservices', service_name) def _get_deployment_path_using_slot(self, service_name, slot=None): return self._get_path( 'services/hostedservices/%s/deploymentslots' % ( _str(service_name) ), slot ) def _get_disk_path(self, disk_name=None): return self._get_path('services/disks', disk_name) def _get_role_path(self, service_name, deployment_name, role_name=None): components = [ 'services/hostedservices/', _str(service_name), '/deployments/', deployment_name, '/roles' ] resource = ''.join(components) return self._get_path(resource, role_name) def _get_storage_service_path(self, service_name=None): return self._get_path('services/storageservices', service_name) def _ex_complete_async_azure_operation(self, response=None, operation_type='create_node'): request_id = self._parse_response_for_async_op(response) operation_status = self._get_operation_status(request_id.request_id) timeout = 60 * 5 waittime = 0 interval = 5 while operation_status.status == "InProgress" and waittime < timeout: operation_status = self._get_operation_status(request_id) if operation_status.status == "Succeeded": break waittime += interval time.sleep(interval) if operation_status.status == 'Failed': raise LibcloudError( 'Message: Async request for operation %s has failed' % operation_type, driver=self.connection.driver ) def raise_for_response(self, response, valid_response): if response.status != valid_response: values = (response.error, response.body, response.status) message = 'Message: %s, Body: %s, Status code: %s' % (values) raise LibcloudError(message, driver=self) """ XML Serializer Borrowed from the Azure SDK for Python which is licensed under Apache 2.0. https://github.com/Azure/azure-sdk-for-python """ def _lower(text): return text.lower() class AzureXmlSerializer(object): @staticmethod def create_storage_service_input_to_xml(service_name, description, label, affinity_group, location, geo_replication_enabled, extended_properties): return AzureXmlSerializer.doc_from_data( 'CreateStorageServiceInput', [ ('ServiceName', service_name), ('Description', description), ('Label', label), ('AffinityGroup', affinity_group), ('Location', location), ('GeoReplicationEnabled', geo_replication_enabled, _lower) ], extended_properties ) @staticmethod def update_storage_service_input_to_xml(description, label, geo_replication_enabled, extended_properties): return AzureXmlSerializer.doc_from_data( 'UpdateStorageServiceInput', [ ('Description', description), ('Label', label, AzureNodeDriver._encode_base64), ('GeoReplicationEnabled', geo_replication_enabled, _lower) ], extended_properties ) @staticmethod def regenerate_keys_to_xml(key_type): return AzureXmlSerializer.doc_from_data( 'RegenerateKeys', [('KeyType', key_type)] ) @staticmethod def update_hosted_service_to_xml(label, description, extended_properties): return AzureXmlSerializer.doc_from_data( 'UpdateHostedService', [ ('Label', label, AzureNodeDriver._encode_base64), ('Description', description) ], extended_properties ) @staticmethod def create_hosted_service_to_xml(service_name, label, description, location, affinity_group=None, extended_properties=None): if affinity_group: return AzureXmlSerializer.doc_from_data( 'CreateHostedService', [ ('ServiceName', service_name), ('Label', label), ('Description', description), ('AffinityGroup', affinity_group), ], extended_properties ) return AzureXmlSerializer.doc_from_data( 'CreateHostedService', [ ('ServiceName', service_name), ('Label', label), ('Description', description), ('Location', location), ], extended_properties ) @staticmethod def create_storage_service_to_xml(service_name, label, description, location, affinity_group, extended_properties=None): return AzureXmlSerializer.doc_from_data( 'CreateStorageServiceInput', [ ('ServiceName', service_name), ('Label', label), ('Description', description), ('Location', location), ('AffinityGroup', affinity_group) ], extended_properties ) @staticmethod def create_deployment_to_xml(name, package_url, label, configuration, start_deployment, treat_warnings_as_error, extended_properties): return AzureXmlSerializer.doc_from_data( 'CreateDeployment', [ ('Name', name), ('PackageUrl', package_url), ('Label', label, AzureNodeDriver._encode_base64), ('Configuration', configuration), ('StartDeployment', start_deployment, _lower), ('TreatWarningsAsError', treat_warnings_as_error, _lower) ], extended_properties ) @staticmethod def swap_deployment_to_xml(production, source_deployment): return AzureXmlSerializer.doc_from_data( 'Swap', [ ('Production', production), ('SourceDeployment', source_deployment) ] ) @staticmethod def update_deployment_status_to_xml(status): return AzureXmlSerializer.doc_from_data( 'UpdateDeploymentStatus', [('Status', status)] ) @staticmethod def change_deployment_to_xml(configuration, treat_warnings_as_error, mode, extended_properties): return AzureXmlSerializer.doc_from_data( 'ChangeConfiguration', [ ('Configuration', configuration), ('TreatWarningsAsError', treat_warnings_as_error, _lower), ('Mode', mode) ], extended_properties ) @staticmethod def upgrade_deployment_to_xml(mode, package_url, configuration, label, role_to_upgrade, force, extended_properties): return AzureXmlSerializer.doc_from_data( 'UpgradeDeployment', [ ('Mode', mode), ('PackageUrl', package_url), ('Configuration', configuration), ('Label', label, AzureNodeDriver._encode_base64), ('RoleToUpgrade', role_to_upgrade), ('Force', force, _lower) ], extended_properties ) @staticmethod def rollback_upgrade_to_xml(mode, force): return AzureXmlSerializer.doc_from_data( 'RollbackUpdateOrUpgrade', [ ('Mode', mode), ('Force', force, _lower) ] ) @staticmethod def walk_upgrade_domain_to_xml(upgrade_domain): return AzureXmlSerializer.doc_from_data( 'WalkUpgradeDomain', [('UpgradeDomain', upgrade_domain)] ) @staticmethod def certificate_file_to_xml(data, certificate_format, password): return AzureXmlSerializer.doc_from_data( 'CertificateFile', [ ('Data', data), ('CertificateFormat', certificate_format), ('Password', password) ] ) @staticmethod def create_affinity_group_to_xml(name, label, description, location): return AzureXmlSerializer.doc_from_data( 'CreateAffinityGroup', [ ('Name', name), ('Label', label, AzureNodeDriver._encode_base64), ('Description', description), ('Location', location) ] ) @staticmethod def update_affinity_group_to_xml(label, description): return AzureXmlSerializer.doc_from_data( 'UpdateAffinityGroup', [ ('Label', label, AzureNodeDriver._encode_base64), ('Description', description) ] ) @staticmethod def subscription_certificate_to_xml(public_key, thumbprint, data): return AzureXmlSerializer.doc_from_data( 'SubscriptionCertificate', [ ('SubscriptionCertificatePublicKey', public_key), ('SubscriptionCertificateThumbprint', thumbprint), ('SubscriptionCertificateData', data) ] ) @staticmethod def os_image_to_xml(label, media_link, name, os): return AzureXmlSerializer.doc_from_data( 'OSImage', [ ('Label', label), ('MediaLink', media_link), ('Name', name), ('OS', os) ] ) @staticmethod def data_virtual_hard_disk_to_xml(host_caching, disk_label, disk_name, lun, logical_disk_size_in_gb, media_link, source_media_link): return AzureXmlSerializer.doc_from_data( 'DataVirtualHardDisk', [ ('HostCaching', host_caching), ('DiskLabel', disk_label), ('DiskName', disk_name), ('Lun', lun), ('LogicalDiskSizeInGB', logical_disk_size_in_gb), ('MediaLink', media_link), ('SourceMediaLink', source_media_link) ] ) @staticmethod def disk_to_xml(has_operating_system, label, media_link, name, os): return AzureXmlSerializer.doc_from_data( 'Disk', [ ('HasOperatingSystem', has_operating_system, _lower), ('Label', label), ('MediaLink', media_link), ('Name', name), ('OS', os) ] ) @staticmethod def restart_role_operation_to_xml(): xml = ET.Element("OperationType") xml.text = "RestartRoleOperation" doc = AzureXmlSerializer.doc_from_xml( 'RestartRoleOperation', xml ) result = ensure_string(ET.tostring(doc, encoding='utf-8')) return result @staticmethod def shutdown_role_operation_to_xml(): xml = ET.Element("OperationType") xml.text = "ShutdownRoleOperation" doc = AzureXmlSerializer.doc_from_xml( 'ShutdownRoleOperation', xml ) result = ensure_string(ET.tostring(doc, encoding='utf-8')) return result @staticmethod def start_role_operation_to_xml(): xml = ET.Element("OperationType") xml.text = "StartRoleOperation" doc = AzureXmlSerializer.doc_from_xml( 'StartRoleOperation', xml ) result = ensure_string(ET.tostring(doc, encoding='utf-8')) return result @staticmethod def windows_configuration_to_xml(configuration, xml): AzureXmlSerializer.data_to_xml( [('ConfigurationSetType', configuration.configuration_set_type)], xml ) AzureXmlSerializer.data_to_xml( [('ComputerName', configuration.computer_name)], xml ) AzureXmlSerializer.data_to_xml( [('AdminPassword', configuration.admin_password)], xml ) AzureXmlSerializer.data_to_xml( [ ( 'ResetPasswordOnFirstLogon', configuration.reset_password_on_first_logon, _lower ) ], xml ) AzureXmlSerializer.data_to_xml( [ ( 'EnableAutomaticUpdates', configuration.enable_automatic_updates, _lower ) ], xml ) AzureXmlSerializer.data_to_xml( [('TimeZone', configuration.time_zone)], xml ) if configuration.domain_join is not None: domain = ET.xml("DomainJoin") # pylint: disable=no-member creds = ET.xml("Credentials") # pylint: disable=no-member domain.appemnd(creds) xml.append(domain) AzureXmlSerializer.data_to_xml( [('Domain', configuration.domain_join.credentials.domain)], creds ) AzureXmlSerializer.data_to_xml( [ ( 'Username', configuration.domain_join.credentials.username ) ], creds ) AzureXmlSerializer.data_to_xml( [ ( 'Password', configuration.domain_join.credentials.password ) ], creds ) AzureXmlSerializer.data_to_xml( [('JoinDomain', configuration.domain_join.join_domain)], domain ) AzureXmlSerializer.data_to_xml( [ ( 'MachineObjectOU', configuration.domain_join.machine_object_ou ) ], domain ) if configuration.stored_certificate_settings is not None: cert_settings = ET.Element("StoredCertificateSettings") xml.append(cert_settings) for cert in configuration.stored_certificate_settings: cert_setting = ET.Element("CertificateSetting") cert_settings.append(cert_setting) cert_setting.append(AzureXmlSerializer.data_to_xml( [('StoreLocation', cert.store_location)]) ) AzureXmlSerializer.data_to_xml( [('StoreName', cert.store_name)], cert_setting ) AzureXmlSerializer.data_to_xml( [('Thumbprint', cert.thumbprint)], cert_setting ) AzureXmlSerializer.data_to_xml( [('AdminUsername', configuration.admin_user_name)], xml ) return xml @staticmethod def linux_configuration_to_xml(configuration, xml): AzureXmlSerializer.data_to_xml( [('ConfigurationSetType', configuration.configuration_set_type)], xml ) AzureXmlSerializer.data_to_xml( [('HostName', configuration.host_name)], xml ) AzureXmlSerializer.data_to_xml( [('UserName', configuration.user_name)], xml ) AzureXmlSerializer.data_to_xml( [('UserPassword', configuration.user_password)], xml ) AzureXmlSerializer.data_to_xml( [ ( 'DisableSshPasswordAuthentication', configuration.disable_ssh_password_authentication, _lower ) ], xml ) if configuration.ssh is not None: ssh = ET.Element("SSH") pkeys = ET.Element("PublicKeys") kpairs = ET.Element("KeyPairs") ssh.append(pkeys) ssh.append(kpairs) xml.append(ssh) for key in configuration.ssh.public_keys: pkey = ET.Element("PublicKey") pkeys.append(pkey) AzureXmlSerializer.data_to_xml( [('Fingerprint', key.fingerprint)], pkey ) AzureXmlSerializer.data_to_xml([('Path', key.path)], pkey) for key in configuration.ssh.key_pairs: kpair = ET.Element("KeyPair") kpairs.append(kpair) AzureXmlSerializer.data_to_xml( [('Fingerprint', key.fingerprint)], kpair ) AzureXmlSerializer.data_to_xml([('Path', key.path)], kpair) if configuration.custom_data is not None: AzureXmlSerializer.data_to_xml( [('CustomData', configuration.custom_data)], xml ) return xml @staticmethod def network_configuration_to_xml(configuration, xml): AzureXmlSerializer.data_to_xml( [('ConfigurationSetType', configuration.configuration_set_type)], xml ) input_endpoints = ET.Element("InputEndpoints") xml.append(input_endpoints) for endpoint in configuration.input_endpoints: input_endpoint = ET.Element("InputEndpoint") input_endpoints.append(input_endpoint) AzureXmlSerializer.data_to_xml( [ ( 'LoadBalancedEndpointSetName', endpoint.load_balanced_endpoint_set_name ) ], input_endpoint ) AzureXmlSerializer.data_to_xml( [('LocalPort', endpoint.local_port)], input_endpoint ) AzureXmlSerializer.data_to_xml( [('Name', endpoint.name)], input_endpoint ) AzureXmlSerializer.data_to_xml( [('Port', endpoint.port)], input_endpoint ) if (endpoint.load_balancer_probe.path or endpoint.load_balancer_probe.port or endpoint.load_balancer_probe.protocol): load_balancer_probe = ET.Element("LoadBalancerProbe") input_endpoint.append(load_balancer_probe) AzureXmlSerializer.data_to_xml( [('Path', endpoint.load_balancer_probe.path)], load_balancer_probe ) AzureXmlSerializer.data_to_xml( [('Port', endpoint.load_balancer_probe.port)], load_balancer_probe ) AzureXmlSerializer.data_to_xml( [('Protocol', endpoint.load_balancer_probe.protocol)], load_balancer_probe ) AzureXmlSerializer.data_to_xml( [('Protocol', endpoint.protocol)], input_endpoint ) AzureXmlSerializer.data_to_xml( [ ( 'EnableDirectServerReturn', endpoint.enable_direct_server_return, _lower ) ], input_endpoint ) subnet_names = ET.Element("SubnetNames") xml.append(subnet_names) for name in configuration.subnet_names: AzureXmlSerializer.data_to_xml( [('SubnetName', name)], subnet_names ) return xml @staticmethod def role_to_xml(availability_set_name, data_virtual_hard_disks, network_configuration_set, os_virtual_hard_disk, vm_image_name, role_name, role_size, role_type, system_configuration_set, xml): AzureXmlSerializer.data_to_xml([('RoleName', role_name)], xml) AzureXmlSerializer.data_to_xml([('RoleType', role_type)], xml) config_sets = ET.Element("ConfigurationSets") xml.append(config_sets) if system_configuration_set is not None: config_set = ET.Element("ConfigurationSet") config_sets.append(config_set) if isinstance(system_configuration_set, WindowsConfigurationSet): AzureXmlSerializer.windows_configuration_to_xml( system_configuration_set, config_set ) elif isinstance(system_configuration_set, LinuxConfigurationSet): AzureXmlSerializer.linux_configuration_to_xml( system_configuration_set, config_set ) if network_configuration_set is not None: config_set = ET.Element("ConfigurationSet") config_sets.append(config_set) AzureXmlSerializer.network_configuration_to_xml( network_configuration_set, config_set ) if availability_set_name is not None: AzureXmlSerializer.data_to_xml( [('AvailabilitySetName', availability_set_name)], xml ) if data_virtual_hard_disks is not None: vhds = ET.Element("DataVirtualHardDisks") xml.append(vhds) for hd in data_virtual_hard_disks: vhd = ET.Element("DataVirtualHardDisk") vhds.append(vhd) AzureXmlSerializer.data_to_xml( [('HostCaching', hd.host_caching)], vhd ) AzureXmlSerializer.data_to_xml( [('DiskLabel', hd.disk_label)], vhd ) AzureXmlSerializer.data_to_xml( [('DiskName', hd.disk_name)], vhd ) AzureXmlSerializer.data_to_xml( [('Lun', hd.lun)], vhd ) AzureXmlSerializer.data_to_xml( [('LogicalDiskSizeInGB', hd.logical_disk_size_in_gb)], vhd ) AzureXmlSerializer.data_to_xml( [('MediaLink', hd.media_link)], vhd ) if os_virtual_hard_disk is not None: hd = ET.Element("OSVirtualHardDisk") xml.append(hd) AzureXmlSerializer.data_to_xml( [('HostCaching', os_virtual_hard_disk.host_caching)], hd ) AzureXmlSerializer.data_to_xml( [('DiskLabel', os_virtual_hard_disk.disk_label)], hd ) AzureXmlSerializer.data_to_xml( [('DiskName', os_virtual_hard_disk.disk_name)], hd ) AzureXmlSerializer.data_to_xml( [('MediaLink', os_virtual_hard_disk.media_link)], hd ) AzureXmlSerializer.data_to_xml( [('SourceImageName', os_virtual_hard_disk.source_image_name)], hd ) if vm_image_name is not None: AzureXmlSerializer.data_to_xml( [('VMImageName', vm_image_name)], xml ) if role_size is not None: AzureXmlSerializer.data_to_xml([('RoleSize', role_size)], xml) return xml @staticmethod def add_role_to_xml(role_name, system_configuration_set, os_virtual_hard_disk, role_type, network_configuration_set, availability_set_name, data_virtual_hard_disks, vm_image_name, role_size): doc = AzureXmlSerializer.doc_from_xml('PersistentVMRole') xml = AzureXmlSerializer.role_to_xml( availability_set_name, data_virtual_hard_disks, network_configuration_set, os_virtual_hard_disk, vm_image_name, role_name, role_size, role_type, system_configuration_set, doc ) result = ensure_string(ET.tostring(xml, encoding='utf-8')) return result @staticmethod def update_role_to_xml(role_name, os_virtual_hard_disk, role_type, network_configuration_set, availability_set_name, data_virtual_hard_disks, vm_image_name, role_size): doc = AzureXmlSerializer.doc_from_xml('PersistentVMRole') AzureXmlSerializer.role_to_xml( availability_set_name, data_virtual_hard_disks, network_configuration_set, os_virtual_hard_disk, vm_image_name, role_name, role_size, role_type, None, doc ) result = ensure_string(ET.tostring(doc, encoding='utf-8')) return result @staticmethod def capture_role_to_xml(post_capture_action, target_image_name, target_image_label, provisioning_configuration): xml = AzureXmlSerializer.data_to_xml( [('OperationType', 'CaptureRoleOperation')] ) AzureXmlSerializer.data_to_xml( [('PostCaptureAction', post_capture_action)], xml ) if provisioning_configuration is not None: provisioning_config = ET.Element("ProvisioningConfiguration") xml.append(provisioning_config) if isinstance(provisioning_configuration, WindowsConfigurationSet): AzureXmlSerializer.windows_configuration_to_xml( provisioning_configuration, provisioning_config ) elif isinstance(provisioning_configuration, LinuxConfigurationSet): AzureXmlSerializer.linux_configuration_to_xml( provisioning_configuration, provisioning_config ) AzureXmlSerializer.data_to_xml( [('TargetImageLabel', target_image_label)], xml ) AzureXmlSerializer.data_to_xml( [('TargetImageName', target_image_name)], xml ) doc = AzureXmlSerializer.doc_from_xml('CaptureRoleOperation', xml) result = ensure_string(ET.tostring(doc, encoding='utf-8')) return result @staticmethod def virtual_machine_deployment_to_xml(deployment_name, deployment_slot, label, role_name, system_configuration_set, os_virtual_hard_disk, role_type, network_configuration_set, availability_set_name, data_virtual_hard_disks, role_size, virtual_network_name, vm_image_name): doc = AzureXmlSerializer.doc_from_xml('Deployment') AzureXmlSerializer.data_to_xml([('Name', deployment_name)], doc) AzureXmlSerializer.data_to_xml( [('DeploymentSlot', deployment_slot)], doc ) AzureXmlSerializer.data_to_xml([('Label', label)], doc) role_list = ET.Element("RoleList") role = ET.Element("Role") role_list.append(role) doc.append(role_list) AzureXmlSerializer.role_to_xml( availability_set_name, data_virtual_hard_disks, network_configuration_set, os_virtual_hard_disk, vm_image_name, role_name, role_size, role_type, system_configuration_set, role ) if virtual_network_name is not None: doc.append( AzureXmlSerializer.data_to_xml( [('VirtualNetworkName', virtual_network_name)] ) ) result = ensure_string(ET.tostring(doc, encoding='utf-8')) return result @staticmethod def data_to_xml(data, xml=None): """ Creates an xml fragment from the specified data. data: Array of tuples, where first: xml element name second: xml element text third: conversion function """ for element in data: name = element[0] val = element[1] if len(element) > 2: converter = element[2] else: converter = None if val is not None: if converter is not None: text = _str(converter(_str(val))) else: text = _str(val) entry = ET.Element(name) entry.text = text if xml is not None: xml.append(entry) else: return entry return xml @staticmethod def doc_from_xml(document_element_name, inner_xml=None): """ Wraps the specified xml in an xml root element with default azure namespaces """ # Note: Namespaces don't work consistency in Python 2 and 3. """ nsmap = { None: "http://www.w3.org/2001/XMLSchema-instance", "i": "http://www.w3.org/2001/XMLSchema-instance" } xml.attrib["xmlns:i"] = "http://www.w3.org/2001/XMLSchema-instance" xml.attrib["xmlns"] = "http://schemas.microsoft.com/windowsazure" """ xml = ET.Element(document_element_name) xml.set("xmlns", "http://schemas.microsoft.com/windowsazure") if inner_xml is not None: xml.append(inner_xml) return xml @staticmethod def doc_from_data(document_element_name, data, extended_properties=None): doc = AzureXmlSerializer.doc_from_xml(document_element_name) AzureXmlSerializer.data_to_xml(data, doc) if extended_properties is not None: doc.append( AzureXmlSerializer.extended_properties_dict_to_xml_fragment( extended_properties ) ) result = ensure_string(ET.tostring(doc, encoding='utf-8')) return result @staticmethod def extended_properties_dict_to_xml_fragment(extended_properties): if extended_properties is not None and len(extended_properties) > 0: xml = ET.Element("ExtendedProperties") for key, val in extended_properties.items(): extended_property = ET.Element("ExtendedProperty") name = ET.Element("Name") name.text = _str(key) value = ET.Element("Value") value.text = _str(val) extended_property.append(name) extended_property.append(value) xml.append(extended_property) return xml """ Data Classes Borrowed from the Azure SDK for Python. """ class WindowsAzureData(object): """ This is the base of data class. It is only used to check whether it is instance or not. """ pass class WindowsAzureDataTypedList(WindowsAzureData): list_type = None xml_element_name = None def __init__(self): self.items = _ListOf(self.list_type, self.xml_element_name) def __iter__(self): return iter(self.items) def __len__(self): return len(self.items) def __getitem__(self, index): return self.items[index] class OSVirtualHardDisk(WindowsAzureData): def __init__(self, source_image_name=None, media_link=None, host_caching=None, disk_label=None, disk_name=None): self.source_image_name = source_image_name self.media_link = media_link self.host_caching = host_caching self.disk_label = disk_label self.disk_name = disk_name self.os = '' # undocumented, not used when adding a role class LinuxConfigurationSet(WindowsAzureData): def __init__(self, host_name=None, user_name=None, user_password=None, disable_ssh_password_authentication=None, custom_data=None): self.configuration_set_type = 'LinuxProvisioningConfiguration' self.host_name = host_name self.user_name = user_name self.user_password = user_password self.disable_ssh_password_authentication = \ disable_ssh_password_authentication self.ssh = SSH() self.custom_data = custom_data class WindowsConfigurationSet(WindowsAzureData): def __init__(self, computer_name=None, admin_password=None, reset_password_on_first_logon=None, enable_automatic_updates=None, time_zone=None, admin_user_name=None): self.configuration_set_type = 'WindowsProvisioningConfiguration' self.computer_name = computer_name self.admin_password = admin_password self.reset_password_on_first_logon = reset_password_on_first_logon self.enable_automatic_updates = enable_automatic_updates self.time_zone = time_zone self.admin_user_name = admin_user_name self.domain_join = DomainJoin() self.stored_certificate_settings = StoredCertificateSettings() class DomainJoin(WindowsAzureData): def __init__(self): self.credentials = Credentials() self.join_domain = '' self.machine_object_ou = '' class Credentials(WindowsAzureData): def __init__(self): self.domain = '' self.username = '' self.password = '' class CertificateSetting(WindowsAzureData): """ Initializes a certificate setting. thumbprint: Specifies the thumbprint of the certificate to be provisioned. The thumbprint must specify an existing service certificate. store_name: Specifies the name of the certificate store from which retrieve certificate. store_location: Specifies the target certificate store location on the virtual machine The only supported value is LocalMachine. """ def __init__(self, thumbprint='', store_name='', store_location=''): self.thumbprint = thumbprint self.store_name = store_name self.store_location = store_location class StoredCertificateSettings(WindowsAzureDataTypedList): list_type = CertificateSetting _repr_attributes = [ 'items' ] class SSH(WindowsAzureData): def __init__(self): self.public_keys = PublicKeys() self.key_pairs = KeyPairs() class PublicKey(WindowsAzureData): def __init__(self, fingerprint='', path=''): self.fingerprint = fingerprint self.path = path class PublicKeys(WindowsAzureDataTypedList): list_type = PublicKey _repr_attributes = [ 'items' ] class AzureKeyPair(WindowsAzureData): def __init__(self, fingerprint='', path=''): self.fingerprint = fingerprint self.path = path class KeyPairs(WindowsAzureDataTypedList): list_type = AzureKeyPair _repr_attributes = [ 'items' ] class LoadBalancerProbe(WindowsAzureData): def __init__(self): self.path = '' self.port = '' self.protocol = '' class ConfigurationSet(WindowsAzureData): def __init__(self): self.configuration_set_type = '' self.role_type = '' self.input_endpoints = ConfigurationSetInputEndpoints() self.subnet_names = ScalarListOf(str, 'SubnetName') class ConfigurationSets(WindowsAzureDataTypedList): list_type = ConfigurationSet _repr_attributes = [ 'items' ] class ConfigurationSetInputEndpoint(WindowsAzureData): def __init__(self, name='', protocol='', port='', local_port='', load_balanced_endpoint_set_name='', enable_direct_server_return=False): self.enable_direct_server_return = enable_direct_server_return self.load_balanced_endpoint_set_name = load_balanced_endpoint_set_name self.local_port = local_port self.name = name self.port = port self.load_balancer_probe = LoadBalancerProbe() self.protocol = protocol class ConfigurationSetInputEndpoints(WindowsAzureDataTypedList): list_type = ConfigurationSetInputEndpoint xml_element_name = 'InputEndpoint' _repr_attributes = [ 'items' ] class Location(WindowsAzureData): def __init__(self): self.name = '' self.display_name = '' self.available_services = ScalarListOf(str, 'AvailableService') self.compute_capabilities = ComputeCapability() class Locations(WindowsAzureDataTypedList): list_type = Location _repr_attributes = [ 'items' ] class ComputeCapability(WindowsAzureData): def __init__(self): self.virtual_machines_role_sizes = ScalarListOf(str, 'RoleSize') class VirtualMachinesRoleSizes(WindowsAzureData): def __init__(self): self.role_size = ScalarListOf(str, 'RoleSize') class OSImage(WindowsAzureData): def __init__(self): self.affinity_group = '' self.category = '' self.location = '' self.logical_size_in_gb = 0 self.label = '' self.media_link = '' self.name = '' self.os = '' self.eula = '' self.description = '' class Images(WindowsAzureDataTypedList): list_type = OSImage _repr_attributes = [ 'items' ] class VMImage(WindowsAzureData): def __init__(self): self.name = '' self.label = '' self.category = '' self.os_disk_configuration = OSDiskConfiguration() self.service_name = '' self.deployment_name = '' self.role_name = '' self.location = '' self.affinity_group = '' class VMImages(WindowsAzureDataTypedList): list_type = VMImage _repr_attributes = [ 'items' ] class VirtualIP(WindowsAzureData): def __init__(self): self.address = '' self.is_dns_programmed = '' self.name = '' class VirtualIPs(WindowsAzureDataTypedList): list_type = VirtualIP _repr_attributes = [ 'items' ] class HostedService(WindowsAzureData, ReprMixin): _repr_attributes = [ 'service_name', 'url' ] def __init__(self): self.url = '' self.service_name = '' self.hosted_service_properties = HostedServiceProperties() self.deployments = Deployments() class HostedServices(WindowsAzureDataTypedList, ReprMixin): list_type = HostedService _repr_attributes = [ 'items' ] class HostedServiceProperties(WindowsAzureData): def __init__(self): self.description = '' self.location = '' self.affinity_group = '' self.label = _Base64String() self.status = '' self.date_created = '' self.date_last_modified = '' self.extended_properties = _DictOf( 'ExtendedProperty', 'Name', 'Value' ) class Deployment(WindowsAzureData): def __init__(self): self.name = '' self.deployment_slot = '' self.private_id = '' self.status = '' self.label = _Base64String() self.url = '' self.configuration = _Base64String() self.role_instance_list = RoleInstanceList() self.upgrade_status = UpgradeStatus() self.upgrade_domain_count = '' self.role_list = RoleList() self.sdk_version = '' self.input_endpoint_list = InputEndpoints() self.locked = False self.rollback_allowed = False self.persistent_vm_downtime_info = PersistentVMDowntimeInfo() self.created_time = '' self.last_modified_time = '' self.extended_properties = _DictOf( 'ExtendedProperty', 'Name', 'Value' ) self.virtual_ips = VirtualIPs() class Deployments(WindowsAzureDataTypedList): list_type = Deployment _repr_attributes = [ 'items' ] class UpgradeStatus(WindowsAzureData): def __init__(self): self.upgrade_type = '' self.current_upgrade_domain_state = '' self.current_upgrade_domain = '' class RoleInstance(WindowsAzureData): def __init__(self): self.role_name = '' self.instance_name = '' self.instance_status = '' self.instance_upgrade_domain = 0 self.instance_fault_domain = 0 self.instance_size = '' self.instance_state_details = '' self.instance_error_code = '' self.ip_address = '' self.instance_endpoints = InstanceEndpoints() self.power_state = '' self.fqdn = '' self.host_name = '' class RoleInstanceList(WindowsAzureDataTypedList): list_type = RoleInstance _repr_attributes = [ 'items' ] class InstanceEndpoint(WindowsAzureData): def __init__(self): self.name = '' self.vip = '' self.public_port = '' self.local_port = '' self.protocol = '' class InstanceEndpoints(WindowsAzureDataTypedList): list_type = InstanceEndpoint _repr_attributes = [ 'items' ] class InputEndpoint(WindowsAzureData): def __init__(self): self.role_name = '' self.vip = '' self.port = '' class InputEndpoints(WindowsAzureDataTypedList): list_type = InputEndpoint _repr_attributes = [ 'items' ] class Role(WindowsAzureData): def __init__(self): self.role_name = '' self.os_version = '' class RoleList(WindowsAzureDataTypedList): list_type = Role _repr_attributes = [ 'items' ] class PersistentVMDowntimeInfo(WindowsAzureData): def __init__(self): self.start_time = '' self.end_time = '' self.status = '' class AsynchronousOperationResult(WindowsAzureData): def __init__(self, request_id=None): self.request_id = request_id class Disk(WindowsAzureData): def __init__(self): self.affinity_group = '' self.attached_to = AttachedTo() self.has_operating_system = '' self.is_corrupted = '' self.location = '' self.logical_disk_size_in_gb = 0 self.label = '' self.media_link = '' self.name = '' self.os = '' self.source_image_name = '' class Disks(WindowsAzureDataTypedList): list_type = Disk _repr_attributes = [ 'items' ] class AttachedTo(WindowsAzureData): def __init__(self): self.hosted_service_name = '' self.deployment_name = '' self.role_name = '' class OperationError(WindowsAzureData): def __init__(self): self.code = '' self.message = '' class Operation(WindowsAzureData): def __init__(self): self.id = '' self.status = '' self.http_status_code = '' self.error = OperationError() class OperatingSystem(WindowsAzureData): def __init__(self): self.version = '' self.label = _Base64String() self.is_default = True self.is_active = True self.family = 0 self.family_label = _Base64String() class OSDiskConfiguration(WindowsAzureData): def __init__(self): self.name = '' self.host_caching = '' self.os_state = '' self.os = '' self.media_link = '' self.logical_disk_size_in_gb = 0 class OperatingSystems(WindowsAzureDataTypedList): list_type = OperatingSystem _repr_attributes = [ 'items' ] class OperatingSystemFamily(WindowsAzureData): def __init__(self): self.name = '' self.label = _Base64String() self.operating_systems = OperatingSystems() class OperatingSystemFamilies(WindowsAzureDataTypedList): list_type = OperatingSystemFamily _repr_attributes = [ 'items' ] class Subscription(WindowsAzureData): def __init__(self): self.subscription_id = '' self.subscription_name = '' self.subscription_status = '' self.account_admin_live_email_id = '' self.service_admin_live_email_id = '' self.max_core_count = 0 self.max_storage_accounts = 0 self.max_hosted_services = 0 self.current_core_count = 0 self.current_hosted_services = 0 self.current_storage_accounts = 0 self.max_virtual_network_sites = 0 self.max_local_network_sites = 0 self.max_dns_servers = 0 class AvailabilityResponse(WindowsAzureData): def __init__(self): self.result = False class SubscriptionCertificate(WindowsAzureData): def __init__(self): self.subscription_certificate_public_key = '' self.subscription_certificate_thumbprint = '' self.subscription_certificate_data = '' self.created = '' class SubscriptionCertificates(WindowsAzureDataTypedList): list_type = SubscriptionCertificate _repr_attributes = [ 'items' ] class AzureHTTPRequest(object): def __init__(self): self.host = '' self.method = '' self.path = '' self.query = [] # list of (name, value) self.headers = {} # list of (header name, header value) self.body = '' self.protocol_override = None class AzureHTTPResponse(object): def __init__(self, status, message, headers, body): self.status = status self.message = message self.headers = headers self.body = body """ Helper classes and functions. """ class _Base64String(str): pass class _ListOf(list): """ A list which carries with it the type that's expected to go in it. Used for deserializaion and construction of the lists """ def __init__(self, list_type, xml_element_name=None): self.list_type = list_type if xml_element_name is None: self.xml_element_name = list_type.__name__ else: self.xml_element_name = xml_element_name super(_ListOf, self).__init__() class ScalarListOf(list): """ A list of scalar types which carries with it the type that's expected to go in it along with its xml element name. Used for deserializaion and construction of the lists """ def __init__(self, list_type, xml_element_name): self.list_type = list_type self.xml_element_name = xml_element_name super(ScalarListOf, self).__init__() class _DictOf(dict): """ A dict which carries with it the xml element names for key,val. Used for deserializaion and construction of the lists """ def __init__(self, pair_xml_element_name, key_xml_element_name, value_xml_element_name): self.pair_xml_element_name = pair_xml_element_name self.key_xml_element_name = key_xml_element_name self.value_xml_element_name = value_xml_element_name super(_DictOf, self).__init__() class AzureNodeLocation(NodeLocation): # we can also have something in here for available services which is an # extra to the API with Azure def __init__(self, id, name, country, driver, available_services, virtual_machine_role_sizes): super(AzureNodeLocation, self).__init__(id, name, country, driver) self.available_services = available_services self.virtual_machine_role_sizes = virtual_machine_role_sizes def __repr__(self): return ( ( '' ) % ( self.id, self.name, self.country, self.driver.name, ','.join(self.available_services), ','.join(self.virtual_machine_role_sizes) ) ) apache-libcloud-2.8.0/libcloud/compute/drivers/azure_arm.py0000664000175000017500000024176513600144066023730 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Driver for Microsoft Azure Resource Manager (ARM) Virtual Machines provider. http://azure.microsoft.com/en-us/services/virtual-machines/ """ import base64 import binascii import os import time from libcloud.common.azure_arm import AzureResourceManagementConnection from libcloud.compute.providers import Provider from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize from libcloud.compute.base import NodeImage, StorageVolume, VolumeSnapshot from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey from libcloud.compute.types import (NodeState, StorageVolumeState, VolumeSnapshotState) from libcloud.common.types import LibcloudError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.common.exceptions import BaseHTTPError from libcloud.storage.drivers.azure_blobs import AzureBlobsStorageDriver from libcloud.utils.py3 import basestring from libcloud.utils import iso8601 RESOURCE_API_VERSION = '2016-04-30-preview' class AzureImage(NodeImage): """Represents a Marketplace node image that an Azure VM can boot from.""" def __init__(self, version, sku, offer, publisher, location, driver): self.publisher = publisher self.offer = offer self.sku = sku self.version = version self.location = location urn = "%s:%s:%s:%s" % (self.publisher, self.offer, self.sku, self.version) name = "%s %s %s %s" % (self.publisher, self.offer, self.sku, self.version) super(AzureImage, self).__init__(urn, name, driver) def __repr__(self): return (('') % (self.id, self.name, self.location)) class AzureVhdImage(NodeImage): """Represents a VHD node image that an Azure VM can boot from.""" def __init__(self, storage_account, blob_container, name, driver): urn = "https://%s.blob%s/%s/%s" % (storage_account, driver.connection.storage_suffix, blob_container, name) super(AzureVhdImage, self).__init__(urn, name, driver) def __repr__(self): return (('') % (self.id, self.name)) class AzureResourceGroup(object): """Represent an Azure resource group.""" def __init__(self, id, name, location, extra): self.id = id self.name = name self.location = location self.extra = extra def __repr__(self): return (('') % (self.id, self.name, self.location)) class AzureNetworkSecurityGroup(object): """Represent an Azure network security group.""" def __init__(self, id, name, location, extra): self.id = id self.name = name self.location = location self.extra = extra def __repr__(self): return ( ('') % (self.id, self.name, self.location)) class AzureNetwork(object): """Represent an Azure virtual network.""" def __init__(self, id, name, location, extra): self.id = id self.name = name self.location = location self.extra = extra def __repr__(self): return (('') % (self.id, self.name, self.location)) class AzureSubnet(object): """Represents a subnet of an Azure virtual network.""" def __init__(self, id, name, extra): self.id = id self.name = name self.extra = extra def __repr__(self): return (('') % (self.id, self.name)) class AzureNic(object): """Represents an Azure virtual network interface controller (NIC).""" def __init__(self, id, name, location, extra): self.id = id self.name = name self.location = location self.extra = extra def __repr__(self): return (('') % (self.id, self.name)) class AzureIPAddress(object): """Represents an Azure public IP address resource.""" def __init__(self, id, name, extra): self.id = id self.name = name self.extra = extra def __repr__(self): return (('') % (self.id, self.name)) class AzureNodeDriver(NodeDriver): """Compute node driver for Azure Resource Manager.""" connectionCls = AzureResourceManagementConnection name = 'Azure Virtual machines' website = 'http://azure.microsoft.com/en-us/services/virtual-machines/' type = Provider.AZURE_ARM features = {'create_node': ['ssh_key', 'password']} # The API doesn't provide state or country information, so fill it in. # Information from https://azure.microsoft.com/en-us/regions/ _location_to_country = { "centralus": "Iowa, USA", "eastus": "Virginia, USA", "eastus2": "Virginia, USA", "usgoviowa": "Iowa, USA", "usgovvirginia": "Virginia, USA", "northcentralus": "Illinois, USA", "southcentralus": "Texas, USA", "westus": "California, USA", "northeurope": "Ireland", "westeurope": "Netherlands", "eastasia": "Hong Kong", "southeastasia": "Singapore", "japaneast": "Tokyo, Japan", "japanwest": "Osaka, Japan", "brazilsouth": "Sao Paulo State, Brazil", "australiaeast": "New South Wales, Australia", "australiasoutheast": "Victoria, Australia" } SNAPSHOT_STATE_MAP = { 'creating': VolumeSnapshotState.CREATING, 'updating': VolumeSnapshotState.UPDATING, 'succeeded': VolumeSnapshotState.AVAILABLE, 'failed': VolumeSnapshotState.ERROR } def __init__(self, tenant_id, subscription_id, key, secret, secure=True, host=None, port=None, api_version=None, region=None, **kwargs): self.tenant_id = tenant_id self.subscription_id = subscription_id self.cloud_environment = kwargs.get("cloud_environment") super(AzureNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) if self.region is not None: loc_id = self.region.lower().replace(" ", "") country = self._location_to_country.get(loc_id) self.default_location = NodeLocation(loc_id, self.region, country, self) else: self.default_location = None def list_locations(self): """ List data centers available with the current subscription. :return: list of node location objects :rtype: ``list`` of :class:`.NodeLocation` """ action = "/subscriptions/%s/providers/Microsoft.Compute" % ( self.subscription_id) r = self.connection.request(action, params={"api-version": "2015-01-01"}) for rt in r.object["resourceTypes"]: if rt["resourceType"] == "virtualMachines": return [self._to_location(l) for l in rt["locations"]] return [] def list_sizes(self, location=None): """ List available VM sizes. :param location: The location at which to list sizes (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :return: list of node size objects :rtype: ``list`` of :class:`.NodeSize` """ if location is None: if self.default_location: location = self.default_location else: raise ValueError("location is required.") action = \ "/subscriptions/%s/providers/Microsoft" \ ".Compute/locations/%s/vmSizes" \ % (self.subscription_id, location.id) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [self._to_node_size(d) for d in r.object["value"]] def list_images(self, location=None, ex_publisher=None, ex_offer=None, ex_sku=None, ex_version=None): """ List available VM images to boot from. :param location: The location at which to list images (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :param ex_publisher: Filter by publisher, or None to list all publishers. :type ex_publisher: ``str`` :param ex_offer: Filter by offer, or None to list all offers. :type ex_offer: ``str`` :param ex_sku: Filter by sku, or None to list all skus. :type ex_sku: ``str`` :param ex_version: Filter by version, or None to list all versions. :type ex_version: ``str`` :return: list of node image objects. :rtype: ``list`` of :class:`.AzureImage` """ images = [] if location is None: locations = [self.default_location] else: locations = [location] for loc in locations: if not ex_publisher: publishers = self.ex_list_publishers(loc) else: publishers = [( "/subscriptions/%s/providers/Microsoft" ".Compute/locations/%s/publishers/%s" % (self.subscription_id, loc.id, ex_publisher), ex_publisher)] for pub in publishers: if not ex_offer: offers = self.ex_list_offers(pub[0]) else: offers = [("%s/artifacttypes/vmimage/offers/%s" % ( pub[0], ex_offer), ex_offer)] for off in offers: if not ex_sku: skus = self.ex_list_skus(off[0]) else: skus = [("%s/skus/%s" % (off[0], ex_sku), ex_sku)] for sku in skus: if not ex_version: versions = self.ex_list_image_versions(sku[0]) else: versions = [("%s/versions/%s" % ( sku[0], ex_version), ex_version)] for v in versions: images.append(AzureImage(v[1], sku[1], off[1], pub[1], loc.id, self.connection.driver)) return images def get_image(self, image_id, location=None): """Returns a single node image from a provider. :param image_id: Either an image urn in the form `Publisher:Offer:Sku:Version` or a Azure blob store URI in the form `http://storageaccount.blob.core.windows.net/container/image.vhd` pointing to a VHD file. :type image_id: ``str`` :param location: The location at which to search for the image (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :rtype :class:`.AzureImage`: or :class:`.AzureVhdImage`: :return: AzureImage or AzureVhdImage instance on success. """ if image_id.startswith("http"): (storageAccount, blobContainer, blob) = _split_blob_uri(image_id) return AzureVhdImage(storageAccount, blobContainer, blob, self) else: (ex_publisher, ex_offer, ex_sku, ex_version) = image_id.split(":") i = self.list_images(location, ex_publisher, ex_offer, ex_sku, ex_version) return i[0] if i else None def list_nodes(self, ex_resource_group=None, ex_fetch_nic=True, ex_fetch_power_state=True): """ List all nodes. :param ex_resource_group: The resource group to list all nodes from. :type ex_resource_group: ``str`` :param ex_fetch_nic: Fetch NIC resources in order to get IP address information for nodes. If True, requires an extra API call for each NIC of each node. If False, IP addresses will not be returned. :type ex_fetch_nic: ``bool`` :param ex_fetch_power_state: Fetch node power state. If True, requires an extra API call for each node. If False, node state will be returned based on provisioning state only. :type ex_fetch_power_state: ``bool`` :return: list of node objects :rtype: ``list`` of :class:`.Node` """ if ex_resource_group: action = "/subscriptions/%s/resourceGroups/%s/" \ "providers/Microsoft.Compute/virtualMachines" \ % (self.subscription_id, ex_resource_group) else: action = "/subscriptions/%s/providers/Microsoft.Compute/" \ "virtualMachines" \ % (self.subscription_id) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [self._to_node(n, fetch_nic=ex_fetch_nic, fetch_power_state=ex_fetch_power_state) for n in r.object["value"]] def create_node(self, name, size, image, auth, ex_resource_group, ex_storage_account, ex_blob_container="vhds", location=None, ex_user_name="azureuser", ex_network=None, ex_subnet=None, ex_nic=None, ex_tags={}, ex_customdata="", ex_use_managed_disks=False, ex_disk_size=None, ex_storage_account_type="Standard_LRS"): """Create a new node instance. This instance will be started automatically. This driver supports the ``ssh_key`` feature flag for ``created_node`` so you can upload a public key into the new instance:: >>> from libcloud.compute.drivers.azure_arm import AzureNodeDriver >>> driver = AzureNodeDriver(...) >>> auth = NodeAuthSSHKey('pubkey data here') >>> node = driver.create_node("test_node", auth=auth) This driver also supports the ``password`` feature flag for ``create_node`` so you can set a password:: >>> driver = AzureNodeDriver(...) >>> auth = NodeAuthPassword('mysecretpassword') >>> node = driver.create_node("test_node", auth=auth, ...) If you don't provide the ``auth`` argument libcloud will assign a password: >>> driver = AzureNodeDriver(...) >>> node = driver.create_node("test_node", ...) >>> password = node.extra["properties"] \ ["osProfile"]["adminPassword"] :param name: String with a name for this new node (required) :type name: ``str`` :param size: The size of resources allocated to this node. (required) :type size: :class:`.NodeSize` :param image: OS Image to boot on node. (required) :type image: :class:`.AzureImage` :param location: Which data center to create a node in. (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :param auth: Initial authentication information for the node (optional) :type auth: :class:`.NodeAuthSSHKey` or :class:`NodeAuthPassword` :param ex_resource_group: The resource group in which to create the node :type ex_resource_group: ``str`` :param ex_storage_account: The storage account id in which to store the node's disk image. Note: when booting from a user image (AzureVhdImage) the source image and the node image must use the same storage account. :type ex_storage_account: ``str`` :param ex_blob_container: The name of the blob container on the storage account in which to store the node's disk image (optional, default "vhds") :type ex_blob_container: ``str`` :param ex_user_name: User name for the initial admin user (optional, default "azureuser") :type ex_user_name: ``str`` :param ex_network: The virtual network the node will be attached to. Must provide either `ex_network` (to create a default NIC for the node on the given network) or `ex_nic` (to supply the NIC explicitly). :type ex_network: ``str`` :param ex_subnet: If ex_network is provided, the subnet of the virtual network the node will be attached to. Optional, default is the "default" subnet. :type ex_subnet: ``str`` :param ex_nic: A virtual NIC to attach to this Node, from `ex_create_network_interface` or `ex_get_nic`. Must provide either `ex_nic` (to supply the NIC explicitly) or ex_network (to create a default NIC for the node on the given network). :type ex_nic: :class:`AzureNic` :param ex_tags: Optional tags to associate with this node. :type ex_tags: ``dict`` :param ex_customdata: Custom data that will be placed in the file /var/lib/waagent/CustomData https://azure.microsoft.com/en-us/documentation/ \ articles/virtual-machines-how-to-inject-custom-data/ :type ex_customdata: ``str`` :param ex_use_managed_disks: Enable this feature to have Azure automatically manage the availability of disks to provide data redundancy and fault tolerance, without creating and managing storage accounts on your own. Managed disks may not be available in all regions (default False). :type ex_use_managed_disks: ``bool`` :param ex_disk_size: Custom OS disk size in GB :type ex_disk_size: ``int`` :param ex_storage_account_type: The Storage Account type, ``Standard_LRS``(HDD disks) or ``Premium_LRS``(SSD disks). :type ex_storage_account_type: str :return: The newly created node. :rtype: :class:`.Node` """ if location is None: location = self.default_location if ex_nic is None: if ex_network is None: raise ValueError("Must provide either ex_network or ex_nic") if ex_subnet is None: ex_subnet = "default" subnet_id = "/subscriptions/%s/resourceGroups/%s/providers" \ "/Microsoft.Network/virtualnetworks/%s/subnets/%s" % \ (self.subscription_id, ex_resource_group, ex_network, ex_subnet) subnet = AzureSubnet(subnet_id, ex_subnet, {}) ex_nic = self.ex_create_network_interface(name + "-nic", subnet, ex_resource_group, location) auth = self._get_and_check_auth(auth) target = "/subscriptions/%s/resourceGroups/%s/providers" \ "/Microsoft.Compute/virtualMachines/%s" % \ (self.subscription_id, ex_resource_group, name) if isinstance(image, AzureVhdImage): instance_vhd = self._get_instance_vhd( name=name, ex_resource_group=ex_resource_group, ex_storage_account=ex_storage_account, ex_blob_container=ex_blob_container) storage_profile = { "osDisk": { "name": name, "osType": "linux", "caching": "ReadWrite", "createOption": "FromImage", "image": { "uri": image.id }, "vhd": { "uri": instance_vhd, } } } if ex_use_managed_disks: raise LibcloudError( "Creating managed OS disk from %s image " "type is not supported." % type(image)) elif isinstance(image, AzureImage): storage_profile = { "imageReference": { "publisher": image.publisher, "offer": image.offer, "sku": image.sku, "version": image.version }, "osDisk": { "name": name, "osType": "linux", "caching": "ReadWrite", "createOption": "FromImage" } } if ex_use_managed_disks: storage_profile["osDisk"]["managedDisk"] = { "storageAccountType": ex_storage_account_type } else: instance_vhd = self._get_instance_vhd( name=name, ex_resource_group=ex_resource_group, ex_storage_account=ex_storage_account, ex_blob_container=ex_blob_container) storage_profile["osDisk"]["vhd"] = { "uri": instance_vhd } else: raise LibcloudError( "Unknown image type %s, expected one of AzureImage, " "AzureVhdImage." % type(image)) data = { "id": target, "name": name, "type": "Microsoft.Compute/virtualMachines", "location": location.id, "tags": ex_tags, "properties": { "hardwareProfile": { "vmSize": size.id }, "storageProfile": storage_profile, "osProfile": { "computerName": name }, "networkProfile": { "networkInterfaces": [ { "id": ex_nic.id } ] } } } if ex_disk_size: data['properties']['storageProfile']['osDisk'].update({ 'diskSizeGB': ex_disk_size }) if ex_customdata: data["properties"]["osProfile"]["customData"] = \ base64.b64encode(ex_customdata) data["properties"]["osProfile"]["adminUsername"] = ex_user_name if isinstance(auth, NodeAuthSSHKey): data["properties"]["osProfile"]["adminPassword"] = \ binascii.hexlify(os.urandom(20)).decode("utf-8") data["properties"]["osProfile"]["linuxConfiguration"] = { "disablePasswordAuthentication": "true", "ssh": { "publicKeys": [ { "path": '/home/%s/.ssh/authorized_keys' % ( ex_user_name), "keyData": auth.pubkey # pylint: disable=no-member } ] } } elif isinstance(auth, NodeAuthPassword): data["properties"]["osProfile"]["linuxConfiguration"] = { "disablePasswordAuthentication": "false" } data["properties"]["osProfile"]["adminPassword"] = auth.password else: raise ValueError( "Must provide NodeAuthSSHKey or NodeAuthPassword in auth") r = self.connection.request( target, params={"api-version": RESOURCE_API_VERSION}, data=data, method="PUT") node = self._to_node(r.object) node.size = size node.image = image return node def reboot_node(self, node): """ Reboot a node. :param node: The node to be rebooted :type node: :class:`.Node` :return: True if the reboot was successful, otherwise False :rtype: ``bool`` """ target = "%s/restart" % node.id try: self.connection.request( target, params={"api-version": RESOURCE_API_VERSION}, method='POST') return True except BaseHTTPError as h: if h.code == 202: return True else: return False def destroy_node(self, node, ex_destroy_nic=True, ex_destroy_vhd=True, ex_poll_qty=10, ex_poll_wait=10): """ Destroy a node. :param node: The node to be destroyed :type node: :class:`.Node` :param ex_destroy_nic: Destroy the NICs associated with this node (default True). :type node: ``bool`` :param ex_destroy_vhd: Destroy the OS disk blob associated with this node (default True). :type node: ``bool`` :param ex_poll_qty: Number of retries checking if the node is gone, destroying the NIC or destroying the VHD (default 10). :type node: ``int`` :param ex_poll_wait: Delay in seconds between retries (default 10). :type node: ``int`` :return: True if the destroy was successful, raises exception otherwise. :rtype: ``bool`` """ do_node_polling = (ex_destroy_nic or ex_destroy_vhd) # This returns a 202 (Accepted) which means that the delete happens # asynchronously. # If returns 404, we may be retrying a previous destroy_node call that # failed to clean up its related resources, so it isn't taken as a # failure. try: self.connection.request(node.id, params={"api-version": "2015-06-15"}, method='DELETE') except BaseHTTPError as h: if h.code == 202: pass elif h.code == 204: # Returns 204 if node already deleted. do_node_polling = False else: raise # Poll until the node actually goes away (otherwise attempt to delete # NIC and VHD will fail with "resource in use" errors). retries = ex_poll_qty while do_node_polling and retries > 0: try: time.sleep(ex_poll_wait) self.connection.request( node.id, params={"api-version": RESOURCE_API_VERSION}) retries -= 1 except BaseHTTPError as h: if h.code in (204, 404): # Node is gone break else: raise # Optionally clean up the network # interfaces that were attached to this node. interfaces = \ node.extra["properties"]["networkProfile"]["networkInterfaces"] if ex_destroy_nic: for nic in interfaces: retries = ex_poll_qty while retries > 0: try: self.ex_destroy_nic(self._to_nic(nic)) break except BaseHTTPError as h: retries -= 1 if (h.code == 400 and h.message.startswith("[NicInUse]") and retries > 0): time.sleep(ex_poll_wait) else: raise # Optionally clean up OS disk VHD. vhd = node.extra["properties"]["storageProfile"]["osDisk"].get("vhd") if ex_destroy_vhd and vhd is not None: retries = ex_poll_qty resourceGroup = node.id.split("/")[4] while retries > 0: try: if self._ex_delete_old_vhd(resourceGroup, vhd["uri"]): break # Unfortunately lease errors usually result in it returning # "False" with no more information. Need to wait and try # again. except LibcloudError as e: retries -= 1 if "LeaseIdMissing" in str(e) and retries > 0: # Unfortunately lease errors # (which occur if the vhd blob # hasn't yet been released by the VM being destroyed) # get raised as plain # LibcloudError. Wait a bit and try again. time.sleep(ex_poll_wait) else: raise time.sleep(10) return True def create_volume(self, size, name, location=None, snapshot=None, ex_resource_group=None, ex_account_type=None, ex_tags=None): """ Create a new managed volume. :param size: Size of volume in gigabytes. :type size: ``int`` :param name: Name of the volume to be created. :type name: ``str`` :param location: Which data center to create a volume in. (required) :type location: :class:`NodeLocation` :param snapshot: Snapshot from which to create the new volume. :type snapshot: :class:`VolumeSnapshot` :param ex_resource_group: The name of resource group in which to create the volume. (required) :type ex_resource_group: ``str`` :param ex_account_type: The Storage Account type, ``Standard_LRS``(HDD disks) or ``Premium_LRS``(SSD disks). :type ex_account_type: ``str`` :param ex_tags: Optional tags to associate with this resource. :type ex_tags: ``dict`` :return: The newly created volume. :rtype: :class:`StorageVolume` """ if location is None: raise ValueError("Must provide `location` value.") if ex_resource_group is None: raise ValueError("Must provide `ex_resource_group` value.") action = ( u'/subscriptions/{subscription_id}/resourceGroups/{resource_group}' u'/providers/Microsoft.Compute/disks/{volume_name}' ).format( subscription_id=self.subscription_id, resource_group=ex_resource_group, volume_name=name, ) tags = ex_tags if ex_tags is not None else {} creation_data = { 'createOption': 'Empty' } if snapshot is None else { 'createOption': 'Copy', 'sourceUri': snapshot.id } data = { 'location': location.id, 'tags': tags, 'properties': { 'creationData': creation_data, 'diskSizeGB': size } } if ex_account_type is not None: data['properties']['accountType'] = ex_account_type response = self.connection.request( action, method='PUT', params={ 'api-version': RESOURCE_API_VERSION, }, data=data ) return self._to_volume( response.object, name=name, ex_resource_group=ex_resource_group ) def list_volumes(self, ex_resource_group=None): """ Lists all the disks under a resource group or subscription. :param ex_resource_group: The identifier of your subscription where the managed disks are located. :type ex_resource_group: ``str`` :rtype: list of :class:`StorageVolume` """ if ex_resource_group: action = u'/subscriptions/{subscription_id}/resourceGroups' \ u'/{resource_group}/providers/Microsoft.Compute/disks' else: action = u'/subscriptions/{subscription_id}' \ u'/providers/Microsoft.Compute/disks' action = action.format( subscription_id=self.subscription_id, resource_group=ex_resource_group ) response = self.connection.request( action, method='GET', params={ 'api-version': RESOURCE_API_VERSION } ) return [self._to_volume(volume) for volume in response.object['value']] def attach_volume(self, node, volume, ex_lun=None, ex_vhd_uri=None, ex_vhd_create=False, **ex_kwargs): """ Attach a volume to node. :param node: A node to attach volume. :type node: :class:`Node` :param volume: A volume to attach. :type volume: :class:`StorageVolume` :param ex_lun: Specifies the logical unit number (LUN) location for the data drive in the virtual machine. Each data disk must have a unique LUN. :type ex_lun: ``int`` :param ex_vhd_uri: Attach old-style unmanaged disk from VHD blob. (optional) :type ex_vhd_uri: ``str`` :param ex_vhd_create: Create a new VHD blob for unmanaged disk. (optional) :type ex_vhd_create: ``bool`` :rtype: ``bool`` """ action = node.extra['id'] location = node.extra['location'] disks = node.extra['properties']['storageProfile']['dataDisks'] if ex_lun is None: # find the smallest unused logical unit number used_luns = [disk['lun'] for disk in disks] free_luns = [lun for lun in range(0, 64) if lun not in used_luns] if len(free_luns) > 0: ex_lun = free_luns[0] else: raise LibcloudError("No LUN available to attach new disk.") if ex_vhd_uri is not None: new_disk = { 'name': volume.name, 'diskSizeGB': volume.size, 'lun': ex_lun, 'createOption': 'empty' if ex_vhd_create else 'attach', 'vhd': {'uri': ex_vhd_uri}, } else: # attach existing managed disk new_disk = { 'lun': ex_lun, 'createOption': 'attach', 'managedDisk': {'id': volume.id}} disks.append(new_disk) self.connection.request( action, method='PUT', params={ 'api-version': RESOURCE_API_VERSION }, data={ 'properties': { 'storageProfile': { 'dataDisks': disks } }, 'location': location }) return True def ex_resize_volume(self, volume, new_size, resource_group): """ Resize a volume. :param volume: A volume to resize. :type volume: :class:`StorageVolume` :param new_size: The new size to resize the volume to in Gib. :type new_size: ``int`` :param resource_group: The name of the resource group in which to create the volume. :type resource_group: ``str`` """ action = ( u'/subscriptions/{subscription_id}/resourceGroups/{resource_group}' u'/providers/Microsoft.Compute/disks/{volume_name}' ).format( subscription_id=self.subscription_id, resource_group=resource_group, volume_name=volume.name, ) data = { 'location': volume.extra['location'], 'properties': { 'diskSizeGB': new_size, 'creationData': volume.extra['properties']['creationData'] } } response = self.connection.request( action, method='PUT', params={ 'api-version': '2018-06-01', }, data=data ) return self._to_volume( response.object, name=volume.name, ex_resource_group=resource_group ) def detach_volume(self, volume, ex_node=None): """ Detach a managed volume from a node. """ if ex_node is None: raise ValueError("Must provide `ex_node` value.") action = ex_node.extra['id'] location = ex_node.extra['location'] disks = ex_node.extra['properties']['storageProfile']['dataDisks'] # remove volume from `properties.storageProfile.dataDisks` disks[:] = [ disk for disk in disks if disk.get('name') != volume.name and disk.get('managedDisk', {}).get('id') != volume.id ] self.connection.request( action, method='PUT', params={ 'api-version': RESOURCE_API_VERSION }, data={ 'properties': { 'storageProfile': { 'dataDisks': disks } }, 'location': location } ) return True def destroy_volume(self, volume): """ Delete a volume. """ self.ex_delete_resource(volume) return True def create_volume_snapshot(self, volume, name=None, location=None, ex_resource_group=None, ex_tags=None): """ Create snapshot from volume. :param volume: Instance of ``StorageVolume``. :type volume: :class`StorageVolume` :param name: Name of snapshot. (required) :type name: ``str`` :param location: Which data center to create a volume in. (required) :type location: :class:`NodeLocation` :param ex_resource_group: The name of resource group in which to create the snapshot. (required) :type ex_resource_group: ``str`` :param ex_tags: Optional tags to associate with this resource. :type ex_tags: ``dict`` :rtype: :class:`VolumeSnapshot` """ if name is None: raise ValueError("Must provide `name` value") if location is None: raise ValueError("Must provide `location` value") if ex_resource_group is None: raise ValueError("Must provide `ex_resource_group` value") snapshot_id = ( u'/subscriptions/{subscription_id}' u'/resourceGroups/{resource_group}' u'/providers/Microsoft.Compute' u'/snapshots/{snapshot_name}' ).format( subscription_id=self.subscription_id, resource_group=ex_resource_group, snapshot_name=name, ) tags = ex_tags if ex_tags is not None else {} data = { 'location': location.id, 'tags': tags, 'properties': { 'creationData': { 'createOption': 'Copy', 'sourceUri': volume.id }, } } response = self.connection.request( snapshot_id, method='PUT', data=data, params={ 'api-version': RESOURCE_API_VERSION }, ) return self._to_snapshot( response.object, name=name, ex_resource_group=ex_resource_group ) def list_volume_snapshots(self, volume): return [snapshot for snapshot in self.list_snapshots() if snapshot.extra['source_id'] == volume.id] def list_snapshots(self, ex_resource_group=None): """ Lists all the snapshots under a resource group or subscription. :param ex_resource_group: The identifier of your subscription where the managed snapshots are located (optional). :type ex_resource_group: ``str`` :rtype: list of :class:`VolumeSnapshot` """ if ex_resource_group: action = u'/subscriptions/{subscription_id}/resourceGroups' \ u'/{resource_group}/providers/Microsoft.Compute/snapshots' else: action = u'/subscriptions/{subscription_id}' \ u'/providers/Microsoft.Compute/snapshots' action = action.format( subscription_id=self.subscription_id, resource_group=ex_resource_group ) response = self.connection.request( action, method='GET', params={ 'api-version': RESOURCE_API_VERSION } ) return [self._to_snapshot(snap) for snap in response.object['value']] def destroy_volume_snapshot(self, snapshot): """ Delete a snapshot. """ self.ex_delete_resource(snapshot) return True def _to_volume(self, volume_obj, name=None, ex_resource_group=None): """ Parse the JSON element and return a StorageVolume object. :param volume_obj: A volume object from an azure response. :type volume_obj: ``dict`` :param name: An optional name for the volume. :type name: ``str`` :param ex_resource_group: An optional resource group for the volume. :type ex_resource_group: ``str`` :rtype: :class:`StorageVolume` """ volume_id = volume_obj.get('id') volume_name = volume_obj.get('name') extra = dict(volume_obj) properties = extra['properties'] size = properties.get('diskSizeGB') if size is not None: size = int(size) provisioning_state = properties.get('provisioningState', '').lower() disk_state = properties.get('diskState', '').lower() if provisioning_state == 'creating': state = StorageVolumeState.CREATING elif provisioning_state == 'updating': state = StorageVolumeState.UPDATING elif provisioning_state == 'succeeded': if disk_state in ('attached', 'reserved', 'activesas'): state = StorageVolumeState.INUSE elif disk_state == 'unattached': state = StorageVolumeState.AVAILABLE else: state = StorageVolumeState.UNKNOWN else: state = StorageVolumeState.UNKNOWN if volume_id is None \ and ex_resource_group is not None \ and name is not None: volume_id = ( u'/subscriptions/{subscription_id}' u'/resourceGroups/{resource_group}' u'/providers/Microsoft.Compute/disks/{volume_name}' ).format( subscription_id=self.subscription_id, resource_group=ex_resource_group, volume_name=name ) if volume_name is None and \ name is not None: volume_name = name return StorageVolume( id=volume_id, name=volume_name, size=size, driver=self, state=state, extra=extra ) def _to_snapshot(self, snapshot_obj, name=None, ex_resource_group=None): """ Parse the JSON element and return a VolumeSnapshot object. :param snapshot_obj: A snapshot object from an azure response. :type snapshot_obj: ``dict`` :param name: An optional name for the volume. :type name: ``str`` :param ex_resource_group: An optional resource group for the volume. :type ex_resource_group: ``str`` :rtype: :class:`VolumeSnapshot` """ snapshot_id = snapshot_obj.get('id') name = snapshot_obj.get('name', name) properties = snapshot_obj['properties'] size = properties.get('diskSizeGB') if size is not None: size = int(size) extra = dict(snapshot_obj) extra['source_id'] = properties['creationData']['sourceUri'] if '/providers/Microsoft.Compute/disks/' in extra['source_id']: extra['volume_id'] = extra['source_id'] state = self.SNAPSHOT_STATE_MAP.get( properties.get('provisioningState', '').lower(), VolumeSnapshotState.UNKNOWN ) try: created_at = iso8601.parse_date(properties.get('timeCreated')) except (TypeError, ValueError, iso8601.ParseError): created_at = None if snapshot_id is None \ and ex_resource_group is not None \ and name is not None: snapshot_id = ( u'/subscriptions/{subscription_id}' u'/resourceGroups/{resource_group}' u'/providers/Microsoft.Compute/snapshots/{snapshot_name}' ).format( subscription_id=self.subscription_id, resource_group=ex_resource_group, snapshot_name=name ) return VolumeSnapshot( snapshot_id, name=name, size=size, driver=self, state=state, extra=extra, created=created_at ) def ex_delete_resource(self, resource): """ Delete a resource. """ if not isinstance(resource, basestring): resource = resource.id r = self.connection.request( resource, method='DELETE', params={ 'api-version': RESOURCE_API_VERSION }, ) return r.status in [200, 202, 204] def ex_get_ratecard(self, offer_durable_id, currency='USD', locale='en-US', region='US'): """ Get rate card :param offer_durable_id: ID of the offer applicable for this user account. (e.g. "0026P") See http://azure.microsoft.com/en-us/support/legal/offer-details/ :type offer_durable_id: str :param currency: Desired currency for the response (default: "USD") :type currency: ``str`` :param locale: Locale (default: "en-US") :type locale: ``str`` :param region: Region (two-letter code) (default: "US") :type region: ``str`` :return: A dictionary of rates whose ID's correspond to nothing at all :rtype: ``dict`` """ action = "/subscriptions/%s/providers/Microsoft.Commerce/" \ "RateCard" % (self.subscription_id,) params = {"api-version": "2016-08-31-preview", "$filter": "OfferDurableId eq 'MS-AZR-%s' and " "Currency eq '%s' and " "Locale eq '%s' and " "RegionInfo eq '%s'" % (offer_durable_id, currency, locale, region)} r = self.connection.request(action, params=params) return r.object def ex_list_publishers(self, location=None): """ List node image publishers. :param location: The location at which to list publishers (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :return: A list of tuples in the form ("publisher id", "publisher name") :rtype: ``list`` """ if location is None: if self.default_location: location = self.default_location else: raise ValueError("location is required.") action = "/subscriptions/%s/providers/Microsoft.Compute/" \ "locations/%s/publishers" \ % (self.subscription_id, location.id) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [(p["id"], p["name"]) for p in r.object] def ex_list_offers(self, publisher): """ List node image offers from a publisher. :param publisher: The complete resource path to a publisher (as returned by `ex_list_publishers`) :type publisher: ``str`` :return: A list of tuples in the form ("offer id", "offer name") :rtype: ``list`` """ action = "%s/artifacttypes/vmimage/offers" % (publisher) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [(p["id"], p["name"]) for p in r.object] def ex_list_skus(self, offer): """ List node image skus in an offer. :param offer: The complete resource path to an offer (as returned by `ex_list_offers`) :type offer: ``str`` :return: A list of tuples in the form ("sku id", "sku name") :rtype: ``list`` """ action = "%s/skus" % offer r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [(sku["id"], sku["name"]) for sku in r.object] def ex_list_image_versions(self, sku): """ List node image versions in a sku. :param sku: The complete resource path to a sku (as returned by `ex_list_skus`) :type publisher: ``str`` :return: A list of tuples in the form ("version id", "version name") :rtype: ``list`` """ action = "%s/versions" % (sku) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [(img["id"], img["name"]) for img in r.object] def ex_list_resource_groups(self): """ List resource groups. :return: A list of resource groups. :rtype: ``list`` of :class:`.AzureResourceGroup` """ action = "/subscriptions/%s/resourceGroups/" % (self.subscription_id) r = self.connection.request(action, params={"api-version": "2016-09-01"}) return [AzureResourceGroup(grp["id"], grp["name"], grp["location"], grp["properties"]) for grp in r.object["value"]] def ex_list_network_security_groups(self, resource_group): """ List network security groups. :param resource_group: List security groups in a specific resource group. :type resource_group: ``str`` :return: A list of network security groups. :rtype: ``list`` of :class:`.AzureNetworkSecurityGroup` """ action = "/subscriptions/%s/resourceGroups/%s/providers/" \ "Microsoft.Network/networkSecurityGroups" \ % (self.subscription_id, resource_group) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [AzureNetworkSecurityGroup(net["id"], net["name"], net["location"], net["properties"]) for net in r.object["value"]] def ex_create_network_security_group(self, name, resource_group, location=None): """ Update tags on any resource supporting tags. :param name: Name of the network security group to create :type name: ``str`` :param resource_group: The resource group to create the network security group in :type resource_group: ``str`` :param location: The location at which to create the network security group (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` """ if location is None: if self.default_location: location = self.default_location else: raise ValueError("location is required.") target = "/subscriptions/%s/resourceGroups/%s/" \ "providers/Microsoft.Network/networkSecurityGroups/%s" \ % (self.subscription_id, resource_group, name) data = { "location": location.id, } self.connection.request(target, params={"api-version": "2016-09-01"}, data=data, method='PUT') def ex_delete_network_security_group(self, name, resource_group, location=None): """ Update tags on any resource supporting tags. :param name: Name of the network security group to delete :type name: ``str`` :param resource_group: The resource group to create the network security group in :type resource_group: ``str`` :param location: The location at which to create the network security group (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` """ if location is None: if self.default_location: location = self.default_location else: raise ValueError("location is required.") target = "/subscriptions/%s/resourceGroups/%s/" \ "providers/Microsoft.Network/networkSecurityGroups/%s" \ % (self.subscription_id, resource_group, name) data = { "location": location.id, } self.connection.request(target, params={"api-version": "2016-09-01"}, data=data, method='DELETE') def ex_list_networks(self): """ List virtual networks. :return: A list of virtual networks. :rtype: ``list`` of :class:`.AzureNetwork` """ action = "/subscriptions/%s/providers/" \ "Microsoft.Network/virtualnetworks" \ % (self.subscription_id) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [AzureNetwork(net["id"], net["name"], net["location"], net["properties"]) for net in r.object["value"]] def ex_list_subnets(self, network): """ List subnets of a virtual network. :param network: The virtual network containing the subnets. :type network: :class:`.AzureNetwork` :return: A list of subnets. :rtype: ``list`` of :class:`.AzureSubnet` """ action = "%s/subnets" % (network.id) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [AzureSubnet(net["id"], net["name"], net["properties"]) for net in r.object["value"]] def ex_list_nics(self, resource_group=None): """ List available virtual network interface controllers in a resource group :param resource_group: List NICS in a specific resource group containing the NICs(optional). :type resource_group: ``str`` :return: A list of NICs. :rtype: ``list`` of :class:`.AzureNic` """ if resource_group is None: action = "/subscriptions/%s/providers/Microsoft.Network" \ "/networkInterfaces" % self.subscription_id else: action = "/subscriptions/%s/resourceGroups/%s/providers" \ "/Microsoft.Network/networkInterfaces" % \ (self.subscription_id, resource_group) r = self.connection.request( action, params={"api-version": "2015-06-15"}) return [self._to_nic(net) for net in r.object["value"]] def ex_get_nic(self, id): """ Fetch information about a NIC. :param id: The complete resource path to the NIC resource. :type id: ``str`` :return: The NIC object :rtype: :class:`.AzureNic` """ r = self.connection.request(id, params={"api-version": "2015-06-15"}) return self._to_nic(r.object) def ex_update_nic_properties(self, network_interface, resource_group, properties): """ Update the properties of an already existing virtual network interface (NIC). :param network_interface: The NIC to update. :type network_interface: :class:`.AzureNic` :param resource_group: The resource group to check the ip address in. :type resource_group: ``str`` :param properties: The dictionary of the NIC's properties :type properties: ``dict`` :return: The NIC object :rtype: :class:`.AzureNic` """ target = "/subscriptions/%s/resourceGroups/%s/providers" \ "/Microsoft.Network/networkInterfaces/%s" \ % (self.subscription_id, resource_group, network_interface.name) data = { "properties": properties, "location": network_interface.location, } r = self.connection.request(target, params={"api-version": '2018-06-01'}, data=data, method='PUT') return AzureNic(r.object["id"], r.object["name"], r.object["location"], r.object["properties"]) def ex_update_network_profile_of_node(self, node, network_profile): """ Update the network profile of a node. This method can be used to attach or detach a NIC to a node. :param node: A node to attach the network interface to. :type node: :class:`Node` :param network_profile: The new network profile to update. :type network_profile: ``dict`` """ action = node.extra['id'] location = node.extra['location'] self.connection.request( action, method='PUT', params={ 'api-version': '2018-06-01' }, data={ "id": node.id, "name": node.name, "type": "Microsoft.Compute/virtualMachines", "location": location, 'properties': { 'networkProfile': network_profile } }) def ex_destroy_nic(self, nic): """ Destroy a NIC. :param nic: The NIC to destroy. :type nic: ``.AzureNic`` :return: True on success :rtype: ``bool`` """ try: self.connection.request( nic.id, params={"api-version": "2015-06-15"}, method='DELETE') return True except BaseHTTPError as h: if h.code in (202, 204): # Deletion is accepted (but deferred), or NIC is already # deleted return True else: raise def ex_check_ip_address_availability(self, resource_group, network, ip_address): """ Checks whether a private IP address is available for use. Also returns an object that contains the available IPs in the subnet. :param resource_group: The resource group to check the ip address in. :type resource_group: ``str`` :param network: The virtual network. :type network: :class:`.AzureNetwork` :param ip_address: The private IP address to be verified. :type ip_address: ``str`` """ params = {"api-version": '2018-06-01'} action = "/subscriptions/%s/resourceGroups/%s/providers" \ "/Microsoft.Network/virtualNetworks/%s/" \ "CheckIPAddressAvailability" % \ (self.subscription_id, resource_group, network.name) if ip_address is not None: params["ipAddress"] = ip_address r = self.connection.request( action, params=params) return r.object def ex_get_node(self, id): """ Fetch information about a node. :param id: The complete resource path to the node resource. :type id: ``str`` :return: The Node object :rtype: :class:`.Node` """ r = self.connection.request( id, params={"api-version": RESOURCE_API_VERSION}) return self._to_node(r.object) def ex_get_volume(self, id): """ Fetch information about a volume. :param id: The complete resource path to the volume resource. :type id: ``str`` :return: The StorageVolume object :rtype: :class:`.StorageVolume` """ r = self.connection.request( id, params={"api-version": RESOURCE_API_VERSION}) return self._to_volume(r.object) def ex_get_snapshot(self, id): """ Fetch information about a snapshot. :param id: The complete resource path to the snapshot resource. :type id: ``str`` :return: The VolumeSnapshot object :rtype: :class:`.VolumeSnapshot` """ r = self.connection.request( id, params={"api-version": RESOURCE_API_VERSION}) return self._to_snapshot(r.object) def ex_get_public_ip(self, id): """ Fetch information about a public IP resource. :param id: The complete resource path to the public IP resource. :type id: ``str` :return: The public ip object :rtype: :class:`.AzureIPAddress` """ r = self.connection.request(id, params={"api-version": "2015-06-15"}) return self._to_ip_address(r.object) def ex_list_public_ips(self, resource_group): """ List public IP resources. :param resource_group: List public IPs in a specific resource group. :type resource_group: ``str`` :return: List of public ip objects :rtype: ``list`` of :class:`.AzureIPAddress` """ action = "/subscriptions/%s/resourceGroups/%s/" \ "providers/Microsoft.Network/publicIPAddresses" \ % (self.subscription_id, resource_group) r = self.connection.request(action, params={"api-version": "2015-06-15"}) return [self._to_ip_address(net) for net in r.object["value"]] def ex_create_public_ip(self, name, resource_group, location=None, public_ip_allocation_method=None): """ Create a public IP resources. :param name: Name of the public IP resource :type name: ``str`` :param resource_group: The resource group to create the public IP :type resource_group: ``str`` :param location: The location at which to create the public IP (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :param public_ip_allocation_method: Call ex_create_public_ip with public_ip_allocation_method="Static" to create a static public IP address :type public_ip_allocation_method: ``str`` :return: The newly created public ip object :rtype: :class:`.AzureIPAddress` """ if location is None: if self.default_location: location = self.default_location else: raise ValueError("location is required.") target = "/subscriptions/%s/resourceGroups/%s/" \ "providers/Microsoft.Network/publicIPAddresses/%s" \ % (self.subscription_id, resource_group, name) data = { "location": location.id, "tags": {}, "properties": { "publicIPAllocationMethod": "Dynamic" } } if public_ip_allocation_method == "Static": data['properties']['publicIPAllocationMethod'] = "Static" r = self.connection.request(target, params={"api-version": "2015-06-15"}, data=data, method='PUT') return self._to_ip_address(r.object) def ex_delete_public_ip(self, public_ip): """ Delete a public ip address resource. :param public_ip: Public ip address resource to delete :type public_ip: `.AzureIPAddress` """ # NOTE: This operation requires API version 2018-11-01 so # "ex_delete_resource" won't for for deleting an IP address resource = public_ip.id r = self.connection.request( resource, method='DELETE', params={ 'api-version': '2019-06-01' }, ) return r.status in [200, 202, 204] def ex_create_network_interface(self, name, subnet, resource_group, location=None, public_ip=None): """ Create a virtual network interface (NIC). :param name: Name of the NIC resource :type name: ``str`` :param subnet: The subnet to attach the NIC :type subnet: :class:`.AzureSubnet` :param resource_group: The resource group to create the NIC :type resource_group: ``str`` :param location: The location at which to create the NIC (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :param public_ip: Associate a public IP resource with this NIC (optional). :type public_ip: :class:`.AzureIPAddress` :return: The newly created NIC :rtype: :class:`.AzureNic` """ if location is None: if self.default_location: location = self.default_location else: raise ValueError("location is required.") target = "/subscriptions/%s/resourceGroups/%s/providers" \ "/Microsoft.Network/networkInterfaces/%s" \ % (self.subscription_id, resource_group, name) data = { "location": location.id, "tags": {}, "properties": { "ipConfigurations": [{ "name": "myip1", "properties": { "subnet": { "id": subnet.id }, "privateIPAllocationMethod": "Dynamic" } }] } } if public_ip: ip_config = data["properties"]["ipConfigurations"][0] ip_config["properties"]["publicIPAddress"] = { "id": public_ip.id } r = self.connection.request(target, params={"api-version": "2015-06-15"}, data=data, method='PUT') return AzureNic(r.object["id"], r.object["name"], r.object["location"], r.object["properties"]) def ex_create_tags(self, resource, tags, replace=False): """ Update tags on any resource supporting tags. :param resource: The resource to update. :type resource: ``str`` or Azure object with an ``id`` attribute. :param tags: The tags to set. :type tags: ``dict`` :param replace: If true, replace all tags with the new tags. If false (default) add or update tags. :type replace: ``bool`` """ if not isinstance(resource, basestring): resource = resource.id r = self.connection.request( resource, params={"api-version": '2018-06-01'}) if replace: r.object["tags"] = tags else: r.object["tags"].update(tags) self.connection.request( resource, data={"tags": r.object["tags"]}, params={"api-version": '2018-06-01'}, method="PATCH") def start_node(self, node): """ Start a stopped node. :param node: The node to be started :type node: :class:`.Node` """ target = "%s/start" % node.id r = self.connection.request(target, params={"api-version": "2015-06-15"}, method='POST') return r.object def stop_node(self, node, ex_deallocate=True): """ Stop a running node. :param node: The node to be stopped :type node: :class:`.Node` :param deallocate: If True (default) stop and then deallocate the node (release the hardware allocated to run the node). If False, stop the node but maintain the hardware allocation. If the node is not deallocated, the subscription will continue to be billed as if it were running. :type deallocate: ``bool`` """ if ex_deallocate: target = "%s/deallocate" % node.id else: target = "%s/powerOff" % node.id r = self.connection.request(target, params={"api-version": "2015-06-15"}, method='POST') return r.object def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node, deallocate=True): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node, ex_deallocate=deallocate) def ex_get_storage_account_keys(self, resource_group, storage_account): """ Get account keys required to access to a storage account (using AzureBlobsStorageDriver). :param resource_group: The resource group containing the storage account :type resource_group: ``str`` :param storage_account: Storage account to access :type storage_account: ``str`` :return: The account keys, in the form `{"key1": "XXX", "key2": "YYY"}` :rtype: ``.dict`` """ action = "/subscriptions/%s/resourceGroups/%s/" \ "providers/Microsoft.Storage/storageAccounts/%s/listKeys" \ % (self.subscription_id, resource_group, storage_account) r = self.connection.request(action, params={ "api-version": "2015-05-01-preview"}, method="POST") return r.object def ex_run_command(self, node, command, filerefs=[], timestamp=0, storage_account_name=None, storage_account_key=None, location=None): """ Run a command on the node as root. Does not require ssh to log in, uses Windows Azure Agent (waagent) running on the node. :param node: The node on which to run the command. :type node: :class:``.Node`` :param command: The actual command to run. Note this is parsed into separate arguments according to shell quoting rules but is executed directly as a subprocess, not a shell command. :type command: ``str`` :param filerefs: Optional files to fetch by URI from Azure blob store (must provide storage_account_name and storage_account_key), or regular HTTP. :type command: ``list`` of ``str`` :param location: The location of the virtual machine (if None, use default location specified as 'region' in __init__) :type location: :class:`.NodeLocation` :param storage_account_name: The storage account from which to fetch files in `filerefs` :type storage_account_name: ``str`` :param storage_account_key: The storage key to authorize to the blob store. :type storage_account_key: ``str`` :type: ``list`` of :class:`.NodeLocation` """ if location is None: if self.default_location: location = self.default_location else: raise ValueError("location is required.") name = "init" target = node.id + "/extensions/" + name data = { "location": location.id, "name": name, "properties": { "publisher": "Microsoft.OSTCExtensions", "type": "CustomScriptForLinux", "typeHandlerVersion": "1.3", "settings": { "fileUris": filerefs, "commandToExecute": command, "timestamp": timestamp } } } if storage_account_name and storage_account_key: data["properties"]["protectedSettings"] = { "storageAccountName": storage_account_name, "storageAccountKey": storage_account_key} r = self.connection.request(target, params={"api-version": "2015-06-15"}, data=data, method='PUT') return r.object def _ex_delete_old_vhd(self, resource_group, uri): try: (storageAccount, blobContainer, blob) = _split_blob_uri(uri) keys = self.ex_get_storage_account_keys(resource_group, storageAccount) blobdriver = AzureBlobsStorageDriver( storageAccount, keys["key1"], host="%s.blob%s" % (storageAccount, self.connection.storage_suffix)) return blobdriver.delete_object( blobdriver.get_object(blobContainer, blob)) except ObjectDoesNotExistError: return True def _ex_connection_class_kwargs(self): kwargs = super(AzureNodeDriver, self)._ex_connection_class_kwargs() kwargs['tenant_id'] = self.tenant_id kwargs['subscription_id'] = self.subscription_id kwargs["cloud_environment"] = self.cloud_environment return kwargs def _fetch_power_state(self, data): state = NodeState.UNKNOWN try: action = "%s/InstanceView" % (data["id"]) r = self.connection.request(action, params={"api-version": "2015-06-15"}) for status in r.object["statuses"]: if status["code"] in ["ProvisioningState/creating"]: state = NodeState.PENDING break elif status["code"] == "ProvisioningState/deleting": state = NodeState.TERMINATED break elif status["code"].startswith("ProvisioningState/failed"): state = NodeState.ERROR break elif status["code"] == "ProvisioningState/updating": state = NodeState.UPDATING break elif status["code"] == "ProvisioningState/succeeded": pass if status["code"] == "PowerState/deallocated": state = NodeState.STOPPED break elif status["code"] == "PowerState/stopped": state = NodeState.PAUSED break elif status["code"] == "PowerState/deallocating": state = NodeState.PENDING break elif status["code"] == "PowerState/running": state = NodeState.RUNNING except BaseHTTPError: pass return state def _to_node(self, data, fetch_nic=True, fetch_power_state=True): private_ips = [] public_ips = [] nics = data["properties"]["networkProfile"]["networkInterfaces"] if fetch_nic: for nic in nics: try: n = self.ex_get_nic(nic["id"]) priv = n.extra["ipConfigurations"][0]["properties"] \ .get("privateIPAddress") if priv: private_ips.append(priv) pub = n.extra["ipConfigurations"][0]["properties"].get( "publicIPAddress") if pub: pub_addr = self.ex_get_public_ip(pub["id"]) addr = pub_addr.extra.get("ipAddress") if addr: public_ips.append(addr) except BaseHTTPError: pass state = NodeState.UNKNOWN if fetch_power_state: state = self._fetch_power_state(data) else: ps = data["properties"]["provisioningState"].lower() if ps == "creating": state = NodeState.PENDING elif ps == "deleting": state = NodeState.TERMINATED elif ps == "failed": state = NodeState.ERROR elif ps == "updating": state = NodeState.UPDATING elif ps == "succeeded": state = NodeState.RUNNING node = Node(data["id"], data["name"], state, public_ips, private_ips, driver=self.connection.driver, extra=data) return node def _to_node_size(self, data): return NodeSize(id=data["name"], name=data["name"], ram=data["memoryInMB"], # convert to disk from MB to GB disk=data["resourceDiskSizeInMB"] / 1024, bandwidth=0, price=0, driver=self.connection.driver, extra={"numberOfCores": data["numberOfCores"], "osDiskSizeInMB": data["osDiskSizeInMB"], "maxDataDiskCount": data["maxDataDiskCount"]}) def _to_nic(self, data): return AzureNic(data["id"], data.get("name"), data.get("location"), data.get("properties")) def _to_ip_address(self, data): return AzureIPAddress(data["id"], data["name"], data["properties"]) def _to_location(self, loc): # XXX for some reason the API returns location names like # "East US" instead of "eastus" which is what is actually needed # for other API calls, so do a name->id fixup. loc_id = loc.lower().replace(" ", "") return NodeLocation(loc_id, loc, self._location_to_country.get(loc_id), self.connection.driver) def _get_instance_vhd(self, name, ex_resource_group, ex_storage_account, ex_blob_container="vhds"): n = 0 errors = [] while n < 10: try: instance_vhd = "https://%s.blob%s" \ "/%s/%s-os_%i.vhd" \ % (ex_storage_account, self.connection.storage_suffix, ex_blob_container, name, n) if self._ex_delete_old_vhd(ex_resource_group, instance_vhd): # We were able to remove it or it doesn't exist, # so we can use it. return instance_vhd except LibcloudError as lce: errors.append(str(lce)) n += 1 raise LibcloudError("Unable to find a name for a VHD to use for " "instance in 10 tries, errors were:\n - %s" % ("\n - ".join(errors))) def _split_blob_uri(uri): uri = uri.split('/') storage_account = uri[2].split('.')[0] blob_container = uri[3] blob_name = '/'.join(uri[4:]) return storage_account, blob_container, blob_name apache-libcloud-2.8.0/libcloud/compute/drivers/bluebox.py0000664000175000017500000001640213577507766023416 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ libcloud driver for the Blue Box Blocks API This driver implements all libcloud functionality for the Blue Box Blocks API. Blue Box home page http://bluebox.net Blue Box API documentation https://boxpanel.bluebox .net/public/the_vault/index.php/Blocks_API """ import copy import base64 from libcloud.utils.py3 import urlencode from libcloud.utils.py3 import b from libcloud.common.base import JsonResponse, ConnectionUserAndKey from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState, InvalidCredsError from libcloud.compute.base import Node, NodeDriver from libcloud.compute.base import NodeSize, NodeImage, NodeLocation from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey # Current end point for Blue Box API. BLUEBOX_API_HOST = "boxpanel.bluebox.net" # The API doesn't currently expose all of the required values for libcloud, # so we simply list what's available right now, along with all of the various # attributes that are needed by libcloud. BLUEBOX_INSTANCE_TYPES = { '1gb': { 'id': '94fd37a7-2606-47f7-84d5-9000deda52ae', 'name': 'Block 1GB Virtual Server', 'ram': 1024, 'disk': 20, 'cpu': 0.5 }, '2gb': { 'id': 'b412f354-5056-4bf0-a42f-6ddd998aa092', 'name': 'Block 2GB Virtual Server', 'ram': 2048, 'disk': 25, 'cpu': 1 }, '4gb': { 'id': '0cd183d3-0287-4b1a-8288-b3ea8302ed58', 'name': 'Block 4GB Virtual Server', 'ram': 4096, 'disk': 50, 'cpu': 2 }, '8gb': { 'id': 'b9b87a5b-2885-4a2e-b434-44a163ca6251', 'name': 'Block 8GB Virtual Server', 'ram': 8192, 'disk': 100, 'cpu': 4 } } RAM_PER_CPU = 2048 NODE_STATE_MAP = {'queued': NodeState.PENDING, 'building': NodeState.PENDING, 'running': NodeState.RUNNING, 'error': NodeState.TERMINATED, 'unknown': NodeState.UNKNOWN} class BlueboxResponse(JsonResponse): def parse_error(self): if int(self.status) == 401: if not self.body: raise InvalidCredsError(str(self.status) + ': ' + self.error) else: raise InvalidCredsError(self.body) return self.body class BlueboxNodeSize(NodeSize): def __init__(self, id, name, cpu, ram, disk, price, driver): self.id = id self.name = name self.cpu = cpu self.ram = ram self.disk = disk self.price = price self.driver = driver def __repr__(self): return (( '') % (self.id, self.name, self.cpu, self.ram, self.disk, self.price, self.driver.name)) class BlueboxConnection(ConnectionUserAndKey): """ Connection class for the Bluebox driver """ host = BLUEBOX_API_HOST secure = True responseCls = BlueboxResponse allow_insecure = False def add_default_headers(self, headers): user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (user_b64) return headers class BlueboxNodeDriver(NodeDriver): """ Bluebox Blocks node driver """ connectionCls = BlueboxConnection type = Provider.BLUEBOX api_name = 'bluebox' name = 'Bluebox Blocks' website = 'http://bluebox.net' features = {'create_node': ['ssh_key', 'password']} def list_nodes(self): result = self.connection.request('/api/blocks.json') return [self._to_node(i) for i in result.object] def list_sizes(self, location=None): sizes = [] for key, values in list(BLUEBOX_INSTANCE_TYPES.items()): attributes = copy.deepcopy(values) attributes.update({'price': self._get_size_price(size_id=key)}) sizes.append(BlueboxNodeSize(driver=self.connection.driver, **attributes)) return sizes def list_images(self, location=None): result = self.connection.request('/api/block_templates.json') images = [] for image in result.object: images.extend([self._to_image(image)]) return images def create_node(self, name, size, image, auth=None, ex_username=None): headers = {'Content-Type': 'application/x-www-form-urlencoded'} auth = self._get_and_check_auth(auth) data = { 'hostname': name, 'product': size.id, 'template': image.id } ssh = None password = None if isinstance(auth, NodeAuthSSHKey): ssh = auth.pubkey # pylint: disable=no-member data.update(ssh_public_key=ssh) elif isinstance(auth, NodeAuthPassword): password = auth.password data.update(password=password) if ex_username: data.update(username=ex_username) if not ssh and not password: raise Exception("SSH public key or password required.") params = urlencode(data) result = self.connection.request('/api/blocks.json', headers=headers, data=params, method='POST') node = self._to_node(result.object) if getattr(auth, "generated", False): node.extra['password'] = auth.password return node def destroy_node(self, node): url = '/api/blocks/%s.json' % (node.id) result = self.connection.request(url, method='DELETE') return result.status == 200 def list_locations(self): return [NodeLocation(0, "Blue Box Seattle US", 'US', self)] def reboot_node(self, node): url = '/api/blocks/%s/reboot.json' % (node.id) result = self.connection.request(url, method="PUT") return result.status == 200 def _to_node(self, vm): state = NODE_STATE_MAP[vm.get('status', NodeState.UNKNOWN)] n = Node(id=vm['id'], name=vm['hostname'], state=state, public_ips=[ip['address'] for ip in vm['ips']], private_ips=[], extra={'storage': vm['storage'], 'cpu': vm['cpu']}, driver=self.connection.driver) return n def _to_image(self, image): image = NodeImage(id=image['id'], name=image['description'], driver=self.connection.driver) return image apache-libcloud-2.8.0/libcloud/compute/drivers/brightbox.py0000664000175000017500000002515313577507766023751 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Brightbox Driver """ from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.brightbox import BrightboxConnection from libcloud.compute.types import Provider, NodeState from libcloud.compute.base import NodeDriver from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation import base64 API_VERSION = '1.0' def _extract(d, keys): return dict((k, d[k]) for k in keys if k in d and d[k] is not None) class BrightboxNodeDriver(NodeDriver): """ Brightbox node driver """ connectionCls = BrightboxConnection type = Provider.BRIGHTBOX name = 'Brightbox' website = 'http://www.brightbox.co.uk/' NODE_STATE_MAP = {'creating': NodeState.PENDING, 'active': NodeState.RUNNING, 'inactive': NodeState.UNKNOWN, 'deleting': NodeState.UNKNOWN, 'deleted': NodeState.TERMINATED, 'failed': NodeState.UNKNOWN, 'unavailable': NodeState.UNKNOWN} def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=API_VERSION, **kwargs): super(BrightboxNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, **kwargs) def _to_node(self, data): extra_data = _extract(data, ['fqdn', 'user_data', 'status', 'interfaces', 'snapshots', 'server_groups', 'hostname', 'started_at', 'created_at', 'deleted_at']) extra_data['zone'] = self._to_location(data['zone']) ipv6_addresses = [interface['ipv6_address'] for interface in data['interfaces'] if 'ipv6_address' in interface] private_ips = [interface['ipv4_address'] for interface in data['interfaces'] if 'ipv4_address' in interface] public_ips = [cloud_ip['public_ip'] for cloud_ip in data['cloud_ips']] public_ips += ipv6_addresses return Node( id=data['id'], name=data['name'], state=self.NODE_STATE_MAP[data['status']], private_ips=private_ips, public_ips=public_ips, driver=self.connection.driver, size=self._to_size(data['server_type']), image=self._to_image(data['image']), extra=extra_data ) def _to_image(self, data): extra_data = _extract(data, ['arch', 'compatibility_mode', 'created_at', 'description', 'disk_size', 'min_ram', 'official', 'owner', 'public', 'source', 'source_type', 'status', 'username', 'virtual_size', 'licence_name']) if data.get('ancestor', None): extra_data['ancestor'] = self._to_image(data['ancestor']) return NodeImage( id=data['id'], name=data['name'], driver=self, extra=extra_data ) def _to_size(self, data): return NodeSize( id=data['id'], name=data['name'], ram=data['ram'], disk=data['disk_size'], bandwidth=0, price=0, driver=self ) def _to_location(self, data): if data: return NodeLocation( id=data['id'], name=data['handle'], country='GB', driver=self ) else: return None def _post(self, path, data={}): headers = {'Content-Type': 'application/json'} return self.connection.request(path, data=data, headers=headers, method='POST') def _put(self, path, data={}): headers = {'Content-Type': 'application/json'} return self.connection.request(path, data=data, headers=headers, method='PUT') def create_node(self, name, size, image, location=None, ex_userdata=None, ex_servergroup=None): """Create a new Brightbox node Reference: https://api.gb1.brightbox.com/1.0/#server_create_server @inherits: :class:`NodeDriver.create_node` :keyword ex_userdata: User data :type ex_userdata: ``str`` :keyword ex_servergroup: Name or list of server group ids to add server to :type ex_servergroup: ``str`` or ``list`` of ``str`` """ data = { 'name': name, 'server_type': size.id, 'image': image.id, } if ex_userdata: data['user_data'] = base64.b64encode(b(ex_userdata)) \ .decode('ascii') if location: data['zone'] = location.id if ex_servergroup: if not isinstance(ex_servergroup, list): ex_servergroup = [ex_servergroup] data['server_groups'] = ex_servergroup data = self._post('/%s/servers' % self.api_version, data).object return self._to_node(data) def destroy_node(self, node): response = self.connection.request( '/%s/servers/%s' % (self.api_version, node.id), method='DELETE') return response.status == httplib.ACCEPTED def list_nodes(self): data = self.connection.request('/%s/servers' % self.api_version).object return list(map(self._to_node, data)) def list_images(self, location=None): data = self.connection.request('/%s/images' % self.api_version).object return list(map(self._to_image, data)) def list_sizes(self): data = self.connection.request('/%s/server_types' % self.api_version) \ .object return list(map(self._to_size, data)) def list_locations(self): data = self.connection.request('/%s/zones' % self.api_version).object return list(map(self._to_location, data)) def ex_list_cloud_ips(self): """ List Cloud IPs @note: This is an API extension for use on Brightbox :rtype: ``list`` of ``dict`` """ return self.connection.request('/%s/cloud_ips' % self.api_version) \ .object def ex_create_cloud_ip(self, reverse_dns=None): """ Requests a new cloud IP address for the account @note: This is an API extension for use on Brightbox :param reverse_dns: Reverse DNS hostname :type reverse_dns: ``str`` :rtype: ``dict`` """ params = {} if reverse_dns: params['reverse_dns'] = reverse_dns return self._post('/%s/cloud_ips' % self.api_version, params).object def ex_update_cloud_ip(self, cloud_ip_id, reverse_dns): """ Update some details of the cloud IP address @note: This is an API extension for use on Brightbox :param cloud_ip_id: The id of the cloud ip. :type cloud_ip_id: ``str`` :param reverse_dns: Reverse DNS hostname :type reverse_dns: ``str`` :rtype: ``dict`` """ response = self._put('/%s/cloud_ips/%s' % (self.api_version, cloud_ip_id), {'reverse_dns': reverse_dns}) return response.status == httplib.OK def ex_map_cloud_ip(self, cloud_ip_id, interface_id): """ Maps (or points) a cloud IP address at a server's interface or a load balancer to allow them to respond to public requests @note: This is an API extension for use on Brightbox :param cloud_ip_id: The id of the cloud ip. :type cloud_ip_id: ``str`` :param interface_id: The Interface ID or LoadBalancer ID to which this Cloud IP should be mapped to :type interface_id: ``str`` :return: True if the mapping was successful. :rtype: ``bool`` """ response = self._post('/%s/cloud_ips/%s/map' % (self.api_version, cloud_ip_id), {'destination': interface_id}) return response.status == httplib.ACCEPTED def ex_unmap_cloud_ip(self, cloud_ip_id): """ Unmaps a cloud IP address from its current destination making it available to remap. This remains in the account's pool of addresses @note: This is an API extension for use on Brightbox :param cloud_ip_id: The id of the cloud ip. :type cloud_ip_id: ``str`` :return: True if the unmap was successful. :rtype: ``bool`` """ response = self._post('/%s/cloud_ips/%s/unmap' % (self.api_version, cloud_ip_id)) return response.status == httplib.ACCEPTED def ex_destroy_cloud_ip(self, cloud_ip_id): """ Release the cloud IP address from the account's ownership @note: This is an API extension for use on Brightbox :param cloud_ip_id: The id of the cloud ip. :type cloud_ip_id: ``str`` :return: True if the unmap was successful. :rtype: ``bool`` """ response = self.connection.request( '/%s/cloud_ips/%s' % (self.api_version, cloud_ip_id), method='DELETE') return response.status == httplib.OK apache-libcloud-2.8.0/libcloud/compute/drivers/bsnl.py0000664000175000017500000000364613535474530022704 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.providers import Provider from libcloud.common.dimensiondata import (DimensionDataConnection, API_ENDPOINTS) from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver DEFAULT_REGION = 'bsnl-in' class BSNLNodeDriver(DimensionDataNodeDriver): """ BSNL node driver, based on Dimension Data driver """ selected_region = None connectionCls = DimensionDataConnection name = 'BSNL' website = 'http://www.bsnlcloud.com/' type = Provider.BSNL features = {'create_node': ['password']} api_version = 1.0 def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS: raise ValueError('Invalid region: %s' % (region)) self.selected_region = API_ENDPOINTS[region] super(BSNLNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) apache-libcloud-2.8.0/libcloud/compute/drivers/cloudscale.py0000664000175000017500000002121413577507766024071 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ A driver for cloudscale.ch. """ import json from libcloud.utils.py3 import httplib from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.compute.types import Provider, NodeState from libcloud.common.types import InvalidCredsError from libcloud.compute.base import NodeDriver from libcloud.compute.base import Node, NodeImage, NodeSize class CloudscaleResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_error(self): body = self.parse_body() if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError(body['detail']) else: # We are taking the first issue here. There might be multiple ones, # but that doesn't really matter. It's nicer if the error is just # one error (because it's a Python API and there's only one # exception. return next(iter(body.values())) def success(self): return self.status in self.valid_response_codes class CloudscaleConnection(ConnectionKey): """ Connection class for the cloudscale.ch driver. """ host = 'api.cloudscale.ch' responseCls = CloudscaleResponse def add_default_headers(self, headers): """ Add headers that are necessary for every request This method adds ``token`` to the request. """ headers['Authorization'] = 'Bearer %s' % (self.key) headers['Content-Type'] = 'application/json' return headers class CloudscaleNodeDriver(NodeDriver): """ Cloudscale's node driver. """ connectionCls = CloudscaleConnection type = Provider.CLOUDSCALE name = 'Cloudscale' website = 'https://www.cloudscale.ch' NODE_STATE_MAP = dict( changing=NodeState.PENDING, running=NodeState.RUNNING, stopped=NodeState.STOPPED, paused=NodeState.PAUSED, ) def __init__(self, key, **kwargs): super(CloudscaleNodeDriver, self).__init__(key, **kwargs) def list_nodes(self): """ List all your existing compute nodes. """ return self._list_resources('/v1/servers', self._to_node) def list_sizes(self): """ Lists all available sizes. On cloudscale these are known as flavors. """ return self._list_resources('/v1/flavors', self._to_size) def list_images(self): """ List all images. Images are identified by slugs on cloudscale.ch. This means that minor version upgrades (e.g. Ubuntu 16.04.1 to Ubuntu 16.04.2) will be possible within the same id ``ubuntu-16.04``. """ return self._list_resources('/v1/images', self._to_image) def create_node(self, name, size, image, location=None, ex_create_attr=None): """ Create a node. The `ex_create_attr` parameter can include the following dictionary key and value pairs: * `ssh_keys`: ``list`` of ``str`` ssh public keys * `volume_size_gb`: ``int`` defaults to 10. * `bulk_volume_size_gb`: defaults to None. * `use_public_network`: ``bool`` defaults to True * `use_private_network`: ``bool`` defaults to False * `use_ipv6`: ``bool`` defaults to True * `anti_affinity_with`: ``uuid`` of a server to create an anti-affinity group with that server or add it to the same group as that server. * `user_data`: ``str`` for optional cloud-config data :keyword ex_create_attr: A dictionary of optional attributes for droplet creation :type ex_create_attr: ``dict`` :return: The newly created node. :rtype: :class:`Node` """ ex_create_attr = ex_create_attr or {} attr = dict(ex_create_attr) attr.update( name=name, image=image.id, flavor=size.id, ) result = self.connection.request( '/v1/servers', data=json.dumps(attr), method='POST' ) return self._to_node(result.object) def reboot_node(self, node): """ Reboot a node. It's also possible to use ``node.reboot()``. """ return self._action(node, 'reboot') def start_node(self, node): """ Start a node. This is only possible if the node is stopped. """ return self._action(node, 'start') def stop_node(self, node): """ Stop a specific node. Similar to ``shutdown -h now``. This is only possible if the node is running. """ return self._action(node, 'stop') def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_node_by_uuid(self, uuid): """ :param str ex_user_data: A valid uuid that references your exisiting cloudscale.ch server. :type ex_user_data: ``str`` :return: The server node you asked for. :rtype: :class:`Node` """ res = self.connection.request(self._get_server_url(uuid)) return self._to_node(res.object) def destroy_node(self, node): """ Delete a node. It's also possible to use ``node.destroy()``. This will irreversibly delete the cloudscale.ch server and all its volumes. So please be cautious. """ res = self.connection.request( self._get_server_url(node.id), method='DELETE' ) return res.status == httplib.NO_CONTENT def _get_server_url(self, uuid): return '/v1/servers/%s' % uuid def _action(self, node, action_name): response = self.connection.request( self._get_server_url(node.id) + '/' + action_name, method='POST' ) return response.status == httplib.OK def _list_resources(self, url, tranform_func): data = self.connection.request(url, method='GET').object return [tranform_func(obj) for obj in data] def _to_node(self, data): state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN) extra_keys_exclude = ['uuid', 'name', 'status', 'flavor', 'image'] extra = {} for k, v in data.items(): if k not in extra_keys_exclude: extra[k] = v public_ips = [] private_ips = [] for interface in data['interfaces']: if interface['type'] == 'public': ips = public_ips else: ips = private_ips for address_obj in interface['addresses']: ips.append(address_obj['address']) return Node( id=data['uuid'], name=data['name'], state=state, public_ips=public_ips, private_ips=private_ips, extra=extra, driver=self, image=self._to_image(data['image']), size=self._to_size(data['flavor']), ) def _to_size(self, data): extra = {'vcpu_count': data['vcpu_count']} ram = data['memory_gb'] * 1024 return NodeSize(id=data['slug'], name=data['name'], ram=ram, disk=10, bandwidth=0, price=0, extra=extra, driver=self) def _to_image(self, data): extra = {'operating_system': data['operating_system']} return NodeImage(id=data['slug'], name=data['name'], extra=extra, driver=self) apache-libcloud-2.8.0/libcloud/compute/drivers/cloudsigma.py0000664000175000017500000020601613600144066024060 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Drivers for CloudSigma API v1.0 and v2.0. """ import re import time import copy import base64 try: import simplejson as json except Exception: import json from libcloud.utils.py3 import b from libcloud.utils.py3 import httplib from libcloud.utils.misc import str2dicts, str2list, dict2str from libcloud.common.base import ConnectionUserAndKey, JsonResponse, Response from libcloud.common.types import InvalidCredsError, ProviderError from libcloud.common.cloudsigma import INSTANCE_TYPES from libcloud.common.cloudsigma import API_ENDPOINTS_1_0 from libcloud.common.cloudsigma import API_ENDPOINTS_2_0 from libcloud.common.cloudsigma import DEFAULT_API_VERSION, DEFAULT_REGION from libcloud.compute.types import NodeState, Provider from libcloud.compute.base import NodeDriver, NodeSize, Node from libcloud.compute.base import NodeImage from libcloud.compute.base import is_private_subnet from libcloud.utils.iso8601 import parse_date from libcloud.utils.misc import get_secure_random_string __all__ = [ 'CloudSigmaNodeDriver', 'CloudSigma_1_0_NodeDriver', 'CloudSigma_2_0_NodeDriver', 'CloudSigmaError', 'CloudSigmaNodeSize', 'CloudSigmaDrive', 'CloudSigmaTag', 'CloudSigmaSubscription', 'CloudSigmaFirewallPolicy', 'CloudSigmaFirewallPolicyRule' ] class CloudSigmaNodeDriver(NodeDriver): name = 'CloudSigma' website = 'http://www.cloudsigma.com/' def __new__(cls, key, secret=None, secure=True, host=None, port=None, api_version=DEFAULT_API_VERSION, **kwargs): if cls is CloudSigmaNodeDriver: if api_version == '1.0': cls = CloudSigma_1_0_NodeDriver elif api_version == '2.0': cls = CloudSigma_2_0_NodeDriver else: raise NotImplementedError('Unsupported API version: %s' % (api_version)) return super(CloudSigmaNodeDriver, cls).__new__(cls) class CloudSigmaException(Exception): def __str__(self): return self.args[0] def __repr__(self): return "" % (self.args[0]) class CloudSigmaInsufficientFundsException(Exception): def __repr__(self): return "" % (self.args[0]) class CloudSigmaNodeSize(NodeSize): def __init__(self, id, name, cpu, ram, disk, bandwidth, price, driver): self.id = id self.name = name self.cpu = cpu self.ram = ram self.disk = disk self.bandwidth = bandwidth self.price = price self.driver = driver def __repr__(self): return (('') % (self.id, self.name, self.cpu, self.ram, self.disk, self.bandwidth, self.price, self.driver.name)) class CloudSigma_1_0_Response(Response): def success(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError() return 200 <= self.status <= 299 def parse_body(self): if not self.body: return self.body return str2dicts(self.body) def parse_error(self): return 'Error: %s' % (self.body.replace('errors:', '').strip()) class CloudSigma_1_0_Connection(ConnectionUserAndKey): host = API_ENDPOINTS_1_0[DEFAULT_REGION]['host'] responseCls = CloudSigma_1_0_Response def add_default_headers(self, headers): headers['Accept'] = 'application/json' headers['Content-Type'] = 'application/json' headers['Authorization'] = 'Basic %s' % (base64.b64encode( b('%s:%s' % (self.user_id, self.key))).decode('utf-8')) return headers class CloudSigma_1_0_NodeDriver(CloudSigmaNodeDriver): type = Provider.CLOUDSIGMA name = 'CloudSigma (API v1.0)' website = 'http://www.cloudsigma.com/' connectionCls = CloudSigma_1_0_Connection IMAGING_TIMEOUT = 20 * 60 # Default timeout (in seconds) for the drive # imaging process NODE_STATE_MAP = { 'active': NodeState.RUNNING, 'stopped': NodeState.TERMINATED, 'dead': NodeState.TERMINATED, 'dumped': NodeState.TERMINATED, } def __init__(self, key, secret=None, secure=True, host=None, port=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS_1_0: raise ValueError('Invalid region: %s' % (region)) self._host_argument_set = host is not None self.api_name = 'cloudsigma_%s' % (region) super(CloudSigma_1_0_NodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) def reboot_node(self, node): """ Reboot a node. Because Cloudsigma API does not provide native reboot call, it's emulated using stop and start. @inherits: :class:`NodeDriver.reboot_node` """ node = self._get_node(node.id) state = node.state if state == NodeState.RUNNING: stopped = self.ex_stop_node(node) else: stopped = True if not stopped: raise CloudSigmaException( 'Could not stop node with id %s' % (node.id)) success = self.ex_start_node(node) return success def destroy_node(self, node): """ Destroy a node (all the drives associated with it are NOT destroyed). If a node is still running, it's stopped before it's destroyed. @inherits: :class:`NodeDriver.destroy_node` """ node = self._get_node(node.id) state = node.state # Node cannot be destroyed while running so it must be stopped first if state == NodeState.RUNNING: stopped = self.ex_stop_node(node) else: stopped = True if not stopped: raise CloudSigmaException( 'Could not stop node with id %s' % (node.id)) response = self.connection.request( action='/servers/%s/destroy' % (node.id), method='POST') return response.status == 204 def list_images(self, location=None): """ Return a list of available standard images (this call might take up to 15 seconds to return). @inherits: :class:`NodeDriver.list_images` """ response = self.connection.request( action='/drives/standard/info').object images = [] for value in response: if value.get('type'): if value['type'] == 'disk': image = NodeImage(id=value['drive'], name=value['name'], driver=self.connection.driver, extra={'size': value['size']}) images.append(image) return images def list_sizes(self, location=None): sizes = [] for value in INSTANCE_TYPES: key = value['id'] size = CloudSigmaNodeSize(id=value['id'], name=value['name'], cpu=value['cpu'], ram=value['memory'], disk=value['disk'], bandwidth=value['bandwidth'], price=self._get_size_price(size_id=key), driver=self.connection.driver) sizes.append(size) return sizes def list_nodes(self): response = self.connection.request(action='/servers/info').object nodes = [] for data in response: node = self._to_node(data) if node: nodes.append(node) return nodes def create_node(self, name, size, image, smp='auto', nic_model='e1000', vnc_password=None, drive_type='hdd'): """ Creates a CloudSigma instance @inherits: :class:`NodeDriver.create_node` :keyword name: String with a name for this new node (required) :type name: ``str`` :keyword smp: Number of virtual processors or None to calculate based on the cpu speed. :type smp: ``int`` :keyword nic_model: e1000, rtl8139 or virtio (is not specified, e1000 is used) :type nic_model: ``str`` :keyword vnc_password: If not set, VNC access is disabled. :type vnc_password: ``bool`` :keyword drive_type: Drive type (ssd|hdd). Defaults to hdd. :type drive_type: ``str`` """ if nic_model not in ['e1000', 'rtl8139', 'virtio']: raise CloudSigmaException('Invalid NIC model specified') if drive_type not in ['hdd', 'ssd']: raise CloudSigmaException('Invalid drive type "%s". Valid types' ' are: hdd, ssd' % (drive_type)) drive_data = {} drive_data.update({'name': name, 'size': '%sG' % (size.disk), 'driveType': drive_type}) response = self.connection.request( action='/drives/%s/clone' % image.id, data=dict2str(drive_data), method='POST').object if not response: raise CloudSigmaException('Drive creation failed') drive_uuid = response[0]['drive'] response = self.connection.request( action='/drives/%s/info' % (drive_uuid)).object imaging_start = time.time() while 'imaging' in response[0]: response = self.connection.request( action='/drives/%s/info' % (drive_uuid)).object elapsed_time = time.time() - imaging_start timed_out = elapsed_time >= self.IMAGING_TIMEOUT if 'imaging' in response[0] and timed_out: raise CloudSigmaException('Drive imaging timed out') time.sleep(1) node_data = {} node_data.update( {'name': name, 'cpu': size.cpu, 'mem': size.ram, 'ide:0:0': drive_uuid, 'boot': 'ide:0:0', 'smp': smp}) node_data.update({'nic:0:model': nic_model, 'nic:0:dhcp': 'auto'}) if vnc_password: node_data.update({'vnc:ip': 'auto', 'vnc:password': vnc_password}) response = self.connection.request(action='/servers/create', data=dict2str(node_data), method='POST').object if not isinstance(response, list): response = [response] node = self._to_node(response[0]) if node is None: # Insufficient funds, destroy created drive self.ex_drive_destroy(drive_uuid) raise CloudSigmaInsufficientFundsException( 'Insufficient funds, node creation failed') # Start the node after it has been created started = self.ex_start_node(node) if started: node.state = NodeState.RUNNING return node def ex_destroy_node_and_drives(self, node): """ Destroy a node and all the drives associated with it. :param node: Node which should be used :type node: :class:`libcloud.compute.base.Node` :rtype: ``bool`` """ node = self._get_node_info(node) drive_uuids = [] for key, value in node.items(): if (key.startswith('ide:') or key.startswith( 'scsi') or key.startswith('block')) and\ not (key.endswith(':bytes') or key.endswith(':requests') or key.endswith('media')): drive_uuids.append(value) node_destroyed = self.destroy_node(self._to_node(node)) if not node_destroyed: return False for drive_uuid in drive_uuids: self.ex_drive_destroy(drive_uuid) return True def ex_static_ip_list(self): """ Return a list of available static IP addresses. :rtype: ``list`` of ``str`` """ response = self.connection.request(action='/resources/ip/list', method='GET') if response.status != 200: raise CloudSigmaException('Could not retrieve IP list') ips = str2list(response.body) return ips def ex_drives_list(self): """ Return a list of all the available drives. :rtype: ``list`` of ``dict`` """ response = self.connection.request(action='/drives/info', method='GET') result = str2dicts(response.body) return result def ex_static_ip_create(self): """ Create a new static IP address.p :rtype: ``list`` of ``dict`` """ response = self.connection.request(action='/resources/ip/create', method='GET') result = str2dicts(response.body) return result def ex_static_ip_destroy(self, ip_address): """ Destroy a static IP address. :param ip_address: IP address which should be used :type ip_address: ``str`` :rtype: ``bool`` """ response = self.connection.request( action='/resources/ip/%s/destroy' % (ip_address), method='GET') return response.status == 204 def ex_drive_destroy(self, drive_uuid): """ Destroy a drive with a specified uuid. If the drive is currently mounted an exception is thrown. :param drive_uuid: Drive uuid which should be used :type drive_uuid: ``str`` :rtype: ``bool`` """ response = self.connection.request( action='/drives/%s/destroy' % (drive_uuid), method='POST') return response.status == 204 def ex_set_node_configuration(self, node, **kwargs): """ Update a node configuration. Changing most of the parameters requires node to be stopped. :param node: Node which should be used :type node: :class:`libcloud.compute.base.Node` :param kwargs: keyword arguments :type kwargs: ``dict`` :rtype: ``bool`` """ valid_keys = ('^name$', '^parent$', '^cpu$', '^smp$', '^mem$', '^boot$', '^nic:0:model$', '^nic:0:dhcp', '^nic:1:model$', '^nic:1:vlan$', '^nic:1:mac$', '^vnc:ip$', '^vnc:password$', '^vnc:tls', '^ide:[0-1]:[0-1](:media)?$', '^scsi:0:[0-7](:media)?$', '^block:[0-7](:media)?$') invalid_keys = [] keys = list(kwargs.keys()) for key in keys: matches = False for regex in valid_keys: if re.match(regex, key): matches = True break if not matches: invalid_keys.append(key) if invalid_keys: raise CloudSigmaException( 'Invalid configuration key specified: %s' % (',' .join(invalid_keys))) response = self.connection.request( action='/servers/%s/set' % (node.id), data=dict2str(kwargs), method='POST') return (response.status == 200 and response.body != '') def ex_start_node(self, node): """ Start a node. :param node: Node which should be used :type node: :class:`libcloud.compute.base.Node` :rtype: ``bool`` """ response = self.connection.request( action='/servers/%s/start' % (node.id), method='POST') return response.status == 200 def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def stop_node(self, node): """ Stop (shutdown) a node. :param node: Node which should be used :type node: :class:`libcloud.compute.base.Node` :rtype: ``bool`` """ response = self.connection.request( action='/servers/%s/stop' % (node.id), method='POST') return response.status == 204 def ex_shutdown_node(self, node): """ Stop (shutdown) a node. @inherits: :class:`CloudSigmaBaseNodeDriver.ex_stop_node` """ return self.ex_stop_node(node) def ex_destroy_drive(self, drive_uuid): """ Destroy a drive. :param drive_uuid: Drive uuid which should be used :type drive_uuid: ``str`` :rtype: ``bool`` """ response = self.connection.request( action='/drives/%s/destroy' % (drive_uuid), method='POST') return response.status == 204 def _ex_connection_class_kwargs(self): """ Return the host value based on the user supplied region. """ kwargs = {} if not self._host_argument_set: kwargs['host'] = API_ENDPOINTS_1_0[self.region]['host'] return kwargs def _to_node(self, data): if data: try: state = self.NODE_STATE_MAP[data['status']] except KeyError: state = NodeState.UNKNOWN if 'server' not in data: # Response does not contain server UUID if the server # creation failed because of insufficient funds. return None public_ips = [] if 'nic:0:dhcp' in data: if isinstance(data['nic:0:dhcp'], list): public_ips = data['nic:0:dhcp'] else: public_ips = [data['nic:0:dhcp']] extra = {} extra_keys = [('cpu', 'int'), ('smp', 'auto'), ('mem', 'int'), ('status', 'str')] for key, value_type in extra_keys: if key in data: value = data[key] if value_type == 'int': value = int(value) elif value_type == 'auto': try: value = int(value) except ValueError: pass extra.update({key: value}) if 'vnc:ip' in data and 'vnc:password' in data: extra.update({'vnc_ip': data['vnc:ip'], 'vnc_password': data['vnc:password']}) node = Node(id=data['server'], name=data['name'], state=state, public_ips=public_ips, private_ips=None, driver=self.connection.driver, extra=extra) return node return None def _get_node(self, node_id): nodes = self.list_nodes() node = [node for node in nodes if node.id == node.id] if not node: raise CloudSigmaException( 'Node with id %s does not exist' % (node_id)) return node[0] def _get_node_info(self, node): response = self.connection.request( action='/servers/%s/info' % (node.id)) result = str2dicts(response.body) return result[0] class CloudSigmaZrhConnection(CloudSigma_1_0_Connection): """ Connection class for the CloudSigma driver for the Zurich end-point """ host = API_ENDPOINTS_1_0['zrh']['host'] class CloudSigmaZrhNodeDriver(CloudSigma_1_0_NodeDriver): """ CloudSigma node driver for the Zurich end-point """ connectionCls = CloudSigmaZrhConnection api_name = 'cloudsigma_zrh' class CloudSigmaLvsConnection(CloudSigma_1_0_Connection): """ Connection class for the CloudSigma driver for the Las Vegas end-point """ host = API_ENDPOINTS_1_0['lvs']['host'] class CloudSigmaLvsNodeDriver(CloudSigma_1_0_NodeDriver): """ CloudSigma node driver for the Las Vegas end-point """ connectionCls = CloudSigmaLvsConnection api_name = 'cloudsigma_lvs' class CloudSigmaError(ProviderError): """ Represents CloudSigma API error. """ def __init__(self, http_code, error_type, error_msg, error_point, driver): """ :param http_code: HTTP status code. :type http_code: ``int`` :param error_type: Type of error (validation / notexist / backend / permissions database / concurrency / billing / payment) :type error_type: ``str`` :param error_msg: A description of the error that occurred. :type error_msg: ``str`` :param error_point: Point at which the error occurred. Can be None. :type error_point: ``str`` or ``None`` """ super(CloudSigmaError, self).__init__(http_code=http_code, value=error_msg, driver=driver) self.error_type = error_type self.error_msg = error_msg self.error_point = error_point class CloudSigmaSubscription(object): """ Represents CloudSigma subscription. """ def __init__(self, id, resource, amount, period, status, price, start_time, end_time, auto_renew, subscribed_object=None): """ :param id: Subscription ID. :type id: ``str`` :param resource: Resource (e.g vlan, ip, etc.). :type resource: ``str`` :param period: Subscription period. :type period: ``str`` :param status: Subscription status (active / inactive). :type status: ``str`` :param price: Subscription price. :type price: ``str`` :param start_time: Start time for this subscription. :type start_time: ``datetime.datetime`` :param end_time: End time for this subscription. :type end_time: ``datetime.datetime`` :param auto_renew: True if the subscription is auto renewed. :type auto_renew: ``bool`` :param subscribed_object: Optional UUID of the subscribed object. :type subscribed_object: ``str`` """ self.id = id self.resource = resource self.amount = amount self.period = period self.status = status self.price = price self.start_time = start_time self.end_time = end_time self.auto_renew = auto_renew self.subscribed_object = subscribed_object def __str__(self): return self.__repr__() def __repr__(self): return ('' % (self.id, self.resource, self.amount, self.period, self.subscribed_object)) class CloudSigmaTag(object): """ Represents a CloudSigma tag object. """ def __init__(self, id, name, resources=None): """ :param id: Tag ID. :type id: ``str`` :param name: Tag name. :type name: ``str`` :param resource: IDs of resources which are associated with this tag. :type resources: ``list`` of ``str`` """ self.id = id self.name = name self.resources = resources if resources else [] def __str__(self): return self.__repr__() def __repr__(self): return ('' % (self.id, self.name, repr(self.resources))) class CloudSigmaDrive(NodeImage): """ Represents a CloudSigma drive. """ def __init__(self, id, name, size, media, status, driver, extra=None): """ :param id: Drive ID. :type id: ``str`` :param name: Drive name. :type name: ``str`` :param size: Drive size (in bytes). :type size: ``int`` :param media: Drive media (cdrom / disk). :type media: ``str`` :param status: Drive status (unmounted / mounted). :type status: ``str`` """ super(CloudSigmaDrive, self).__init__(id=id, name=name, driver=driver, extra=extra) self.size = size self.media = media self.status = status def __str__(self): return self.__repr__() def __repr__(self): return (('') % (self.id, self.name, self.size, self.media, self.status)) class CloudSigmaFirewallPolicy(object): """ Represents a CloudSigma firewall policy. """ def __init__(self, id, name, rules): """ :param id: Policy ID. :type id: ``str`` :param name: Policy name. :type name: ``str`` :param rules: Rules associated with this policy. :type rules: ``list`` of :class:`.CloudSigmaFirewallPolicyRule` objects """ self.id = id self.name = name self.rules = rules if rules else [] def __str__(self): return self.__repr__() def __repr__(self): return (('') % (self.id, self.name, repr(self.rules))) class CloudSigmaFirewallPolicyRule(object): """ Represents a CloudSigma firewall policy rule. """ def __init__(self, action, direction, ip_proto=None, src_ip=None, src_port=None, dst_ip=None, dst_port=None, comment=None): """ :param action: Action (drop / accept). :type action: ``str`` :param direction: Rule direction (in / out / both)> :type direction: ``str`` :param ip_proto: IP protocol (tcp / udp). :type ip_proto: ``str``. :param src_ip: Source IP in CIDR notation. :type src_ip: ``str`` :param src_port: Source port or a port range. :type src_port: ``str`` :param dst_ip: Destination IP in CIDR notation. :type dst_ip: ``str`` :param src_port: Destination port or a port range. :type src_port: ``str`` :param comment: Comment associated with the policy. :type comment: ``str`` """ self.action = action self.direction = direction self.ip_proto = ip_proto self.src_ip = src_ip self.src_port = src_port self.dst_ip = dst_ip self.dst_port = dst_port self.comment = comment def __str__(self): return self.__repr__() def __repr__(self): return (('') % (self.action, self.direction)) class CloudSigma_2_0_Response(JsonResponse): success_status_codes = [ httplib.OK, httplib.ACCEPTED, httplib.NO_CONTENT, httplib.CREATED ] def success(self): return self.status in self.success_status_codes def parse_error(self): if int(self.status) == httplib.UNAUTHORIZED: raise InvalidCredsError('Invalid credentials') body = self.parse_body() errors = self._parse_errors_from_body(body=body) if errors: # Throw first error raise errors[0] return body def _parse_errors_from_body(self, body): """ Parse errors from the response body. :return: List of error objects. :rtype: ``list`` of :class:`.CloudSigmaError` objects """ errors = [] if not isinstance(body, list): return None for item in body: if 'error_type' not in item: # Unrecognized error continue error = CloudSigmaError(http_code=self.status, error_type=item['error_type'], error_msg=item['error_message'], error_point=item['error_point'], driver=self.connection.driver) errors.append(error) return errors class CloudSigma_2_0_Connection(ConnectionUserAndKey): host = API_ENDPOINTS_2_0[DEFAULT_REGION]['host'] responseCls = CloudSigma_2_0_Response api_prefix = '/api/2.0' def add_default_headers(self, headers): headers['Accept'] = 'application/json' headers['Content-Type'] = 'application/json' headers['Authorization'] = 'Basic %s' % (base64.b64encode( b('%s:%s' % (self.user_id, self.key))).decode('utf-8')) return headers def encode_data(self, data): data = json.dumps(data) return data def request(self, action, params=None, data=None, headers=None, method='GET', raw=False): params = params or {} action = self.api_prefix + action if method == 'GET': params['limit'] = 0 # we want all the items back return super(CloudSigma_2_0_Connection, self).request(action=action, params=params, data=data, headers=headers, method=method, raw=raw) class CloudSigma_2_0_NodeDriver(CloudSigmaNodeDriver): """ Driver for CloudSigma API v2.0. """ name = 'CloudSigma (API v2.0)' api_name = 'cloudsigma_zrh' website = 'http://www.cloudsigma.com/' connectionCls = CloudSigma_2_0_Connection # Default drive transition timeout in seconds DRIVE_TRANSITION_TIMEOUT = 500 # How long to sleep between different polling periods while waiting for # drive transition DRIVE_TRANSITION_SLEEP_INTERVAL = 5 NODE_STATE_MAP = { 'starting': NodeState.PENDING, 'stopping': NodeState.PENDING, 'unavailable': NodeState.ERROR, 'running': NodeState.RUNNING, 'stopped': NodeState.STOPPED, 'paused': NodeState.PAUSED } def __init__(self, key, secret, secure=True, host=None, port=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS_2_0: raise ValueError('Invalid region: %s' % (region)) if not secure: # CloudSigma drive uses Basic Auth authentication and we don't want # to allow user to accidentally send credentials over the wire in # plain-text raise ValueError('CloudSigma driver only supports a ' 'secure connection') self._host_argument_set = host is not None super(CloudSigma_2_0_NodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) def list_nodes(self, ex_tag=None): """ List available nodes. :param ex_tag: If specified, only return servers tagged with the provided tag. :type ex_tag: :class:`CloudSigmaTag` """ if ex_tag: action = '/tags/%s/servers/detail/' % (ex_tag.id) else: action = '/servers/detail/' response = self.connection.request(action=action, method='GET').object nodes = [self._to_node(data=item) for item in response['objects']] return nodes def list_sizes(self): """ List available sizes. """ sizes = [] for value in INSTANCE_TYPES: key = value['id'] size = CloudSigmaNodeSize(id=value['id'], name=value['name'], cpu=value['cpu'], ram=value['memory'], disk=value['disk'], bandwidth=value['bandwidth'], price=self._get_size_price(size_id=key), driver=self.connection.driver) sizes.append(size) return sizes def list_images(self): """ Return a list of available pre-installed library drives. Note: If you want to list all the available library drives (both pre-installed and installation CDs), use :meth:`ex_list_library_drives` method. """ response = self.connection.request(action='/libdrives/').object images = [self._to_image(data=item) for item in response['objects']] # We filter out non pre-installed library drives by default because # they can't be used directly following a default Libcloud server # creation flow. images = [image for image in images if image.extra['image_type'] == 'preinst'] return images def create_node(self, name, size, image, ex_metadata=None, ex_vnc_password=None, ex_avoid=None, ex_vlan=None): """ Create a new server. Server creation consists multiple steps depending on the type of the image used. 1. Installation CD: 1. Create a server and attach installation cd 2. Start a server 2. Pre-installed image: 1. Clone provided library drive so we can use it 2. Resize cloned drive to the desired size 3. Create a server and attach cloned drive 4. Start a server :param ex_metadata: Key / value pairs to associate with the created node. (optional) :type ex_metadata: ``dict`` :param ex_vnc_password: Password to use for VNC access. If not provided, random password is generated. :type ex_vnc_password: ``str`` :param ex_avoid: A list of server UUIDs to avoid when starting this node. (optional) :type ex_avoid: ``list`` :param ex_vlan: Optional UUID of a VLAN network to use. If specified, server will have two nics assigned - 1 with a public ip and 1 with the provided VLAN. :type ex_vlan: ``str`` """ is_installation_cd = self._is_installation_cd(image=image) if ex_vnc_password: vnc_password = ex_vnc_password else: # VNC password is not provided, generate a random one. vnc_password = get_secure_random_string(size=12) drive_name = '%s-drive' % (name) # size is specified in GB drive_size = (size.disk * 1024 * 1024 * 1024) if not is_installation_cd: # 1. Clone library drive so we can use it drive = self.ex_clone_drive(drive=image, name=drive_name) # Wait for drive clone to finish drive = self._wait_for_drive_state_transition(drive=drive, state='unmounted') # 2. Resize drive to the desired disk size if the desired disk size # is larger than the cloned drive size. if drive_size > drive.size: drive = self.ex_resize_drive(drive=drive, size=drive_size) # Wait for drive resize to finish drive = self._wait_for_drive_state_transition(drive=drive, state='unmounted') else: # No need to clone installation CDs drive = image # 3. Create server and attach cloned drive # ide 0:0 data = {} data['name'] = name data['cpu'] = size.cpu data['mem'] = (size.ram * 1024 * 1024) data['vnc_password'] = vnc_password if ex_metadata: data['meta'] = ex_metadata # Assign 1 public interface (DHCP) to the node nic = { 'boot_order': None, 'ip_v4_conf': { 'conf': 'dhcp', }, 'ip_v6_conf': None } nics = [nic] if ex_vlan: # Assign another interface for VLAN nic = { 'boot_order': None, 'ip_v4_conf': None, 'ip_v6_conf': None, 'vlan': ex_vlan } nics.append(nic) # Need to use IDE for installation CDs if is_installation_cd: device_type = 'ide' else: device_type = 'virtio' drive = { 'boot_order': 1, 'dev_channel': '0:0', 'device': device_type, 'drive': drive.id } drives = [drive] data['nics'] = nics data['drives'] = drives action = '/servers/' response = self.connection.request(action=action, method='POST', data=data) node = self._to_node(response.object['objects'][0]) # 4. Start server self.ex_start_node(node=node, ex_avoid=ex_avoid) return node def destroy_node(self, node): """ Destroy the node and all the associated drives. :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ action = '/servers/%s/' % (node.id) params = {'recurse': 'all_drives'} response = self.connection.request(action=action, method='DELETE', params=params) return response.status == httplib.NO_CONTENT # Server extension methods def ex_edit_node(self, node, params): """ Edit a node. :param node: Node to edit. :type node: :class:`libcloud.compute.base.Node` :param params: Node parameters to update. :type params: ``dict`` :return Edited node. :rtype: :class:`libcloud.compute.base.Node` """ data = {} # name, cpu, mem and vnc_password attributes must always be present so # we just copy them from the to-be-edited node data['name'] = node.name data['cpu'] = node.extra['cpu'] data['mem'] = node.extra['mem'] data['vnc_password'] = node.extra['vnc_password'] nics = copy.deepcopy(node.extra.get('nics', [])) data['nics'] = nics data.update(params) action = '/servers/%s/' % (node.id) response = self.connection.request(action=action, method='PUT', data=data).object node = self._to_node(data=response) return node def start_node(self, node, ex_avoid=None): """ Start a node. :param node: Node to start. :type node: :class:`libcloud.compute.base.Node` :param ex_avoid: A list of other server uuids to avoid when starting this node. If provided, node will attempt to be started on a different physical infrastructure from other servers specified using this argument. (optional) :type ex_avoid: ``list`` """ params = {} if ex_avoid: params['avoid'] = ','.join(ex_avoid) path = '/servers/%s/action/' % (node.id) response = self._perform_action(path=path, action='start', params=params, method='POST') return response.status == httplib.ACCEPTED def stop_node(self, node): path = '/servers/%s/action/' % (node.id) response = self._perform_action(path=path, action='stop', method='POST') return response.status == httplib.ACCEPTED def ex_start_node(self, node, ex_avoid=None): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node, ex_avoid=ex_avoid) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 """ Stop a node. """ return self.stop_node(node=node) def ex_clone_node(self, node, name=None, random_vnc_password=None): """ Clone the provided node. :param name: Optional name for the cloned node. :type name: ``str`` :param random_vnc_password: If True, a new random VNC password will be generated for the cloned node. Otherwise password from the cloned node will be reused. :type random_vnc_password: ``bool`` :return: Cloned node. :rtype: :class:`libcloud.compute.base.Node` """ data = {} data['name'] = name data['random_vnc_password'] = random_vnc_password path = '/servers/%s/action/' % (node.id) response = self._perform_action(path=path, action='clone', method='POST', data=data).object node = self._to_node(data=response) return node def ex_open_vnc_tunnel(self, node): """ Open a VNC tunnel to the provided node and return the VNC url. :param node: Node to open the VNC tunnel to. :type node: :class:`libcloud.compute.base.Node` :return: URL of the opened VNC tunnel. :rtype: ``str`` """ path = '/servers/%s/action/' % (node.id) response = self._perform_action(path=path, action='open_vnc', method='POST').object vnc_url = response['vnc_url'] return vnc_url def ex_close_vnc_tunnel(self, node): """ Close a VNC server to the provided node. :param node: Node to close the VNC tunnel to. :type node: :class:`libcloud.compute.base.Node` :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ path = '/servers/%s/action/' % (node.id) response = self._perform_action(path=path, action='close_vnc', method='POST') return response.status == httplib.ACCEPTED # Drive extension methods def ex_list_library_drives(self): """ Return a list of all the available library drives (pre-installed and installation CDs). :rtype: ``list`` of :class:`.CloudSigmaDrive` objects """ response = self.connection.request(action='/libdrives/').object drives = [self._to_drive(data=item) for item in response['objects']] return drives def ex_list_user_drives(self): """ Return a list of all the available user's drives. :rtype: ``list`` of :class:`.CloudSigmaDrive` objects """ response = self.connection.request(action='/drives/detail/').object drives = [self._to_drive(data=item) for item in response['objects']] return drives def ex_create_drive(self, name, size, media='disk', ex_avoid=None): """ Create a new drive. :param name: Drive name. :type name: ``str`` :param size: Drive size in bytes. :type size: ``int`` :param media: Drive media type (cdrom, disk). :type media: ``str`` :param ex_avoid: A list of other drive uuids to avoid when creating this drive. If provided, drive will attempt to be created on a different physical infrastructure from other drives specified using this argument. (optional) :type ex_avoid: ``list`` :return: Created drive object. :rtype: :class:`.CloudSigmaDrive` """ params = {} data = { 'name': name, 'size': size, 'media': media } if ex_avoid: params['avoid'] = ','.join(ex_avoid) action = '/drives/' response = self.connection.request(action=action, method='POST', params=params, data=data).object drive = self._to_drive(data=response['objects'][0]) return drive def ex_clone_drive(self, drive, name=None, ex_avoid=None): """ Clone a library or a standard drive. :param drive: Drive to clone. :type drive: :class:`libcloud.compute.base.NodeImage` or :class:`.CloudSigmaDrive` :param name: Optional name for the cloned drive. :type name: ``str`` :param ex_avoid: A list of other drive uuids to avoid when creating this drive. If provided, drive will attempt to be created on a different physical infrastructure from other drives specified using this argument. (optional) :type ex_avoid: ``list`` :return: New cloned drive. :rtype: :class:`.CloudSigmaDrive` """ params = {} data = {} if ex_avoid: params['avoid'] = ','.join(ex_avoid) if name: data['name'] = name path = '/drives/%s/action/' % (drive.id) response = self._perform_action(path=path, action='clone', params=params, data=data, method='POST') drive = self._to_drive(data=response.object['objects'][0]) return drive def ex_resize_drive(self, drive, size): """ Resize a drive. :param drive: Drive to resize. :param size: New drive size in bytes. :type size: ``int`` :return: Drive object which is being resized. :rtype: :class:`.CloudSigmaDrive` """ path = '/drives/%s/action/' % (drive.id) data = {'name': drive.name, 'size': size, 'media': 'disk'} response = self._perform_action(path=path, action='resize', method='POST', data=data) drive = self._to_drive(data=response.object['objects'][0]) return drive def ex_attach_drive(self, node): """ Attach a drive to the provided node. """ # TODO pass def ex_get_drive(self, drive_id): """ Retrieve information about a single drive. :param drive_id: ID of the drive to retrieve. :type drive_id: ``str`` :return: Drive object. :rtype: :class:`.CloudSigmaDrive` """ action = '/drives/%s/' % (drive_id) response = self.connection.request(action=action).object drive = self._to_drive(data=response) return drive # Firewall policies extension methods def ex_list_firewall_policies(self): """ List firewall policies. :rtype: ``list`` of :class:`.CloudSigmaFirewallPolicy` """ action = '/fwpolicies/detail/' response = self.connection.request(action=action, method='GET').object policies = [self._to_firewall_policy(data=item) for item in response['objects']] return policies def ex_create_firewall_policy(self, name, rules=None): """ Create a firewall policy. :param name: Policy name. :type name: ``str`` :param rules: List of firewall policy rules to associate with this policy. (optional) :type rules: ``list`` of ``dict`` :return: Created firewall policy object. :rtype: :class:`.CloudSigmaFirewallPolicy` """ data = {} obj = {} obj['name'] = name if rules: obj['rules'] = rules data['objects'] = [obj] action = '/fwpolicies/' response = self.connection.request(action=action, method='POST', data=data).object policy = self._to_firewall_policy(data=response['objects'][0]) return policy def ex_attach_firewall_policy(self, policy, node, nic_mac=None): """ Attach firewall policy to a public NIC interface on the server. :param policy: Firewall policy to attach. :type policy: :class:`.CloudSigmaFirewallPolicy` :param node: Node to attach policy to. :type node: :class:`libcloud.compute.base.Node` :param nic_mac: Optional MAC address of the NIC to add the policy to. If not specified, first public interface is used instead. :type nic_mac: ``str`` :return: Node object to which the policy was attached to. :rtype: :class:`libcloud.compute.base.Node` """ nics = copy.deepcopy(node.extra.get('nics', [])) if nic_mac: nic = [n for n in nics if n['mac'] == nic_mac] else: nic = nics if len(nic) == 0: raise ValueError('Cannot find the NIC interface to attach ' 'a policy to') nic = nic[0] nic['firewall_policy'] = policy.id params = {'nics': nics} node = self.ex_edit_node(node=node, params=params) return node def ex_delete_firewall_policy(self, policy): """ Delete a firewall policy. :param policy: Policy to delete to. :type policy: :class:`.CloudSigmaFirewallPolicy` :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ action = '/fwpolicies/%s/' % (policy.id) response = self.connection.request(action=action, method='DELETE') return response.status == httplib.NO_CONTENT # Availability groups extension methods def ex_list_servers_availability_groups(self): """ Return which running servers share the same physical compute host. :return: A list of server UUIDs which share the same physical compute host. Servers which share the same host will be stored under the same list index. :rtype: ``list`` of ``list`` """ action = '/servers/availability_groups/' response = self.connection.request(action=action, method='GET') return response.object def ex_list_drives_availability_groups(self): """ Return which drives share the same physical storage host. :return: A list of drive UUIDs which share the same physical storage host. Drives which share the same host will be stored under the same list index. :rtype: ``list`` of ``list`` """ action = '/drives/availability_groups/' response = self.connection.request(action=action, method='GET') return response.object # Tag extension methods def ex_list_tags(self): """ List all the available tags. :rtype: ``list`` of :class:`.CloudSigmaTag` objects """ action = '/tags/detail/' response = self.connection.request(action=action, method='GET').object tags = [self._to_tag(data=item) for item in response['objects']] return tags def ex_get_tag(self, tag_id): """ Retrieve a single tag. :param tag_id: ID of the tag to retrieve. :type tag_id: ``str`` :rtype: ``list`` of :class:`.CloudSigmaTag` objects """ action = '/tags/%s/' % (tag_id) response = self.connection.request(action=action, method='GET').object tag = self._to_tag(data=response) return tag def ex_create_tag(self, name, resource_uuids=None): """ Create a tag. :param name: Tag name. :type name: ``str`` :param resource_uuids: Optional list of resource UUIDs to assign this tag go. :type resource_uuids: ``list`` of ``str`` :return: Created tag object. :rtype: :class:`.CloudSigmaTag` """ data = {} data['objects'] = [ { 'name': name } ] if resource_uuids: data['resources'] = resource_uuids action = '/tags/' response = self.connection.request(action=action, method='POST', data=data).object tag = self._to_tag(data=response['objects'][0]) return tag def ex_tag_resource(self, resource, tag): """ Associate tag with the provided resource. :param resource: Resource to associate a tag with. :type resource: :class:`libcloud.compute.base.Node` or :class:`.CloudSigmaDrive` :param tag: Tag to associate with the resources. :type tag: :class:`.CloudSigmaTag` :return: Updated tag object. :rtype: :class:`.CloudSigmaTag` """ if not hasattr(resource, 'id'): raise ValueError('Resource doesn\'t have id attribute') return self.ex_tag_resources(resources=[resource], tag=tag) def ex_tag_resources(self, resources, tag): """ Associate tag with the provided resources. :param resources: Resources to associate a tag with. :type resources: ``list`` of :class:`libcloud.compute.base.Node` or :class:`.CloudSigmaDrive` :param tag: Tag to associate with the resources. :type tag: :class:`.CloudSigmaTag` :return: Updated tag object. :rtype: :class:`.CloudSigmaTag` """ resources = tag.resources[:] for resource in resources: if not hasattr(resource, 'id'): raise ValueError('Resource doesn\'t have id attribute') resources.append(resource.id) resources = list(set(resources)) data = { 'name': tag.name, 'resources': resources } action = '/tags/%s/' % (tag.id) response = self.connection.request(action=action, method='PUT', data=data).object tag = self._to_tag(data=response) return tag def ex_delete_tag(self, tag): """ Delete a tag. :param tag: Tag to delete. :type tag: :class:`.CloudSigmaTag` :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ action = '/tags/%s/' % (tag.id) response = self.connection.request(action=action, method='DELETE') return response.status == httplib.NO_CONTENT # Account extension methods def ex_get_balance(self): """ Retrieve account balance information. :return: Dictionary with two items ("balance" and "currency"). :rtype: ``dict`` """ action = '/balance/' response = self.connection.request(action=action, method='GET') return response.object def ex_get_pricing(self): """ Retrieve pricing information that are applicable to the cloud. :return: Dictionary with pricing information. :rtype: ``dict`` """ action = '/pricing/' response = self.connection.request(action=action, method='GET') return response.object def ex_get_usage(self): """ Retrieve account current usage information. :return: Dictionary with two items ("balance" and "usage"). :rtype: ``dict`` """ action = '/currentusage/' response = self.connection.request(action=action, method='GET') return response.object def ex_list_subscriptions(self, status='all', resources=None): """ List subscriptions for this account. :param status: Only return subscriptions with the provided status (optional). :type status: ``str`` :param resources: Only return subscriptions for the provided resources (optional). :type resources: ``list`` :rtype: ``list`` """ params = {} if status: params['status'] = status if resources: params['resource'] = ','.join(resources) response = self.connection.request(action='/subscriptions/', params=params).object subscriptions = self._to_subscriptions(data=response) return subscriptions def ex_toggle_subscription_auto_renew(self, subscription): """ Toggle subscription auto renew status. :param subscription: Subscription to toggle the auto renew flag for. :type subscription: :class:`.CloudSigmaSubscription` :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ path = '/subscriptions/%s/action/' % (subscription.id) response = self._perform_action(path=path, action='auto_renew', method='POST') return response.status == httplib.OK def ex_create_subscription(self, amount, period, resource, auto_renew=False): """ Create a new subscription. :param amount: Subscription amount. For example, in dssd case this would be disk size in gigabytes. :type amount: ``int`` :param period: Subscription period. For example: 30 days, 1 week, 1 month, ... :type period: ``str`` :param resource: Resource the purchase the subscription for. :type resource: ``str`` :param auto_renew: True to automatically renew the subscription. :type auto_renew: ``bool`` """ data = [ { 'amount': amount, 'period': period, 'auto_renew': auto_renew, 'resource': resource } ] response = self.connection.request(action='/subscriptions/', data=data, method='POST') data = response.object['objects'][0] subscription = self._to_subscription(data=data) return subscription # Misc extension methods def ex_list_capabilities(self): """ Retrieve all the basic and sensible limits of the API. :rtype: ``dict`` """ action = '/capabilities/' response = self.connection.request(action=action, method='GET') capabilities = response.object return capabilities def _parse_ips_from_nic(self, nic): """ Parse private and public IP addresses from the provided network interface object. :param nic: NIC object. :type nic: ``dict`` :return: (public_ips, private_ips) tuple. :rtype: ``tuple`` """ public_ips, private_ips = [], [] ipv4_conf = nic['ip_v4_conf'] ipv6_conf = nic['ip_v6_conf'] ip_v4 = ipv4_conf['ip'] if ipv4_conf else None ip_v6 = ipv6_conf['ip'] if ipv6_conf else None ipv4 = ip_v4['uuid'] if ip_v4 else None ipv6 = ip_v4['uuid'] if ip_v6 else None ips = [] if ipv4: ips.append(ipv4) if ipv6: ips.append(ipv6) runtime = nic['runtime'] ip_v4 = runtime['ip_v4'] if nic['runtime'] else None ip_v6 = runtime['ip_v6'] if nic['runtime'] else None ipv4 = ip_v4['uuid'] if ip_v4 else None ipv6 = ip_v4['uuid'] if ip_v6 else None if ipv4: ips.append(ipv4) if ipv6: ips.append(ipv6) ips = set(ips) for ip in ips: if is_private_subnet(ip): private_ips.append(ip) else: public_ips.append(ip) return public_ips, private_ips def _to_node(self, data): extra_keys = ['cpu', 'mem', 'nics', 'vnc_password', 'meta'] id = data['uuid'] name = data['name'] state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN) public_ips = [] private_ips = [] extra = self._extract_values(obj=data, keys=extra_keys) for nic in data['nics']: _public_ips, _private_ips = self._parse_ips_from_nic(nic=nic) public_ips.extend(_public_ips) private_ips.extend(_private_ips) node = Node(id=id, name=name, state=state, public_ips=public_ips, private_ips=private_ips, driver=self, extra=extra) return node def _to_image(self, data): extra_keys = ['description', 'arch', 'image_type', 'os', 'licenses', 'media', 'meta'] id = data['uuid'] name = data['name'] extra = self._extract_values(obj=data, keys=extra_keys) image = NodeImage(id=id, name=name, driver=self, extra=extra) return image def _to_drive(self, data): id = data['uuid'] name = data['name'] size = data['size'] media = data['media'] status = data['status'] extra = {} drive = CloudSigmaDrive(id=id, name=name, size=size, media=media, status=status, driver=self, extra=extra) return drive def _to_tag(self, data): resources = data['resources'] resources = [resource['uuid'] for resource in resources] tag = CloudSigmaTag(id=data['uuid'], name=data['name'], resources=resources) return tag def _to_subscriptions(self, data): subscriptions = [] for item in data['objects']: subscription = self._to_subscription(data=item) subscriptions.append(subscription) return subscriptions def _to_subscription(self, data): if data.get('start_time', None): start_time = parse_date(data['start_time']) else: start_time = None if data.get('end_time', None): end_time = parse_date(data['end_time']) else: end_time = None obj_uuid = data['subscribed_object'] subscription = CloudSigmaSubscription(id=data['id'], resource=data['resource'], amount=int(data['amount']), period=data['period'], status=data['status'], price=data['price'], start_time=start_time, end_time=end_time, auto_renew=data['auto_renew'], subscribed_object=obj_uuid) return subscription def _to_firewall_policy(self, data): rules = [] for item in data.get('rules', []): rule = CloudSigmaFirewallPolicyRule(action=item['action'], direction=item['direction'], ip_proto=item['ip_proto'], src_ip=item['src_ip'], src_port=item['src_port'], dst_ip=item['dst_ip'], dst_port=item['dst_port'], comment=item['comment']) rules.append(rule) policy = CloudSigmaFirewallPolicy(id=data['uuid'], name=data['name'], rules=rules) return policy def _perform_action(self, path, action, method='POST', params=None, data=None): """ Perform API action and return response object. """ if params: params = params.copy() else: params = {} params['do'] = action response = self.connection.request(action=path, method=method, params=params, data=data) return response def _is_installation_cd(self, image): """ Detect if the provided image is an installation CD. :rtype: ``bool`` """ if isinstance(image, CloudSigmaDrive) and image.media == 'cdrom': return True return False def _extract_values(self, obj, keys): """ Extract values from a dictionary and return a new dictionary with extracted values. :param obj: Dictionary to extract values from. :type obj: ``dict`` :param keys: Keys to extract. :type keys: ``list`` :return: Dictionary with extracted values. :rtype: ``dict`` """ result = {} for key in keys: result[key] = obj[key] return result def _wait_for_drive_state_transition(self, drive, state, timeout=DRIVE_TRANSITION_TIMEOUT): """ Wait for a drive to transition to the provided state. Note: This function blocks and periodically calls "GET drive" endpoint to check if the drive has already transitioned to the desired state. :param drive: Drive to wait for. :type drive: :class:`.CloudSigmaDrive` :param state: Desired drive state. :type state: ``str`` :param timeout: How long to wait for the transition (in seconds) before timing out. :type timeout: ``int`` :return: Drive object. :rtype: :class:`.CloudSigmaDrive` """ start_time = time.time() while drive.status != state: drive = self.ex_get_drive(drive_id=drive.id) if drive.status == state: break current_time = time.time() delta = (current_time - start_time) if delta >= timeout: msg = ('Timed out while waiting for drive transition ' '(timeout=%s seconds)' % (timeout)) raise Exception(msg) time.sleep(self.DRIVE_TRANSITION_SLEEP_INTERVAL) return drive def _ex_connection_class_kwargs(self): """ Return the host value based on the user supplied region. """ kwargs = {} if not self._host_argument_set: kwargs['host'] = API_ENDPOINTS_2_0[self.region]['host'] return kwargs apache-libcloud-2.8.0/libcloud/compute/drivers/cloudstack.py0000664000175000017500000047777213577507766024137 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import base64 import warnings from libcloud.utils.py3 import b from libcloud.utils.py3 import urlparse from libcloud.compute.providers import Provider from libcloud.common.cloudstack import CloudStackDriverMixIn from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation from libcloud.compute.base import NodeSize, StorageVolume, VolumeSnapshot from libcloud.compute.base import KeyPair from libcloud.compute.types import NodeState, LibcloudError from libcloud.compute.types import KeyPairDoesNotExistError, StorageVolumeState from libcloud.utils.networking import is_private_subnet # Utility functions def transform_int_or_unlimited(value): try: return int(value) except ValueError as e: if str(value).lower() == 'unlimited': return -1 raise e """ Define the extra dictionary for specific resources """ RESOURCE_EXTRA_ATTRIBUTES_MAP = { 'network': { 'broadcast_domain_type': { 'key_name': 'broadcastdomaintype', 'transform_func': str }, 'traffic_type': { 'key_name': 'traffictype', 'transform_func': str }, 'zone_name': { 'key_name': 'zonename', 'transform_func': str }, 'network_offering_name': { 'key_name': 'networkofferingname', 'transform_func': str }, 'network_offeringdisplay_text': { 'key_name': 'networkofferingdisplaytext', 'transform_func': str }, 'network_offering_availability': { 'key_name': 'networkofferingavailability', 'transform_func': str }, 'is_system': { 'key_name': 'issystem', 'transform_func': str }, 'state': { 'key_name': 'state', 'transform_func': str }, 'dns1': { 'key_name': 'dns1', 'transform_func': str }, 'dns2': { 'key_name': 'dns2', 'transform_func': str }, 'type': { 'key_name': 'type', 'transform_func': str }, 'acl_type': { 'key_name': 'acltype', 'transform_func': str }, 'subdomain_access': { 'key_name': 'subdomainaccess', 'transform_func': str }, 'network_domain': { 'key_name': 'networkdomain', 'transform_func': str }, 'physical_network_id': { 'key_name': 'physicalnetworkid', 'transform_func': str }, 'can_use_for_deploy': { 'key_name': 'canusefordeploy', 'transform_func': str }, 'gateway': { 'key_name': 'gateway', 'transform_func': str }, 'netmask': { 'key_name': 'netmask', 'transform_func': str }, 'vpc_id': { 'key_name': 'vpcid', 'transform_func': str }, 'project_id': { 'key_name': 'projectid', 'transform_func': str } }, 'node': { 'haenable': { 'key_name': 'haenable', 'transform_func': str }, 'zone_id': { 'key_name': 'zoneid', 'transform_func': str }, 'zone_name': { 'key_name': 'zonename', 'transform_func': str }, 'key_name': { 'key_name': 'keypair', 'transform_func': str }, 'password': { 'key_name': 'password', 'transform_func': str }, 'image_id': { 'key_name': 'templateid', 'transform_func': str }, 'image_name': { 'key_name': 'templatename', 'transform_func': str }, 'template_display_text': { 'key_name': 'templatdisplaytext', 'transform_func': str }, 'password_enabled': { 'key_name': 'passwordenabled', 'transform_func': str }, 'size_id': { 'key_name': 'serviceofferingid', 'transform_func': str }, 'size_name': { 'key_name': 'serviceofferingname', 'transform_func': str }, 'root_device_id': { 'key_name': 'rootdeviceid', 'transform_func': str }, 'root_device_type': { 'key_name': 'rootdevicetype', 'transform_func': str }, 'hypervisor': { 'key_name': 'hypervisor', 'transform_func': str }, 'project': { 'key_name': 'project', 'transform_func': str }, 'project_id': { 'key_name': 'projectid', 'transform_func': str }, 'nics:': { 'key_name': 'nic', 'transform_func': list } }, 'volume': { 'created': { 'key_name': 'created', 'transform_func': str }, 'device_id': { 'key_name': 'deviceid', 'transform_func': transform_int_or_unlimited }, 'instance_id': { 'key_name': 'virtualmachineid', 'transform_func': str }, 'serviceoffering_id': { 'key_name': 'serviceofferingid', 'transform_func': str }, 'state': { 'key_name': 'state', 'transform_func': str }, 'volume_type': { 'key_name': 'type', 'transform_func': str }, 'zone_id': { 'key_name': 'zoneid', 'transform_func': str }, 'zone_name': { 'key_name': 'zonename', 'transform_func': str } }, 'vpc': { 'created': { 'key_name': 'created', 'transform_func': str }, 'domain': { 'key_name': 'domain', 'transform_func': str }, 'domain_id': { 'key_name': 'domainid', 'transform_func': transform_int_or_unlimited }, 'network_domain': { 'key_name': 'networkdomain', 'transform_func': str }, 'state': { 'key_name': 'state', 'transform_func': str }, 'vpc_offering_id': { 'key_name': 'vpcofferingid', 'transform_func': str }, 'zone_name': { 'key_name': 'zonename', 'transform_func': str }, 'zone_id': { 'key_name': 'zoneid', 'transform_func': str } }, 'project': { 'account': {'key_name': 'account', 'transform_func': str}, 'cpuavailable': {'key_name': 'cpuavailable', 'transform_func': transform_int_or_unlimited}, 'cpulimit': {'key_name': 'cpulimit', 'transform_func': transform_int_or_unlimited}, 'cputotal': {'key_name': 'cputotal', 'transform_func': transform_int_or_unlimited}, 'domain': {'key_name': 'domain', 'transform_func': str}, 'domainid': {'key_name': 'domainid', 'transform_func': str}, 'ipavailable': {'key_name': 'ipavailable', 'transform_func': transform_int_or_unlimited}, 'iplimit': {'key_name': 'iplimit', 'transform_func': transform_int_or_unlimited}, 'iptotal': {'key_name': 'iptotal', 'transform_func': transform_int_or_unlimited}, 'memoryavailable': {'key_name': 'memoryavailable', 'transform_func': transform_int_or_unlimited}, 'memorylimit': {'key_name': 'memorylimit', 'transform_func': transform_int_or_unlimited}, 'memorytotal': {'key_name': 'memorytotal', 'transform_func': transform_int_or_unlimited}, 'networkavailable': {'key_name': 'networkavailable', 'transform_func': transform_int_or_unlimited}, 'networklimit': {'key_name': 'networklimit', 'transform_func': transform_int_or_unlimited}, 'networktotal': {'key_name': 'networktotal', 'transform_func': transform_int_or_unlimited}, 'primarystorageavailable': { 'key_name': 'primarystorageavailable', 'transform_func': transform_int_or_unlimited}, 'primarystoragelimit': {'key_name': 'primarystoragelimit', 'transform_func': transform_int_or_unlimited}, 'primarystoragetotal': {'key_name': 'primarystoragetotal', 'transform_func': transform_int_or_unlimited}, 'secondarystorageavailable': { 'key_name': 'secondarystorageavailable', 'transform_func': transform_int_or_unlimited}, 'secondarystoragelimit': { 'key_name': 'secondarystoragelimit', 'transform_func': transform_int_or_unlimited}, 'secondarystoragetotal': { 'key_name': 'secondarystoragetotal', 'transform_func': transform_int_or_unlimited}, 'snapshotavailable': {'key_name': 'snapshotavailable', 'transform_func': transform_int_or_unlimited}, 'snapshotlimit': {'key_name': 'snapshotlimit', 'transform_func': transform_int_or_unlimited}, 'snapshottotal': {'key_name': 'snapshottotal', 'transform_func': transform_int_or_unlimited}, 'state': {'key_name': 'state', 'transform_func': str}, 'tags': {'key_name': 'tags', 'transform_func': str}, 'templateavailable': {'key_name': 'templateavailable', 'transform_func': transform_int_or_unlimited}, 'templatelimit': {'key_name': 'templatelimit', 'transform_func': transform_int_or_unlimited}, 'templatetotal': {'key_name': 'templatetotal', 'transform_func': transform_int_or_unlimited}, 'vmavailable': {'key_name': 'vmavailable', 'transform_func': transform_int_or_unlimited}, 'vmlimit': {'key_name': 'vmlimit', 'transform_func': transform_int_or_unlimited}, 'vmrunning': {'key_name': 'vmrunning', 'transform_func': transform_int_or_unlimited}, 'vmtotal': {'key_name': 'vmtotal', 'transform_func': transform_int_or_unlimited}, 'volumeavailable': {'key_name': 'volumeavailable', 'transform_func': transform_int_or_unlimited}, 'volumelimit': {'key_name': 'volumelimit', 'transform_func': transform_int_or_unlimited}, 'volumetotal': {'key_name': 'volumetotal', 'transform_func': transform_int_or_unlimited}, 'vpcavailable': {'key_name': 'vpcavailable', 'transform_func': transform_int_or_unlimited}, 'vpclimit': {'key_name': 'vpclimit', 'transform_func': transform_int_or_unlimited}, 'vpctotal': {'key_name': 'vpctotal', 'transform_func': transform_int_or_unlimited} }, 'nic': { 'secondary_ip': { 'key_name': 'secondaryip', 'transform_func': list } }, 'vpngateway': { 'for_display': { 'key_name': 'fordisplay', 'transform_func': str }, 'project': { 'key_name': 'project', 'transform_func': str }, 'project_id': { 'key_name': 'projectid', 'transform_func': str }, 'removed': { 'key_name': 'removed', 'transform_func': str } }, 'vpncustomergateway': { 'account': { 'key_name': 'account', 'transform_func': str }, 'domain': { 'key_name': 'domain', 'transform_func': str }, 'domain_id': { 'key_name': 'domainid', 'transform_func': str }, 'dpd': { 'key_name': 'dpd', 'transform_func': bool }, 'esp_lifetime': { 'key_name': 'esplifetime', 'transform_func': transform_int_or_unlimited }, 'ike_lifetime': { 'key_name': 'ikelifetime', 'transform_func': transform_int_or_unlimited }, 'name': { 'key_name': 'name', 'transform_func': str } }, 'vpnconnection': { 'account': { 'key_name': 'account', 'transform_func': str }, 'domain': { 'key_name': 'domain', 'transform_func': str }, 'domain_id': { 'key_name': 'domainid', 'transform_func': str }, 'for_display': { 'key_name': 'fordisplay', 'transform_func': str }, 'project': { 'key_name': 'project', 'transform_func': str }, 'project_id': { 'key_name': 'projectid', 'transform_func': str } } } class CloudStackNode(Node): """ Subclass of Node so we can expose our extension methods. """ def ex_allocate_public_ip(self): """ Allocate a public IP and bind it to this node. """ return self.driver.ex_allocate_public_ip(self) def ex_release_public_ip(self, address): """ Release a public IP that this node holds. """ return self.driver.ex_release_public_ip(self, address) def ex_create_ip_forwarding_rule(self, address, protocol, start_port, end_port=None): """ Add a NAT/firewall forwarding rule for a port or ports. """ return self.driver.ex_create_ip_forwarding_rule(node=self, address=address, protocol=protocol, start_port=start_port, end_port=end_port) def ex_create_port_forwarding_rule(self, address, private_port, public_port, protocol, public_end_port=None, private_end_port=None, openfirewall=True): """ Add a port forwarding rule for port or ports. """ return self.driver.ex_create_port_forwarding_rule( node=self, address=address, private_port=private_port, public_port=public_port, protocol=protocol, public_end_port=public_end_port, private_end_port=private_end_port, openfirewall=openfirewall) def ex_delete_ip_forwarding_rule(self, rule): """ Delete a port forwarding rule. """ return self.driver.ex_delete_ip_forwarding_rule(node=self, rule=rule) def ex_delete_port_forwarding_rule(self, rule): """ Delete a NAT/firewall rule. """ return self.driver.ex_delete_port_forwarding_rule(node=self, rule=rule) def ex_restore(self, template=None): """ Restore virtual machine """ return self.driver.ex_restore(node=self, template=template) def ex_change_node_size(self, offering): """ Change virtual machine offering/size """ return self.driver.ex_change_node_size(node=self, offering=offering) def ex_start(self): """ Starts a stopped virtual machine. """ return self.driver.ex_start(node=self) def ex_stop(self): """ Stops a running virtual machine. """ return self.driver.ex_stop(node=self) class CloudStackAddress(object): """ A public IP address. :param id: UUID of the Public IP :type id: ``str`` :param address: The public IP address :type address: ``str`` :param associated_network_id: The ID of the network where this address has been associated with :type associated_network_id: ``str`` :param vpc_id: VPC the ip belongs to :type vpc_id: ``str`` :param virtualmachine_id: The ID of virutal machine this address is assigned to :type virtualmachine_id: ``str`` """ def __init__(self, id, address, driver, associated_network_id=None, vpc_id=None, virtualmachine_id=None): self.id = id self.address = address self.driver = driver self.associated_network_id = associated_network_id self.vpc_id = vpc_id self.virtualmachine_id = virtualmachine_id def release(self): self.driver.ex_release_public_ip(address=self) def __str__(self): return self.address def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackFirewallRule(object): """ A firewall rule. """ def __init__(self, id, address, cidr_list, protocol, icmp_code=None, icmp_type=None, start_port=None, end_port=None): """ A Firewall rule. @note: This is a non-standard extension API, and only works for CloudStack. :param id: Firewall Rule ID :type id: ``int`` :param address: External IP address :type address: :class:`CloudStackAddress` :param cidr_list: cidr list :type cidr_list: ``str`` :param protocol: TCP/IP Protocol (TCP, UDP) :type protocol: ``str`` :param icmp_code: Error code for this icmp message :type icmp_code: ``int`` :param icmp_type: Type of the icmp message being sent :type icmp_type: ``int`` :param start_port: start of port range :type start_port: ``int`` :param end_port: end of port range :type end_port: ``int`` :rtype: :class:`CloudStackFirewallRule` """ self.id = id self.address = address self.cidr_list = cidr_list self.protocol = protocol self.icmp_code = icmp_code self.icmp_type = icmp_type self.start_port = start_port self.end_port = end_port def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackEgressFirewallRule(object): """ A egress firewall rule. """ def __init__(self, id, network_id, cidr_list, protocol, icmp_code=None, icmp_type=None, start_port=None, end_port=None): """ A egress firewall rule. @note: This is a non-standard extension API, and only works for CloudStack. :param id: Firewall Rule ID :type id: ``int`` :param network_id: the id network network for the egress firwall services :type network_id: ``str`` :param protocol: TCP/IP Protocol (TCP, UDP) :type protocol: ``str`` :param cidr_list: cidr list :type cidr_list: ``str`` :param icmp_code: Error code for this icmp message :type icmp_code: ``int`` :param icmp_type: Type of the icmp message being sent :type icmp_type: ``int`` :param start_port: start of port range :type start_port: ``int`` :param end_port: end of port range :type end_port: ``int`` :rtype: :class:`CloudStackEgressFirewallRule` """ self.id = id self.network_id = network_id self.cidr_list = cidr_list self.protocol = protocol self.icmp_code = icmp_code self.icmp_type = icmp_type self.start_port = start_port self.end_port = end_port def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackIPForwardingRule(object): """ A NAT/firewall forwarding rule. """ def __init__(self, node, id, address, protocol, start_port, end_port=None): """ A NAT/firewall forwarding rule. @note: This is a non-standard extension API, and only works for CloudStack. :param node: Node for rule :type node: :class:`Node` :param id: Rule ID :type id: ``int`` :param address: External IP address :type address: :class:`CloudStackAddress` :param protocol: TCP/IP Protocol (TCP, UDP) :type protocol: ``str`` :param start_port: Start port for the rule :type start_port: ``int`` :param end_port: End port for the rule :type end_port: ``int`` :rtype: :class:`CloudStackIPForwardingRule` """ self.node = node self.id = id self.address = address self.protocol = protocol self.start_port = start_port self.end_port = end_port def delete(self): self.node.ex_delete_ip_forwarding_rule(rule=self) def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackPortForwardingRule(object): """ A Port forwarding rule for Source NAT. """ def __init__(self, node, rule_id, address, protocol, public_port, private_port, public_end_port=None, private_end_port=None, network_id=None): """ A Port forwarding rule for Source NAT. @note: This is a non-standard extension API, and only works for EC2. :param node: Node for rule :type node: :class:`Node` :param rule_id: Rule ID :type rule_id: ``int`` :param address: External IP address :type address: :class:`CloudStackAddress` :param protocol: TCP/IP Protocol (TCP, UDP) :type protocol: ``str`` :param public_port: External port for rule (or start port if public_end_port is also provided) :type public_port: ``int`` :param private_port: Internal node port for rule (or start port if public_end_port is also provided) :type private_port: ``int`` :param public_end_port: End of external port range :type public_end_port: ``int`` :param private_end_port: End of internal port range :type private_end_port: ``int`` :param network_id: The network of the vm the Port Forwarding rule will be created for. Required when public Ip address is not associated with any Guest network yet (VPC case) :type network_id: ``str`` :rtype: :class:`CloudStackPortForwardingRule` """ self.node = node self.id = rule_id self.address = address self.protocol = protocol self.public_port = public_port self.public_end_port = public_end_port self.private_port = private_port self.private_end_port = private_end_port def delete(self): self.node.ex_delete_port_forwarding_rule(rule=self) def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackNetworkACLList(object): """ a Network ACL for the given VPC """ def __init__(self, acl_id, name, vpc_id, driver, description=None): """ a Network ACL for the given VPC @note: This is a non-standard extension API, and only works for Cloudstack. :param acl_id: ACL ID :type acl_id: ``int`` :param name: Name of the network ACL List :type name: ``str`` :param vpc_id: Id of the VPC associated with this network ACL List :type vpc_id: ``string`` :param description: Description of the network ACL List :type description: ``str`` :rtype: :class:`CloudStackNetworkACLList` """ self.id = acl_id self.name = name self.vpc_id = vpc_id self.driver = driver self.description = description def __repr__(self): return (('') % (self.id, self.name, self.vpc_id, self.driver.name, self.description)) class CloudStackNetworkACL(object): """ a ACL rule in the given network (the network has to belong to VPC) """ def __init__(self, id, protocol, acl_id, action, cidr_list, start_port, end_port, traffic_type=None): """ a ACL rule in the given network (the network has to belong to VPC) @note: This is a non-standard extension API, and only works for Cloudstack. :param id: the ID of the ACL Item :type id ``int`` :param protocol: the protocol for the ACL rule. Valid values are TCP/UDP/ICMP/ALL or valid protocol number :type protocol: ``string`` :param acl_id: Name of the network ACL List :type acl_id: ``str`` :param action: scl entry action, allow or deny :type action: ``string`` :param cidr_list: the cidr list to allow traffic from/to :type cidr_list: ``str`` :param start_port: the starting port of ACL :type start_port: ``str`` :param end_port: the ending port of ACL :type end_port: ``str`` :param traffic_type: the traffic type for the ACL,can be Ingress or Egress, defaulted to Ingress if not specified :type traffic_type: ``str`` :rtype: :class:`CloudStackNetworkACL` """ self.id = id self.protocol = protocol self.acl_id = acl_id self.action = action self.cidr_list = cidr_list self.start_port = start_port self.end_port = end_port self.traffic_type = traffic_type def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackDiskOffering(object): """ A disk offering within CloudStack. """ def __init__(self, id, name, size, customizable): self.id = id self.name = name self.size = size self.customizable = customizable def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackNetwork(object): """ Class representing a CloudStack Network. """ def __init__(self, displaytext, name, networkofferingid, id, zoneid, driver, extra=None): self.displaytext = displaytext self.name = name self.networkofferingid = networkofferingid self.id = id self.zoneid = zoneid self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.displaytext, self.name, self.networkofferingid, self.id, self.zoneid, self.driver.name)) class CloudStackNetworkOffering(object): """ Class representing a CloudStack Network Offering. """ def __init__(self, name, display_text, guest_ip_type, id, service_offering_id, for_vpc, driver, extra=None): self.display_text = display_text self.name = name self.guest_ip_type = guest_ip_type self.id = id self.service_offering_id = service_offering_id self.for_vpc = for_vpc self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.name, self.display_text, self.guest_ip_type, self.service_offering_id, self.for_vpc, self.driver.name)) class CloudStackNic(object): """ Class representing a CloudStack Network Interface. """ def __init__(self, id, network_id, net_mask, gateway, ip_address, is_default, mac_address, driver, extra=None): self.id = id self.network_id = network_id self.net_mask = net_mask self.gateway = gateway self.ip_address = ip_address self.is_default = is_default self.mac_address = mac_address self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.network_id, self.net_mask, self.gateway, self.ip_address, self.is_default, self.mac_address, self.driver.name)) def __eq__(self, other): return self.__class__ is other.__class__ and self.id == other.id class CloudStackVPC(object): """ Class representing a CloudStack VPC. """ def __init__(self, name, vpc_offering_id, id, cidr, driver, zone_id=None, display_text=None, extra=None): self.display_text = display_text self.name = name self.vpc_offering_id = vpc_offering_id self.id = id self.zone_id = zone_id self.cidr = cidr self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.name, self.vpc_offering_id, self.id, self.cidr, self.driver.name, self.zone_id, self.display_text)) class CloudStackVPCOffering(object): """ Class representing a CloudStack VPC Offering. """ def __init__(self, name, display_text, id, driver, extra=None): self.name = name self.display_text = display_text self.id = id self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.name, self.display_text, self.id, self.driver.name)) class CloudStackVpnGateway(object): """ Class representing a CloudStack VPN Gateway. """ def __init__(self, id, account, domain, domain_id, public_ip, vpc_id, driver, extra=None): self.id = id self.account = account self.domain = domain self.domain_id = domain_id self.public_ip = public_ip self.vpc_id = vpc_id self.driver = driver self.extra = extra or {} @property def vpc(self): for vpc in self.driver.ex_list_vpcs(): if self.vpc_id == vpc.id: return vpc raise LibcloudError('VPC with id=%s not found' % self.vpc_id) def delete(self): return self.driver.ex_delete_vpn_gateway(vpn_gateway=self) def __repr__(self): return (('') % (self.account, self.domain, self.domain_id, self.id, self.public_ip, self.vpc_id, self.driver.name)) class CloudStackVpnCustomerGateway(object): """ Class representing a CloudStack VPN Customer Gateway. """ def __init__(self, id, cidr_list, esp_policy, gateway, ike_policy, ipsec_psk, driver, extra=None): self.id = id self.cidr_list = cidr_list self.esp_policy = esp_policy self.gateway = gateway self.ike_policy = ike_policy self.ipsec_psk = ipsec_psk self.driver = driver self.extra = extra or {} def delete(self): return self.driver.ex_delete_vpn_customer_gateway( vpn_customer_gateway=self) def __repr__(self): return (('') % (self.id, self.cidr_list, self.esp_policy, self.gateway, self.ike_policy, self.ipsec_psk, self.driver.name)) class CloudStackVpnConnection(object): """ Class representing a CloudStack VPN Connection. """ def __init__(self, id, passive, vpn_customer_gateway_id, vpn_gateway_id, state, driver, extra=None): self.id = id self.passive = passive self.vpn_customer_gateway_id = vpn_customer_gateway_id self.vpn_gateway_id = vpn_gateway_id self.state = state self.driver = driver self.extra = extra or {} @property def vpn_customer_gateway(self): try: return self.driver.ex_list_vpn_customer_gateways( id=self.vpn_customer_gateway_id)[0] except IndexError: raise LibcloudError('VPN Customer Gateway with id=%s not found' % self.vpn_customer_gateway_id) @property def vpn_gateway(self): try: return self.driver.ex_list_vpn_gateways(id=self.vpn_gateway_id)[0] except IndexError: raise LibcloudError('VPN Gateway with id=%s not found' % self.vpn_gateway_id) def delete(self): return self.driver.ex_delete_vpn_connection(vpn_connection=self) def __repr__(self): return (('') % (self.id, self.passive, self.vpn_customer_gateway_id, self.vpn_gateway_id, self.state, self.driver.name)) class CloudStackRouter(object): """ Class representing a CloudStack Router. """ def __init__(self, id, name, state, public_ip, vpc_id, driver): self.id = id self.name = name self.state = state self.public_ip = public_ip self.vpc_id = vpc_id self.driver = driver def __repr__(self): return (('') % (self.id, self.name, self.state, self.public_ip, self.vpc_id, self.driver.name)) class CloudStackProject(object): """ Class representing a CloudStack Project. """ def __init__(self, id, name, display_text, driver, extra=None): self.id = id self.name = name self.display_text = display_text self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.display_text, self.name, self.driver.name)) class CloudStackAffinityGroup(object): """ Class representing a CloudStack AffinityGroup. """ def __init__(self, id, account, description, domain, domainid, name, group_type, virtualmachine_ids): """ A CloudStack Affinity Group. @note: This is a non-standard extension API, and only works for CloudStack. :param id: CloudStack Affinity Group ID :type id: ``str`` :param account: An account for the affinity group. Must be used with domainId. :type account: ``str`` :param description: optional description of the affinity group :type description: ``str`` :param domain: the domain name of the affinity group :type domain: ``str`` :param domainid: domain ID of the account owning the affinity group :type domainid: ``str`` :param name: name of the affinity group :type name: ``str`` :param group_type: the type of the affinity group :type group_type: :class:`CloudStackAffinityGroupType` :param virtualmachine_ids: virtual machine Ids associated with this affinity group :type virtualmachine_ids: ``str`` :rtype: :class:`CloudStackAffinityGroup` """ self.id = id self.account = account self.description = description self.domain = domain self.domainid = domainid self.name = name self.type = group_type self.virtualmachine_ids = virtualmachine_ids def __repr__(self): return (('') % (self.id, self.name, self.type)) class CloudStackAffinityGroupType(object): """ Class representing a CloudStack AffinityGroupType. """ def __init__(self, type_name): """ A CloudStack Affinity Group Type. @note: This is a non-standard extension API, and only works for CloudStack. :param type_name: the type of the affinity group :type type_name: ``str`` :rtype: :class:`CloudStackAffinityGroupType` """ self.type = type_name def __repr__(self): return (('') % self.type) class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver): """ Driver for the CloudStack API. :cvar host: The host where the API can be reached. :cvar path: The path where the API can be reached. :cvar async_poll_frequency: How often (in seconds) to poll for async job completion. :type async_poll_frequency: ``int``""" name = 'CloudStack' api_name = 'cloudstack' website = 'http://cloudstack.org/' type = Provider.CLOUDSTACK features = {'create_node': ['generates_password']} NODE_STATE_MAP = { 'Running': NodeState.RUNNING, 'Starting': NodeState.REBOOTING, 'Migrating': NodeState.MIGRATING, 'Stopped': NodeState.STOPPED, 'Stopping': NodeState.PENDING, 'Destroyed': NodeState.TERMINATED, 'Expunging': NodeState.PENDING, 'Error': NodeState.TERMINATED } VOLUME_STATE_MAP = { 'Creating': StorageVolumeState.CREATING, 'Destroying': StorageVolumeState.DELETING, 'Expunging': StorageVolumeState.DELETING, 'Destroy': StorageVolumeState.DELETED, 'Expunged': StorageVolumeState.DELETED, 'Allocated': StorageVolumeState.AVAILABLE, 'Ready': StorageVolumeState.AVAILABLE, 'Snapshotting': StorageVolumeState.BACKUP, 'UploadError': StorageVolumeState.ERROR, 'Migrating': StorageVolumeState.MIGRATING } def __init__(self, key, secret=None, secure=True, host=None, path=None, port=None, url=None, *args, **kwargs): """ :inherits: :class:`NodeDriver.__init__` :param host: The host where the API can be reached. (required) :type host: ``str`` :param path: The path where the API can be reached. (required) :type path: ``str`` :param url: Full URL to the API endpoint. Mutually exclusive with host and path argument. :type url: ``str`` """ if url: parsed = urlparse.urlparse(url) path = parsed.path scheme = parsed.scheme split = parsed.netloc.split(':') if len(split) == 1: # No port provided, use the default one host = parsed.netloc port = 443 if scheme == 'https' else 80 else: host = split[0] port = int(split[1]) else: host = host if host else self.host path = path if path else self.path if path is not None: self.path = path if host is not None: self.host = host if (self.type == Provider.CLOUDSTACK) and (not host or not path): raise Exception('When instantiating CloudStack driver directly ' 'you also need to provide url or host and path ' 'argument') super(CloudStackNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port) def list_images(self, location=None): args = { 'templatefilter': 'executable' } if location is not None: args['zoneid'] = location.id imgs = self._sync_request(command='listTemplates', params=args, method='GET') images = [] for img in imgs.get('template', []): extra = {'hypervisor': img['hypervisor'], 'format': img['format'], 'os': img['ostypename'], 'displaytext': img['displaytext']} size = img.get('size', None) if size is not None: extra.update({'size': img['size']}) images.append(NodeImage( id=img['id'], name=img['name'], driver=self.connection.driver, extra=extra)) return images def list_locations(self): """ :rtype ``list`` of :class:`NodeLocation` """ locs = self._sync_request('listZones') locations = [] for loc in locs['zone']: location = NodeLocation(str(loc['id']), loc['name'], 'Unknown', self) locations.append(location) return locations def list_nodes(self, project=None, location=None): """ @inherits: :class:`NodeDriver.list_nodes` :keyword project: Limit nodes returned to those configured under the defined project. :type project: :class:`.CloudStackProject` :keyword location: Limit nodes returned to those in the defined location. :type location: :class:`.NodeLocation` :rtype: ``list`` of :class:`CloudStackNode` """ args = {} if project: args['projectid'] = project.id if location is not None: args['zoneid'] = location.id vms = self._sync_request('listVirtualMachines', params=args) addrs = self._sync_request('listPublicIpAddresses', params=args) port_forwarding_rules = self._sync_request('listPortForwardingRules') ip_forwarding_rules = self._sync_request('listIpForwardingRules') public_ips_map = {} for addr in addrs.get('publicipaddress', []): if 'virtualmachineid' not in addr: continue vm_id = str(addr['virtualmachineid']) if vm_id not in public_ips_map: public_ips_map[vm_id] = {} public_ips_map[vm_id][addr['ipaddress']] = addr['id'] nodes = [] for vm in vms.get('virtualmachine', []): public_ips = public_ips_map.get(str(vm['id']), {}).keys() public_ips = list(public_ips) node = self._to_node(data=vm, public_ips=public_ips) addresses = public_ips_map.get(str(vm['id']), {}).items() addresses = [CloudStackAddress(id=address_id, address=address, driver=node.driver) for address, address_id in addresses] node.extra['ip_addresses'] = addresses rules = [] for addr in addresses: for r in ip_forwarding_rules.get('ipforwardingrule', []): if str(r['virtualmachineid']) == node.id: rule = CloudStackIPForwardingRule(node, r['id'], addr, r['protocol'] .upper(), r['startport'], r['endport']) rules.append(rule) node.extra['ip_forwarding_rules'] = rules rules = [] for r in port_forwarding_rules.get('portforwardingrule', []): if str(r['virtualmachineid']) == node.id: addr = [CloudStackAddress(id=a['id'], address=a['ipaddress'], driver=node.driver) for a in addrs.get('publicipaddress', []) if a['ipaddress'] == r['ipaddress']] rule = CloudStackPortForwardingRule(node, r['id'], addr[0], r['protocol'].upper(), r['publicport'], r['privateport'], r['publicendport'], r['privateendport']) if not addr[0].address in node.public_ips: node.public_ips.append(addr[0].address) rules.append(rule) node.extra['port_forwarding_rules'] = rules nodes.append(node) return nodes def ex_get_node(self, node_id, project=None): """ Return a Node object based on its ID. :param node_id: The id of the node :type node_id: ``str`` :keyword project: Limit node returned to those configured under the defined project. :type project: :class:`.CloudStackProject` :rtype: :class:`CloudStackNode` """ list_nodes_args = {'id': node_id} list_ips_args = {} if project: list_nodes_args['projectid'] = project.id list_ips_args['projectid'] = project.id vms = self._sync_request('listVirtualMachines', params=list_nodes_args) if not vms: raise Exception("Node '%s' not found" % node_id) vm = vms['virtualmachine'][0] addrs = self._sync_request('listPublicIpAddresses', params=list_ips_args) public_ips = {} for addr in addrs.get('publicipaddress', []): if 'virtualmachineid' not in addr: continue public_ips[addr['ipaddress']] = addr['id'] node = self._to_node(data=vm, public_ips=list(public_ips.keys())) addresses = [CloudStackAddress(id=address_id, address=address, driver=node.driver) for address, address_id in public_ips.items()] node.extra['ip_addresses'] = addresses rules = [] list_fw_rules = {'virtualmachineid': node_id} for addr in addresses: result = self._sync_request('listIpForwardingRules', params=list_fw_rules) for r in result.get('ipforwardingrule', []): if str(r['virtualmachineid']) == node.id: rule = CloudStackIPForwardingRule(node, r['id'], addr, r['protocol'] .upper(), r['startport'], r['endport']) rules.append(rule) node.extra['ip_forwarding_rules'] = rules rules = [] public_ips = self.ex_list_public_ips() result = self._sync_request('listPortForwardingRules', params=list_fw_rules) for r in result.get('portforwardingrule', []): if str(r['virtualmachineid']) == node.id: addr = [a for a in public_ips if a.address == r['ipaddress']] rule = CloudStackPortForwardingRule(node, r['id'], addr[0], r['protocol'].upper(), r['publicport'], r['privateport'], r['publicendport'], r['privateendport']) if not addr[0].address in node.public_ips: node.public_ips.append(addr[0].address) rules.append(rule) node.extra['port_forwarding_rules'] = rules return node def list_sizes(self, location=None): """ :rtype ``list`` of :class:`NodeSize` """ szs = self._sync_request(command='listServiceOfferings', method='GET') sizes = [] for sz in szs['serviceoffering']: extra = {'cpu': sz['cpunumber']} sizes.append(NodeSize(sz['id'], sz['name'], sz['memory'], 0, 0, 0, self, extra=extra)) return sizes def create_node(self, name, size, image, location=None, networks=None, project=None, diskoffering=None, ex_keyname=None, ex_userdata=None, ex_security_groups=None, ex_displayname=None, ex_ip_address=None, ex_start_vm=False, ex_rootdisksize=None, ex_affinity_groups=None): """ Create a new node @inherits: :class:`NodeDriver.create_node` :keyword networks: Optional list of networks to launch the server into. :type networks: ``list`` of :class:`.CloudStackNetwork` :keyword project: Optional project to create the new node under. :type project: :class:`.CloudStackProject` :keyword diskoffering: Optional disk offering to add to the new node. :type diskoffering: :class:`.CloudStackDiskOffering` :keyword ex_keyname: Name of existing keypair :type ex_keyname: ``str`` :keyword ex_userdata: String containing user data :type ex_userdata: ``str`` :keyword ex_security_groups: List of security groups to assign to the node :type ex_security_groups: ``list`` of ``str`` :keyword ex_displayname: String containing instance display name :type ex_displayname: ``str`` :keyword ex_ip_address: String with ipaddress for the default nic :type ex_ip_address: ``str`` :keyword ex_start_vm: Boolean to specify to start VM after creation Default Cloudstack behaviour is to start a VM, if not specified. :type ex_start_vm: ``bool`` :keyword ex_rootdisksize: String with rootdisksize for the template :type ex_rootdisksize: ``str`` :keyword ex_affinity_groups: List of affinity groups to assign to the node :type ex_affinity_groups: ``list`` of :class:`.CloudStackAffinityGroup` :rtype: :class:`.CloudStackNode` """ server_params = self._create_args_to_params( node=None, name=name, size=size, image=image, location=location, networks=networks, diskoffering=diskoffering, ex_keyname=ex_keyname, ex_userdata=ex_userdata, ex_security_groups=ex_security_groups, ex_displayname=ex_displayname, ex_ip_address=ex_ip_address, ex_start_vm=ex_start_vm, ex_rootdisksize=ex_rootdisksize, ex_affinity_groups=ex_affinity_groups) data = self._async_request(command='deployVirtualMachine', params=server_params, method='GET')['virtualmachine'] node = self._to_node(data=data) return node def _create_args_to_params(self, node, name, size, image, location=None, networks=None, project=None, diskoffering=None, ex_keyname=None, ex_userdata=None, ex_security_groups=None, ex_displayname=None, ex_ip_address=None, ex_start_vm=False, ex_rootdisksize=None, ex_affinity_groups=None): server_params = {} if name: server_params['name'] = name if ex_displayname: server_params['displayname'] = ex_displayname if size: server_params['serviceofferingid'] = size.id if image: server_params['templateid'] = image.id if location: server_params['zoneid'] = location.id else: # Use a default location server_params['zoneid'] = self.list_locations()[0].id if networks: networks = ','.join([str(network.id) for network in networks]) server_params['networkids'] = networks if project: server_params['projectid'] = project.id if diskoffering: server_params['diskofferingid'] = diskoffering.id if ex_keyname: server_params['keypair'] = ex_keyname if ex_userdata: ex_userdata = base64.b64encode(b(ex_userdata)).decode('ascii') server_params['userdata'] = ex_userdata if ex_security_groups: ex_security_groups = ','.join(ex_security_groups) server_params['securitygroupnames'] = ex_security_groups if ex_ip_address: server_params['ipaddress'] = ex_ip_address if ex_rootdisksize: server_params['rootdisksize'] = ex_rootdisksize if ex_start_vm is not None: server_params['startvm'] = ex_start_vm if ex_affinity_groups: affinity_group_ids = ','.join(ag.id for ag in ex_affinity_groups) server_params['affinitygroupids'] = affinity_group_ids return server_params def destroy_node(self, node, ex_expunge=False): """ @inherits: :class:`NodeDriver.reboot_node` :type node: :class:`CloudStackNode` :keyword ex_expunge: If true is passed, the vm is expunged immediately. False by default. :type ex_expunge: ``bool`` :rtype: ``bool`` """ args = { 'id': node.id, } if ex_expunge: args['expunge'] = ex_expunge self._async_request(command='destroyVirtualMachine', params=args, method='GET') return True def reboot_node(self, node): """ @inherits: :class:`NodeDriver.reboot_node` :type node: :class:`CloudStackNode` :rtype: ``bool`` """ self._async_request(command='rebootVirtualMachine', params={'id': node.id}, method='GET') return True def ex_restore(self, node, template=None): """ Restore virtual machine :param node: Node to restore :type node: :class:`CloudStackNode` :param template: Optional new template :type template: :class:`NodeImage` :rtype ``str`` """ params = {'virtualmachineid': node.id} if template: params['templateid'] = template.id res = self._async_request(command='restoreVirtualMachine', params=params, method='GET') return res['virtualmachine']['templateid'] def ex_change_node_size(self, node, offering): """ Change offering/size of a virtual machine :param node: Node to change size :type node: :class:`CloudStackNode` :param offering: The new offering :type offering: :class:`NodeSize` :rtype ``str`` """ res = self._async_request(command='scaleVirtualMachine', params={ 'id': node.id, 'serviceofferingid': offering.id }, method='GET') return res['virtualmachine']['serviceofferingid'] def ex_start(self, node): """ Starts/Resumes a stopped virtual machine :type node: :class:`CloudStackNode` :param id: The ID of the virtual machine (required) :type id: ``str`` :param hostid: destination Host ID to deploy the VM to parameter available for root admin only :type hostid: ``str`` :rtype ``str`` """ res = self._async_request(command='startVirtualMachine', params={'id': node.id}, method='GET') return res['virtualmachine']['state'] def ex_stop(self, node): """ Stops/Suspends a running virtual machine :param node: Node to stop. :type node: :class:`CloudStackNode` :rtype: ``str`` """ res = self._async_request(command='stopVirtualMachine', params={'id': node.id}, method='GET') return res['virtualmachine']['state'] def ex_list_disk_offerings(self): """ Fetch a list of all available disk offerings. :rtype: ``list`` of :class:`CloudStackDiskOffering` """ diskOfferings = [] diskOfferResponse = self._sync_request(command='listDiskOfferings', method='GET') for diskOfferDict in diskOfferResponse.get('diskoffering', ()): diskOfferings.append( CloudStackDiskOffering( id=diskOfferDict['id'], name=diskOfferDict['name'], size=diskOfferDict['disksize'], customizable=diskOfferDict['iscustomized'])) return diskOfferings def ex_list_networks(self, project=None): """ List the available networks :param project: Optional project the networks belongs to. :type project: :class:`.CloudStackProject` :rtype ``list`` of :class:`CloudStackNetwork` """ args = {} if project is not None: args['projectid'] = project.id res = self._sync_request(command='listNetworks', params=args, method='GET') nets = res.get('network', []) networks = [] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['network'] for net in nets: extra = self._get_extra_dict(net, extra_map) if 'tags' in net: extra['tags'] = self._get_resource_tags(net['tags']) networks.append(CloudStackNetwork( net['displaytext'], net['name'], net['networkofferingid'], net['id'], net['zoneid'], self, extra=extra)) return networks def ex_list_network_offerings(self): """ List the available network offerings :rtype ``list`` of :class:`CloudStackNetworkOffering` """ res = self._sync_request(command='listNetworkOfferings', method='GET') netoffers = res.get('networkoffering', []) networkofferings = [] for netoffer in netoffers: networkofferings.append(CloudStackNetworkOffering( netoffer['name'], netoffer['displaytext'], netoffer['guestiptype'], netoffer['id'], netoffer['serviceofferingid'], netoffer['forvpc'], self)) return networkofferings def ex_create_network(self, display_text, name, network_offering, location, gateway=None, netmask=None, network_domain=None, vpc_id=None, project_id=None): """ Creates a Network, only available in advanced zones. :param display_text: the display text of the network :type display_text: ``str`` :param name: the name of the network :type name: ``str`` :param network_offering: NetworkOffering object :type network_offering: :class:'CloudStackNetworkOffering` :param location: Zone object :type location: :class:`NodeLocation` :param gateway: Optional, the Gateway of this network :type gateway: ``str`` :param netmask: Optional, the netmask of this network :type netmask: ``str`` :param network_domain: Optional, the DNS domain of the network :type network_domain: ``str`` :param vpc_id: Optional, the VPC id the network belongs to :type vpc_id: ``str`` :param project_id: Optional, the project id the networks belongs to :type project_id: ``str`` :rtype: :class:`CloudStackNetwork` """ extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['network'] args = { 'displaytext': display_text, 'name': name, 'networkofferingid': network_offering.id, 'zoneid': location.id, } if gateway is not None: args['gateway'] = gateway if netmask is not None: args['netmask'] = netmask if network_domain is not None: args['networkdomain'] = network_domain if vpc_id is not None: args['vpcid'] = vpc_id if project_id is not None: args['projectid'] = project_id """ Cloudstack allows for duplicate network names, this should be handled in the code leveraging libcloud As there could be use cases for duplicate names. e.g. management from ROOT level""" # for net in self.ex_list_networks(): # if name == net.name: # raise LibcloudError('This network name already exists') result = self._sync_request(command='createNetwork', params=args, method='GET') result = result['network'] extra = self._get_extra_dict(result, extra_map) network = CloudStackNetwork(display_text, name, network_offering.id, result['id'], location.id, self, extra=extra) return network def ex_delete_network(self, network, force=None): """ Deletes a Network, only available in advanced zones. :param network: The network :type network: :class: 'CloudStackNetwork' :param force: Force deletion of the network? :type force: ``bool`` :rtype: ``bool`` """ args = {'id': network.id, 'forced': force} self._async_request(command='deleteNetwork', params=args, method='GET') return True def ex_list_vpc_offerings(self): """ List the available vpc offerings :rtype ``list`` of :class:`CloudStackVPCOffering` """ res = self._sync_request(command='listVPCOfferings', method='GET') vpcoffers = res.get('vpcoffering', []) vpcofferings = [] for vpcoffer in vpcoffers: vpcofferings.append(CloudStackVPCOffering( vpcoffer['name'], vpcoffer['displaytext'], vpcoffer['id'], self)) return vpcofferings def ex_list_vpcs(self, project=None): """ List the available VPCs :keyword project: Optional project under which VPCs are present. :type project: :class:`.CloudStackProject` :rtype ``list`` of :class:`CloudStackVPC` """ args = {} if project is not None: args['projectid'] = project.id res = self._sync_request(command='listVPCs', params=args, method='GET') vpcs = res.get('vpc', []) networks = [] for vpc in vpcs: networks.append(CloudStackVPC( vpc['name'], vpc['vpcofferingid'], vpc['id'], vpc['cidr'], self, vpc['zoneid'], vpc['displaytext'])) return networks def ex_list_routers(self, vpc_id=None): """ List routers :rtype ``list`` of :class:`CloudStackRouter` """ args = {} if vpc_id is not None: args['vpcid'] = vpc_id res = self._sync_request(command='listRouters', params=args, method='GET') rts = res.get('router', []) routers = [] for router in rts: routers.append(CloudStackRouter( router['id'], router['name'], router['state'], router['publicip'], router['vpcid'], self)) return routers def ex_create_vpc(self, cidr, display_text, name, vpc_offering, zone_id, network_domain=None): """ Creates a VPC, only available in advanced zones. :param cidr: the cidr of the VPC. All VPC guest networks' cidrs should be within this CIDR :type display_text: ``str`` :param display_text: the display text of the VPC :type display_text: ``str`` :param name: the name of the VPC :type name: ``str`` :param vpc_offering: the ID of the VPC offering :type vpc_offering: :class:'CloudStackVPCOffering` :param zone_id: the ID of the availability zone :type zone_id: ``str`` :param network_domain: Optional, the DNS domain of the network :type network_domain: ``str`` :rtype: :class:`CloudStackVPC` """ extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpc'] args = { 'cidr': cidr, 'displaytext': display_text, 'name': name, 'vpcofferingid': vpc_offering.id, 'zoneid': zone_id, } if network_domain is not None: args['networkdomain'] = network_domain result = self._sync_request(command='createVPC', params=args, method='GET') extra = self._get_extra_dict(result, extra_map) vpc = CloudStackVPC(name, vpc_offering.id, result['id'], cidr, self, zone_id, display_text, extra=extra) return vpc def ex_delete_vpc(self, vpc): """ Deletes a VPC, only available in advanced zones. :param vpc: The VPC :type vpc: :class: 'CloudStackVPC' :rtype: ``bool`` """ args = {'id': vpc.id} self._async_request(command='deleteVPC', params=args, method='GET') return True def ex_list_projects(self): """ List the available projects :rtype ``list`` of :class:`CloudStackProject` """ res = self._sync_request(command='listProjects', method='GET') projs = res.get('project', []) projects = [] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['project'] for proj in projs: extra = self._get_extra_dict(proj, extra_map) if 'tags' in proj: extra['tags'] = self._get_resource_tags(proj['tags']) projects.append(CloudStackProject( id=proj['id'], name=proj['name'], display_text=proj['displaytext'], driver=self, extra=extra)) return projects def create_volume(self, size, name, location=None, snapshot=None, ex_volume_type=None): """ Creates a data volume Defaults to the first location """ if ex_volume_type is None: for diskOffering in self.ex_list_disk_offerings(): if diskOffering.size == size or diskOffering.customizable: break else: raise LibcloudError( 'Disk offering with size=%s not found' % size) else: for diskOffering in self.ex_list_disk_offerings(): if diskOffering.name == ex_volume_type: if not diskOffering.customizable: size = diskOffering.size break else: raise LibcloudError( 'Volume type with name=%s not found' % ex_volume_type) if location is None: location = self.list_locations()[0] params = {'name': name, 'diskOfferingId': diskOffering.id, 'zoneId': location.id} if diskOffering.customizable: params['size'] = size requestResult = self._async_request(command='createVolume', params=params, method='GET') volumeResponse = requestResult['volume'] state = self._to_volume_state(volumeResponse) return StorageVolume(id=volumeResponse['id'], name=name, size=size, state=state, driver=self, extra=dict(name=volumeResponse['name'])) def destroy_volume(self, volume): """ :rtype: ``bool`` """ self._sync_request(command='deleteVolume', params={'id': volume.id}, method='GET') return True def attach_volume(self, node, volume, device=None): """ @inherits: :class:`NodeDriver.attach_volume` :type node: :class:`CloudStackNode` :rtype: ``bool`` """ # TODO Add handling for device name self._async_request(command='attachVolume', params={'id': volume.id, 'virtualMachineId': node.id}, method='GET') return True def detach_volume(self, volume): """ :rtype: ``bool`` """ self._async_request(command='detachVolume', params={'id': volume.id}, method='GET') return True def list_volumes(self, node=None): """ List all volumes :param node: Only return volumes for the provided node. :type node: :class:`CloudStackNode` :rtype: ``list`` of :class:`StorageVolume` """ if node: volumes = self._sync_request(command='listVolumes', params={'virtualmachineid': node.id}, method='GET') else: volumes = self._sync_request(command='listVolumes', method='GET') list_volumes = [] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['volume'] for vol in volumes.get('volume', []): extra = self._get_extra_dict(vol, extra_map) if 'tags' in vol: extra['tags'] = self._get_resource_tags(vol['tags']) state = self._to_volume_state(vol) list_volumes.append(StorageVolume(id=vol['id'], name=vol['name'], size=vol['size'], state=state, driver=self, extra=extra)) return list_volumes def ex_get_volume(self, volume_id, project=None): """ Return a StorageVolume object based on its ID. :param volume_id: The id of the volume :type volume_id: ``str`` :keyword project: Limit volume returned to those configured under the defined project. :type project: :class:`.CloudStackProject` :rtype: :class:`CloudStackNode` """ args = {'id': volume_id} if project: args['projectid'] = project.id volumes = self._sync_request(command='listVolumes', params=args) if not volumes: raise Exception("Volume '%s' not found" % volume_id) vol = volumes['volume'][0] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['volume'] extra = self._get_extra_dict(vol, extra_map) if 'tags' in vol: extra['tags'] = self._get_resource_tags(vol['tags']) state = self._to_volume_state(vol) volume = StorageVolume(id=vol['id'], name=vol['name'], state=state, size=vol['size'], driver=self, extra=extra) return volume def list_key_pairs(self, **kwargs): """ List registered key pairs. :param projectid: list objects by project :type projectid: ``str`` :param page: The page to list the keypairs from :type page: ``int`` :param keyword: List by keyword :type keyword: ``str`` :param listall: If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false :type listall: ``bool`` :param pagesize: The number of results per page :type pagesize: ``int`` :param account: List resources by account. Must be used with the domainId parameter :type account: ``str`` :param isrecursive: Defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves. :type isrecursive: ``bool`` :param fingerprint: A public key fingerprint to look for :type fingerprint: ``str`` :param name: A key pair name to look for :type name: ``str`` :param domainid: List only resources belonging to the domain specified :type domainid: ``str`` :return: A list of key par objects. :rtype: ``list`` of :class:`libcloud.compute.base.KeyPair` """ extra_args = kwargs.copy() res = self._sync_request(command='listSSHKeyPairs', params=extra_args, method='GET') key_pairs = res.get('sshkeypair', []) key_pairs = self._to_key_pairs(data=key_pairs) return key_pairs def get_key_pair(self, name): """ Retrieve a single key pair. :param name: Name of the key pair to retrieve. :type name: ``str`` :rtype: :class:`.KeyPair` """ params = {'name': name} res = self._sync_request(command='listSSHKeyPairs', params=params, method='GET') key_pairs = res.get('sshkeypair', []) if len(key_pairs) == 0: raise KeyPairDoesNotExistError(name=name, driver=self) key_pair = self._to_key_pair(data=key_pairs[0]) return key_pair def create_key_pair(self, name, **kwargs): """ Create a new key pair object. :param name: Key pair name. :type name: ``str`` :param name: Name of the keypair (required) :type name: ``str`` :param projectid: An optional project for the ssh key :type projectid: ``str`` :param domainid: An optional domainId for the ssh key. If the account parameter is used, domainId must also be used. :type domainid: ``str`` :param account: An optional account for the ssh key. Must be used with domainId. :type account: ``str`` :return: Created key pair object. :rtype: :class:`libcloud.compute.base.KeyPair` """ extra_args = kwargs.copy() params = {'name': name} params.update(extra_args) res = self._sync_request(command='createSSHKeyPair', params=params, method='GET') key_pair = self._to_key_pair(data=res['keypair']) return key_pair def import_key_pair_from_string(self, name, key_material): """ Import a new public key from string. :param name: Key pair name. :type name: ``str`` :param key_material: Public key material. :type key_material: ``str`` :return: Imported key pair object. :rtype: :class:`libcloud.compute.base.KeyPair` """ res = self._sync_request(command='registerSSHKeyPair', params={'name': name, 'publickey': key_material}, method='GET') key_pair = self._to_key_pair(data=res['keypair']) return key_pair def delete_key_pair(self, key_pair, **kwargs): """ Delete an existing key pair. :param key_pair: Key pair object. :type key_pair: :class:`libcloud.compute.base.KeyPair` :param projectid: The project associated with keypair :type projectid: ``str`` :param domainid: The domain ID associated with the keypair :type domainid: ``str`` :param account: The account associated with the keypair. Must be used with the domainId parameter. :type account: ``str`` :return: True of False based on success of Keypair deletion :rtype: ``bool`` """ extra_args = kwargs.copy() params = {'name': key_pair.name} params.update(extra_args) res = self._sync_request(command='deleteSSHKeyPair', params=params, method='GET') return res['success'] == 'true' def ex_list_public_ips(self): """ Lists all Public IP Addresses. :rtype: ``list`` of :class:`CloudStackAddress` """ ips = [] res = self._sync_request(command='listPublicIpAddresses', method='GET') # Workaround for basic zones if not res: return ips for ip in res['publicipaddress']: ips.append(CloudStackAddress(ip['id'], ip['ipaddress'], self, ip.get('associatednetworkid', []), ip.get('vpcid'), ip.get('virtualmachineid'))) return ips def ex_allocate_public_ip(self, vpc_id=None, network_id=None, location=None): """ Allocate a public IP. :param vpc_id: VPC the ip belongs to :type vpc_id: ``str`` :param network_id: Network where this IP is connected to. :type network_id: ''str'' :param location: Zone :type location: :class:`NodeLocation` :rtype: :class:`CloudStackAddress` """ args = {} if location is not None: args['zoneid'] = location.id else: args['zoneid'] = self.list_locations()[0].id if vpc_id is not None: args['vpcid'] = vpc_id if network_id is not None: args['networkid'] = network_id addr = self._async_request(command='associateIpAddress', params=args, method='GET') addr = addr['ipaddress'] addr = CloudStackAddress(addr['id'], addr['ipaddress'], self) return addr def ex_release_public_ip(self, address): """ Release a public IP. :param address: CloudStackAddress which should be used :type address: :class:`CloudStackAddress` :rtype: ``bool`` """ res = self._async_request(command='disassociateIpAddress', params={'id': address.id}, method='GET') return res['success'] def ex_list_firewall_rules(self): """ Lists all Firewall Rules :rtype: ``list`` of :class:`CloudStackFirewallRule` """ rules = [] result = self._sync_request(command='listFirewallRules', method='GET') if result != {}: public_ips = self.ex_list_public_ips() for rule in result['firewallrule']: addr = [a for a in public_ips if a.address == rule['ipaddress']] rules.append(CloudStackFirewallRule(rule['id'], addr[0], rule['cidrlist'], rule['protocol'], rule.get('icmpcode'), rule.get('icmptype'), rule.get('startport'), rule.get('endport'))) return rules def ex_create_firewall_rule(self, address, cidr_list, protocol, icmp_code=None, icmp_type=None, start_port=None, end_port=None): """ Creates a Firewall Rule :param address: External IP address :type address: :class:`CloudStackAddress` :param cidr_list: cidr list :type cidr_list: ``str`` :param protocol: TCP/IP Protocol (TCP, UDP) :type protocol: ``str`` :param icmp_code: Error code for this icmp message :type icmp_code: ``int`` :param icmp_type: Type of the icmp message being sent :type icmp_type: ``int`` :param start_port: start of port range :type start_port: ``int`` :param end_port: end of port range :type end_port: ``int`` :rtype: :class:`CloudStackFirewallRule` """ args = { 'ipaddressid': address.id, 'cidrlist': cidr_list, 'protocol': protocol } if icmp_code is not None: args['icmpcode'] = int(icmp_code) if icmp_type is not None: args['icmptype'] = int(icmp_type) if start_port is not None: args['startport'] = int(start_port) if end_port is not None: args['endport'] = int(end_port) result = self._async_request(command='createFirewallRule', params=args, method='GET') rule = CloudStackFirewallRule(result['firewallrule']['id'], address, cidr_list, protocol, icmp_code, icmp_type, start_port, end_port) return rule def ex_delete_firewall_rule(self, firewall_rule): """ Remove a Firewall Rule. :param firewall_rule: Firewall rule which should be used :type firewall_rule: :class:`CloudStackFirewallRule` :rtype: ``bool`` """ res = self._async_request(command='deleteFirewallRule', params={'id': firewall_rule.id}, method='GET') return res['success'] def ex_list_egress_firewall_rules(self): """ Lists all egress Firewall Rules :rtype: ``list`` of :class:`CloudStackEgressFirewallRule` """ rules = [] result = self._sync_request(command='listEgressFirewallRules', method='GET') for rule in result['firewallrule']: rules.append(CloudStackEgressFirewallRule(rule['id'], rule['networkid'], rule['cidrlist'], rule['protocol'], rule.get('icmpcode'), rule.get('icmptype'), rule.get('startport'), rule.get('endport'))) return rules def ex_create_egress_firewall_rule(self, network_id, cidr_list, protocol, icmp_code=None, icmp_type=None, start_port=None, end_port=None): """ Creates a Firewall Rule :param network_id: the id network network for the egress firewall services :type network_id: ``str`` :param cidr_list: cidr list :type cidr_list: ``str`` :param protocol: TCP/IP Protocol (TCP, UDP) :type protocol: ``str`` :param icmp_code: Error code for this icmp message :type icmp_code: ``int`` :param icmp_type: Type of the icmp message being sent :type icmp_type: ``int`` :param start_port: start of port range :type start_port: ``int`` :param end_port: end of port range :type end_port: ``int`` :rtype: :class:`CloudStackEgressFirewallRule` """ args = { 'networkid': network_id, 'cidrlist': cidr_list, 'protocol': protocol } if icmp_code is not None: args['icmpcode'] = int(icmp_code) if icmp_type is not None: args['icmptype'] = int(icmp_type) if start_port is not None: args['startport'] = int(start_port) if end_port is not None: args['endport'] = int(end_port) result = self._async_request(command='createEgressFirewallRule', params=args, method='GET') rule = CloudStackEgressFirewallRule(result['firewallrule']['id'], network_id, cidr_list, protocol, icmp_code, icmp_type, start_port, end_port) return rule def ex_delete_egress_firewall_rule(self, firewall_rule): """ Remove a Firewall rule. :param egress_firewall_rule: Firewall rule which should be used :type egress_firewall_rule: :class:`CloudStackEgressFirewallRule` :rtype: ``bool`` """ res = self._async_request(command='deleteEgressFirewallRule', params={'id': firewall_rule.id}, method='GET') return res['success'] def ex_list_port_forwarding_rules(self, account=None, domain_id=None, id=None, ipaddress_id=None, is_recursive=None, keyword=None, list_all=None, network_id=None, page=None, page_size=None, project_id=None): """ Lists all Port Forwarding Rules :param account: List resources by account. Must be used with the domainId parameter :type account: ``str`` :param domain_id: List only resources belonging to the domain specified :type domain_id: ``str`` :param for_display: List resources by display flag (only root admin is eligible to pass this parameter). :type for_display: ``bool`` :param id: Lists rule with the specified ID :type id: ``str`` :param ipaddress_id: list the rule belonging to this public ip address :type ipaddress_id: ``str`` :param is_recursive: Defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves. :type is_recursive: ``bool`` :param keyword: List by keyword :type keyword: ``str`` :param list_all: If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false :type list_all: ``bool`` :param network_id: list port forwarding rules for certain network :type network_id: ``string`` :param page: The page to list the keypairs from :type page: ``int`` :param page_size: The number of results per page :type page_size: ``int`` :param project_id: list objects by project :type project_id: ``str`` :rtype: ``list`` of :class:`CloudStackPortForwardingRule` """ args = {} if account is not None: args['account'] = account if domain_id is not None: args['domainid'] = domain_id if id is not None: args['id'] = id if ipaddress_id is not None: args['ipaddressid'] = ipaddress_id if is_recursive is not None: args['isrecursive'] = is_recursive if keyword is not None: args['keyword'] = keyword if list_all is not None: args['listall'] = list_all if network_id is not None: args['networkid'] = network_id if page is not None: args['page'] = page if page_size is not None: args['pagesize'] = page_size if project_id is not None: args['projectid'] = project_id rules = [] result = self._sync_request(command='listPortForwardingRules', params=args, method='GET') if result != {}: public_ips = self.ex_list_public_ips() nodes = self.list_nodes() for rule in result['portforwardingrule']: node = [n for n in nodes if n.id == str(rule['virtualmachineid'])] addr = [a for a in public_ips if a.address == rule['ipaddress']] rules.append(CloudStackPortForwardingRule (node[0], rule['id'], addr[0], rule['protocol'], rule['publicport'], rule['privateport'], rule['publicendport'], rule['privateendport'])) return rules def ex_create_port_forwarding_rule(self, node, address, private_port, public_port, protocol, public_end_port=None, private_end_port=None, openfirewall=True, network_id=None): """ Creates a Port Forwarding Rule, used for Source NAT :param address: IP address of the Source NAT :type address: :class:`CloudStackAddress` :param private_port: Port of the virtual machine :type private_port: ``int`` :param protocol: Protocol of the rule :type protocol: ``str`` :param public_port: Public port on the Source NAT address :type public_port: ``int`` :param node: The virtual machine :type node: :class:`CloudStackNode` :param network_id: The network of the vm the Port Forwarding rule will be created for. Required when public Ip address is not associated with any Guest network yet (VPC case) :type network_id: ``string`` :rtype: :class:`CloudStackPortForwardingRule` """ args = { 'ipaddressid': address.id, 'protocol': protocol, 'privateport': int(private_port), 'publicport': int(public_port), 'virtualmachineid': node.id, 'openfirewall': openfirewall } if public_end_port: args['publicendport'] = int(public_end_port) if private_end_port: args['privateendport'] = int(private_end_port) if network_id: args['networkid'] = network_id result = self._async_request(command='createPortForwardingRule', params=args, method='GET') rule = CloudStackPortForwardingRule(node, result['portforwardingrule'] ['id'], address, protocol, public_port, private_port, public_end_port, private_end_port, network_id) node.extra['port_forwarding_rules'].append(rule) node.public_ips.append(address.address) return rule def ex_delete_port_forwarding_rule(self, node, rule): """ Remove a Port forwarding rule. :param node: Node used in the rule :type node: :class:`CloudStackNode` :param rule: Forwarding rule which should be used :type rule: :class:`CloudStackPortForwardingRule` :rtype: ``bool`` """ node.extra['port_forwarding_rules'].remove(rule) node.public_ips.remove(rule.address.address) res = self._async_request(command='deletePortForwardingRule', params={'id': rule.id}, method='GET') return res['success'] def ex_list_ip_forwarding_rules(self, account=None, domain_id=None, id=None, ipaddress_id=None, is_recursive=None, keyword=None, list_all=None, page=None, page_size=None, project_id=None, virtualmachine_id=None): """ Lists all NAT/firewall forwarding rules :param account: List resources by account. Must be used with the domainId parameter :type account: ``str`` :param domain_id: List only resources belonging to the domain specified :type domain_id: ``str`` :param id: Lists rule with the specified ID :type id: ``str`` :param ipaddress_id: list the rule belonging to this public ip address :type ipaddress_id: ``str`` :param is_recursive: Defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves. :type is_recursive: ``bool`` :param keyword: List by keyword :type keyword: ``str`` :param list_all: If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false :type list_all: ``bool`` :param page: The page to list the keypairs from :type page: ``int`` :param page_size: The number of results per page :type page_size: ``int`` :param project_id: list objects by project :type project_id: ``str`` :param virtualmachine_id: Lists all rules applied to the specified Vm :type virtualmachine_id: ``str`` :rtype: ``list`` of :class:`CloudStackIPForwardingRule` """ args = {} if account is not None: args['account'] = account if domain_id is not None: args['domainid'] = domain_id if id is not None: args['id'] = id if ipaddress_id is not None: args['ipaddressid'] = ipaddress_id if is_recursive is not None: args['isrecursive'] = is_recursive if keyword is not None: args['keyword'] = keyword if list_all is not None: args['listall'] = list_all if page is not None: args['page'] = page if page_size is not None: args['pagesize'] = page_size if project_id is not None: args['projectid'] = project_id if virtualmachine_id is not None: args['virtualmachineid'] = virtualmachine_id result = self._sync_request(command='listIpForwardingRules', params=args, method='GET') rules = [] if result != {}: public_ips = self.ex_list_public_ips() nodes = self.list_nodes() for rule in result['ipforwardingrule']: node = [n for n in nodes if n.id == str(rule['virtualmachineid'])] addr = [a for a in public_ips if a.address == rule['ipaddress']] rules.append(CloudStackIPForwardingRule (node[0], rule['id'], addr[0], rule['protocol'], rule['startport'], rule['endport'])) return rules def ex_create_ip_forwarding_rule(self, node, address, protocol, start_port, end_port=None): """ "Add a NAT/firewall forwarding rule. :param node: Node which should be used :type node: :class:`CloudStackNode` :param address: CloudStackAddress which should be used :type address: :class:`CloudStackAddress` :param protocol: Protocol which should be used (TCP or UDP) :type protocol: ``str`` :param start_port: Start port which should be used :type start_port: ``int`` :param end_port: End port which should be used :type end_port: ``int`` :rtype: :class:`CloudStackForwardingRule` """ protocol = protocol.upper() if protocol not in ('TCP', 'UDP'): return None args = { 'ipaddressid': address.id, 'protocol': protocol, 'startport': int(start_port) } if end_port is not None: args['endport'] = int(end_port) result = self._async_request(command='createIpForwardingRule', params=args, method='GET') result = result['ipforwardingrule'] rule = CloudStackIPForwardingRule(node, result['id'], address, protocol, start_port, end_port) node.extra['ip_forwarding_rules'].append(rule) return rule def ex_delete_ip_forwarding_rule(self, node, rule): """ Remove a NAT/firewall forwarding rule. :param node: Node which should be used :type node: :class:`CloudStackNode` :param rule: Forwarding rule which should be used :type rule: :class:`CloudStackForwardingRule` :rtype: ``bool`` """ node.extra['ip_forwarding_rules'].remove(rule) self._async_request(command='deleteIpForwardingRule', params={'id': rule.id}, method='GET') return True def ex_create_network_acllist(self, name, vpc_id, description=None): """ Create an ACL List for a network within a VPC. :param name: Name of the network ACL List :type name: ``string`` :param vpc_id: Id of the VPC associated with this network ACL List :type vpc_id: ``string`` :param description: Description of the network ACL List :type description: ``string`` :rtype: :class:`CloudStackNetworkACLList` """ args = { 'name': name, 'vpcid': vpc_id } if description: args['description'] = description result = self._sync_request(command='createNetworkACLList', params=args, method='GET') acl_list = CloudStackNetworkACLList(result['id'], name, vpc_id, self, description) return acl_list def ex_create_network_acl(self, protocol, acl_id, cidr_list, start_port, end_port, action=None, traffic_type=None): """ Creates an ACL rule in the given network (the network has to belong to VPC) :param protocol: the protocol for the ACL rule. Valid values are TCP/UDP/ICMP/ALL or valid protocol number :type protocol: ``string`` :param acl_id: Name of the network ACL List :type acl_id: ``str`` :param cidr_list: the cidr list to allow traffic from/to :type cidr_list: ``str`` :param start_port: the starting port of ACL :type start_port: ``str`` :param end_port: the ending port of ACL :type end_port: ``str`` :param action: scl entry action, allow or deny :type action: ``str`` :param traffic_type: the traffic type for the ACL,can be Ingress or Egress, defaulted to Ingress if not specified :type traffic_type: ``str`` :rtype: :class:`CloudStackNetworkACL` """ args = { 'protocol': protocol, 'aclid': acl_id, 'cidrlist': cidr_list, 'startport': start_port, 'endport': end_port } if action: args['action'] = action else: action = "allow" if traffic_type: args['traffictype'] = traffic_type result = self._async_request(command='createNetworkACL', params=args, method='GET') acl = CloudStackNetworkACL(result['networkacl']['id'], protocol, acl_id, action, cidr_list, start_port, end_port, traffic_type) return acl def ex_list_network_acllists(self): """ Lists all network ACLs :rtype: ``list`` of :class:`CloudStackNetworkACLList` """ acllists = [] result = self._sync_request(command='listNetworkACLLists', method='GET') if not result: return acllists for acllist in result['networkacllist']: acllists.append(CloudStackNetworkACLList(acllist['id'], acllist['name'], acllist.get('vpcid', []), self, acllist['description'])) return acllists def ex_replace_network_acllist(self, acl_id, network_id): """ Create an ACL List for a network within a VPC.Replaces ACL associated with a Network or private gateway :param acl_id: the ID of the network ACL :type acl_id: ``string`` :param network_id: the ID of the network :type network_id: ``string`` :rtype: :class:`CloudStackNetworkACLList` """ args = { 'aclid': acl_id, 'networkid': network_id } self._async_request(command='replaceNetworkACLList', params=args, method='GET') return True def ex_list_network_acl(self): """ Lists all network ACL items :rtype: ``list`` of :class:`CloudStackNetworkACL` """ acls = [] result = self._sync_request(command='listNetworkACLs', method='GET') if not result: return acls for acl in result['networkacl']: acls.append(CloudStackNetworkACL(acl['id'], acl['protocol'], acl['aclid'], acl['action'], acl['cidrlist'], acl.get('startport', []), acl.get('endport', []), acl['traffictype'])) return acls def ex_list_keypairs(self, **kwargs): """ List Registered SSH Key Pairs :param projectid: list objects by project :type projectid: ``str`` :param page: The page to list the keypairs from :type page: ``int`` :param keyword: List by keyword :type keyword: ``str`` :param listall: If set to false, list only resources belonging to the command's caller; if set to true - list resources that the caller is authorized to see. Default value is false :type listall: ``bool`` :param pagesize: The number of results per page :type pagesize: ``int`` :param account: List resources by account. Must be used with the domainId parameter :type account: ``str`` :param isrecursive: Defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves. :type isrecursive: ``bool`` :param fingerprint: A public key fingerprint to look for :type fingerprint: ``str`` :param name: A key pair name to look for :type name: ``str`` :param domainid: List only resources belonging to the domain specified :type domainid: ``str`` :return: A list of keypair dictionaries :rtype: ``list`` of ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'list_key_pairs method') key_pairs = self.list_key_pairs(**kwargs) result = [] for key_pair in key_pairs: item = { 'name': key_pair.name, 'fingerprint': key_pair.fingerprint, 'privateKey': key_pair.private_key } result.append(item) return result def ex_create_keypair(self, name, **kwargs): """ Creates a SSH KeyPair, returns fingerprint and private key :param name: Name of the keypair (required) :type name: ``str`` :param projectid: An optional project for the ssh key :type projectid: ``str`` :param domainid: An optional domainId for the ssh key. If the account parameter is used, domainId must also be used. :type domainid: ``str`` :param account: An optional account for the ssh key. Must be used with domainId. :type account: ``str`` :return: A keypair dictionary :rtype: ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'create_key_pair method') key_pair = self.create_key_pair(name=name, **kwargs) result = { 'name': key_pair.name, 'fingerprint': key_pair.fingerprint, 'privateKey': key_pair.private_key } return result def ex_import_keypair_from_string(self, name, key_material): """ Imports a new public key where the public key is passed in as a string :param name: The name of the public key to import. :type name: ``str`` :param key_material: The contents of a public key file. :type key_material: ``str`` :rtype: ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'import_key_pair_from_string method') key_pair = self.import_key_pair_from_string(name=name, key_material=key_material) result = { 'keyName': key_pair.name, 'keyFingerprint': key_pair.fingerprint } return result def ex_import_keypair(self, name, keyfile): """ Imports a new public key where the public key is passed via a filename :param name: The name of the public key to import. :type name: ``str`` :param keyfile: The filename with path of the public key to import. :type keyfile: ``str`` :rtype: ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'import_key_pair_from_file method') key_pair = self.import_key_pair_from_file(name=name, key_file_path=keyfile) result = { 'keyName': key_pair.name, 'keyFingerprint': key_pair.fingerprint } return result def ex_delete_keypair(self, keypair, **kwargs): """ Deletes an existing SSH KeyPair :param keypair: Name of the keypair (required) :type keypair: ``str`` :param projectid: The project associated with keypair :type projectid: ``str`` :param domainid: The domain ID associated with the keypair :type domainid: ``str`` :param account: The account associated with the keypair. Must be used with the domainId parameter. :type account: ``str`` :return: True of False based on success of Keypair deletion :rtype: ``bool`` """ warnings.warn('This method has been deprecated in favor of ' 'delete_key_pair method') key_pair = KeyPair(name=keypair, public_key=None, fingerprint=None, driver=self) return self.delete_key_pair(key_pair=key_pair) def ex_list_security_groups(self, **kwargs): """ Lists Security Groups :param domainid: List only resources belonging to the domain specified :type domainid: ``str`` :param account: List resources by account. Must be used with the domainId parameter. :type account: ``str`` :param listall: If set to false, list only resources belonging to the command's caller; if set to true list resources that the caller is authorized to see. Default value is false :type listall: ``bool`` :param pagesize: Number of entries per page :type pagesize: ``int`` :param keyword: List by keyword :type keyword: ``str`` :param tags: List resources by tags (key/value pairs) :type tags: ``dict`` :param id: list the security group by the id provided :type id: ``str`` :param securitygroupname: lists security groups by name :type securitygroupname: ``str`` :param virtualmachineid: lists security groups by virtual machine id :type virtualmachineid: ``str`` :param projectid: list objects by project :type projectid: ``str`` :param isrecursive: (boolean) defaults to false, but if true, lists all resources from the parent specified by the domainId till leaves. :type isrecursive: ``bool`` :param page: (integer) :type page: ``int`` :rtype ``list`` """ extra_args = kwargs.copy() res = self._sync_request(command='listSecurityGroups', params=extra_args, method='GET') security_groups = res.get('securitygroup', []) return security_groups def ex_create_security_group(self, name, **kwargs): """ Creates a new Security Group :param name: name of the security group (required) :type name: ``str`` :param account: An optional account for the security group. Must be used with domainId. :type account: ``str`` :param domainid: An optional domainId for the security group. If the account parameter is used, domainId must also be used. :type domainid: ``str`` :param description: The description of the security group :type description: ``str`` :param projectid: Deploy vm for the project :type projectid: ``str`` :rtype: ``dict`` """ extra_args = kwargs.copy() for sg in self.ex_list_security_groups(): if name in sg['name']: raise LibcloudError('This Security Group name already exists') params = {'name': name} params.update(extra_args) return self._sync_request(command='createSecurityGroup', params=params, method='GET')['securitygroup'] def ex_delete_security_group(self, name): """ Deletes a given Security Group :param domainid: The domain ID of account owning the security group :type domainid: ``str`` :param id: The ID of the security group. Mutually exclusive with name parameter :type id: ``str`` :param name: The ID of the security group. Mutually exclusive with id parameter :type name: ``str`` :param account: The account of the security group. Must be specified with domain ID :type account: ``str`` :param projectid: The project of the security group :type projectid: ``str`` :rtype: ``bool`` """ return self._sync_request(command='deleteSecurityGroup', params={'name': name}, method='GET')['success'] def ex_authorize_security_group_ingress(self, securitygroupname, protocol, cidrlist, startport=None, endport=None, icmptype=None, icmpcode=None, **kwargs): """ Creates a new Security Group Ingress rule :param securitygroupname: The name of the security group. Mutually exclusive with securitygroupid. :type securitygroupname: ``str`` :param protocol: Can be TCP, UDP or ICMP. Sometime other protocols can be used like AH, ESP or GRE. :type protocol: ``str`` :param cidrlist: Source address CIDR for which this rule applies. :type cidrlist: ``str`` :param startport: Start port of the range for this ingress rule. Applies to protocols TCP and UDP. :type startport: ``int`` :param endport: End port of the range for this ingress rule. It can be None to set only one port. Applies to protocols TCP and UDP. :type endport: ``int`` :param icmptype: Type of the ICMP packet (eg: 8 for Echo Request). -1 or None means "all types". Applies to protocol ICMP. :type icmptype: ``int`` :param icmpcode: Code of the ICMP packet for the specified type. If the specified type doesn't require a code set this value to 0. -1 or None means "all codes". Applies to protocol ICMP. :type icmpcode: ``int`` :keyword account: An optional account for the security group. Must be used with domainId. :type account: ``str`` :keyword domainid: An optional domainId for the security group. If the account parameter is used, domainId must also be used. :keyword projectid: An optional project of the security group :type projectid: ``str`` :keyword securitygroupid: The ID of the security group. Mutually exclusive with securitygroupname :type securitygroupid: ``str`` :keyword usersecuritygrouplist: User to security group mapping :type usersecuritygrouplist: ``dict`` :rtype: ``dict`` """ args = kwargs.copy() protocol = protocol.upper() args.update({ 'securitygroupname': securitygroupname, 'protocol': protocol, 'cidrlist': cidrlist }) if protocol not in ('TCP', 'UDP') and \ (startport is not None or endport is not None): raise LibcloudError('"startport" and "endport" are only valid ' 'with protocol TCP or UDP.') if protocol != 'ICMP' and \ (icmptype is not None or icmpcode is not None): raise LibcloudError('"icmptype" and "icmpcode" are only valid ' 'with protocol ICMP.') if protocol in ('TCP', 'UDP'): if startport is None: raise LibcloudError('Protocols TCP and UDP require at least ' '"startport" to be set.') if startport is not None and endport is None: endport = startport args.update({ 'startport': startport, 'endport': endport }) if protocol == 'ICMP': if icmptype is None: icmptype = -1 if icmpcode is None: icmpcode = -1 args.update({ 'icmptype': icmptype, 'icmpcode': icmpcode }) return self._async_request(command='authorizeSecurityGroupIngress', params=args, method='GET')['securitygroup'] def ex_revoke_security_group_ingress(self, rule_id): """ Revoke/delete an ingress security rule :param id: The ID of the ingress security rule :type id: ``str`` :rtype: ``bool`` """ self._async_request(command='revokeSecurityGroupIngress', params={'id': rule_id}, method='GET') return True def ex_create_affinity_group(self, name, group_type): """ Creates a new Affinity Group :param name: Name of the affinity group :type name: ``str`` :param group_type: Type of the affinity group from the available affinity/anti-affinity group types :type group_type: :class:`CloudStackAffinityGroupType` :param description: Optional description of the affinity group :type description: ``str`` :param domainid: domain ID of the account owning the affinity group :type domainid: ``str`` :rtype: :class:`CloudStackAffinityGroup` """ for ag in self.ex_list_affinity_groups(): if name == ag.name: raise LibcloudError('This Affinity Group name already exists') params = {'name': name, 'type': group_type.type} result = self._async_request(command='createAffinityGroup', params=params, method='GET') return self._to_affinity_group(result['affinitygroup']) def ex_delete_affinity_group(self, affinity_group): """ Delete an Affinity Group :param affinity_group: Instance of affinity group :type affinity_group: :class:`CloudStackAffinityGroup` :rtype ``bool`` """ return self._async_request(command='deleteAffinityGroup', params={'id': affinity_group.id}, method='GET')['success'] def ex_update_node_affinity_group(self, node, affinity_group_list): """ Updates the affinity/anti-affinity group associations of a virtual machine. The VM has to be stopped and restarted for the new properties to take effect. :param node: Node to update. :type node: :class:`CloudStackNode` :param affinity_group_list: List of CloudStackAffinityGroup to associate :type affinity_group_list: ``list`` of :class:`CloudStackAffinityGroup` :rtype :class:`CloudStackNode` """ affinity_groups = ','.join(ag.id for ag in affinity_group_list) result = self._async_request(command='updateVMAffinityGroup', params={ 'id': node.id, 'affinitygroupids': affinity_groups}, method='GET') return self._to_node(data=result['virtualmachine']) def ex_list_affinity_groups(self): """ List Affinity Groups :rtype ``list`` of :class:`CloudStackAffinityGroup` """ result = self._sync_request(command='listAffinityGroups', method='GET') if not result.get('count'): return [] affinity_groups = [] for ag in result['affinitygroup']: affinity_groups.append(self._to_affinity_group(ag)) return affinity_groups def ex_list_affinity_group_types(self): """ List Affinity Group Types :rtype ``list`` of :class:`CloudStackAffinityGroupTypes` """ result = self._sync_request(command='listAffinityGroupTypes', method='GET') if not result.get('count'): return [] affinity_group_types = [] for agt in result['affinityGroupType']: affinity_group_types.append( CloudStackAffinityGroupType(agt['type'])) return affinity_group_types def ex_register_iso(self, name, url, location=None, **kwargs): """ Registers an existing ISO by URL. :param name: Name which should be used :type name: ``str`` :param url: Url should be used :type url: ``str`` :param location: Location which should be used :type location: :class:`NodeLocation` :rtype: ``str`` """ if location is None: location = self.list_locations()[0] params = {'name': name, 'displaytext': name, 'url': url, 'zoneid': location.id} params['bootable'] = kwargs.pop('bootable', False) if params['bootable']: os_type_id = kwargs.pop('ostypeid', None) if not os_type_id: raise LibcloudError('If bootable=True, ostypeid is required!') params['ostypeid'] = os_type_id return self._sync_request(command='registerIso', params=params) def ex_limits(self): """ Extra call to get account's resource limits, such as the amount of instances, volumes, snapshots and networks. CloudStack uses integers as the resource type so we will convert them to a more human readable string using the resource map A list of the resource type mappings can be found at http://goo.gl/17C6Gk :return: dict :rtype: ``dict`` """ result = self._sync_request(command='listResourceLimits', method='GET') limits = {} resource_map = { 0: 'max_instances', 1: 'max_public_ips', 2: 'max_volumes', 3: 'max_snapshots', 4: 'max_images', 5: 'max_projects', 6: 'max_networks', 7: 'max_vpc', 8: 'max_cpu', 9: 'max_memory', 10: 'max_primary_storage', 11: 'max_secondary_storage' } for limit in result.get('resourcelimit', []): # We will ignore unknown types resource = resource_map.get(int(limit['resourcetype']), None) if not resource: continue limits[resource] = int(limit['max']) return limits def ex_create_tags(self, resource_ids, resource_type, tags): """ Create tags for a resource (Node/StorageVolume/etc). A list of resource types can be found at http://goo.gl/6OKphH :param resource_ids: Resource IDs to be tagged. The resource IDs must all be associated with the resource_type. For example, for virtual machines (UserVm) you can only specify a list of virtual machine IDs. :type resource_ids: ``list`` of resource IDs :param resource_type: Resource type (eg: UserVm) :type resource_type: ``str`` :param tags: A dictionary or other mapping of strings to strings, associating tag names with tag values. :type tags: ``dict`` :rtype: ``bool`` """ params = {'resourcetype': resource_type, 'resourceids': ','.join(resource_ids)} for i, key in enumerate(tags): params['tags[%d].key' % i] = key params['tags[%d].value' % i] = tags[key] self._async_request(command='createTags', params=params, method='GET') return True def ex_delete_tags(self, resource_ids, resource_type, tag_keys): """ Delete tags from a resource. :param resource_ids: Resource IDs to be tagged. The resource IDs must all be associated with the resource_type. For example, for virtual machines (UserVm) you can only specify a list of virtual machine IDs. :type resource_ids: ``list`` of resource IDs :param resource_type: Resource type (eg: UserVm) :type resource_type: ``str`` :param tag_keys: A list of keys to delete. CloudStack only requires the keys from the key/value pair. :type tag_keys: ``list`` :rtype: ``bool`` """ params = {'resourcetype': resource_type, 'resourceids': ','.join(resource_ids)} for i, key in enumerate(tag_keys): params['tags[%s].key' % i] = key self._async_request(command='deleteTags', params=params, method='GET') return True def list_snapshots(self): """ Describe all snapshots. :rtype: ``list`` of :class:`VolumeSnapshot` """ snapshots = self._sync_request('listSnapshots', method='GET') list_snapshots = [] for snap in snapshots['snapshot']: list_snapshots.append(self._to_snapshot(snap)) return list_snapshots def create_volume_snapshot(self, volume, name=None): """ Create snapshot from volume :param volume: Instance of ``StorageVolume`` :type volume: ``StorageVolume`` :param name: The name of the snapshot is disregarded by CloudStack drivers :type name: `str` :rtype: :class:`VolumeSnapshot` """ snapshot = self._async_request(command='createSnapshot', params={'volumeid': volume.id}, method='GET') return self._to_snapshot(snapshot['snapshot']) def destroy_volume_snapshot(self, snapshot): self._async_request(command='deleteSnapshot', params={'id': snapshot.id}, method='GET') return True def ex_create_snapshot_template(self, snapshot, name, ostypeid, displaytext=None): """ Create a template from a snapshot :param snapshot: Instance of ``VolumeSnapshot`` :type volume: ``VolumeSnapshot`` :param name: the name of the template :type name: ``str`` :param name: the os type id :type name: ``str`` :param name: the display name of the template :type name: ``str`` :rtype: :class:`NodeImage` """ if not displaytext: displaytext = name resp = self._async_request(command='createTemplate', params={ 'displaytext': displaytext, 'name': name, 'ostypeid': ostypeid, 'snapshotid': snapshot.id}) img = resp.get('template') extra = { 'hypervisor': img['hypervisor'], 'format': img['format'], 'os': img['ostypename'], 'displaytext': img['displaytext'] } return NodeImage(id=img['id'], name=img['name'], driver=self.connection.driver, extra=extra) def ex_list_os_types(self): """ List all registered os types (needed for snapshot creation) :rtype: ``list`` """ ostypes = self._sync_request('listOsTypes') return ostypes['ostype'] def ex_list_nics(self, node): """ List the available networks :param vm: Node Object :type vm: :class:`CloudStackNode :rtype ``list`` of :class:`CloudStackNic` """ res = self._sync_request(command='listNics', params={'virtualmachineid': node.id}, method='GET') items = res.get('nic', []) nics = [] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['nic'] for item in items: extra = self._get_extra_dict(item, extra_map) nics.append(CloudStackNic( id=item['id'], network_id=item['networkid'], net_mask=item['netmask'], gateway=item['gateway'], ip_address=item['ipaddress'], is_default=item['isdefault'], mac_address=item['macaddress'], driver=self, extra=extra)) return nics def ex_attach_nic_to_node(self, node, network, ip_address=None): """ Add an extra Nic to a VM :param network: NetworkOffering object :type network: :class:'CloudStackNetwork` :param node: Node Object :type node: :class:'CloudStackNode` :param ip_address: Optional, specific IP for this Nic :type ip_address: ``str`` :rtype: ``bool`` """ args = { 'virtualmachineid': node.id, 'networkid': network.id } if ip_address is not None: args['ipaddress'] = ip_address self._async_request(command='addNicToVirtualMachine', params=args) return True def ex_detach_nic_from_node(self, nic, node): """ Remove Nic from a VM :param nic: Nic object :type nic: :class:'CloudStackNetwork` :param node: Node Object :type node: :class:'CloudStackNode` :rtype: ``bool`` """ self._async_request(command='removeNicFromVirtualMachine', params={'nicid': nic.id, 'virtualmachineid': node.id}) return True def ex_list_vpn_gateways(self, account=None, domain_id=None, for_display=None, id=None, is_recursive=None, keyword=None, list_all=None, page=None, page_size=None, project_id=None, vpc_id=None): """ List VPN Gateways. :param account: List resources by account (must be used with the domain_id parameter). :type account: ``str`` :param domain_id: List only resources belonging to the domain specified. :type domain_id: ``str`` :param for_display: List resources by display flag (only root admin is eligible to pass this parameter). :type for_display: ``bool`` :param id: ID of the VPN Gateway. :type id: ``str`` :param is_recursive: Defaults to False, but if true, lists all resources from the parent specified by the domain ID till leaves. :type is_recursive: ``bool`` :param keyword: List by keyword. :type keyword: ``str`` :param list_all: If set to False, list only resources belonging to the command's caller; if set to True - list resources that the caller is authorized to see. Default value is False. :type list_all: ``str`` :param page: Start from page. :type page: ``int`` :param page_size: Items per page. :type page_size: ``int`` :param project_id: List objects by project. :type project_id: ``str`` :param vpc_id: List objects by VPC. :type vpc_id: ``str`` :rtype: ``list`` of :class:`CloudStackVpnGateway` """ args = {} if account is not None: args['account'] = account if domain_id is not None: args['domainid'] = domain_id if for_display is not None: args['fordisplay'] = for_display if id is not None: args['id'] = id if is_recursive is not None: args['isrecursive'] = is_recursive if keyword is not None: args['keyword'] = keyword if list_all is not None: args['listall'] = list_all if page is not None: args['page'] = page if page_size is not None: args['pagesize'] = page_size if project_id is not None: args['projectid'] = project_id if vpc_id is not None: args['vpcid'] = vpc_id res = self._sync_request(command='listVpnGateways', params=args, method='GET') items = res.get('vpngateway', []) vpn_gateways = [] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpngateway'] for item in items: extra = self._get_extra_dict(item, extra_map) vpn_gateways.append(CloudStackVpnGateway( id=item['id'], account=item['account'], domain=item['domain'], domain_id=item['domainid'], public_ip=item['publicip'], vpc_id=item['vpcid'], driver=self, extra=extra)) return vpn_gateways def ex_create_vpn_gateway(self, vpc, for_display=None): """ Creates a VPN Gateway. :param vpc: VPC to create the Gateway for (required). :type vpc: :class: `CloudStackVPC` :param for_display: Display the VPC to the end user or not. :type for_display: ``bool`` :rtype: :class: `CloudStackVpnGateway` """ args = { 'vpcid': vpc.id, } if for_display is not None: args['fordisplay'] = for_display res = self._async_request(command='createVpnGateway', params=args, method='GET') item = res['vpngateway'] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpngateway'] return CloudStackVpnGateway(id=item['id'], account=item['account'], domain=item['domain'], domain_id=item['domainid'], public_ip=item['publicip'], vpc_id=vpc.id, driver=self, extra=self._get_extra_dict(item, extra_map)) def ex_delete_vpn_gateway(self, vpn_gateway): """ Deletes a VPN Gateway. :param vpn_gateway: The VPN Gateway (required). :type vpn_gateway: :class:`CloudStackVpnGateway` :rtype: ``bool`` """ res = self._async_request(command='deleteVpnGateway', params={'id': vpn_gateway.id}, method='GET') return res['success'] def ex_list_vpn_customer_gateways(self, account=None, domain_id=None, id=None, is_recursive=None, keyword=None, list_all=None, page=None, page_size=None, project_id=None): """ List VPN Customer Gateways. :param account: List resources by account (must be used with the domain_id parameter). :type account: ``str`` :param domain_id: List only resources belonging to the domain specified. :type domain_id: ``str`` :param id: ID of the VPN Customer Gateway. :type id: ``str`` :param is_recursive: Defaults to False, but if true, lists all resources from the parent specified by the domain_id till leaves. :type is_recursive: ``bool`` :param keyword: List by keyword. :type keyword: ``str`` :param list_all: If set to False, list only resources belonging to the command's caller; if set to True - list resources that the caller is authorized to see. Default value is False. :type list_all: ``str`` :param page: Start from page. :type page: ``int`` :param page_size: Items per page. :type page_size: ``int`` :param project_id: List objects by project. :type project_id: ``str`` :rtype: ``list`` of :class:`CloudStackVpnCustomerGateway` """ args = {} if account is not None: args['account'] = account if domain_id is not None: args['domainid'] = domain_id if id is not None: args['id'] = id if is_recursive is not None: args['isrecursive'] = is_recursive if keyword is not None: args['keyword'] = keyword if list_all is not None: args['listall'] = list_all if page is not None: args['page'] = page if page_size is not None: args['pagesize'] = page_size if project_id is not None: args['projectid'] = project_id res = self._sync_request(command='listVpnCustomerGateways', params=args, method='GET') items = res.get('vpncustomergateway', []) vpn_customer_gateways = [] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpncustomergateway'] for item in items: extra = self._get_extra_dict(item, extra_map) vpn_customer_gateways.append(CloudStackVpnCustomerGateway( id=item['id'], cidr_list=item['cidrlist'], esp_policy=item['esppolicy'], gateway=item['gateway'], ike_policy=item['ikepolicy'], ipsec_psk=item['ipsecpsk'], driver=self, extra=extra)) return vpn_customer_gateways def ex_create_vpn_customer_gateway(self, cidr_list, esp_policy, gateway, ike_policy, ipsec_psk, account=None, domain_id=None, dpd=None, esp_lifetime=None, ike_lifetime=None, name=None): """ Creates a VPN Customer Gateway. :param cidr_list: Guest CIDR list of the Customer Gateway (required). :type cidr_list: ``str`` :param esp_policy: ESP policy of the Customer Gateway (required). :type esp_policy: ``str`` :param gateway: Public IP address of the Customer Gateway (required). :type gateway: ``str`` :param ike_policy: IKE policy of the Customer Gateway (required). :type ike_policy: ``str`` :param ipsec_psk: IPsec preshared-key of the Customer Gateway (required). :type ipsec_psk: ``str`` :param account: The associated account with the Customer Gateway (must be used with the domain_id param). :type account: ``str`` :param domain_id: The domain ID associated with the Customer Gateway. If used with the account parameter returns the gateway associated with the account for the specified domain. :type domain_id: ``str`` :param dpd: If DPD is enabled for the VPN connection. :type dpd: ``bool`` :param esp_lifetime: Lifetime of phase 2 VPN connection to the Customer Gateway, in seconds. :type esp_lifetime: ``int`` :param ike_lifetime: Lifetime of phase 1 VPN connection to the Customer Gateway, in seconds. :type ike_lifetime: ``int`` :param name: Name of the Customer Gateway. :type name: ``str`` :rtype: :class: `CloudStackVpnCustomerGateway` """ args = { 'cidrlist': cidr_list, 'esppolicy': esp_policy, 'gateway': gateway, 'ikepolicy': ike_policy, 'ipsecpsk': ipsec_psk } if account is not None: args['account'] = account if domain_id is not None: args['domainid'] = domain_id if dpd is not None: args['dpd'] = dpd if esp_lifetime is not None: args['esplifetime'] = esp_lifetime if ike_lifetime is not None: args['ikelifetime'] = ike_lifetime if name is not None: args['name'] = name res = self._async_request(command='createVpnCustomerGateway', params=args, method='GET') item = res['vpncustomergateway'] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpncustomergateway'] return CloudStackVpnCustomerGateway(id=item['id'], cidr_list=cidr_list, esp_policy=esp_policy, gateway=gateway, ike_policy=ike_policy, ipsec_psk=ipsec_psk, driver=self, extra=self._get_extra_dict( item, extra_map)) def ex_delete_vpn_customer_gateway(self, vpn_customer_gateway): """ Deletes a VPN Customer Gateway. :param vpn_customer_gateway: The VPN Customer Gateway (required). :type vpn_customer_gateway: :class:`CloudStackVpnCustomerGateway` :rtype: ``bool`` """ res = self._async_request(command='deleteVpnCustomerGateway', params={'id': vpn_customer_gateway.id}, method='GET') return res['success'] def ex_list_vpn_connections(self, account=None, domain_id=None, for_display=None, id=None, is_recursive=None, keyword=None, list_all=None, page=None, page_size=None, project_id=None, vpc_id=None): """ List VPN Connections. :param account: List resources by account (must be used with the domain_id parameter). :type account: ``str`` :param domain_id: List only resources belonging to the domain specified. :type domain_id: ``str`` :param for_display: List resources by display flag (only root admin is eligible to pass this parameter). :type for_display: ``bool`` :param id: ID of the VPN Connection. :type id: ``str`` :param is_recursive: Defaults to False, but if true, lists all resources from the parent specified by the domain_id till leaves. :type is_recursive: ``bool`` :param keyword: List by keyword. :type keyword: ``str`` :param list_all: If set to False, list only resources belonging to the command's caller; if set to True - list resources that the caller is authorized to see. Default value is False. :type list_all: ``str`` :param page: Start from page. :type page: ``int`` :param page_size: Items per page. :type page_size: ``int`` :param project_id: List objects by project. :type project_id: ``str`` :param vpc_id: List objects by VPC. :type vpc_id: ``str`` :rtype: ``list`` of :class:`CloudStackVpnConnection` """ args = {} if account is not None: args['account'] = account if domain_id is not None: args['domainid'] = domain_id if for_display is not None: args['fordisplay'] = for_display if id is not None: args['id'] = id if is_recursive is not None: args['isrecursive'] = is_recursive if keyword is not None: args['keyword'] = keyword if list_all is not None: args['listall'] = list_all if page is not None: args['page'] = page if page_size is not None: args['pagesize'] = page_size if project_id is not None: args['projectid'] = project_id if vpc_id is not None: args['vpcid'] = vpc_id res = self._sync_request(command='listVpnConnections', params=args, method='GET') items = res.get('vpnconnection', []) vpn_connections = [] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpnconnection'] for item in items: extra = self._get_extra_dict(item, extra_map) vpn_connections.append(CloudStackVpnConnection( id=item['id'], passive=item['passive'], vpn_customer_gateway_id=item['s2scustomergatewayid'], vpn_gateway_id=item['s2svpngatewayid'], state=item['state'], driver=self, extra=extra)) return vpn_connections def ex_create_vpn_connection(self, vpn_customer_gateway, vpn_gateway, for_display=None, passive=None): """ Creates a VPN Connection. :param vpn_customer_gateway: The VPN Customer Gateway (required). :type vpn_customer_gateway: :class:`CloudStackVpnCustomerGateway` :param vpn_gateway: The VPN Gateway (required). :type vpn_gateway: :class:`CloudStackVpnGateway` :param for_display: Display the Connection to the end user or not. :type for_display: ``str`` :param passive: If True, sets the connection to be passive. :type passive: ``bool`` :rtype: :class: `CloudStackVpnConnection` """ args = { 's2scustomergatewayid': vpn_customer_gateway.id, 's2svpngatewayid': vpn_gateway.id, } if for_display is not None: args['fordisplay'] = for_display if passive is not None: args['passive'] = passive res = self._async_request(command='createVpnConnection', params=args, method='GET') item = res['vpnconnection'] extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpnconnection'] return CloudStackVpnConnection( id=item['id'], passive=item['passive'], vpn_customer_gateway_id=vpn_customer_gateway.id, vpn_gateway_id=vpn_gateway.id, state=item['state'], driver=self, extra=self._get_extra_dict(item, extra_map)) def ex_delete_vpn_connection(self, vpn_connection): """ Deletes a VPN Connection. :param vpn_connection: The VPN Connection (required). :type vpn_connection: :class:`CloudStackVpnConnection` :rtype: ``bool`` """ res = self._async_request(command='deleteVpnConnection', params={'id': vpn_connection.id}, method='GET') return res['success'] def _to_snapshot(self, data): """ Create snapshot object from data :param data: Node data object. :type data: ``dict`` :rtype: :class:`VolumeSnapshot` """ extra = { 'tags': data.get('tags', None), 'name': data.get('name', None), 'volume_id': data.get('volumeid', None), } return VolumeSnapshot(data['id'], driver=self, extra=extra) def _to_node(self, data, public_ips=None): """ :param data: Node data object. :type data: ``dict`` :param public_ips: A list of additional IP addresses belonging to this node. (optional) :type public_ips: ``list`` or ``None`` """ id = data['id'] if 'name' in data: name = data['name'] elif 'displayname' in data: name = data['displayname'] else: name = None state = self.NODE_STATE_MAP[data['state']] public_ips = public_ips if public_ips else [] private_ips = [] for nic in data['nic']: if 'ipaddress' not in nic: continue if is_private_subnet(nic['ipaddress']): private_ips.append(nic['ipaddress']) else: public_ips.append(nic['ipaddress']) security_groups = data.get('securitygroup', []) if security_groups: security_groups = [sg['name'] for sg in security_groups] affinity_groups = data.get('affinitygroup', []) if affinity_groups: affinity_groups = [ag['id'] for ag in affinity_groups] created = data.get('created', False) extra = self._get_extra_dict(data, RESOURCE_EXTRA_ATTRIBUTES_MAP['node']) # Add additional parameters to extra extra['security_group'] = security_groups extra['affinity_group'] = affinity_groups extra['ip_addresses'] = [] extra['ip_forwarding_rules'] = [] extra['port_forwarding_rules'] = [] extra['created'] = created if 'tags' in data: extra['tags'] = self._get_resource_tags(data['tags']) node = CloudStackNode(id=id, name=name, state=state, public_ips=list(set(public_ips)), private_ips=private_ips, driver=self, extra=extra) return node def _to_key_pairs(self, data): key_pairs = [self._to_key_pair(data=item) for item in data] return key_pairs def _to_key_pair(self, data): key_pair = KeyPair(name=data['name'], fingerprint=data['fingerprint'], public_key=data.get('publickey', None), private_key=data.get('privatekey', None), driver=self) return key_pair def _to_affinity_group(self, data): affinity_group = CloudStackAffinityGroup( id=data['id'], name=data['name'], group_type=CloudStackAffinityGroupType(data['type']), account=data.get('account', ''), domain=data.get('domain', ''), domainid=data.get('domainid', ''), description=data.get('description', ''), virtualmachine_ids=data.get('virtualmachineIds', '')) return affinity_group def _get_resource_tags(self, tag_set): """ Parse tags from the provided element and return a dictionary with key/value pairs. :param tag_set: A list of key/value tag pairs :type tag_set: ``list``` :rtype: ``dict`` """ tags = {} for tag in tag_set: key = tag['key'] value = tag['value'] tags[key] = value return tags def _get_extra_dict(self, response, mapping): """ Extract attributes from the element based on rules provided in the mapping dictionary. :param response: The JSON response to parse the values from. :type response: ``dict`` :param mapping: Dictionary with the extra layout :type mapping: ``dict`` :rtype: ``dict`` """ extra = {} for attribute, values in mapping.items(): transform_func = values['transform_func'] value = response.get(values['key_name'], None) if value is not None: extra[attribute] = transform_func(value) else: extra[attribute] = None return extra def _to_volume_state(self, vol): state = self.VOLUME_STATE_MAP.get(vol['state'], StorageVolumeState.UNKNOWN) # If a volume is 'Ready' and is attached to a virtualmachine, set # the status to INUSE if state == StorageVolumeState.AVAILABLE and 'virtualmachineid' in vol: state = StorageVolumeState.INUSE return state apache-libcloud-2.8.0/libcloud/compute/drivers/cloudwatt.py0000664000175000017500000001174613570310635023746 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Cloudwatt driver. """ try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import httplib from libcloud.compute.types import Provider from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection from libcloud.compute.drivers.openstack import OpenStack_1_1_NodeDriver from libcloud.common.openstack_identity import OpenStackIdentityConnection from libcloud.utils.iso8601 import parse_date from libcloud.compute.types import InvalidCredsError, MalformedResponseError __all__ = [ 'CloudwattNodeDriver' ] BASE_URL = 'https://identity.fr1.cloudwatt.com/v2.0' AUTH_URL = BASE_URL + '/tokens' class CloudwattAuthConnection(OpenStackIdentityConnection): """ AuthConnection class for the Cloudwatt driver. """ name = 'Cloudwatt Auth' def __init__(self, *args, **kwargs): self._ex_tenant_id = kwargs.pop('ex_tenant_id') super(CloudwattAuthConnection, self).__init__(*args, **kwargs) def authenticate(self, force=False): reqbody = json.dumps({'auth': { 'passwordCredentials': { 'username': self.user_id, 'password': self.key }, 'tenantId': self._ex_tenant_id }}) resp = self.request('/tokens', data=reqbody, headers={}, method='POST') if resp.status == httplib.UNAUTHORIZED: # HTTP UNAUTHORIZED (401): auth failed raise InvalidCredsError() elif resp.status != httplib.OK: body = 'code: %s body:%s' % (resp.status, resp.body) raise MalformedResponseError('Malformed response', body=body, driver=self.driver) else: try: body = json.loads(resp.body) except Exception as e: raise MalformedResponseError('Failed to parse JSON', e) try: expires = body['access']['token']['expires'] self.auth_token = body['access']['token']['id'] self.auth_token_expires = parse_date(expires) self.urls = body['access']['serviceCatalog'] self.auth_user_info = None except KeyError as e: raise MalformedResponseError('Auth JSON response is \ missing required elements', e) return self class CloudwattConnection(OpenStack_1_1_Connection): """ Connection class for the Cloudwatt driver. """ auth_url = BASE_URL service_region = 'fr1' service_type = 'compute' def __init__(self, *args, **kwargs): self.ex_tenant_id = kwargs.pop('ex_tenant_id') super(CloudwattConnection, self).__init__(*args, **kwargs) osa = CloudwattAuthConnection( auth_url=AUTH_URL, user_id=self.user_id, key=self.key, tenant_name=self._ex_tenant_name, timeout=self.timeout, ex_tenant_id=self.ex_tenant_id, parent_conn=self ) self._osa = osa self._auth_version = '2.0' class CloudwattNodeDriver(OpenStack_1_1_NodeDriver): """ Implements the :class:`NodeDriver`'s for Cloudwatt. """ name = 'Cloudwatt' website = 'https://www.cloudwatt.com/' connectionCls = CloudwattConnection type = Provider.CLOUDWATT def __init__(self, key, secret, tenant_id, secure=True, tenant_name=None, host=None, port=None, **kwargs): """ @inherits: :class:`NodeDriver.__init__` :param tenant_id: ID of tenant required for Cloudwatt auth :type tenant_id: ``str`` """ self.ex_tenant_id = tenant_id self.extra = {} super(CloudwattNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, **kwargs ) def attach_volume(self, node, volume, device=None): return super(CloudwattNodeDriver, self)\ .attach_volume(node, volume, device) def _ex_connection_class_kwargs(self): """ Includes ``tenant_id`` in Connection. """ return { 'ex_tenant_id': self.ex_tenant_id } apache-libcloud-2.8.0/libcloud/compute/drivers/digitalocean.py0000664000175000017500000006441413577507766024407 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ DigitalOcean Driver """ import json import warnings from libcloud.utils.iso8601 import parse_date from libcloud.utils.py3 import httplib from libcloud.common.digitalocean import DigitalOcean_v1_Error from libcloud.common.digitalocean import DigitalOcean_v2_BaseDriver from libcloud.common.types import InvalidCredsError from libcloud.compute.types import Provider, NodeState from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, KeyPair from libcloud.compute.base import Node, NodeDriver from libcloud.compute.base import StorageVolume, VolumeSnapshot __all__ = [ 'DigitalOceanNodeDriver', 'DigitalOcean_v2_NodeDriver' ] class DigitalOceanNodeDriver(NodeDriver): """ DigitalOcean NodeDriver defaulting to using APIv2. :keyword key: Personal Access Token required for authentication. :type key: ``str`` :keyword secret: Previously used with API version ``v1``. (deprecated) :type secret: ``str`` :keyword api_version: Specifies the API version to use. Defaults to using ``v2``, currently the only valid option. (optional) :type api_version: ``str`` """ type = Provider.DIGITAL_OCEAN name = 'DigitalOcean' website = 'https://www.digitalocean.com' def __new__(cls, key, secret=None, api_version='v2', **kwargs): if cls is DigitalOceanNodeDriver: if api_version == 'v1' or secret is not None: if secret is not None and api_version == 'v2': raise InvalidCredsError( 'secret not accepted for v2 authentication') raise DigitalOcean_v1_Error() elif api_version == 'v2': cls = DigitalOcean_v2_NodeDriver else: raise NotImplementedError('Unsupported API version: %s' % (api_version)) return super(DigitalOceanNodeDriver, cls).__new__(cls, **kwargs) # TODO Implement v1 driver using KeyPair class SSHKey(object): def __init__(self, id, name, pub_key): self.id = id self.name = name self.pub_key = pub_key def __repr__(self): return (('') % (self.id, self.name, self.pub_key)) class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver, DigitalOceanNodeDriver): """ DigitalOcean NodeDriver using v2 of the API. """ NODE_STATE_MAP = {'new': NodeState.PENDING, 'off': NodeState.STOPPED, 'active': NodeState.RUNNING, 'archive': NodeState.TERMINATED} EX_CREATE_ATTRIBUTES = ['backups', 'ipv6', 'private_networking', 'tags', 'ssh_keys'] def list_images(self): data = self._paginated_request('/v2/images', 'images') return list(map(self._to_image, data)) def list_key_pairs(self): """ List all the available SSH keys. :return: Available SSH keys. :rtype: ``list`` of :class:`KeyPair` """ data = self._paginated_request('/v2/account/keys', 'ssh_keys') return list(map(self._to_key_pair, data)) def list_locations(self, ex_available=True): """ List locations :param ex_available: Only return locations which are available. :type ex_evailable: ``bool`` """ locations = [] data = self._paginated_request('/v2/regions', 'regions') for location in data: if ex_available: if location.get('available'): locations.append(self._to_location(location)) else: locations.append(self._to_location(location)) return locations def list_nodes(self): data = self._paginated_request('/v2/droplets', 'droplets') return list(map(self._to_node, data)) def list_sizes(self): data = self._paginated_request('/v2/sizes', 'sizes') return list(map(self._to_size, data)) def list_volumes(self): data = self._paginated_request('/v2/volumes', 'volumes') return list(map(self._to_volume, data)) def create_node(self, name, size, image, location, ex_create_attr=None, ex_ssh_key_ids=None, ex_user_data=None): """ Create a node. The `ex_create_attr` parameter can include the following dictionary key and value pairs: * `backups`: ``bool`` defaults to False * `ipv6`: ``bool`` defaults to False * `private_networking`: ``bool`` defaults to False * `tags`: ``list`` of ``str`` tags * `user_data`: ``str`` for cloud-config data * `ssh_keys`: ``list`` of ``int`` key ids or ``str`` fingerprints `ex_create_attr['ssh_keys']` will override `ex_ssh_key_ids` assignment. :keyword ex_create_attr: A dictionary of optional attributes for droplet creation :type ex_create_attr: ``dict`` :keyword ex_ssh_key_ids: A list of ssh key ids which will be added to the server. (optional) :type ex_ssh_key_ids: ``list`` of ``int`` key ids or ``str`` key fingerprints :keyword ex_user_data: User data to be added to the node on create. (optional) :type ex_user_data: ``str`` :return: The newly created node. :rtype: :class:`Node` """ attr = {'name': name, 'size': size.name, 'image': image.id, 'region': location.id, 'user_data': ex_user_data} if ex_ssh_key_ids: warnings.warn("The ex_ssh_key_ids parameter has been deprecated in" " favor of the ex_create_attr parameter.") attr['ssh_keys'] = ex_ssh_key_ids ex_create_attr = ex_create_attr or {} for key in ex_create_attr.keys(): if key in self.EX_CREATE_ATTRIBUTES: attr[key] = ex_create_attr[key] res = self.connection.request('/v2/droplets', data=json.dumps(attr), method='POST') data = res.object['droplet'] # TODO: Handle this in the response class status = res.object.get('status', 'OK') if status == 'ERROR': message = res.object.get('message', None) error_message = res.object.get('error_message', message) raise ValueError('Failed to create node: %s' % (error_message)) return self._to_node(data=data) def destroy_node(self, node): res = self.connection.request('/v2/droplets/%s' % (node.id), method='DELETE') return res.status == httplib.NO_CONTENT def reboot_node(self, node): attr = {'type': 'reboot'} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def create_image(self, node, name): """ Create an image from a Node. @inherits: :class:`NodeDriver.create_image` :param node: Node to use as base for image :type node: :class:`Node` :param node: Name for image :type node: ``str`` :rtype: ``bool`` """ attr = {'type': 'snapshot', 'name': name} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def delete_image(self, image): """Delete an image for node. @inherits: :class:`NodeDriver.delete_image` :param image: the image to be deleted :type image: :class:`NodeImage` :rtype: ``bool`` """ res = self.connection.request('/v2/images/%s' % (image.id), method='DELETE') return res.status == httplib.NO_CONTENT def get_image(self, image_id): """ Get an image based on an image_id @inherits: :class:`NodeDriver.get_image` :param image_id: Image identifier :type image_id: ``int`` :return: A NodeImage object :rtype: :class:`NodeImage` """ data = self._paginated_request('/v2/images/%s' % (image_id), 'image') return self._to_image(data) def ex_change_kernel(self, node, kernel_id): attr = {'type': 'change_kernel', 'kernel': kernel_id} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def ex_enable_ipv6(self, node): attr = {'type': 'enable_ipv6'} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def ex_rename_node(self, node, name): attr = {'type': 'rename', 'name': name} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def ex_shutdown_node(self, node): attr = {'type': 'shutdown'} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def ex_hard_reboot(self, node): attr = {'type': 'power_cycle'} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def ex_power_on_node(self, node): attr = {'type': 'power_on'} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def ex_rebuild_node(self, node): """ Destroy and rebuild the node using its base image. :param node: Node to rebuild :type node: :class:`Node` :return True if the operation began successfully :rtype ``bool`` """ attr = {'type': 'rebuild', 'image': node.extra['image']['id']} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def ex_resize_node(self, node, size): """ Resize the node to a different machine size. Note that some resize operations are reversible, and others are irreversible. :param node: Node to rebuild :type node: :class:`Node` :param size: New size for this machine :type node: :class:`NodeSize` :return True if the operation began successfully :rtype ``bool`` """ attr = {'type': 'resize', 'size': size.name} res = self.connection.request('/v2/droplets/%s/actions' % (node.id), data=json.dumps(attr), method='POST') return res.status == httplib.CREATED def create_key_pair(self, name, public_key=''): """ Create a new SSH key. :param name: Key name (required) :type name: ``str`` :param public_key: Valid public key string (required) :type public_key: ``str`` """ attr = {'name': name, 'public_key': public_key} res = self.connection.request('/v2/account/keys', method='POST', data=json.dumps(attr)) data = res.object['ssh_key'] return self._to_key_pair(data=data) def delete_key_pair(self, key): """ Delete an existing SSH key. :param key: SSH key (required) :type key: :class:`KeyPair` """ key_id = key.extra['id'] res = self.connection.request('/v2/account/keys/%s' % (key_id), method='DELETE') return res.status == httplib.NO_CONTENT def get_key_pair(self, name): """ Retrieve a single key pair. :param name: Name of the key pair to retrieve. :type name: ``str`` :rtype: :class:`.KeyPair` """ qkey = [k for k in self.list_key_pairs() if k.name == name][0] data = self.connection.request('/v2/account/keys/%s' % qkey.extra['id']).object['ssh_key'] return self._to_key_pair(data=data) def create_volume(self, size, name, location=None, snapshot=None): """ Create a new volume. :param size: Size of volume in gigabytes (required) :type size: ``int`` :param name: Name of the volume to be created :type name: ``str`` :param location: Which data center to create a volume in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param snapshot: Snapshot from which to create the new volume. (optional) :type snapshot: :class:`.VolumeSnapshot` :return: The newly created volume. :rtype: :class:`StorageVolume` """ attr = {'name': name, 'size_gigabytes': size, 'region': location.id} res = self.connection.request('/v2/volumes', data=json.dumps(attr), method='POST') data = res.object['volume'] status = res.object.get('status', 'OK') if status == 'ERROR': message = res.object.get('message', None) error_message = res.object.get('error_message', message) raise ValueError('Failed to create volume: %s' % (error_message)) return self._to_volume(data=data) def destroy_volume(self, volume): """ Destroys a storage volume. :param volume: Volume to be destroyed :type volume: :class:`StorageVolume` :rtype: ``bool`` """ res = self.connection.request('/v2/volumes/%s' % volume.id, method='DELETE') return res.status == httplib.NO_CONTENT def attach_volume(self, node, volume, device=None): """ Attaches volume to node. :param node: Node to attach volume to. :type node: :class:`.Node` :param volume: Volume to attach. :type volume: :class:`.StorageVolume` :param device: Where the device is exposed, e.g. '/dev/sdb' :type device: ``str`` :rytpe: ``bool`` """ attr = {'type': 'attach', 'droplet_id': node.id, 'volume_name': volume.name, 'region': volume.extra['region_slug']} res = self.connection.request('/v2/volumes/actions', data=json.dumps(attr), method='POST') return res.status == httplib.ACCEPTED def detach_volume(self, volume): """ Detaches a volume from a node. :param volume: Volume to be detached :type volume: :class:`.StorageVolume` :rtype: ``bool`` """ attr = {'type': 'detach', 'volume_name': volume.name, 'region': volume.extra['region_slug']} responses = [] for droplet_id in volume.extra['droplet_ids']: attr['droplet_id'] = droplet_id res = self.connection.request('/v2/volumes/actions', data=json.dumps(attr), method='POST') responses.append(res) return all([r.status == httplib.ACCEPTED for r in responses]) def create_volume_snapshot(self, volume, name): """ Create a new volume snapshot. :param volume: Volume to create a snapshot for :type volume: class:`StorageVolume` :return: The newly created volume snapshot. :rtype: :class:`VolumeSnapshot` """ attr = {'name': name} res = self.connection.request('/v2/volumes/%s/snapshots' % ( volume.id), data=json.dumps(attr), method='POST') data = res.object['snapshot'] return self._to_volume_snapshot(data=data) def list_volume_snapshots(self, volume): """ List snapshots for a volume. :param volume: Volume to list snapshots for :type volume: class:`StorageVolume` :return: List of volume snapshots. :rtype: ``list`` of :class: `StorageVolume` """ data = self._paginated_request('/v2/volumes/%s/snapshots' % (volume.id), 'snapshots') return list(map(self._to_volume_snapshot, data)) def delete_volume_snapshot(self, snapshot): """ Delete a volume snapshot :param snapshot: volume snapshot to delete :type snapshot: class:`VolumeSnapshot` :rtype: ``bool`` """ res = self.connection.request('v2/snapshots/%s' % (snapshot.id), method='DELETE') return res.status == httplib.NO_CONTENT def ex_get_node_details(self, node_id): """ Lists details of the specified server. :param node_id: ID of the node which should be used :type node_id: ``str`` :rtype: :class:`Node` """ data = self._paginated_request( '/v2/droplets/{}'.format(node_id), 'droplet' ) return self._to_node(data) def ex_create_floating_ip(self, location): """ Create new floating IP reserved to a region. The newly created floating IP will not be associated to a Droplet. See https://developers.digitalocean.com/documentation/v2/#floating-ips :param location: Which data center to create the floating IP in. :type location: :class:`.NodeLocation` :rtype: :class:`DigitalOcean_v2_FloatingIpAddress` """ attr = {'region': location.id} resp = self.connection.request('/v2/floating_ips', data=json.dumps(attr), method='POST') return self._to_floating_ip(resp.object['floating_ip']) def ex_delete_floating_ip(self, ip): """ Delete specified floating IP :param ip: floating IP to remove :type ip: :class:`DigitalOcean_v2_FloatingIpAddress` :rtype: ``bool`` """ resp = self.connection.request('/v2/floating_ips/{}'.format(ip.id), method='DELETE') return resp.status == httplib.NO_CONTENT def ex_list_floating_ips(self): """ List floating IPs :rtype: ``list`` of :class:`DigitalOcean_v2_FloatingIpAddress` """ return self._to_floating_ips( self._paginated_request('/v2/floating_ips', 'floating_ips') ) def ex_get_floating_ip(self, ip): """ Get specified floating IP :param ip: floating IP to get :type ip: ``str`` :rtype: :class:`DigitalOcean_v2_FloatingIpAddress` """ floating_ips = self.ex_list_floating_ips() matching_ips = [x for x in floating_ips if x.ip_address == ip] if not matching_ips: raise ValueError('Floating ip %s not found' % ip) return matching_ips[0] def ex_attach_floating_ip_to_node(self, node, ip): """ Attach the floating IP to the node :param node: node :type node: :class:`Node` :param ip: floating IP to attach :type ip: ``str`` or :class:`DigitalOcean_v2_FloatingIpAddress` :rtype: ``bool`` """ data = { 'type': 'assign', 'droplet_id': node.id } resp = self.connection.request( '/v2/floating_ips/%s/actions' % ip.ip_address, data=json.dumps(data), method='POST' ) return resp.status == httplib.CREATED def ex_detach_floating_ip_from_node(self, node, ip): """ Detach a floating IP from the given node Note: the 'node' object is not used in this method but it is added to the signature of ex_detach_floating_ip_from_node anyway so it conforms to the interface of the method of the same name for other drivers like for example OpenStack. :param node: Node from which the IP should be detached :type node: :class:`Node` :param ip: Floating IP to detach :type ip: :class:`DigitalOcean_v2_FloatingIpAddress` :rtype: ``bool`` """ data = { 'type': 'unassign' } resp = self.connection.request( '/v2/floating_ips/%s/actions' % ip.ip_address, data=json.dumps(data), method='POST' ) return resp.status == httplib.CREATED def _to_node(self, data): extra_keys = ['memory', 'vcpus', 'disk', 'image', 'size', 'size_slug', 'locked', 'created_at', 'networks', 'kernel', 'backup_ids', 'snapshot_ids', 'features', 'tags'] if 'status' in data: state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN) else: state = NodeState.UNKNOWN created = parse_date(data['created_at']) networks = data['networks'] private_ips = [] public_ips = [] if networks: for net in networks['v4']: if net['type'] == 'private': private_ips = [net['ip_address']] if net['type'] == 'public': public_ips = [net['ip_address']] extra = {} for key in extra_keys: if key in data: extra[key] = data[key] extra['region'] = data.get('region', {}).get('name') node = Node(id=data['id'], name=data['name'], state=state, public_ips=public_ips, private_ips=private_ips, created_at=created, driver=self, extra=extra) return node def _to_image(self, data): extra = {'distribution': data['distribution'], 'public': data['public'], 'slug': data['slug'], 'regions': data['regions'], 'min_disk_size': data['min_disk_size'], 'created_at': data['created_at']} return NodeImage(id=data['id'], name=data['name'], driver=self, extra=extra) def _to_volume(self, data): extra = {'created_at': data['created_at'], 'droplet_ids': data['droplet_ids'], 'region': data['region'], 'region_slug': data['region']['slug']} return StorageVolume(id=data['id'], name=data['name'], size=data['size_gigabytes'], driver=self, extra=extra) def _to_location(self, data): extra = data.get('features', []) return NodeLocation(id=data['slug'], name=data['name'], country=None, extra=extra, driver=self) def _to_size(self, data): extra = {'vcpus': data['vcpus'], 'regions': data['regions'], 'price_monthly': data['price_monthly']} return NodeSize(id=data['slug'], name=data['slug'], ram=data['memory'], disk=data['disk'], bandwidth=data['transfer'], price=data['price_hourly'], driver=self, extra=extra) def _to_key_pair(self, data): extra = {'id': data['id']} return KeyPair(name=data['name'], fingerprint=data['fingerprint'], public_key=data['public_key'], private_key=None, driver=self, extra=extra) def _to_volume_snapshot(self, data): extra = {'created_at': data['created_at'], 'resource_id': data['resource_id'], 'regions': data['regions'], 'min_disk_size': data['min_disk_size']} return VolumeSnapshot(id=data['id'], name=data['name'], size=data['size_gigabytes'], driver=self, extra=extra) def _to_floating_ips(self, obj): return [self._to_floating_ip(ip) for ip in obj] def _to_floating_ip(self, obj): return DigitalOcean_v2_FloatingIpAddress( # There is no ID, but the IP is unique so we can use that id=obj['ip'], ip_address=obj['ip'], node_id=obj['droplet']['id'] if obj['droplet'] else None, extra={ 'region': obj['region'], }, driver=self ) class DigitalOcean_v2_FloatingIpAddress(object): """ Floating IP info. """ def __init__(self, id, ip_address, node_id=None, extra=None, driver=None): self.id = str(id) self.ip_address = ip_address self.extra = extra self.node_id = node_id self.driver = driver def delete(self): """ Delete this floating IP :rtype: ``bool`` """ return self.driver.ex_delete_floating_ip(self) def __repr__(self): return ('' % (self.id, self.ip_address, self.driver)) apache-libcloud-2.8.0/libcloud/compute/drivers/dimensiondata.py0000664000175000017500000056216513576514553024600 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Dimension Data Driver """ from libcloud.utils.py3 import ET from libcloud.common.dimensiondata import LooseVersion from libcloud.common.exceptions import BaseHTTPError from libcloud.compute.base import NodeDriver, Node, NodeAuthPassword from libcloud.compute.base import NodeSize, NodeImage, NodeLocation from libcloud.common.dimensiondata import dd_object_to_id from libcloud.common.dimensiondata import DimensionDataAPIException from libcloud.common.dimensiondata import (DimensionDataConnection, DimensionDataStatus) from libcloud.common.dimensiondata import DimensionDataNetwork from libcloud.common.dimensiondata import DimensionDataNetworkDomain from libcloud.common.dimensiondata import DimensionDataVlan from libcloud.common.dimensiondata import DimensionDataServerCpuSpecification from libcloud.common.dimensiondata import DimensionDataServerDisk from libcloud.common.dimensiondata import DimensionDataServerVMWareTools from libcloud.common.dimensiondata import DimensionDataPublicIpBlock from libcloud.common.dimensiondata import DimensionDataFirewallRule from libcloud.common.dimensiondata import DimensionDataFirewallAddress from libcloud.common.dimensiondata import DimensionDataNatRule from libcloud.common.dimensiondata import DimensionDataAntiAffinityRule from libcloud.common.dimensiondata import DimensionDataIpAddressList from libcloud.common.dimensiondata import DimensionDataChildIpAddressList from libcloud.common.dimensiondata import DimensionDataIpAddress from libcloud.common.dimensiondata import DimensionDataPortList from libcloud.common.dimensiondata import DimensionDataPort from libcloud.common.dimensiondata import DimensionDataChildPortList from libcloud.common.dimensiondata import DimensionDataNic from libcloud.common.dimensiondata import NetworkDomainServicePlan from libcloud.common.dimensiondata import DimensionDataTagKey from libcloud.common.dimensiondata import DimensionDataTag from libcloud.common.dimensiondata import API_ENDPOINTS, DEFAULT_REGION from libcloud.common.dimensiondata import TYPES_URN from libcloud.common.dimensiondata import SERVER_NS, NETWORK_NS, GENERAL_NS from libcloud.utils.py3 import urlencode, ensure_string from libcloud.utils.xml import fixxpath, findtext, findall from libcloud.utils.py3 import basestring from libcloud.compute.types import NodeState, Provider import sys # Node state map is a dictionary with the keys as tuples # These tuples represent: # (, , ) NODE_STATE_MAP = { ('NORMAL', 'false', None): NodeState.STOPPED, ('PENDING_CHANGE', 'false', None): NodeState.PENDING, ('PENDING_CHANGE', 'false', 'CHANGE_NETWORK_ADAPTER'): NodeState.PENDING, ('PENDING_CHANGE', 'true', 'CHANGE_NETWORK_ADAPTER'): NodeState.PENDING, ('PENDING_CHANGE', 'false', 'EXCHANGE_NIC_VLANS'): NodeState.PENDING, ('PENDING_CHANGE', 'true', 'EXCHANGE_NIC_VLANS'): NodeState.PENDING, ('NORMAL', 'true', None): NodeState.RUNNING, ('PENDING_CHANGE', 'true', 'START_SERVER'): NodeState.STARTING, ('PENDING_ADD', 'true', 'DEPLOY_SERVER'): NodeState.STARTING, ('PENDING_ADD', 'true', 'DEPLOY_SERVER_WITH_DISK_SPEED'): NodeState.STARTING, ('PENDING_CHANGE', 'true', 'SHUTDOWN_SERVER'): NodeState.STOPPING, ('PENDING_CHANGE', 'true', 'POWER_OFF_SERVER'): NodeState.STOPPING, ('PENDING_CHANGE', 'true', 'REBOOT_SERVER'): NodeState.REBOOTING, ('PENDING_CHANGE', 'true', 'RESET_SERVER'): NodeState.REBOOTING, ('PENDING_CHANGE', 'true', 'RECONFIGURE_SERVER'): NodeState.RECONFIGURING, } OBJECT_TO_TAGGING_ASSET_TYPE_MAP = { 'Node': 'SERVER', 'NodeImage': 'CUSTOMER_IMAGE', 'DimensionDataNetworkDomain': 'NETWORK_DOMAIN', 'DimensionDataVlan': 'VLAN', 'DimensionDataPublicIpBlock': 'PUBLIC_IP_BLOCK' } class DimensionDataNodeDriver(NodeDriver): """ DimensionData node driver. Default api_version is used unless specified. """ selected_region = None connectionCls = DimensionDataConnection name = 'DimensionData' website = 'http://www.dimensiondata.com/' type = Provider.DIMENSIONDATA features = {'create_node': ['password']} api_version = 1.0 def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS and host is None: raise ValueError( 'Invalid region: %s, no host specified' % (region)) if region is not None: self.selected_region = API_ENDPOINTS[region] if api_version is not None: self.api_version = api_version super(DimensionDataNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) def _ex_connection_class_kwargs(self): """ Add the region to the kwargs before the connection is instantiated """ kwargs = super(DimensionDataNodeDriver, self)._ex_connection_class_kwargs() kwargs['region'] = self.selected_region kwargs['api_version'] = self.api_version return kwargs def _create_node_mcp1(self, name, image, auth, ex_description, ex_network=None, ex_memory_gb=None, ex_cpu_specification=None, ex_is_started=True, ex_primary_dns=None, ex_secondary_dns=None, **kwargs): """ Create a new DimensionData node :keyword name: String with a name for this new node (required) :type name: ``str`` :keyword image: OS Image to boot on node. (required) :type image: :class:`NodeImage` or ``str`` :keyword auth: Initial authentication information for the node. (If this is a customer LINUX image auth will be ignored) :type auth: :class:`NodeAuthPassword` or ``str`` or ``None`` :keyword ex_description: description for this node (required) :type ex_description: ``str`` :keyword ex_network: Network to create the node within (required unless using ex_network_domain or ex_primary_ipv4) :type ex_network: :class:`DimensionDataNetwork` or ``str`` :keyword ex_memory_gb: The amount of memory in GB for the server :type ex_memory_gb: ``int`` :keyword ex_cpu_specification: The spec of CPU to deploy ( optional) :type ex_cpu_specification: :class:`DimensionDataServerCpuSpecification` :keyword ex_is_started: Start server after creation? default true (required) :type ex_is_started: ``bool`` :keyword ex_primary_dns: The node's primary DNS :type ex_primary_dns: ``str`` :keyword ex_secondary_dns: The node's secondary DNS :type ex_secondary_dns: ``str`` :return: The newly created :class:`Node`. :rtype: :class:`Node` """ password = None image_needs_auth = self._image_needs_auth(image) if image_needs_auth: if isinstance(auth, basestring): auth_obj = NodeAuthPassword(password=auth) password = auth else: auth_obj = self._get_and_check_auth(auth) password = auth_obj.password server_elm = ET.Element('deployServer', {'xmlns': TYPES_URN}) ET.SubElement(server_elm, "name").text = name ET.SubElement(server_elm, "description").text = ex_description image_id = self._image_to_image_id(image) ET.SubElement(server_elm, "imageId").text = image_id ET.SubElement(server_elm, "start").text = str( ex_is_started).lower() if password is not None: ET.SubElement(server_elm, "administratorPassword").text = password if ex_cpu_specification is not None: cpu = ET.SubElement(server_elm, "cpu") cpu.set('speed', ex_cpu_specification.performance) cpu.set('count', str(ex_cpu_specification.cpu_count)) cpu.set('coresPerSocket', str(ex_cpu_specification.cores_per_socket)) if ex_memory_gb is not None: ET.SubElement(server_elm, "memoryGb").text = str(ex_memory_gb) if ex_network is not None: network_elm = ET.SubElement(server_elm, "network") network_id = self._network_to_network_id(ex_network) ET.SubElement(network_elm, "networkId").text = network_id if ex_primary_dns: dns_elm = ET.SubElement(server_elm, "primaryDns") dns_elm.text = ex_primary_dns if ex_secondary_dns: dns_elm = ET.SubElement(server_elm, "secondaryDns") dns_elm.text = ex_secondary_dns response = self.connection.request_with_orgId_api_2( 'server/deployServer', method='POST', data=ET.tostring(server_elm)).object node_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'serverId': node_id = info.get('value') node = self.ex_get_node_by_id(node_id) if image_needs_auth: if getattr(auth_obj, "generated", False): node.extra['password'] = auth_obj.password return node def create_node(self, name, image, auth, ex_network_domain=None, ex_primary_nic_private_ipv4=None, ex_primary_nic_vlan=None, ex_primary_nic_network_adapter=None, ex_additional_nics=None, ex_description=None, ex_disks=None, ex_cpu_specification=None, ex_memory_gb=None, ex_is_started=True, ex_primary_dns=None, ex_secondary_dns=None, ex_ipv4_gateway=None, ex_microsoft_time_zone=None, **kwargs ): """ Create a new DimensionData node in MCP2. However, it is still backward compatible for MCP1 for a limited time. Please consider using MCP2 datacenter as MCP1 will phase out soon. Legacy Create Node for MCP1 datacenter >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.base import NodeAuthPassword >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = False >>> DimensionData = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Password >>> root_pw = NodeAuthPassword('password123') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU1') >>> >>> # Get network by location >>> my_network = driver.list_networks(location=location)[0] >>> pprint(my_network) >>> >>> # Get Image >>> images = driver.list_images(location=location) >>> image = images[0] >>> >>> node = driver.create_node(name='test_blah_2', image=image, >>> auth=root_pw, >>> ex_description='test3 node', >>> ex_network=my_network, >>> ex_is_started=False) >>> pprint(node) Create Node in MCP2 Data Center >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.base import NodeAuthPassword >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Password >>> root_pw = NodeAuthPassword('password123') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> vlan = driver.ex_list_vlans(location=location, >>> network_domain=my_network_domain)[0] >>> pprint(vlan) >>> >>> # Get Image >>> images = driver.list_images(location=location) >>> image = images[0] >>> >>> # Create node using vlan instead of private IPv4 >>> node = driver.create_node(name='test_server_01', image=image, >>> auth=root_pw, >>> ex_description='test2 node', >>> ex_network_domain=my_network_domain, >>> ex_primary_nic_vlan=vlan, >>> ex_is_started=False) >>> >>> # Option: Create node using private IPv4 instead of vlan >>> # node = driver.create_node(name='test_server_02', image=image, >>> # auth=root_pw, >>> # ex_description='test2 node', >>> # ex_network_domain=my_network_domain, >>> # ex_primary_nic_private_ipv4='10.1.1.7', >>> # ex_is_started=False) >>> >>> # Option: Create node using by specifying Network Adapter >>> # node = driver.create_node(name='test_server_03', image=image, >>> # auth=root_pw, >>> # ex_description='test2 node', >>> # ex_network_domain=my_network_domain, >>> # ex_primary_nic_vlan=vlan, >>> # ex_primary_nic_network_adapter='E1000', >>> # ex_is_started=False) >>> :keyword name: (required) String with a name for this new node :type name: ``str`` :keyword image: (required) OS Image to boot on node. :type image: :class:`NodeImage` or ``str`` :keyword auth: Initial authentication information for the node. (If this is a customer LINUX image auth will be ignored) :type auth: :class:`NodeAuthPassword` or ``str`` or ``None`` :keyword ex_description: (optional) description for this node :type ex_description: ``str`` :keyword ex_network_domain: (required) Network Domain or Network Domain ID to create the node :type ex_network_domain: :class:`DimensionDataNetworkDomain` or ``str`` :keyword ex_primary_nic_private_ipv4: Provide private IPv4. Ignore if ex_primary_nic_vlan is provided. Use one or the other. Not both. :type ex_primary_nic_private_ipv4: :``str`` :keyword ex_primary_nic_vlan: Provide VLAN for the node if ex_primary_nic_private_ipv4 NOT provided. One or the other. Not both. :type ex_primary_nic_vlan: :class: DimensionDataVlan or ``str`` :keyword ex_primary_nic_network_adapter: (Optional) Default value for the Operating System will be used if leave empty. Example: "E1000". :type ex_primary_nic_network_adapter: :``str`` :keyword ex_additional_nics: (optional) List :class:'DimensionDataNic' or None :type ex_additional_nics: ``list`` of :class:'DimensionDataNic' or ``str`` :keyword ex_memory_gb: (optional) The amount of memory in GB for the server Can be used to override the memory value inherited from the source Server Image. :type ex_memory_gb: ``int`` :keyword ex_cpu_specification: (optional) The spec of CPU to deploy :type ex_cpu_specification: :class:`DimensionDataServerCpuSpecification` :keyword ex_is_started: (required) Start server after creation. Default is set to true. :type ex_is_started: ``bool`` :keyword ex_primary_dns: (Optional) The node's primary DNS :type ex_primary_dns: ``str`` :keyword ex_secondary_dns: (Optional) The node's secondary DNS :type ex_secondary_dns: ``str`` :keyword ex_ipv4_gateway: (Optional) IPv4 address in dot-decimal notation, which will be used as the Primary NIC gateway instead of the default gateway assigned by the system. If ipv4Gateway is provided it does not have to be on the VLAN of the Primary NIC but MUST be reachable or the Guest OS will not be configured correctly. :type ex_ipv4_gateway: ``str`` :keyword ex_disks: (optional) Dimensiondata disks. Optional disk elements can be used to define the disk speed that each disk on the Server; inherited from the source Server Image will be deployed to. It is not necessary to include a diskelement for every disk; only those that you wish to set a disk speed value for. Note that scsiId 7 cannot be used.Up to 13 disks can be present in addition to the required OS disk on SCSI ID 0. Refer to https://docs.mcp-services.net/x/UwIu for disk :type ex_disks: List or tuple of :class:'DimensionDataServerDisk` :keyword ex_microsoft_time_zone: (optional) For use with Microsoft Windows source Server Images only. For the exact value to use please refer to the table of time zone indexes in the following Microsoft Technet documentation. If none is supplied, the default time zone for the data center geographic region will be used. :type ex_microsoft_time_zone: `str`` :return: The newly created :class:`Node`. :rtype: :class:`Node` """ # Neither legacy MCP1 network nor MCP2 network domain provided if ex_network_domain is None and 'ex_network' not in kwargs: raise ValueError('You must provide either ex_network_domain ' 'for MCP2 or ex_network for legacy MCP1') # Ambiguous parameter provided. Can't determine if it is MCP 1 or 2. if ex_network_domain is not None and 'ex_network' in kwargs: raise ValueError('You can only supply either ' 'ex_network_domain ' 'for MCP2 or ex_network for legacy MCP1') # Set ex_is_started to False by default if none bool data type provided if not isinstance(ex_is_started, bool): ex_is_started = True # Handle MCP1 legacy if 'ex_network' in kwargs: new_node = self._create_node_mcp1( name=name, image=image, auth=auth, ex_network=kwargs.get("ex_network"), ex_description=ex_description, ex_memory_gb=ex_memory_gb, ex_cpu_specification=ex_cpu_specification, ex_is_started=ex_is_started, ex_primary_ipv4=ex_primary_nic_private_ipv4, ex_disks=ex_disks, ex_additional_nics_vlan=kwargs.get("ex_additional_nics_vlan"), ex_additional_nics_ipv4=kwargs.get("ex_additional_nics_ipv4"), ex_primary_dns=ex_primary_dns, ex_secondary_dns=ex_secondary_dns ) else: # Handle MCP2 legacy. CaaS api 2.2 or earlier if 'ex_vlan' in kwargs: ex_primary_nic_vlan = kwargs.get('ex_vlan') if 'ex_primary_ipv4' in kwargs: ex_primary_nic_private_ipv4 = kwargs.get( 'ex_primary_ipv4') additional_nics = [] if 'ex_additional_nics_vlan' in kwargs: vlans = kwargs.get('ex_additional_nics_vlan') if isinstance(vlans, (list, tuple)): for v in vlans: add_nic = DimensionDataNic(vlan=v) additional_nics.append(add_nic) else: raise TypeError("ex_additional_nics_vlan must " "be None or a tuple/list") if 'ex_additional_nics_ipv4' in kwargs: ips = kwargs.get('ex_additional_nics_ipv4') if isinstance(ips, (list, tuple)): for ip in ips: add_nic = DimensionDataNic(private_ip_v4=ip) additional_nics.append(add_nic) else: if ips is not None: raise TypeError("ex_additional_nics_ipv4 must " "be None or a tuple/list") if ('ex_additional_nics_vlan' in kwargs or 'ex_additional_nics_ipv4' in kwargs): ex_additional_nics = additional_nics # Handle MCP2 latest. CaaS API 2.3 onwards if ex_network_domain is None: raise ValueError("ex_network_domain must be specified") password = None image_needs_auth = self._image_needs_auth(image) if image_needs_auth: if isinstance(auth, basestring): auth_obj = NodeAuthPassword(password=auth) password = auth else: auth_obj = self._get_and_check_auth(auth) password = auth_obj.password server_elm = ET.Element('deployServer', {'xmlns': TYPES_URN}) ET.SubElement(server_elm, "name").text = name ET.SubElement(server_elm, "description").text = ex_description image_id = self._image_to_image_id(image) ET.SubElement(server_elm, "imageId").text = image_id ET.SubElement(server_elm, "start").text = str( ex_is_started).lower() if password is not None: ET.SubElement(server_elm, "administratorPassword").text = password if ex_cpu_specification is not None: cpu = ET.SubElement(server_elm, "cpu") cpu.set('speed', ex_cpu_specification.performance) cpu.set('count', str(ex_cpu_specification.cpu_count)) cpu.set('coresPerSocket', str(ex_cpu_specification.cores_per_socket)) if ex_memory_gb is not None: ET.SubElement(server_elm, "memoryGb").text = str(ex_memory_gb) if (ex_primary_nic_private_ipv4 is None and ex_primary_nic_vlan is None): raise ValueError("Missing argument. Either " "ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "must be specified.") if (ex_primary_nic_private_ipv4 is not None and ex_primary_nic_vlan is not None): raise ValueError("Either ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "be specified. Not both.") network_elm = ET.SubElement(server_elm, "networkInfo") net_domain_id = self._network_domain_to_network_domain_id( ex_network_domain) network_elm.set('networkDomainId', net_domain_id) pri_nic = ET.SubElement(network_elm, 'primaryNic') if ex_primary_nic_private_ipv4 is not None: ET.SubElement(pri_nic, 'privateIpv4').text = ex_primary_nic_private_ipv4 if ex_primary_nic_vlan is not None: vlan_id = self._vlan_to_vlan_id(ex_primary_nic_vlan) ET.SubElement(pri_nic, 'vlanId').text = vlan_id if ex_primary_nic_network_adapter is not None: ET.SubElement(pri_nic, "networkAdapter").text = \ ex_primary_nic_network_adapter if isinstance(ex_additional_nics, (list, tuple)): for nic in ex_additional_nics: additional_nic = ET.SubElement(network_elm, 'additionalNic') if (nic.private_ip_v4 is None and nic.vlan is None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic.") if (nic.private_ip_v4 is not None and nic.vlan is not None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic. Not both.") if nic.private_ip_v4 is not None: ET.SubElement(additional_nic, 'privateIpv4').text = nic.private_ip_v4 if nic.vlan is not None: vlan_id = self._vlan_to_vlan_id(nic.vlan) ET.SubElement(additional_nic, 'vlanId').text = vlan_id if nic.network_adapter_name is not None: ET.SubElement(additional_nic, "networkAdapter").text = \ nic.network_adapter_name elif ex_additional_nics is not None: raise TypeError( "ex_additional_NICs must be None or tuple/list") if ex_primary_dns: dns_elm = ET.SubElement(server_elm, "primaryDns") dns_elm.text = ex_primary_dns if ex_secondary_dns: dns_elm = ET.SubElement(server_elm, "secondaryDns") dns_elm.text = ex_secondary_dns if ex_ipv4_gateway: ET.SubElement(server_elm, "ipv4Gateway").text = ex_ipv4_gateway if isinstance(ex_disks, (list, tuple)): for disk in ex_disks: disk_elm = ET.SubElement(server_elm, 'disk') disk_elm.set('scsiId', disk.scsi_id) disk_elm.set('speed', disk.speed) elif ex_disks is not None: raise TypeError("ex_disks must be None or tuple/list") if ex_microsoft_time_zone: ET.SubElement(server_elm, "microsoftTimeZone").text = \ ex_microsoft_time_zone response = self.connection.request_with_orgId_api_2( 'server/deployServer', method='POST', data=ET.tostring(server_elm)).object node_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'serverId': node_id = info.get('value') new_node = self.ex_get_node_by_id(node_id) if image_needs_auth: if getattr(auth_obj, "generated", False): new_node.extra['password'] = auth_obj.password return new_node def destroy_node(self, node): """ Deletes a node, node must be stopped before deletion :keyword node: The node to delete :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('deleteServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/deleteServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def reboot_node(self, node): """ Reboots a node by requesting the OS restart via the hypervisor :keyword node: The node to reboot :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('rebootServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/rebootServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def list_nodes(self, ex_location=None, ex_name=None, ex_ipv6=None, ex_ipv4=None, ex_vlan=None, ex_image=None, ex_deployed=None, ex_started=None, ex_state=None, ex_network=None, ex_network_domain=None): """ List nodes deployed for your organization. :keyword ex_location: Filters the node list to nodes that are located in this location :type ex_location: :class:`NodeLocation` or ``str`` :keyword ex_name: Filters the node list to nodes that have this name :type ex_name ``str`` :keyword ex_ipv6: Filters the node list to nodes that have this ipv6 address :type ex_ipv6: ``str`` :keyword ex_ipv4: Filters the node list to nodes that have this ipv4 address :type ex_ipv4: ``str`` :keyword ex_vlan: Filters the node list to nodes that are in this VLAN :type ex_vlan: :class:`DimensionDataVlan` or ``str`` :keyword ex_image: Filters the node list to nodes that have this image :type ex_image: :class:`NodeImage` or ``str`` :keyword ex_deployed: Filters the node list to nodes that are deployed or not :type ex_deployed: ``bool`` :keyword ex_started: Filters the node list to nodes that are started or not :type ex_started: ``bool`` :keyword ex_state: Filters the node list by nodes that are in this state :type ex_state: ``str`` :keyword ex_network: Filters the node list to nodes in this network :type ex_network: :class:`DimensionDataNetwork` or ``str`` :keyword ex_network_domain: Filters the node list to nodes in this network domain :type ex_network_domain: :class:`DimensionDataNetworkDomain` or ``str`` :return: a list of `Node` objects :rtype: ``list`` of :class:`Node` """ node_list = [] for nodes in self.ex_list_nodes_paginated( location=ex_location, name=ex_name, ipv6=ex_ipv6, ipv4=ex_ipv4, vlan=ex_vlan, image=ex_image, deployed=ex_deployed, started=ex_started, state=ex_state, network=ex_network, network_domain=ex_network_domain): node_list.extend(nodes) return node_list def list_images(self, location=None): """ List images available Note: Currently only returns the default 'base OS images' provided by DimensionData. Customer images (snapshots) use ex_list_customer_images :keyword ex_location: Filters the node list to nodes that are located in this location :type ex_location: :class:`NodeLocation` or ``str`` :return: List of images available :rtype: ``list`` of :class:`NodeImage` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) return self._to_images( self.connection.request_with_orgId_api_2( 'image/osImage', params=params) .object) def list_sizes(self, location=None): """ return a list of available sizes Currently, the size of the node is dictated by the chosen OS base image, they cannot be set explicitly. @inherits: :class:`NodeDriver.list_sizes` """ return [ NodeSize(id=1, name="default", ram=0, disk=0, bandwidth=0, price=0, driver=self.connection.driver), ] def list_locations(self, ex_id=None): """ List locations (datacenters) available for instantiating servers and networks. :keyword ex_id: Filters the location list to this id :type ex_id: ``str`` :return: List of locations :rtype: ``list`` of :class:`NodeLocation` """ params = {} if ex_id is not None: params['id'] = ex_id return self._to_locations( self.connection .request_with_orgId_api_2( 'infrastructure/datacenter', params=params ).object ) def list_networks(self, location=None): """ List networks deployed across all data center locations for your organization. The response includes the location of each network. :keyword location: The location :type location: :class:`NodeLocation` or ``str`` :return: a list of DimensionDataNetwork objects :rtype: ``list`` of :class:`DimensionDataNetwork` """ url_ext = '' if location is not None: url_ext = '/' + self._location_to_location_id(location) return self._to_networks( self.connection .request_with_orgId_api_1('networkWithLocation%s' % url_ext) .object) def import_image(self, ovf_package_name, name, cluster_id=None, datacenter_id=None, description=None, is_guest_os_customization=None, tagkey_name_value_dictionaries=None): """ Import image :param ovf_package_name: Image OVF package name :type ovf_package_name: ``str`` :param name: Image name :type name: ``str`` :param cluster_id: Provide either cluster_id or datacenter_id :type cluster_id: ``str`` :param datacenter_id: Provide either cluster_id or datacenter_id :type datacenter_id: ``str`` :param description: Optional. Description of image :type description: ``str`` :param is_guest_os_customization: Optional. true for NGOC image :type is_guest_os_customization: ``bool`` :param tagkey_name_value_dictionaries: Optional tagkey name value dict :type tagkey_name_value_dictionaries: dictionaries :return: Return true if successful :rtype: ``bool`` """ # Unsupported for version lower than 2.4 if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): raise Exception("import image is feature is NOT supported in " "api version earlier than 2.4") elif cluster_id is None and datacenter_id is None: raise ValueError("Either cluster_id or datacenter_id must be " "provided") elif cluster_id is not None and datacenter_id is not None: raise ValueError("Cannot accept both cluster_id and " "datacenter_id. Please provide either one") else: import_image_elem = ET.Element( 'urn:importImage', { 'xmlns:urn': TYPES_URN, }) ET.SubElement( import_image_elem, 'urn:ovfPackage' ).text = ovf_package_name ET.SubElement( import_image_elem, 'urn:name' ).text = name if description is not None: ET.SubElement( import_image_elem, 'urn:description' ).text = description if cluster_id is not None: ET.SubElement( import_image_elem, 'urn:clusterId' ).text = cluster_id else: ET.SubElement( import_image_elem, 'urn:datacenterId' ).text = datacenter_id if is_guest_os_customization is not None: ET.SubElement( import_image_elem, 'urn:guestOsCustomization' ).text = is_guest_os_customization if len(tagkey_name_value_dictionaries) > 0: for k, v in tagkey_name_value_dictionaries.items(): tag_elem = ET.SubElement( import_image_elem, 'urn:tag') ET.SubElement(tag_elem, 'urn:tagKeyName').text = k if v is not None: ET.SubElement(tag_elem, 'urn:value').text = v response = self.connection.request_with_orgId_api_2( 'image/importImage', method='POST', data=ET.tostring(import_image_elem)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def start_node(self, node): """ Powers on an existing deployed server :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('startServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/startServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def stop_node(self, node): """ This function will attempt to "gracefully" stop a server by initiating a shutdown sequence within the guest operating system. A successful response on this function means the system has successfully passed the request into the operating system. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('shutdownServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/shutdownServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_nodes_paginated(self, name=None, location=None, ipv6=None, ipv4=None, vlan=None, image=None, deployed=None, started=None, state=None, network=None, network_domain=None): """ Return a generator which yields node lists in pages :keyword location: Filters the node list to nodes that are located in this location :type location: :class:`NodeLocation` or ``str`` :keyword name: Filters the node list to nodes that have this name :type name ``str`` :keyword ipv6: Filters the node list to nodes that have this ipv6 address :type ipv6: ``str`` :keyword ipv4: Filters the node list to nodes that have this ipv4 address :type ipv4: ``str`` :keyword vlan: Filters the node list to nodes that are in this VLAN :type vlan: :class:`DimensionDataVlan` or ``str`` :keyword image: Filters the node list to nodes that have this image :type image: :class:`NodeImage` or ``str`` :keyword deployed: Filters the node list to nodes that are deployed or not :type deployed: ``bool`` :keyword started: Filters the node list to nodes that are started or not :type started: ``bool`` :keyword state: Filters the node list to nodes that are in this state :type state: ``str`` :keyword network: Filters the node list to nodes in this network :type network: :class:`DimensionDataNetwork` or ``str`` :keyword network_domain: Filters the node list to nodes in this network domain :type network_domain: :class:`DimensionDataNetworkDomain` or ``str`` :return: a list of `Node` objects :rtype: ``generator`` of `list` of :class:`Node` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) if ipv6 is not None: params['ipv6'] = ipv6 if ipv4 is not None: params['privateIpv4'] = ipv4 if state is not None: params['state'] = state if started is not None: params['started'] = started if deployed is not None: params['deployed'] = deployed if name is not None: params['name'] = name if network_domain is not None: params['networkDomainId'] = \ self._network_domain_to_network_domain_id(network_domain) if network is not None: params['networkId'] = self._network_to_network_id(network) if vlan is not None: params['vlanId'] = self._vlan_to_vlan_id(vlan) if image is not None: params['sourceImageId'] = self._image_to_image_id(image) nodes_obj = self._list_nodes_single_page(params) yield self._to_nodes(nodes_obj) while nodes_obj.get('pageCount') >= nodes_obj.get('pageSize'): params['pageNumber'] = int(nodes_obj.get('pageNumber')) + 1 nodes_obj = self._list_nodes_single_page(params) yield self._to_nodes(nodes_obj) def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_shutdown_graceful(self, node): return self.stop_node(node=node) def ex_power_off(self, node): """ This function will abruptly power-off a server. Unlike ex_shutdown_graceful, success ensures the node will stop but some OS and application configurations may be adversely affected by the equivalent of pulling the power plug out of the machine. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('powerOffServer', {'xmlns': TYPES_URN, 'id': node.id}) try: body = self.connection.request_with_orgId_api_2( 'server/powerOffServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) except (DimensionDataAPIException, NameError, BaseHTTPError): r = self.ex_get_node_by_id(node.id) response_code = r.state.upper() return response_code in ['IN_PROGRESS', 'OK', 'STOPPED', 'STOPPING'] def ex_reset(self, node): """ This function will abruptly reset a server. Unlike reboot_node, success ensures the node will restart but some OS and application configurations may be adversely affected by the equivalent of pulling the power plug out of the machine. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('resetServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/resetServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_update_vm_tools(self, node): """ This function triggers an update of the VMware Tools software running on the guest OS of a Server. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('updateVmwareTools', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/updateVmwareTools', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_update_node(self, node, name=None, description=None, cpu_count=None, ram_mb=None): """ Update the node, the name, CPU or RAM :param node: Node which should be used :type node: :class:`Node` :param name: The new name (optional) :type name: ``str`` :param description: The new description (optional) :type description: ``str`` :param cpu_count: The new CPU count (optional) :type cpu_count: ``int`` :param ram_mb: The new Memory in MB (optional) :type ram_mb: ``int`` :rtype: ``bool`` """ data = {} if name is not None: data['name'] = name if description is not None: data['description'] = description if cpu_count is not None: data['cpuCount'] = str(cpu_count) if ram_mb is not None: data['memory'] = str(ram_mb) body = self.connection.request_with_orgId_api_1( 'server/%s' % (node.id), method='POST', data=urlencode(data, True)).object response_code = findtext(body, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_create_anti_affinity_rule(self, node_list): """ Create an anti affinity rule given a list of nodes Anti affinity rules ensure that servers will not reside on the same VMware ESX host :param node_list: The list of nodes to create a rule for :type node_list: ``list`` of :class:`Node` or ``list`` of ``str`` :rtype: ``bool`` """ if not isinstance(node_list, (list, tuple)): raise TypeError("Node list must be a list or a tuple.") anti_affinity_xml_request = ET.Element('NewAntiAffinityRule', {'xmlns': SERVER_NS}) for node in node_list: ET.SubElement(anti_affinity_xml_request, 'serverId').text = \ self._node_to_node_id(node) result = self.connection.request_with_orgId_api_1( 'antiAffinityRule', method='POST', data=ET.tostring(anti_affinity_xml_request)).object response_code = findtext(result, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_delete_anti_affinity_rule(self, anti_affinity_rule): """ Remove anti affinity rule :param anti_affinity_rule: The anti affinity rule to delete :type anti_affinity_rule: :class:`DimensionDataAntiAffinityRule` or ``str`` :rtype: ``bool`` """ rule_id = self._anti_affinity_rule_to_anti_affinity_rule_id( anti_affinity_rule) result = self.connection.request_with_orgId_api_1( 'antiAffinityRule/%s?delete' % (rule_id), method='GET').object response_code = findtext(result, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_list_anti_affinity_rules(self, network=None, network_domain=None, node=None, filter_id=None, filter_state=None): """ List anti affinity rules for a network, network domain, or node :param network: The network to list anti affinity rules for One of network, network_domain, or node is required :type network: :class:`DimensionDataNetwork` or ``str`` :param network_domain: The network domain to list anti affinity rules One of network, network_domain, or node is required :type network_domain: :class:`DimensionDataNetworkDomain` or ``str`` :param node: The node to list anti affinity rules for One of network, netwok_domain, or node is required :type node: :class:`Node` or ``str`` :param filter_id: This will allow you to filter the rules by this node id :type filter_id: ``str`` :type filter_state: This will allow you to filter rules by node state (i.e. NORMAL) :type filter_state: ``str`` :rtype: ``list`` of :class:`DimensionDataAntiAffinityRule` """ not_none_arguments = [key for key in (network, network_domain, node) if key is not None] if len(not_none_arguments) != 1: raise ValueError("One and ONLY one of network, " "network_domain, or node must be set") params = {} if network_domain is not None: params['networkDomainId'] = \ self._network_domain_to_network_domain_id(network_domain) if network is not None: params['networkId'] = \ self._network_to_network_id(network) if node is not None: params['serverId'] = \ self._node_to_node_id(node) if filter_id is not None: params['id'] = filter_id if filter_state is not None: params['state'] = filter_state paged_result = self.connection.paginated_request_with_orgId_api_2( 'server/antiAffinityRule', method='GET', params=params ) rules = [] for result in paged_result: rules.extend(self._to_anti_affinity_rules(result)) return rules def ex_attach_node_to_vlan(self, node, vlan=None, private_ipv4=None): """ Attach a node to a VLAN by adding an additional NIC to the node on the target VLAN. The IP will be automatically assigned based on the VLAN IP network space. Alternatively, provide a private IPv4 address instead of VLAN information, and this will be assigned to the node on corresponding NIC. :param node: Node which should be used :type node: :class:`Node` :param vlan: VLAN to attach the node to (required unless private_ipv4) :type vlan: :class:`DimensionDataVlan` :keyword private_ipv4: Private nic IPv4 Address (required unless vlan) :type private_ipv4: ``str`` :rtype: ``bool`` """ request = ET.Element('addNic', {'xmlns': TYPES_URN}) ET.SubElement(request, 'serverId').text = node.id nic = ET.SubElement(request, 'nic') if vlan is not None: ET.SubElement(nic, 'vlanId').text = vlan.id elif private_ipv4 is not None: ET.SubElement(nic, 'privateIpv4').text = private_ipv4 else: raise ValueError("One of vlan or primary_ipv4 " "must be specified") response = self.connection.request_with_orgId_api_2( 'server/addNic', method='POST', data=ET.tostring(request)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_destroy_nic(self, nic_id): """ Remove a NIC on a node, removing the node from a VLAN :param nic_id: The identifier of the NIC to remove :type nic_id: ``str`` :rtype: ``bool`` """ request = ET.Element('removeNic', {'xmlns': TYPES_URN, 'id': nic_id}) response = self.connection.request_with_orgId_api_2( 'server/removeNic', method='POST', data=ET.tostring(request)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_networks(self, location=None): """ List networks deployed across all data center locations for your organization. The response includes the location of each network. :param location: The target location :type location: :class:`NodeLocation` or ``str`` :return: a list of DimensionDataNetwork objects :rtype: ``list`` of :class:`DimensionDataNetwork` """ return self.list_networks(location=location) def ex_create_network(self, location, name, description=None): """ Create a new network in an MCP 1.0 location :param location: The target location (MCP1) :type location: :class:`NodeLocation` or ``str`` :param name: The name of the network :type name: ``str`` :param description: Additional description of the network :type description: ``str`` :return: A new instance of `DimensionDataNetwork` :rtype: Instance of :class:`DimensionDataNetwork` """ network_location = self._location_to_location_id(location) create_node = ET.Element('NewNetworkWithLocation', {'xmlns': NETWORK_NS}) ET.SubElement(create_node, "name").text = name if description is not None: ET.SubElement(create_node, "description").text = description ET.SubElement(create_node, "location").text = network_location self.connection.request_with_orgId_api_1( 'networkWithLocation', method='POST', data=ET.tostring(create_node)) # MCP1 API does not return the ID, but name is unique for location network = list( filter(lambda x: x.name == name, self.ex_list_networks(location)))[0] return network def ex_delete_network(self, network): """ Delete a network from an MCP 1 data center :param network: The network to delete :type network: :class:`DimensionDataNetwork` :rtype: ``bool`` """ response = self.connection.request_with_orgId_api_1( 'network/%s?delete' % network.id, method='GET').object response_code = findtext(response, 'result', GENERAL_NS) return response_code == "SUCCESS" def ex_rename_network(self, network, new_name): """ Rename a network in MCP 1 data center :param network: The network to rename :type network: :class:`DimensionDataNetwork` :param new_name: The new name of the network :type new_name: ``str`` :rtype: ``bool`` """ response = self.connection.request_with_orgId_api_1( 'network/%s' % network.id, method='POST', data='name=%s' % new_name).object response_code = findtext(response, 'result', GENERAL_NS) return response_code == "SUCCESS" def ex_get_network_domain(self, network_domain_id): """ Get an individual Network Domain, by identifier :param network_domain_id: The identifier of the network domain :type network_domain_id: ``str`` :rtype: :class:`DimensionDataNetworkDomain` """ locations = self.list_locations() net = self.connection.request_with_orgId_api_2( 'network/networkDomain/%s' % network_domain_id).object return self._to_network_domain(net, locations) def ex_list_network_domains(self, location=None, name=None, service_plan=None, state=None): """ List networks domains deployed across all data center locations domain. for your organization. The response includes the location of each network :param location: Only network domains in the location (optional) :type location: :class:`NodeLocation` or ``str`` :param name: Only network domains of this name (optional) :type name: ``str`` :param service_plan: Only network domains of this type (optional) :type service_plan: ``str`` :param state: Only network domains in this state (optional) :type state: ``str`` :return: a list of `DimensionDataNetwork` objects :rtype: ``list`` of :class:`DimensionDataNetwork` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) if name is not None: params['name'] = name if service_plan is not None: params['type'] = service_plan if state is not None: params['state'] = state response = self.connection \ .request_with_orgId_api_2('network/networkDomain', params=params).object return self._to_network_domains(response) def ex_create_network_domain(self, location, name, service_plan, description=None): """ Deploy a new network domain to a data center :param location: The data center to list :type location: :class:`NodeLocation` or ``str`` :param name: The name of the network domain to create :type name: ``str`` :param service_plan: The service plan, either "ESSENTIALS" or "ADVANCED" :type service_plan: ``str`` :param description: An additional description of the network domain :type description: ``str`` :return: an instance of `DimensionDataNetworkDomain` :rtype: :class:`DimensionDataNetworkDomain` """ create_node = ET.Element('deployNetworkDomain', {'xmlns': TYPES_URN}) ET.SubElement( create_node, "datacenterId" ).text = self._location_to_location_id(location) ET.SubElement(create_node, "name").text = name if description is not None: ET.SubElement(create_node, "description").text = description ET.SubElement(create_node, "type").text = service_plan response = self.connection.request_with_orgId_api_2( 'network/deployNetworkDomain', method='POST', data=ET.tostring(create_node)).object network_domain_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'networkDomainId': network_domain_id = info.get('value') return DimensionDataNetworkDomain( id=network_domain_id, name=name, description=description, location=location, status=NodeState.RUNNING, plan=service_plan ) def ex_update_network_domain(self, network_domain): """ Update the properties of a network domain :param network_domain: The network domain with updated properties :type network_domain: :class:`DimensionDataNetworkDomain` :return: an instance of `DimensionDataNetworkDomain` :rtype: :class:`DimensionDataNetworkDomain` """ edit_node = ET.Element('editNetworkDomain', {'xmlns': TYPES_URN}) edit_node.set('id', network_domain.id) ET.SubElement(edit_node, "name").text = network_domain.name if network_domain.description is not None: ET.SubElement(edit_node, "description").text \ = network_domain.description ET.SubElement(edit_node, "type").text = network_domain.plan self.connection.request_with_orgId_api_2( 'network/editNetworkDomain', method='POST', data=ET.tostring(edit_node)).object return network_domain def ex_delete_network_domain(self, network_domain): """ Delete a network domain :param network_domain: The network domain to delete :type network_domain: :class:`DimensionDataNetworkDomain` :rtype: ``bool`` """ delete_node = ET.Element('deleteNetworkDomain', {'xmlns': TYPES_URN}) delete_node.set('id', network_domain.id) result = self.connection.request_with_orgId_api_2( 'network/deleteNetworkDomain', method='POST', data=ET.tostring(delete_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_vlan(self, network_domain, name, private_ipv4_base_address, description=None, private_ipv4_prefix_size=24): """ Deploy a new VLAN to a network domain :param network_domain: The network domain to add the VLAN to :type network_domain: :class:`DimensionDataNetworkDomain` :param name: The name of the VLAN to create :type name: ``str`` :param private_ipv4_base_address: The base IPv4 address e.g. 192.168.1.0 :type private_ipv4_base_address: ``str`` :param description: An additional description of the VLAN :type description: ``str`` :param private_ipv4_prefix_size: The size of the IPv4 address space, e.g 24 :type private_ipv4_prefix_size: ``int`` :return: an instance of `DimensionDataVlan` :rtype: :class:`DimensionDataVlan` """ create_node = ET.Element('deployVlan', {'xmlns': TYPES_URN}) ET.SubElement(create_node, "networkDomainId").text = network_domain.id ET.SubElement(create_node, "name").text = name if description is not None: ET.SubElement(create_node, "description").text = description ET.SubElement(create_node, "privateIpv4BaseAddress").text = \ private_ipv4_base_address ET.SubElement(create_node, "privateIpv4PrefixSize").text = \ str(private_ipv4_prefix_size) response = self.connection.request_with_orgId_api_2( 'network/deployVlan', method='POST', data=ET.tostring(create_node)).object vlan_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'vlanId': vlan_id = info.get('value') return self.ex_get_vlan(vlan_id) def ex_get_vlan(self, vlan_id): """ Get a single VLAN, by it's identifier :param vlan_id: The identifier of the VLAN :type vlan_id: ``str`` :return: an instance of `DimensionDataVlan` :rtype: :class:`DimensionDataVlan` """ locations = self.list_locations() vlan = self.connection.request_with_orgId_api_2( 'network/vlan/%s' % vlan_id).object return self._to_vlan(vlan, locations) def ex_update_vlan(self, vlan): """ Updates the properties of the given VLAN Only name and description are updated :param vlan: The VLAN to update :type vlan: :class:`DimensionDataNetworkDomain` :return: an instance of `DimensionDataVlan` :rtype: :class:`DimensionDataVlan` """ edit_node = ET.Element('editVlan', {'xmlns': TYPES_URN}) edit_node.set('id', vlan.id) ET.SubElement(edit_node, "name").text = vlan.name if vlan.description is not None: ET.SubElement(edit_node, "description").text \ = vlan.description self.connection.request_with_orgId_api_2( 'network/editVlan', method='POST', data=ET.tostring(edit_node)).object return vlan def ex_expand_vlan(self, vlan): """ Expands the VLAN to the prefix size in private_ipv4_range_size The expansion will not be permitted if the proposed IP space overlaps with an already deployed VLANs IP space. :param vlan: The VLAN to update :type vlan: :class:`DimensionDataNetworkDomain` :return: an instance of `DimensionDataVlan` :rtype: :class:`DimensionDataVlan` """ edit_node = ET.Element('expandVlan', {'xmlns': TYPES_URN}) edit_node.set('id', vlan.id) ET.SubElement(edit_node, "privateIpv4PrefixSize").text =\ vlan.private_ipv4_range_size self.connection.request_with_orgId_api_2( 'network/expandVlan', method='POST', data=ET.tostring(edit_node)).object return vlan def ex_delete_vlan(self, vlan): """ Deletes an existing VLAN :param vlan: The VLAN to delete :type vlan: :class:`DimensionDataNetworkDomain` :rtype: ``bool`` """ delete_node = ET.Element('deleteVlan', {'xmlns': TYPES_URN}) delete_node.set('id', vlan.id) result = self.connection.request_with_orgId_api_2( 'network/deleteVlan', method='POST', data=ET.tostring(delete_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_vlans(self, location=None, network_domain=None, name=None, ipv4_address=None, ipv6_address=None, state=None): """ List VLANs available, can filter by location and/or network domain :param location: Only VLANs in this location (optional) :type location: :class:`NodeLocation` or ``str`` :param network_domain: Only VLANs in this domain (optional) :type network_domain: :class:`DimensionDataNetworkDomain` :param name: Only VLANs with this name (optional) :type name: ``str`` :param ipv4_address: Only VLANs with this ipv4 address (optional) :type ipv4_address: ``str`` :param ipv6_address: Only VLANs with this ipv6 address (optional) :type ipv6_address: ``str`` :param state: Only VLANs with this state (optional) :type state: ``str`` :return: a list of DimensionDataVlan objects :rtype: ``list`` of :class:`DimensionDataVlan` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) if network_domain is not None: params['networkDomainId'] = \ self._network_domain_to_network_domain_id(network_domain) if name is not None: params['name'] = name if ipv4_address is not None: params['privateIpv4Address'] = ipv4_address if ipv6_address is not None: params['ipv6Address'] = ipv6_address if state is not None: params['state'] = state response = self.connection.request_with_orgId_api_2('network/vlan', params=params) \ .object return self._to_vlans(response) def ex_add_public_ip_block_to_network_domain(self, network_domain): add_node = ET.Element('addPublicIpBlock', {'xmlns': TYPES_URN}) ET.SubElement(add_node, "networkDomainId").text =\ network_domain.id response = self.connection.request_with_orgId_api_2( 'network/addPublicIpBlock', method='POST', data=ET.tostring(add_node)).object block_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'ipBlockId': block_id = info.get('value') return self.ex_get_public_ip_block(block_id) def ex_list_public_ip_blocks(self, network_domain): params = {} params['networkDomainId'] = network_domain.id response = self.connection \ .request_with_orgId_api_2('network/publicIpBlock', params=params).object return self._to_ip_blocks(response) def ex_get_public_ip_block(self, block_id): locations = self.list_locations() block = self.connection.request_with_orgId_api_2( 'network/publicIpBlock/%s' % block_id).object return self._to_ip_block(block, locations) def ex_delete_public_ip_block(self, block): delete_node = ET.Element('removePublicIpBlock', {'xmlns': TYPES_URN}) delete_node.set('id', block.id) result = self.connection.request_with_orgId_api_2( 'network/removePublicIpBlock', method='POST', data=ET.tostring(delete_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_node_by_id(self, id): node = self.connection.request_with_orgId_api_2( 'server/server/%s' % id).object return self._to_node(node) def ex_list_firewall_rules(self, network_domain, page_size=50, page_number=1): params = {'pageSize': page_size, 'pageNumber': page_number} params['networkDomainId'] = self._network_domain_to_network_domain_id( network_domain) response = self.connection \ .request_with_orgId_api_2('network/firewallRule', params=params).object return self._to_firewall_rules(response, network_domain) def ex_create_firewall_rule(self, network_domain, rule, position, position_relative_to_rule=None): """ Creates a firewall rule :param network_domain: The network domain in which to create the firewall rule :type network_domain: :class:`DimensionDataNetworkDomain` or ``str`` :param rule: The rule in which to create :type rule: :class:`DimensionDataFirewallRule` :param position: The position in which to create the rule There are two types of positions with position_relative_to_rule arg and without it With: 'BEFORE' or 'AFTER' Without: 'FIRST' or 'LAST' :type position: ``str`` :param position_relative_to_rule: The rule or rule name in which to decide positioning by :type position_relative_to_rule: :class:`DimensionDataFirewallRule` or ``str`` :rtype: ``bool`` """ positions_without_rule = ('FIRST', 'LAST') positions_with_rule = ('BEFORE', 'AFTER') create_node = ET.Element('createFirewallRule', {'xmlns': TYPES_URN}) ET.SubElement(create_node, "networkDomainId").text = \ self._network_domain_to_network_domain_id(network_domain) ET.SubElement(create_node, "name").text = rule.name ET.SubElement(create_node, "action").text = rule.action ET.SubElement(create_node, "ipVersion").text = rule.ip_version ET.SubElement(create_node, "protocol").text = rule.protocol # Setup source port rule source = ET.SubElement(create_node, "source") if rule.source.address_list_id is not None: source_ip = ET.SubElement(source, 'ipAddressListId') source_ip.text = rule.source.address_list_id else: source_ip = ET.SubElement(source, 'ip') if rule.source.any_ip: source_ip.set('address', 'ANY') else: source_ip.set('address', rule.source.ip_address) if rule.source.ip_prefix_size is not None: source_ip.set('prefixSize', str(rule.source.ip_prefix_size)) if rule.source.port_list_id is not None: source_port = ET.SubElement(source, 'portListId') source_port.text = rule.source.port_list_id else: if rule.source.port_begin is not None: source_port = ET.SubElement(source, 'port') source_port.set('begin', rule.source.port_begin) if rule.source.port_end is not None: source_port.set('end', rule.source.port_end) # Setup destination port rule dest = ET.SubElement(create_node, "destination") if rule.destination.address_list_id is not None: dest_ip = ET.SubElement(dest, 'ipAddressListId') dest_ip.text = rule.destination.address_list_id else: dest_ip = ET.SubElement(dest, 'ip') if rule.destination.any_ip: dest_ip.set('address', 'ANY') else: dest_ip.set('address', rule.destination.ip_address) if rule.destination.ip_prefix_size is not None: dest_ip.set('prefixSize', rule.destination.ip_prefix_size) if rule.destination.port_list_id is not None: dest_port = ET.SubElement(dest, 'portListId') dest_port.text = rule.destination.port_list_id else: if rule.destination.port_begin is not None: dest_port = ET.SubElement(dest, 'port') dest_port.set('begin', rule.destination.port_begin) if rule.destination.port_end is not None: dest_port.set('end', rule.destination.port_end) # Set up positioning of rule ET.SubElement(create_node, "enabled").text = str(rule.enabled).lower() placement = ET.SubElement(create_node, "placement") if position_relative_to_rule is not None: if position not in positions_with_rule: raise ValueError("When position_relative_to_rule is specified" " position must be %s" % ', '.join(positions_with_rule)) if isinstance(position_relative_to_rule, DimensionDataFirewallRule): rule_name = position_relative_to_rule.name else: rule_name = position_relative_to_rule placement.set('relativeToRule', rule_name) else: if position not in positions_without_rule: raise ValueError("When position_relative_to_rule is not" " specified position must be %s" % ', '.join(positions_without_rule)) placement.set('position', position) response = self.connection.request_with_orgId_api_2( 'network/createFirewallRule', method='POST', data=ET.tostring(create_node)).object rule_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'firewallRuleId': rule_id = info.get('value') rule.id = rule_id return rule def ex_edit_firewall_rule(self, rule, position, relative_rule_for_position=None): """ Edit a firewall rule >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> >>> # List firewall rules >>> firewall_rules = driver.ex_list_firewall_rules(my_network_domain) >>> >>> # Get Firewall Rule by name >>> pprint("List specific firewall rule by name") >>> fire_rule_under_test = (list(filter(lambda x: x.name == 'My_New_Firewall_Rule', firewall_rules))[0]) >>> pprint(fire_rule_under_test.source) >>> pprint(fire_rule_under_test.destination) >>> >>> # Edit Firewall >>> fire_rule_under_test.destination.address_list_id = '5e7c323f-c885-4e4b-9a27-94c44217dbd3' >>> fire_rule_under_test.destination.port_list_id = 'b6557c5a-45fa-4138-89bd-8fe68392691b' >>> result = driver.ex_edit_firewall_rule(fire_rule_under_test, 'LAST') >>> pprint(result) :param rule: (required) The rule in which to create :type rule: :class:`DimensionDataFirewallRule` :param position: (required) There are two types of positions with position_relative_to_rule arg and without it With: 'BEFORE' or 'AFTER' Without: 'FIRST' or 'LAST' :type position: ``str`` :param relative_rule_for_position: (optional) The rule or rule name in which to decide the relative rule for positioning. :type relative_rule_for_position: :class:`DimensionDataFirewallRule` or ``str`` :rtype: ``bool`` """ positions_without_rule = ('FIRST', 'LAST') positions_with_rule = ('BEFORE', 'AFTER') edit_node = ET.Element('editFirewallRule', {'xmlns': TYPES_URN, 'id': rule.id}) ET.SubElement(edit_node, "action").text = rule.action ET.SubElement(edit_node, "protocol").text = rule.protocol # Source address source = ET.SubElement(edit_node, "source") if rule.source.address_list_id is not None: source_ip = ET.SubElement(source, 'ipAddressListId') source_ip.text = rule.source.address_list_id else: source_ip = ET.SubElement(source, 'ip') if rule.source.any_ip: source_ip.set('address', 'ANY') else: source_ip.set('address', rule.source.ip_address) if rule.source.ip_prefix_size is not None: source_ip.set('prefixSize', str(rule.source.ip_prefix_size)) # Setup source port rule if rule.source.port_list_id is not None: source_port = ET.SubElement(source, 'portListId') source_port.text = rule.source.port_list_id else: if rule.source.port_begin is not None: source_port = ET.SubElement(source, 'port') source_port.set('begin', rule.source.port_begin) if rule.source.port_end is not None: source_port.set('end', rule.source.port_end) # Setup destination port rule dest = ET.SubElement(edit_node, "destination") if rule.destination.address_list_id is not None: dest_ip = ET.SubElement(dest, 'ipAddressListId') dest_ip.text = rule.destination.address_list_id else: dest_ip = ET.SubElement(dest, 'ip') if rule.destination.any_ip: dest_ip.set('address', 'ANY') else: dest_ip.set('address', rule.destination.ip_address) if rule.destination.ip_prefix_size is not None: dest_ip.set('prefixSize', rule.destination.ip_prefix_size) if rule.destination.port_list_id is not None: dest_port = ET.SubElement(dest, 'portListId') dest_port.text = rule.destination.port_list_id else: if rule.destination.port_begin is not None: dest_port = ET.SubElement(dest, 'port') dest_port.set('begin', rule.destination.port_begin) if rule.destination.port_end is not None: dest_port.set('end', rule.destination.port_end) # Set up positioning of rule ET.SubElement(edit_node, "enabled").text = str(rule.enabled).lower() placement = ET.SubElement(edit_node, "placement") if relative_rule_for_position is not None: if position not in positions_with_rule: raise ValueError("When position_relative_to_rule is specified" " position must be %s" % ', '.join(positions_with_rule)) if isinstance(relative_rule_for_position, DimensionDataFirewallRule): rule_name = relative_rule_for_position.name else: rule_name = relative_rule_for_position placement.set('relativeToRule', rule_name) else: if position not in positions_without_rule: raise ValueError("When position_relative_to_rule is not" " specified position must be %s" % ', '.join(positions_without_rule)) placement.set('position', position) response = self.connection.request_with_orgId_api_2( 'network/editFirewallRule', method='POST', data=ET.tostring(edit_node)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_firewall_rule(self, network_domain, rule_id): locations = self.list_locations() rule = self.connection.request_with_orgId_api_2( 'network/firewallRule/%s' % rule_id).object return self._to_firewall_rule(rule, locations, network_domain) def ex_set_firewall_rule_state(self, rule, state): """ Change the state (enabled or disabled) of a rule :param rule: The rule to delete :type rule: :class:`DimensionDataFirewallRule` :param state: The desired state enabled (True) or disabled (False) :type state: ``bool`` :rtype: ``bool`` """ update_node = ET.Element('editFirewallRule', {'xmlns': TYPES_URN}) update_node.set('id', rule.id) ET.SubElement(update_node, 'enabled').text = str(state).lower() result = self.connection.request_with_orgId_api_2( 'network/editFirewallRule', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_firewall_rule(self, rule): """ Delete a firewall rule :param rule: The rule to delete :type rule: :class:`DimensionDataFirewallRule` :rtype: ``bool`` """ update_node = ET.Element('deleteFirewallRule', {'xmlns': TYPES_URN}) update_node.set('id', rule.id) result = self.connection.request_with_orgId_api_2( 'network/deleteFirewallRule', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_nat_rule(self, network_domain, internal_ip, external_ip): """ Create a NAT rule :param network_domain: The network domain the rule belongs to :type network_domain: :class:`DimensionDataNetworkDomain` :param internal_ip: The IPv4 address internally :type internal_ip: ``str`` :param external_ip: The IPv4 address externally :type external_ip: ``str`` :rtype: :class:`DimensionDataNatRule` """ create_node = ET.Element('createNatRule', {'xmlns': TYPES_URN}) ET.SubElement(create_node, 'networkDomainId').text = network_domain.id ET.SubElement(create_node, 'internalIp').text = internal_ip ET.SubElement(create_node, 'externalIp').text = external_ip result = self.connection.request_with_orgId_api_2( 'network/createNatRule', method='POST', data=ET.tostring(create_node)).object rule_id = None for info in findall(result, 'info', TYPES_URN): if info.get('name') == 'natRuleId': rule_id = info.get('value') return DimensionDataNatRule( id=rule_id, network_domain=network_domain, internal_ip=internal_ip, external_ip=external_ip, status=NodeState.RUNNING ) def ex_list_nat_rules(self, network_domain): """ Get NAT rules for the network domain :param network_domain: The network domain the rules belongs to :type network_domain: :class:`DimensionDataNetworkDomain` :rtype: ``list`` of :class:`DimensionDataNatRule` """ params = {} params['networkDomainId'] = network_domain.id response = self.connection \ .request_with_orgId_api_2('network/natRule', params=params).object return self._to_nat_rules(response, network_domain) def ex_get_nat_rule(self, network_domain, rule_id): """ Get a NAT rule by ID :param network_domain: The network domain the rule belongs to :type network_domain: :class:`DimensionDataNetworkDomain` :param rule_id: The ID of the NAT rule to fetch :type rule_id: ``str`` :rtype: :class:`DimensionDataNatRule` """ rule = self.connection.request_with_orgId_api_2( 'network/natRule/%s' % rule_id).object return self._to_nat_rule(rule, network_domain) def ex_delete_nat_rule(self, rule): """ Delete an existing NAT rule :param rule: The rule to delete :type rule: :class:`DimensionDataNatRule` :rtype: ``bool`` """ update_node = ET.Element('deleteNatRule', {'xmlns': TYPES_URN}) update_node.set('id', rule.id) result = self.connection.request_with_orgId_api_2( 'network/deleteNatRule', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_location_by_id(self, id): """ Get location by ID. :param id: ID of the node location which should be used :type id: ``str`` :rtype: :class:`NodeLocation` """ location = None if id is not None: location = self.list_locations(ex_id=id)[0] return location def ex_wait_for_state(self, state, func, poll_interval=2, timeout=60, *args, **kwargs): """ Wait for the function which returns a instance with field status to match Keep polling func until one of the desired states is matched :param state: Either the desired state (`str`) or a `list` of states :type state: ``str`` or ``list`` :param func: The function to call, e.g. ex_get_vlan :type func: ``function`` :param poll_interval: The number of seconds to wait between checks :type poll_interval: `int` :param timeout: The total number of seconds to wait to reach a state :type timeout: `int` :param args: The arguments for func :type args: Positional arguments :param kwargs: The arguments for func :type kwargs: Keyword arguments """ return self.connection.wait_for_state(state, func, poll_interval, timeout, *args, **kwargs) def ex_enable_monitoring(self, node, service_plan="ESSENTIALS"): """ Enables cloud monitoring on a node :param node: The node to monitor :type node: :class:`Node` :param service_plan: The service plan, one of ESSENTIALS or ADVANCED :type service_plan: ``str`` :rtype: ``bool`` """ update_node = ET.Element('enableServerMonitoring', {'xmlns': TYPES_URN}) update_node.set('id', node.id) ET.SubElement(update_node, 'servicePlan').text = service_plan result = self.connection.request_with_orgId_api_2( 'server/enableServerMonitoring', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_update_monitoring_plan(self, node, service_plan="ESSENTIALS"): """ Updates the service plan on a node with monitoring :param node: The node to monitor :type node: :class:`Node` :param service_plan: The service plan, one of ESSENTIALS or ADVANCED :type service_plan: ``str`` :rtype: ``bool`` """ update_node = ET.Element('changeServerMonitoringPlan', {'xmlns': TYPES_URN}) update_node.set('id', node.id) ET.SubElement(update_node, 'servicePlan').text = service_plan result = self.connection.request_with_orgId_api_2( 'server/changeServerMonitoringPlan', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_disable_monitoring(self, node): """ Disables cloud monitoring for a node :param node: The node to stop monitoring :type node: :class:`Node` :rtype: ``bool`` """ update_node = ET.Element('disableServerMonitoring', {'xmlns': TYPES_URN}) update_node.set('id', node.id) result = self.connection.request_with_orgId_api_2( 'server/disableServerMonitoring', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_add_storage_to_node(self, node, amount, speed='STANDARD', scsi_id=None): """ Add storage to the node :param node: The server to add storage to :type node: :class:`Node` :param amount: The amount of storage to add, in GB :type amount: ``int`` :param speed: The disk speed type :type speed: ``str`` :param scsi_id: The target SCSI ID (optional) :type scsi_id: ``int`` :rtype: ``bool`` """ update_node = ET.Element('addDisk', {'xmlns': TYPES_URN}) update_node.set('id', node.id) ET.SubElement(update_node, 'sizeGb').text = str(amount) ET.SubElement(update_node, 'speed').text = speed.upper() if scsi_id is not None: ET.SubElement(update_node, 'scsiId').text = str(scsi_id) result = self.connection.request_with_orgId_api_2( 'server/addDisk', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_remove_storage_from_node(self, node, scsi_id): """ Remove storage from a node :param node: The server to add storage to :type node: :class:`Node` :param scsi_id: The ID of the disk to remove :type scsi_id: ``str`` :rtype: ``bool`` """ disk = [disk for disk in node.extra['disks'] if disk.scsi_id == scsi_id][0] return self.ex_remove_storage(disk.id) def ex_remove_storage(self, disk_id): """ Remove storage from a node :param node: The server to add storage to :type node: :class:`Node` :param disk_id: The ID of the disk to remove :type disk_id: ``str`` :rtype: ``bool`` """ remove_disk = ET.Element('removeDisk', {'xmlns': TYPES_URN}) remove_disk.set('id', disk_id) result = self.connection.request_with_orgId_api_2( 'server/removeDisk', method='POST', data=ET.tostring(remove_disk)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_change_storage_speed(self, node, disk_id, speed): """ Change the speed (disk tier) of a disk :param node: The server to change the disk speed of :type node: :class:`Node` :param disk_id: The ID of the disk to change :type disk_id: ``str`` :param speed: The disk speed type e.g. STANDARD :type speed: ``str`` :rtype: ``bool`` """ create_node = ET.Element('ChangeDiskSpeed', {'xmlns': SERVER_NS}) ET.SubElement(create_node, 'speed').text = speed result = self.connection.request_with_orgId_api_1( 'server/%s/disk/%s/changeSpeed' % (node.id, disk_id), method='POST', data=ET.tostring(create_node)).object response_code = findtext(result, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_change_storage_size(self, node, disk_id, size): """ Change the size of a disk :param node: The server to change the disk of :type node: :class:`Node` :param disk_id: The ID of the disk to resize :type disk_id: ``str`` :param size: The disk size in GB :type size: ``int`` :rtype: ``bool`` """ create_node = ET.Element('ChangeDiskSize', {'xmlns': SERVER_NS}) ET.SubElement(create_node, 'newSizeGb').text = str(size) result = self.connection.request_with_orgId_api_1( 'server/%s/disk/%s/changeSize' % (node.id, disk_id), method='POST', data=ET.tostring(create_node)).object response_code = findtext(result, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_reconfigure_node(self, node, memory_gb, cpu_count, cores_per_socket, cpu_performance): """ Reconfigure the virtual hardware specification of a node :param node: The server to change :type node: :class:`Node` :param memory_gb: The amount of memory in GB (optional) :type memory_gb: ``int`` :param cpu_count: The number of CPU (optional) :type cpu_count: ``int`` :param cores_per_socket: Number of CPU cores per socket (optional) :type cores_per_socket: ``int`` :param cpu_performance: CPU Performance type (optional) :type cpu_performance: ``str`` :rtype: ``bool`` """ update = ET.Element('reconfigureServer', {'xmlns': TYPES_URN}) update.set('id', node.id) if memory_gb is not None: ET.SubElement(update, 'memoryGb').text = str(memory_gb) if cpu_count is not None: ET.SubElement(update, 'cpuCount').text = str(cpu_count) if cpu_performance is not None: ET.SubElement(update, 'cpuSpeed').text = cpu_performance if cores_per_socket is not None: ET.SubElement(update, 'coresPerSocket').text = \ str(cores_per_socket) result = self.connection.request_with_orgId_api_2( 'server/reconfigureServer', method='POST', data=ET.tostring(update)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_clone_node_to_image(self, node, image_name, image_description=None, cluster_id=None, is_guest_Os_Customization=None, tag_key_id=None, tag_value=None): """ Clone a server into a customer image. :param node: The server to clone :type node: :class:`Node` :param image_name: The name of the clone image :type image_name: ``str`` :param description: The description of the image :type description: ``str`` :rtype: ``bool`` """ if image_description is None: image_description = '' node_id = self._node_to_node_id(node) # Version 2.3 and lower if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): response = self.connection.request_with_orgId_api_1( 'server/%s?clone=%s&desc=%s' % (node_id, image_name, image_description)).object # Version 2.4 and higher else: clone_server_elem = ET.Element('cloneServer', {'id': node_id, 'xmlns': TYPES_URN}) ET.SubElement(clone_server_elem, 'imageName').text = image_name if image_description is not None: ET.SubElement(clone_server_elem, 'description').text = \ image_description if cluster_id is not None: ET.SubElement(clone_server_elem, 'clusterId').text = \ cluster_id if is_guest_Os_Customization is not None: ET.SubElement(clone_server_elem, 'guestOsCustomization')\ .text = is_guest_Os_Customization if tag_key_id is not None: tag_elem = ET.SubElement(clone_server_elem, 'tagById') ET.SubElement(tag_elem, 'tagKeyId').text = tag_key_id if tag_value is not None: ET.SubElement(tag_elem, 'value').text = tag_value response = self.connection.request_with_orgId_api_2( 'server/cloneServer', method='POST', data=ET.tostring(clone_server_elem)).object # Version 2.3 and lower if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): response_code = findtext(response, 'result', GENERAL_NS) else: response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_clean_failed_deployment(self, node): """ Removes a node that has failed to deploy :param node: The failed node to clean :type node: :class:`Node` or ``str`` """ node_id = self._node_to_node_id(node) request_elm = ET.Element('cleanServer', {'xmlns': TYPES_URN, 'id': node_id}) body = self.connection.request_with_orgId_api_2( 'server/cleanServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_customer_images(self, location=None): """ Return a list of customer imported images :param location: The target location :type location: :class:`NodeLocation` or ``str`` :rtype: ``list`` of :class:`NodeImage` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) return self._to_images( self.connection.request_with_orgId_api_2( 'image/customerImage', params=params) .object, 'customerImage') def ex_get_base_image_by_id(self, id): """ Gets a Base image in the Dimension Data Cloud given the id :param id: The id of the image :type id: ``str`` :rtype: :class:`NodeImage` """ image = self.connection.request_with_orgId_api_2( 'image/osImage/%s' % id).object return self._to_image(image) def ex_get_customer_image_by_id(self, id): """ Gets a Customer image in the Dimension Data Cloud given the id :param id: The id of the image :type id: ``str`` :rtype: :class:`NodeImage` """ image = self.connection.request_with_orgId_api_2( 'image/customerImage/%s' % id).object return self._to_image(image) def ex_get_image_by_id(self, id): """ Gets a Base/Customer image in the Dimension Data Cloud given the id Note: This first checks the base image If it is not a base image we check if it is a customer image If it is not in either of these a DimensionDataAPIException is thrown :param id: The id of the image :type id: ``str`` :rtype: :class:`NodeImage` """ try: return self.ex_get_base_image_by_id(id) except DimensionDataAPIException as e: if e.code != 'RESOURCE_NOT_FOUND': raise e return self.ex_get_customer_image_by_id(id) def ex_create_tag_key(self, name, description=None, value_required=True, display_on_report=True): """ Creates a tag key in the Dimension Data Cloud :param name: The name of the tag key (required) :type name: ``str`` :param description: The description of the tag key :type description: ``str`` :param value_required: If a value is required for the tag Tags themselves can be just a tag, or be a key/value pair :type value_required: ``bool`` :param display_on_report: Should this key show up on the usage reports :type display_on_report: ``bool`` :rtype: ``bool`` """ create_tag_key = ET.Element('createTagKey', {'xmlns': TYPES_URN}) ET.SubElement(create_tag_key, 'name').text = name if description is not None: ET.SubElement(create_tag_key, 'description').text = description ET.SubElement(create_tag_key, 'valueRequired').text = \ str(value_required).lower() ET.SubElement(create_tag_key, 'displayOnReport').text = \ str(display_on_report).lower() response = self.connection.request_with_orgId_api_2( 'tag/createTagKey', method='POST', data=ET.tostring(create_tag_key)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_tag_keys(self, id=None, name=None, value_required=None, display_on_report=None): """ List tag keys in the Dimension Data Cloud :param id: Filter the list to the id of the tag key :type id: ``str`` :param name: Filter the list to the name of the tag key :type name: ``str`` :param value_required: Filter the list to if a value is required for a tag key :type value_required: ``bool`` :param display_on_report: Filter the list to if the tag key should show up on usage reports :type display_on_report: ``bool`` :rtype: ``list`` of :class:`DimensionDataTagKey` """ params = {} if id is not None: params['id'] = id if name is not None: params['name'] = name if value_required is not None: params['valueRequired'] = str(value_required).lower() if display_on_report is not None: params['displayOnReport'] = str(display_on_report).lower() paged_result = self.connection.paginated_request_with_orgId_api_2( 'tag/tagKey', method='GET', params=params ) tag_keys = [] for result in paged_result: tag_keys.extend(self._to_tag_keys(result)) return tag_keys def ex_get_tag_key_by_id(self, id): """ Get a specific tag key by ID :param id: ID of the tag key you want (required) :type id: ``str`` :rtype: :class:`DimensionDataTagKey` """ tag_key = self.connection.request_with_orgId_api_2( 'tag/tagKey/%s' % id).object return self._to_tag_key(tag_key) def ex_get_tag_key_by_name(self, name): """ Get a specific tag key by Name :param name: Name of the tag key you want (required) :type name: ``str`` :rtype: :class:`DimensionDataTagKey` """ tag_keys = self.ex_list_tag_keys(name=name) if len(tag_keys) != 1: raise ValueError("No tags found with name %s" % name) return tag_keys[0] def ex_modify_tag_key(self, tag_key, name=None, description=None, value_required=None, display_on_report=None): """ Modify a specific tag key :param tag_key: The tag key you want to modify (required) :type tag_key: :class:`DimensionDataTagKey` or ``str`` :param name: Set to modifiy the name of the tag key :type name: ``str`` :param description: Set to modify the description of the tag key :type description: ``str`` :param value_required: Set to modify if a value is required for the tag key :type value_required: ``bool`` :param display_on_report: Set to modify if this tag key should display on the usage reports :type display_on_report: ``bool`` :rtype: ``bool`` """ tag_key_id = self._tag_key_to_tag_key_id(tag_key) modify_tag_key = ET.Element('editTagKey', {'xmlns': TYPES_URN, 'id': tag_key_id}) if name is not None: ET.SubElement(modify_tag_key, 'name').text = name if description is not None: ET.SubElement(modify_tag_key, 'description').text = description if value_required is not None: ET.SubElement(modify_tag_key, 'valueRequired').text = \ str(value_required).lower() if display_on_report is not None: ET.SubElement(modify_tag_key, 'displayOnReport').text = \ str(display_on_report).lower() response = self.connection.request_with_orgId_api_2( 'tag/editTagKey', method='POST', data=ET.tostring(modify_tag_key)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_remove_tag_key(self, tag_key): """ Modify a specific tag key :param tag_key: The tag key you want to remove (required) :type tag_key: :class:`DimensionDataTagKey` or ``str`` :rtype: ``bool`` """ tag_key_id = self._tag_key_to_tag_key_id(tag_key) remove_tag_key = ET.Element('deleteTagKey', {'xmlns': TYPES_URN, 'id': tag_key_id}) response = self.connection.request_with_orgId_api_2( 'tag/deleteTagKey', method='POST', data=ET.tostring(remove_tag_key)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_apply_tag_to_asset(self, asset, tag_key, value=None): """ Apply a tag to a Dimension Data Asset :param asset: The asset to apply a tag to. (required) :type asset: :class:`Node` or :class:`NodeImage` or :class:`DimensionDataNewtorkDomain` or :class:`DimensionDataVlan` or :class:`DimensionDataPublicIpBlock` :param tag_key: The tag_key to apply to the asset. (required) :type tag_key: :class:`DimensionDataTagKey` or ``str`` :param value: The value to be assigned to the tag key This is only required if the :class:`DimensionDataTagKey` requires it :type value: ``str`` :rtype: ``bool`` """ asset_type = self._get_tagging_asset_type(asset) tag_key_name = self._tag_key_to_tag_key_name(tag_key) apply_tags = ET.Element('applyTags', {'xmlns': TYPES_URN}) ET.SubElement(apply_tags, 'assetType').text = asset_type ET.SubElement(apply_tags, 'assetId').text = asset.id tag_ele = ET.SubElement(apply_tags, 'tag') ET.SubElement(tag_ele, 'tagKeyName').text = tag_key_name if value is not None: ET.SubElement(tag_ele, 'value').text = value response = self.connection.request_with_orgId_api_2( 'tag/applyTags', method='POST', data=ET.tostring(apply_tags)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_remove_tag_from_asset(self, asset, tag_key): """ Remove a tag from an asset :param asset: The asset to remove a tag from. (required) :type asset: :class:`Node` or :class:`NodeImage` or :class:`DimensionDataNewtorkDomain` or :class:`DimensionDataVlan` or :class:`DimensionDataPublicIpBlock` :param tag_key: The tag key you want to remove (required) :type tag_key: :class:`DimensionDataTagKey` or ``str`` :rtype: ``bool`` """ asset_type = self._get_tagging_asset_type(asset) tag_key_name = self._tag_key_to_tag_key_name(tag_key) apply_tags = ET.Element('removeTags', {'xmlns': TYPES_URN}) ET.SubElement(apply_tags, 'assetType').text = asset_type ET.SubElement(apply_tags, 'assetId').text = asset.id ET.SubElement(apply_tags, 'tagKeyName').text = tag_key_name response = self.connection.request_with_orgId_api_2( 'tag/removeTags', method='POST', data=ET.tostring(apply_tags)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_tags(self, asset_id=None, asset_type=None, location=None, tag_key_name=None, tag_key_id=None, value=None, value_required=None, display_on_report=None): """ List tags in the Dimension Data Cloud :param asset_id: Filter the list by asset id :type asset_id: ``str`` :param asset_type: Filter the list by asset type :type asset_type: ``str`` :param location: Filter the list by the assets location :type location: :class:``NodeLocation`` or ``str`` :param tag_key_name: Filter the list by a tag key name :type tag_key_name: ``str`` :param tag_key_id: Filter the list by a tag key id :type tag_key_id: ``str`` :param value: Filter the list by a tag value :type value: ``str`` :param value_required: Filter the list to if a value is required for a tag :type value_required: ``bool`` :param display_on_report: Filter the list to if the tag should show up on usage reports :type display_on_report: ``bool`` :rtype: ``list`` of :class:`DimensionDataTag` """ params = {} if asset_id is not None: params['assetId'] = asset_id if asset_type is not None: params['assetType'] = asset_type if location is not None: params['datacenterId'] = self._location_to_location_id(location) if tag_key_name is not None: params['tagKeyName'] = tag_key_name if tag_key_id is not None: params['tagKeyId'] = tag_key_id if value is not None: params['value'] = value if value_required is not None: params['valueRequired'] = str(value_required).lower() if display_on_report is not None: params['displayOnReport'] = str(display_on_report).lower() paged_result = self.connection.paginated_request_with_orgId_api_2( 'tag/tag', method='GET', params=params ) tags = [] for result in paged_result: tags.extend(self._to_tags(result)) return tags def ex_summary_usage_report(self, start_date, end_date): """ Get summary usage information :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'report/usage?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_detailed_usage_report(self, start_date, end_date): """ Get detailed usage information :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'report/usageDetailed?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_software_usage_report(self, start_date, end_date): """ Get detailed software usage reports :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'report/usageSoftwareUnits?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_audit_log_report(self, start_date, end_date): """ Get audit log report :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'auditlog?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_backup_usage_report(self, start_date, end_date, location): """ Get audit log report :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :keyword location: Filters the node list to nodes that are located in this location :type location: :class:`NodeLocation` or ``str`` :rtype: ``list`` of ``list`` """ datacenter_id = self._location_to_location_id(location) result = self.connection.raw_request_with_orgId_api_1( 'backup/detailedUsageReport?datacenterId=%s&fromDate=%s&toDate=%s' % (datacenter_id, start_date, end_date)) return self._format_csv(result.response) def ex_list_ip_address_list(self, ex_network_domain): """ List IP Address List by network domain ID specified >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # List IP Address List of network domain >>> ipaddresslist_list = driver.ex_list_ip_address_list( >>> ex_network_domain=my_network_domain) >>> pprint(ipaddresslist_list) :param ex_network_domain: The network domain or network domain ID :type ex_network_domain: :class:`DimensionDataNetworkDomain` or 'str' :return: a list of DimensionDataIpAddressList objects :rtype: ``list`` of :class:`DimensionDataIpAddressList` """ params = {'networkDomainId': self._network_domain_to_network_domain_id( ex_network_domain)} response = self.connection.request_with_orgId_api_2( 'network/ipAddressList', params=params).object return self._to_ip_address_lists(response) def ex_get_ip_address_list(self, ex_network_domain, ex_ip_address_list_name): """ Get IP Address List by name in network domain specified >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # Get IP Address List by Name >>> ipaddresslist_list_by_name = driver.ex_get_ip_address_list( >>> ex_network_domain=my_network_domain, >>> ex_ip_address_list_name='My_IP_AddressList_1') >>> pprint(ipaddresslist_list_by_name) :param ex_network_domain: (required) The network domain or network domain ID in which ipaddresslist resides. :type ex_network_domain: :class:`DimensionDataNetworkDomain` or 'str' :param ex_ip_address_list_name: (required) Get 'IP Address List' by name :type ex_ip_address_list_name: :``str`` :return: a list of DimensionDataIpAddressList objects :rtype: ``list`` of :class:`DimensionDataIpAddressList` """ ip_address_lists = self.ex_list_ip_address_list(ex_network_domain) return list(filter(lambda x: x.name == ex_ip_address_list_name, ip_address_lists)) def ex_create_ip_address_list(self, ex_network_domain, name, description, ip_version, ip_address_collection, child_ip_address_list=None): """ Create IP Address List. IP Address list. >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.dimensiondata import DimensionDataIpAddress >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # IP Address collection >>> ipAddress_1 = DimensionDataIpAddress(begin='190.2.2.100') >>> ipAddress_2 = DimensionDataIpAddress(begin='190.2.2.106', end='190.2.2.108') >>> ipAddress_3 = DimensionDataIpAddress(begin='190.2.2.0', prefix_size='24') >>> ip_address_collection = [ipAddress_1, ipAddress_2, ipAddress_3] >>> >>> # Create IPAddressList >>> result = driver.ex_create_ip_address_list( >>> ex_network_domain=my_network_domain, >>> name='My_IP_AddressList_2', >>> ip_version='IPV4', >>> description='Test only', >>> ip_address_collection=ip_address_collection, >>> child_ip_address_list='08468e26-eeb3-4c3d-8ff2-5351fa6d8a04' >>> ) >>> >>> pprint(result) :param ex_network_domain: The network domain or network domain ID :type ex_network_domain: :class:`DimensionDataNetworkDomain` or 'str' :param name: IP Address List Name (required) :type name: :``str`` :param description: IP Address List Description (optional) :type description: :``str`` :param ip_version: IP Version of ip address (required) :type ip_version: :``str`` :param ip_address_collection: List of IP Address. At least one ipAddress element or one childIpAddressListId element must be provided. :type ip_address_collection: :``str`` :param child_ip_address_list: Child IP Address List or id to be included in this IP Address List. At least one ipAddress or one childIpAddressListId must be provided. :type child_ip_address_list: :class:'DimensionDataChildIpAddressList` or `str`` :return: a list of DimensionDataIpAddressList objects :rtype: ``list`` of :class:`DimensionDataIpAddressList` """ if (ip_address_collection is None and child_ip_address_list is None): raise ValueError("At least one ipAddress element or one " "childIpAddressListId element must be " "provided.") create_ip_address_list = ET.Element('createIpAddressList', {'xmlns': TYPES_URN}) ET.SubElement( create_ip_address_list, 'networkDomainId' ).text = self._network_domain_to_network_domain_id(ex_network_domain) ET.SubElement( create_ip_address_list, 'name' ).text = name ET.SubElement( create_ip_address_list, 'description' ).text = description ET.SubElement( create_ip_address_list, 'ipVersion' ).text = ip_version for ip in ip_address_collection: ip_address = ET.SubElement( create_ip_address_list, 'ipAddress', ) ip_address.set('begin', ip.begin) if ip.end: ip_address.set('end', ip.end) if ip.prefix_size: ip_address.set('prefixSize', ip.prefix_size) if child_ip_address_list is not None: ET.SubElement( create_ip_address_list, 'childIpAddressListId' ).text = \ self._child_ip_address_list_to_child_ip_address_list_id( child_ip_address_list) response = self.connection.request_with_orgId_api_2( 'network/createIpAddressList', method='POST', data=ET.tostring(create_ip_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_edit_ip_address_list(self, ex_ip_address_list, description, ip_address_collection, child_ip_address_lists=None): """ Edit IP Address List. IP Address list. >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.dimensiondata import DimensionDataIpAddress >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # IP Address collection >>> ipAddress_1 = DimensionDataIpAddress(begin='190.2.2.100') >>> ipAddress_2 = DimensionDataIpAddress(begin='190.2.2.106', >>> end='190.2.2.108') >>> ipAddress_3 = DimensionDataIpAddress( >>> begin='190.2.2.0', prefix_size='24') >>> ip_address_collection = [ipAddress_1, ipAddress_2, ipAddress_3] >>> >>> # Edit IP Address List >>> ip_address_list_id = '5e7c323f-c885-4e4b-9a27-94c44217dbd3' >>> result = driver.ex_edit_ip_address_list( >>> ex_ip_address_list=ip_address_list_id, >>> description="Edit Test", >>> ip_address_collection=ip_address_collection, >>> child_ip_address_lists=None >>> ) >>> pprint(result) :param ex_ip_address_list: (required) IpAddressList object or IpAddressList ID :type ex_ip_address_list: :class:'DimensionDataIpAddressList' or ``str`` :param description: IP Address List Description :type description: :``str`` :param ip_address_collection: List of IP Address :type ip_address_collection: ''list'' of :class:'DimensionDataIpAddressList' :param child_ip_address_lists: Child IP Address List or id to be included in this IP Address List :type child_ip_address_lists: ``list`` of :class:'DimensionDataChildIpAddressList' or ``str`` :return: a list of DimensionDataIpAddressList objects :rtype: ``list`` of :class:`DimensionDataIpAddressList` """ edit_ip_address_list = ET.Element( 'editIpAddressList', {'xmlns': TYPES_URN, "id": self._ip_address_list_to_ip_address_list_id( ex_ip_address_list), 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance" }) ET.SubElement( edit_ip_address_list, 'description' ).text = description for ip in ip_address_collection: ip_address = ET.SubElement( edit_ip_address_list, 'ipAddress', ) ip_address.set('begin', ip.begin) if ip.end: ip_address.set('end', ip.end) if ip.prefix_size: ip_address.set('prefixSize', ip.prefix_size) if child_ip_address_lists is not None: ET.SubElement( edit_ip_address_list, 'childIpAddressListId' ).text = self._child_ip_address_list_to_child_ip_address_list_id( child_ip_address_lists) else: ET.SubElement( edit_ip_address_list, 'childIpAddressListId', {'xsi:nil': 'true'} ) response = self.connection.request_with_orgId_api_2( 'network/editIpAddressList', method='POST', data=ET.tostring(edit_ip_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_ip_address_list(self, ex_ip_address_list): """ Delete IP Address List by ID >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> ip_address_list_id = '5e7c323f-c885-4e4b-9a27-94c44217dbd3' >>> result = driver.ex_delete_ip_address_list(ip_address_list_id) >>> pprint(result) :param ex_ip_address_list: IP Address List object or IP Address List ID (required) :type ex_ip_address_list: :class:'DimensionDataIpAddressList' or ``str`` :rtype: ``bool`` """ delete_ip_address_list = \ ET.Element('deleteIpAddressList', {'xmlns': TYPES_URN, 'id': self ._ip_address_list_to_ip_address_list_id( ex_ip_address_list)}) response = self.connection.request_with_orgId_api_2( 'network/deleteIpAddressList', method='POST', data=ET.tostring(delete_ip_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_portlist(self, ex_network_domain): """ List Portlist by network domain ID specified >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == >>> networkDomainName][0] >>> >>> # List portlist >>> portLists = driver.ex_list_portlist( >>> ex_network_domain=my_network_domain) >>> pprint(portLists) >>> :param ex_network_domain: The network domain or network domain ID :type ex_network_domain: :class:`DimensionDataNetworkDomain` or 'str' :return: a list of DimensionDataPortList objects :rtype: ``list`` of :class:`DimensionDataPortList` """ params = {'networkDomainId': self._network_domain_to_network_domain_id(ex_network_domain)} response = self.connection.request_with_orgId_api_2( 'network/portList', params=params).object return self._to_port_lists(response) def ex_get_portlist(self, ex_portlist_id): """ Get Port List >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get specific portlist by ID >>> portlist_id = '27dd8c66-80ff-496b-9f54-2a3da2fe679e' >>> portlist = driver.ex_get_portlist(portlist_id) >>> pprint(portlist) :param ex_portlist_id: The ex_port_list or ex_port_list ID :type ex_portlist_id: :class:`DimensionDataNetworkDomain` or 'str' :return: DimensionDataPortList object :rtype: :class:`DimensionDataPort` """ url_path = ('network/portList/%s' % ex_portlist_id) response = self.connection.request_with_orgId_api_2( url_path).object return self._to_port_list(response) def ex_create_portlist(self, ex_network_domain, name, description, port_collection, child_portlist_list=None): """ Create Port List. >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.dimensiondata import DimensionDataPort >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # Port Collection >>> port_1 = DimensionDataPort(begin='1000') >>> port_2 = DimensionDataPort(begin='1001', end='1003') >>> port_collection = [port_1, port_2] >>> >>> # Create Port List >>> new_portlist = driver.ex_create_portlist( >>> ex_network_domain=my_network_domain, >>> name='MyPortListX', >>> description="Test only", >>> port_collection=port_collection, >>> child_portlist_list={'a9cd4984-6ff5-4f93-89ff-8618ab642bb9'} >>> ) >>> pprint(new_portlist) :param ex_network_domain: (required) The network domain in which to create PortList. Provide networkdomain object or its id. :type ex_network_domain: :``str`` :param name: Port List Name :type name: :``str`` :param description: IP Address List Description :type description: :``str`` :param port_collection: List of Port Address :type port_collection: :``str`` :param child_portlist_list: List of Child Portlist to be included in this Port List :type child_portlist_list: :``str`` or ''list of :class:'DimensionDataChildPortList' :return: result of operation :rtype: ``bool`` """ new_port_list = ET.Element('createPortList', {'xmlns': TYPES_URN}) ET.SubElement( new_port_list, 'networkDomainId' ).text = self._network_domain_to_network_domain_id(ex_network_domain) ET.SubElement( new_port_list, 'name' ).text = name ET.SubElement( new_port_list, 'description' ).text = description for port in port_collection: p = ET.SubElement( new_port_list, 'port' ) p.set('begin', port.begin) if port.end: p.set('end', port.end) if child_portlist_list is not None: for child in child_portlist_list: ET.SubElement( new_port_list, 'childPortListId' ).text = self._child_port_list_to_child_port_list_id(child) response = self.connection.request_with_orgId_api_2( 'network/createPortList', method='POST', data=ET.tostring(new_port_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_edit_portlist(self, ex_portlist, description, port_collection, child_portlist_list=None): """ Edit Port List. >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.dimensiondata import DimensionDataPort >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Port Collection >>> port_1 = DimensionDataPort(begin='4200') >>> port_2 = DimensionDataPort(begin='4201', end='4210') >>> port_collection = [port_1, port_2] >>> >>> # Edit Port List >>> editPortlist = driver.ex_get_portlist( '27dd8c66-80ff-496b-9f54-2a3da2fe679e') >>> >>> result = driver.ex_edit_portlist( >>> ex_portlist=editPortlist.id, >>> description="Make Changes in portlist", >>> port_collection=port_collection, >>> child_portlist_list={'a9cd4984-6ff5-4f93-89ff-8618ab642bb9'} >>> ) >>> pprint(result) :param ex_portlist: Port List to be edited (required) :type ex_portlist: :``str`` or :class:'DimensionDataPortList' :param description: Port List Description :type description: :``str`` :param port_collection: List of Ports :type port_collection: :``str`` :param child_portlist_list: Child PortList to be included in this IP Address List :type child_portlist_list: :``list`` of :class'DimensionDataChildPortList' or ''str'' :return: a list of DimensionDataPortList objects :rtype: ``list`` of :class:`DimensionDataPortList` """ existing_port_address_list = ET.Element( 'editPortList', { "id": self._port_list_to_port_list_id(ex_portlist), 'xmlns': TYPES_URN, 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance" }) ET.SubElement( existing_port_address_list, 'description' ).text = description for port in port_collection: p = ET.SubElement( existing_port_address_list, 'port' ) p.set('begin', port.begin) if port.end: p.set('end', port.end) if child_portlist_list is not None: for child in child_portlist_list: ET.SubElement( existing_port_address_list, 'childPortListId' ).text = self._child_port_list_to_child_port_list_id(child) else: ET.SubElement( existing_port_address_list, 'childPortListId', {'xsi:nil': 'true'} ) response = self.connection.request_with_orgId_api_2( 'network/editPortList', method='POST', data=ET.tostring(existing_port_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_portlist(self, ex_portlist): """ Delete Port List >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get dimension data driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.DIMENSIONDATA) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Delete Port List >>> portlist_id = '157531ce-77d4-493c-866b-d3d3fc4a912a' >>> response = driver.ex_delete_portlist(portlist_id) >>> pprint(response) :param ex_portlist: Port List to be deleted :type ex_portlist: :``str`` or :class:'DimensionDataPortList' :rtype: ``bool`` """ delete_port_list = ET.Element( 'deletePortList', {'xmlns': TYPES_URN, 'id': self._port_list_to_port_list_id(ex_portlist)}) response = self.connection.request_with_orgId_api_2( 'network/deletePortList', method='POST', data=ET.tostring(delete_port_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_exchange_nic_vlans(self, nic_id_1, nic_id_2): """ Exchange NIC Vlans :param nic_id_1: Nic ID 1 :type nic_id_1: :``str`` :param nic_id_2: Nic ID 2 :type nic_id_2: :``str`` :rtype: ``bool`` """ exchange_elem = ET.Element( 'urn:exchangeNicVlans', { 'xmlns:urn': TYPES_URN, }) ET.SubElement(exchange_elem, 'urn:nicId1').text = nic_id_1 ET.SubElement(exchange_elem, 'urn:nicId2').text = nic_id_2 response = self.connection.request_with_orgId_api_2( 'server/exchangeNicVlans', method='POST', data=ET.tostring(exchange_elem)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_change_nic_network_adapter(self, nic_id, network_adapter_name): """ Change network adapter of a NIC on a cloud server :param nic_id: Nic ID :type nic_id: :``str`` :param network_adapter_name: Network adapter name :type network_adapter_name: :``str`` :rtype: ``bool`` """ change_elem = ET.Element( 'changeNetworkAdapter', { 'nicId': nic_id, 'xmlns': TYPES_URN }) ET.SubElement(change_elem, 'networkAdapter').text = \ network_adapter_name response = self.connection.request_with_orgId_api_2( 'server/changeNetworkAdapter', method='POST', data=ET.tostring(change_elem)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_node_uncustomized(self, name, image, ex_network_domain, ex_is_started=True, ex_description=None, ex_cluster_id=None, ex_cpu_specification=None, ex_memory_gb=None, ex_primary_nic_private_ipv4=None, ex_primary_nic_vlan=None, ex_primary_nic_network_adapter=None, ex_additional_nics=None, ex_disks=None, ex_tagid_value_pairs=None, ex_tagname_value_pairs=None ): """ This MCP 2.0 only function deploys a new Cloud Server from a CloudControl compatible Server Image, which does not utilize VMware Guest OS Customization process. Create Node in MCP2 Data Center :keyword name: (required) String with a name for this new node :type name: ``str`` :keyword image: (UUID of the Server Image being used as the target for the new Server deployment. The source Server Image (OS Image or Customer Image) must have osCustomization set to true. See Get/List OS Image(s) and Get/List Customer Image(s). :type image: :class:`NodeImage` or ``str`` :keyword ex_network_domain: (required) Network Domain or Network Domain ID to create the node :type ex_network_domain: :class:`DimensionDataNetworkDomain` or ``str`` :keyword ex_description: (optional) description for this node :type ex_description: ``str`` :keyword ex_cluster_id: (optional) For multiple cluster environments, it is possible to set a destination cluster for the new Customer Image. Note that performance of this function is optimal when either the Server cluster and destination are the same or when shared data storage is in place for the multiple clusters. :type ex_cluster_id: ``str`` :keyword ex_primary_nic_private_ipv4: Provide private IPv4. Ignore if ex_primary_nic_vlan is provided. Use one or the other. Not both. :type ex_primary_nic_private_ipv4: :``str`` :keyword ex_primary_nic_vlan: Provide VLAN for the node if ex_primary_nic_private_ipv4 NOT provided. One or the other. Not both. :type ex_primary_nic_vlan: :class: DimensionDataVlan or ``str`` :keyword ex_primary_nic_network_adapter: (Optional) Default value for the Operating System will be used if leave empty. Example: "E1000". :type ex_primary_nic_network_adapter: :``str`` :keyword ex_additional_nics: (optional) List :class:'DimensionDataNic' or None :type ex_additional_nics: ``list`` of :class:'DimensionDataNic' or ``str`` :keyword ex_memory_gb: (optional) The amount of memory in GB for the server Can be used to override the memory value inherited from the source Server Image. :type ex_memory_gb: ``int`` :keyword ex_cpu_specification: (optional) The spec of CPU to deploy :type ex_cpu_specification: :class:`DimensionDataServerCpuSpecification` :keyword ex_is_started: (required) Start server after creation. Default is set to true. :type ex_is_started: ``bool`` :keyword ex_disks: (optional) Dimensiondata disks. Optional disk elements can be used to define the disk speed that each disk on the Server; inherited from the source Server Image will be deployed to. It is not necessary to include a diskelement for every disk; only those that you wish to set a disk speed value for. Note that scsiId 7 cannot be used.Up to 13 disks can be present in addition to the required OS disk on SCSI ID 0. Refer to https://docs.mcp-services.net/x/UwIu for disk :type ex_disks: List or tuple of :class:'DimensionDataServerDisk` :keyword ex_tagid_value_pairs: (Optional) up to 10 tag elements may be provided. A combination of tagById and tag name cannot be supplied in the same request. Note: ex_tagid_value_pairs and ex_tagname_value_pairs is mutually exclusive. Use one or other. :type ex_tagname_value_pairs: ``dict``. Value can be None. :keyword ex_tagname_value_pairs: (Optional) up to 10 tag elements may be provided. A combination of tagById and tag name cannot be supplied in the same request. Note: ex_tagid_value_pairs and ex_tagname_value_pairs is mutually exclusive. Use one or other. :type ex_tagname_value_pairs: ``dict```. :return: The newly created :class:`Node`. :rtype: :class:`Node` """ # Unsupported for version lower than 2.4 if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): raise Exception("This feature is NOT supported in " "earlier api version of 2.4") # Default start to true if input is invalid if not isinstance(ex_is_started, bool): ex_is_started = True print("Warning: ex_is_started input value is invalid. Default" "to True") server_uncustomized_elm = ET.Element('deployUncustomizedServer', {'xmlns': TYPES_URN}) ET.SubElement(server_uncustomized_elm, "name").text = name ET.SubElement(server_uncustomized_elm, "description").text = \ ex_description image_id = self._image_to_image_id(image) ET.SubElement(server_uncustomized_elm, "imageId").text = image_id if ex_cluster_id: dns_elm = ET.SubElement(server_uncustomized_elm, "primaryDns") dns_elm.text = ex_cluster_id if ex_is_started is not None: ET.SubElement(server_uncustomized_elm, "start").text = str( ex_is_started).lower() if ex_cpu_specification is not None: cpu = ET.SubElement(server_uncustomized_elm, "cpu") cpu.set('speed', ex_cpu_specification.performance) cpu.set('count', str(ex_cpu_specification.cpu_count)) cpu.set('coresPerSocket', str(ex_cpu_specification.cores_per_socket)) if ex_memory_gb is not None: ET.SubElement(server_uncustomized_elm, "memoryGb").text = \ str(ex_memory_gb) if (ex_primary_nic_private_ipv4 is None and ex_primary_nic_vlan is None): raise ValueError("Missing argument. Either " "ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "must be specified.") if (ex_primary_nic_private_ipv4 is not None and ex_primary_nic_vlan is not None): raise ValueError("Either ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "be specified. Not both.") network_elm = ET.SubElement(server_uncustomized_elm, "networkInfo") net_domain_id = self._network_domain_to_network_domain_id( ex_network_domain) network_elm.set('networkDomainId', net_domain_id) pri_nic = ET.SubElement(network_elm, 'primaryNic') if ex_primary_nic_private_ipv4 is not None: ET.SubElement(pri_nic, 'privateIpv4').text = ex_primary_nic_private_ipv4 if ex_primary_nic_vlan is not None: vlan_id = self._vlan_to_vlan_id(ex_primary_nic_vlan) ET.SubElement(pri_nic, 'vlanId').text = vlan_id if ex_primary_nic_network_adapter is not None: ET.SubElement(pri_nic, "networkAdapter").text = \ ex_primary_nic_network_adapter if isinstance(ex_additional_nics, (list, tuple)): for nic in ex_additional_nics: additional_nic = ET.SubElement(network_elm, 'additionalNic') if (nic.private_ip_v4 is None and nic.vlan is None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic.") if (nic.private_ip_v4 is not None and nic.vlan is not None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic. Not both.") if nic.private_ip_v4 is not None: ET.SubElement(additional_nic, 'privateIpv4').text = nic.private_ip_v4 if nic.vlan is not None: vlan_id = self._vlan_to_vlan_id(nic.vlan) ET.SubElement(additional_nic, 'vlanId').text = vlan_id if nic.network_adapter_name is not None: ET.SubElement(additional_nic, "networkAdapter").text = \ nic.network_adapter_name elif ex_additional_nics is not None: raise TypeError( "ex_additional_NICs must be None or tuple/list") if isinstance(ex_disks, (list, tuple)): for disk in ex_disks: disk_elm = ET.SubElement(server_uncustomized_elm, 'disk') disk_elm.set('scsiId', disk.scsi_id) disk_elm.set('speed', disk.speed) elif ex_disks is not None: raise TypeError("ex_disks must be None or tuple/list") # tagid and tagname value pair should not co-exists if ex_tagid_value_pairs is not None and ex_tagname_value_pairs is \ not None: raise ValueError("ex_tagid_value_pairs and ex_tagname_value_pairs" "is mutually exclusive. Use one or the other.") # Tag by ID if ex_tagid_value_pairs is not None: if not isinstance(ex_tagid_value_pairs, dict): raise ValueError( "ex_tagid_value_pairs must be a dictionary." ) if sys.version_info[0] < 3: tagid_items = ex_tagid_value_pairs.iteritems() else: tagid_items = ex_tagid_value_pairs.items() for k, v in tagid_items: tag_elem = ET.SubElement(server_uncustomized_elm, 'tagById') ET.SubElement(tag_elem, 'tagKeyId').text = k if v is not None: ET.SubElement(tag_elem, 'value').text = v if ex_tagname_value_pairs is not None: if not isinstance(ex_tagname_value_pairs, dict): raise ValueError( "ex_tagname_value_pairs must be a dictionary" ) if sys.version_info[0] < 3: tags_items = ex_tagname_value_pairs.iteritems() else: tags_items = ex_tagname_value_pairs.items() for k, v in tags_items: tag_name_elem = ET.SubElement(server_uncustomized_elm, 'tag') ET.SubElement(tag_name_elem, 'tagKeyName').text = k if v is not None: ET.SubElement(tag_name_elem, 'value').text = v response = self.connection.request_with_orgId_api_2( 'server/deployUncustomizedServer', method='POST', data=ET.tostring(server_uncustomized_elm)).object node_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'serverId': node_id = info.get('value') new_node = self.ex_get_node_by_id(node_id) return new_node def _format_csv(self, http_response): text = http_response.read() lines = str.splitlines(ensure_string(text)) return [line.split(',') for line in lines] @staticmethod def _get_tagging_asset_type(asset): objecttype = type(asset) if objecttype.__name__ in OBJECT_TO_TAGGING_ASSET_TYPE_MAP: return OBJECT_TO_TAGGING_ASSET_TYPE_MAP[objecttype.__name__] raise TypeError("Asset type %s cannot be tagged" % objecttype.__name__) def _list_nodes_single_page(self, params={}): nodes = self.connection.request_with_orgId_api_2( 'server/server', params=params).object return nodes def _to_tags(self, object): tags = [] for element in object.findall(fixxpath('tag', TYPES_URN)): tags.append(self._to_tag(element)) return tags def _to_tag(self, element): tag_key = self._to_tag_key(element, from_tag_api=True) return DimensionDataTag( asset_type=findtext(element, 'assetType', TYPES_URN), asset_id=findtext(element, 'assetId', TYPES_URN), asset_name=findtext(element, 'assetName', TYPES_URN), datacenter=findtext(element, 'datacenterId', TYPES_URN), key=tag_key, value=findtext(element, 'value', TYPES_URN) ) def _to_tag_keys(self, object): keys = [] for element in object.findall(fixxpath('tagKey', TYPES_URN)): keys.append(self._to_tag_key(element)) return keys def _to_tag_key(self, element, from_tag_api=False): if from_tag_api: id = findtext(element, 'tagKeyId', TYPES_URN) name = findtext(element, 'tagKeyName', TYPES_URN) else: id = element.get('id') name = findtext(element, 'name', TYPES_URN) return DimensionDataTagKey( id=id, name=name, description=findtext(element, 'description', TYPES_URN), value_required=self._str2bool( findtext(element, 'valueRequired', TYPES_URN) ), display_on_report=self._str2bool( findtext(element, 'displayOnReport', TYPES_URN) ) ) def _to_images(self, object, el_name='osImage'): images = [] locations = self.list_locations() # The CloudControl API will return all images # in the current geographic region (even ones in # datacenters the user's organisation does not have access to) # # We therefore need to filter out those images (since we can't # get a NodeLocation for them) location_ids = set(location.id for location in locations) for element in object.findall(fixxpath(el_name, TYPES_URN)): location_id = element.get('datacenterId') if location_id in location_ids: images.append(self._to_image(element, locations)) return images def _to_image(self, element, locations=None): location_id = element.get('datacenterId') if locations is None: locations = self.list_locations(location_id) location = [loc for loc in locations if loc.id == location_id][0] cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN))) if LooseVersion(self.connection.active_api_version) > LooseVersion( '2.3'): os_el = element.find(fixxpath('guest/operatingSystem', TYPES_URN)) else: os_el = element.find(fixxpath('operatingSystem', TYPES_URN)) if element.tag.endswith('customerImage'): is_customer_image = True else: is_customer_image = False extra = { 'description': findtext(element, 'description', TYPES_URN), 'OS_type': os_el.get('family'), 'OS_displayName': os_el.get('displayName'), 'cpu': cpu_spec, 'memoryGb': findtext(element, 'memoryGb', TYPES_URN), 'osImageKey': findtext(element, 'osImageKey', TYPES_URN), 'created': findtext(element, 'createTime', TYPES_URN), 'location': location, 'isCustomerImage': is_customer_image } return NodeImage(id=element.get('id'), name=str(findtext(element, 'name', TYPES_URN)), extra=extra, driver=self.connection.driver) def _to_nat_rules(self, object, network_domain): rules = [] for element in findall(object, 'natRule', TYPES_URN): rules.append( self._to_nat_rule(element, network_domain)) return rules def _to_nat_rule(self, element, network_domain): return DimensionDataNatRule( id=element.get('id'), network_domain=network_domain, internal_ip=findtext(element, 'internalIp', TYPES_URN), external_ip=findtext(element, 'externalIp', TYPES_URN), status=findtext(element, 'state', TYPES_URN)) def _to_anti_affinity_rules(self, object): rules = [] for element in findall(object, 'antiAffinityRule', TYPES_URN): rules.append( self._to_anti_affinity_rule(element)) return rules def _to_anti_affinity_rule(self, element): node_list = [] for node in findall(element, 'serverSummary', TYPES_URN): node_list.append(node.get('id')) return DimensionDataAntiAffinityRule( id=element.get('id'), node_list=node_list ) def _to_firewall_rules(self, object, network_domain): rules = [] locations = self.list_locations() for element in findall(object, 'firewallRule', TYPES_URN): rules.append( self._to_firewall_rule(element, locations, network_domain)) return rules def _to_firewall_rule(self, element, locations, network_domain): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] return DimensionDataFirewallRule( id=element.get('id'), network_domain=network_domain, name=findtext(element, 'name', TYPES_URN), action=findtext(element, 'action', TYPES_URN), ip_version=findtext(element, 'ipVersion', TYPES_URN), protocol=findtext(element, 'protocol', TYPES_URN), enabled=findtext(element, 'enabled', TYPES_URN), source=self._to_firewall_address( element.find(fixxpath('source', TYPES_URN))), destination=self._to_firewall_address( element.find(fixxpath('destination', TYPES_URN))), location=location, status=findtext(element, 'state', TYPES_URN)) def _to_firewall_address(self, element): ip = element.find(fixxpath('ip', TYPES_URN)) port = element.find(fixxpath('port', TYPES_URN)) port_list = element.find(fixxpath('portList', TYPES_URN)) address_list = element.find(fixxpath('ipAddressList', TYPES_URN)) if address_list is None: return DimensionDataFirewallAddress( any_ip=ip.get('address') == 'ANY', ip_address=ip.get('address'), ip_prefix_size=ip.get('prefixSize'), port_begin=port.get('begin') if port is not None else None, port_end=port.get('end') if port is not None else None, port_list_id=port_list.get('id', None) if port_list is not None else None, address_list_id=address_list.get('id') if address_list is not None else None) else: return DimensionDataFirewallAddress( any_ip=False, ip_address=None, ip_prefix_size=None, port_begin=None, port_end=None, port_list_id=port_list.get('id', None) if port_list is not None else None, address_list_id=address_list.get('id') if address_list is not None else None) def _to_ip_blocks(self, object): blocks = [] locations = self.list_locations() for element in findall(object, 'publicIpBlock', TYPES_URN): blocks.append(self._to_ip_block(element, locations)) return blocks def _to_ip_block(self, element, locations): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] return DimensionDataPublicIpBlock( id=element.get('id'), network_domain=self.ex_get_network_domain( findtext(element, 'networkDomainId', TYPES_URN) ), base_ip=findtext(element, 'baseIp', TYPES_URN), size=findtext(element, 'size', TYPES_URN), location=location, status=findtext(element, 'state', TYPES_URN)) def _to_networks(self, object): networks = [] locations = self.list_locations() for element in findall(object, 'network', NETWORK_NS): networks.append(self._to_network(element, locations)) return networks def _to_network(self, element, locations): multicast = False if findtext(element, 'multicast', NETWORK_NS) == 'true': multicast = True status = self._to_status(element.find(fixxpath('status', NETWORK_NS))) location_id = findtext(element, 'location', NETWORK_NS) location = list(filter(lambda x: x.id == location_id, locations))[0] return DimensionDataNetwork( id=findtext(element, 'id', NETWORK_NS), name=findtext(element, 'name', NETWORK_NS), description=findtext(element, 'description', NETWORK_NS), location=location, private_net=findtext(element, 'privateNet', NETWORK_NS), multicast=multicast, status=status) def _to_network_domains(self, object): network_domains = [] locations = self.list_locations() for element in findall(object, 'networkDomain', TYPES_URN): network_domains.append(self._to_network_domain(element, locations)) return network_domains def _to_network_domain(self, element, locations): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] plan = findtext(element, 'type', TYPES_URN) if plan == 'ESSENTIALS': plan_type = NetworkDomainServicePlan.ESSENTIALS else: plan_type = NetworkDomainServicePlan.ADVANCED return DimensionDataNetworkDomain( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), plan=plan_type, location=location, status=findtext(element, 'state', TYPES_URN)) def _to_vlans(self, object): vlans = [] locations = self.list_locations() for element in findall(object, 'vlan', TYPES_URN): vlans.append(self._to_vlan(element, locations=locations)) return vlans def _to_vlan(self, element, locations): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] ip_range = element.find(fixxpath('privateIpv4Range', TYPES_URN)) ip6_range = element.find(fixxpath('ipv6Range', TYPES_URN)) network_domain_el = element.find( fixxpath('networkDomain', TYPES_URN)) network_domain = self.ex_get_network_domain( network_domain_el.get('id')) return DimensionDataVlan( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), network_domain=network_domain, private_ipv4_range_address=ip_range.get('address'), private_ipv4_range_size=int(ip_range.get('prefixSize')), ipv6_range_address=ip6_range.get('address'), ipv6_range_size=int(ip6_range.get('prefixSize')), ipv4_gateway=findtext( element, 'ipv4GatewayAddress', TYPES_URN), ipv6_gateway=findtext( element, 'ipv6GatewayAddress', TYPES_URN), location=location, status=findtext(element, 'state', TYPES_URN)) def _to_locations(self, object): locations = [] for element in object.findall(fixxpath('datacenter', TYPES_URN)): locations.append(self._to_location(element)) return locations def _to_location(self, element): loc = NodeLocation(id=element.get('id'), name=findtext(element, 'displayName', TYPES_URN), country=findtext(element, 'country', TYPES_URN), driver=self) return loc def _to_cpu_spec(self, element): return DimensionDataServerCpuSpecification( cpu_count=int(element.get('count')), cores_per_socket=int(element.get('coresPerSocket')), performance=element.get('speed')) def _to_vmware_tools(self, element): status = None if hasattr(element, 'runningStatus'): status = element.get('runningStatus') version_status = None if hasattr(element, 'version_status'): version_status = element.get('version_status') api_version = None if hasattr(element, 'apiVersion'): api_version = element.get('apiVersion') return DimensionDataServerVMWareTools( status=status, version_status=version_status, api_version=api_version) def _to_disks(self, object): disk_elements = object.findall(fixxpath('disk', TYPES_URN)) return [self._to_disk(el) for el in disk_elements] def _to_disk(self, element): return DimensionDataServerDisk( id=element.get('id'), scsi_id=int(element.get('scsiId')), size_gb=int(element.get('sizeGb')), speed=element.get('speed'), state=element.get('state') ) def _to_nodes(self, object): node_elements = object.findall(fixxpath('server', TYPES_URN)) return [self._to_node(el) for el in node_elements] def _to_node(self, element): started = findtext(element, 'started', TYPES_URN) status = self._to_status(element.find(fixxpath('progress', TYPES_URN))) dd_state = findtext(element, 'state', TYPES_URN) node_state = self._get_node_state(dd_state, started, status.action) has_network_info \ = element.find(fixxpath('networkInfo', TYPES_URN)) is not None cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN))) disks = self._to_disks(element) # Vmware Tools # Version 2.3 or earlier if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): vmware_tools = self._to_vmware_tools( element.find(fixxpath('vmwareTools', TYPES_URN))) operation_system = element.find(fixxpath( 'operatingSystem', TYPES_URN)) # Version 2.4 or later else: # vmtools_elm = fixxpath('guest/vmTools', TYPES_URN) vmtools_elm = element.find(fixxpath('guest/vmTools', TYPES_URN)) if vmtools_elm is not None: vmware_tools = self._to_vmware_tools(vmtools_elm) else: vmware_tools = \ DimensionDataServerVMWareTools( status=None, version_status=None, api_version=None ) operation_system = element.find(fixxpath( 'guest/operatingSystem', TYPES_URN)) extra = { 'description': findtext(element, 'description', TYPES_URN), 'sourceImageId': findtext(element, 'sourceImageId', TYPES_URN), 'networkId': findtext(element, 'networkId', TYPES_URN), 'networkDomainId': element.find(fixxpath('networkInfo', TYPES_URN)) .get('networkDomainId') if has_network_info else None, 'datacenterId': element.get('datacenterId'), 'deployedTime': findtext(element, 'createTime', TYPES_URN), 'cpu': cpu_spec, 'memoryMb': int(findtext( element, 'memoryGb', TYPES_URN)) * 1024, 'OS_id': operation_system.get('id'), 'OS_type': operation_system.get('family'), 'OS_displayName': operation_system.get('displayName'), 'status': status, 'disks': disks, 'vmWareTools': vmware_tools } public_ip = findtext(element, 'publicIpAddress', TYPES_URN) private_ip = element.find( fixxpath('networkInfo/primaryNic', TYPES_URN)) \ .get('privateIpv4') \ if has_network_info else \ element.find(fixxpath('nic', TYPES_URN)).get('privateIpv4') extra['ipv6'] = element.find( fixxpath('networkInfo/primaryNic', TYPES_URN)) \ .get('ipv6') \ if has_network_info else \ element.find(fixxpath('nic', TYPES_URN)).get('ipv6') n = Node(id=element.get('id'), name=findtext(element, 'name', TYPES_URN), state=node_state, public_ips=[public_ip] if public_ip is not None else [], private_ips=[private_ip] if private_ip is not None else [], size=self.list_sizes()[0], image=NodeImage(extra['sourceImageId'], extra['OS_displayName'], self.connection.driver), driver=self.connection.driver, extra=extra) return n def _to_status(self, element): if element is None: return DimensionDataStatus() s = DimensionDataStatus(action=findtext(element, 'action', TYPES_URN), request_time=findtext( element, 'requestTime', TYPES_URN), user_name=findtext( element, 'userName', TYPES_URN), number_of_steps=findtext( element, 'numberOfSteps', TYPES_URN), step_name=findtext( element, 'step/name', TYPES_URN), step_number=findtext( element, 'step_number', TYPES_URN), step_percent_complete=findtext( element, 'step/percentComplete', TYPES_URN), failure_reason=findtext( element, 'failureReason', TYPES_URN)) return s def _to_ip_address_lists(self, object): ip_address_lists = [] for element in findall(object, 'ipAddressList', TYPES_URN): ip_address_lists.append(self._to_ip_address_list(element)) return ip_address_lists def _to_ip_address_list(self, element): ipAddresses = [] for ip in findall(element, 'ipAddress', TYPES_URN): ipAddresses.append(self._to_ip_address(ip)) child_ip_address_lists = [] for child_ip_list in findall(element, 'childIpAddressList', TYPES_URN): child_ip_address_lists.append(self ._to_child_ip_list(child_ip_list)) return DimensionDataIpAddressList( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), ip_version=findtext(element, 'ipVersion', TYPES_URN), ip_address_collection=ipAddresses, state=findtext(element, 'state', TYPES_URN), create_time=findtext(element, 'createTime', TYPES_URN), child_ip_address_lists=child_ip_address_lists ) def _to_child_ip_list(self, element): return DimensionDataChildIpAddressList( id=element.get('id'), name=element.get('name') ) def _to_ip_address(self, element): return DimensionDataIpAddress( begin=element.get('begin'), end=element.get('end'), prefix_size=element.get('prefixSize') ) def _to_port_lists(self, object): port_lists = [] for element in findall(object, 'portList', TYPES_URN): port_lists.append(self._to_port_list(element)) return port_lists def _to_port_list(self, element): ports = [] for port in findall(element, 'port', TYPES_URN): ports.append(self._to_port(element=port)) child_portlist_list = [] for child in findall(element, 'childPortList', TYPES_URN): child_portlist_list.append( self._to_child_port_list(element=child)) return DimensionDataPortList( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), port_collection=ports, child_portlist_list=child_portlist_list, state=findtext(element, 'state', TYPES_URN), create_time=findtext(element, 'createTime', TYPES_URN) ) def _image_needs_auth(self, image): if not isinstance(image, NodeImage): image = self.ex_get_image_by_id(image) if image.extra['isCustomerImage'] and image.extra['OS_type'] == 'UNIX': return False return True @staticmethod def _to_port(element): return DimensionDataPort( begin=element.get('begin'), end=element.get('end') ) @staticmethod def _to_child_port_list(element): return DimensionDataChildPortList( id=element.get('id'), name=element.get('name') ) @staticmethod def _get_node_state(state, started, action): try: return NODE_STATE_MAP[(state, started, action)] except KeyError: if started == 'true': return NodeState.RUNNING else: return NodeState.TERMINATED @staticmethod def _node_to_node_id(node): return dd_object_to_id(node, Node) @staticmethod def _location_to_location_id(location): return dd_object_to_id(location, NodeLocation) @staticmethod def _vlan_to_vlan_id(vlan): return dd_object_to_id(vlan, DimensionDataVlan) @staticmethod def _image_to_image_id(image): return dd_object_to_id(image, NodeImage) @staticmethod def _network_to_network_id(network): return dd_object_to_id(network, DimensionDataNetwork) @staticmethod def _anti_affinity_rule_to_anti_affinity_rule_id(rule): return dd_object_to_id(rule, DimensionDataAntiAffinityRule) @staticmethod def _network_domain_to_network_domain_id(network_domain): return dd_object_to_id(network_domain, DimensionDataNetworkDomain) @staticmethod def _tag_key_to_tag_key_id(tag_key): return dd_object_to_id(tag_key, DimensionDataTagKey) @staticmethod def _tag_key_to_tag_key_name(tag_key): return dd_object_to_id(tag_key, DimensionDataTagKey, id_value='name') @staticmethod def _ip_address_list_to_ip_address_list_id(ip_addr_list): return dd_object_to_id(ip_addr_list, DimensionDataIpAddressList, id_value='id') @staticmethod def _child_ip_address_list_to_child_ip_address_list_id(child_ip_addr_list): return dd_object_to_id(child_ip_addr_list, DimensionDataChildIpAddressList, id_value='id') @staticmethod def _port_list_to_port_list_id(port_list): return dd_object_to_id(port_list, DimensionDataPortList, id_value='id') @staticmethod def _child_port_list_to_child_port_list_id(child_port_list): return dd_object_to_id(child_port_list, DimensionDataChildPortList, id_value='id') @staticmethod def _str2bool(string): return string.lower() in ("true") apache-libcloud-2.8.0/libcloud/compute/drivers/dummy.py0000664000175000017500000002550213577507766023112 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Dummy Driver @note: This driver is out of date """ import uuid import socket import struct from libcloud.common.base import ConnectionKey from libcloud.compute.base import NodeImage, NodeSize, Node from libcloud.compute.base import NodeDriver, NodeLocation from libcloud.compute.base import KeyPair from libcloud.compute.types import Provider, NodeState class DummyConnection(ConnectionKey): """ Dummy connection class """ def connect(self, host=None, port=None): pass class DummyNodeDriver(NodeDriver): """ Dummy node driver This is a fake driver which appears to always create or destroy nodes successfully. >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> node=driver.create_node() >>> node.public_ips[0] '127.0.0.3' >>> node.name 'dummy-3' If the credentials you give convert to an integer then the next node to be created will be one higher. Each time you create a node you will get a different IP address. >>> driver = DummyNodeDriver(22) >>> node=driver.create_node() >>> node.name 'dummy-23' """ name = "Dummy Node Provider" website = 'http://example.com' type = Provider.DUMMY def __init__(self, creds): """ :param creds: Credentials :type creds: ``str`` :rtype: ``None`` """ self.creds = creds try: num = int(creds) except ValueError: num = None if num: self.nl = [] startip = _ip_to_int('127.0.0.1') for i in range(num): ip = _int_to_ip(startip + i) self.nl.append( Node(id=i, name='dummy-%d' % (i), state=NodeState.RUNNING, public_ips=[ip], private_ips=[], driver=self, extra={'foo': 'bar'}) ) else: self.nl = [ Node(id=1, name='dummy-1', state=NodeState.RUNNING, public_ips=['127.0.0.1'], private_ips=[], driver=self, extra={'foo': 'bar'}), Node(id=2, name='dummy-2', state=NodeState.RUNNING, public_ips=['127.0.0.1'], private_ips=[], driver=self, extra={'foo': 'bar'}), ] self.connection = DummyConnection(self.creds) def get_uuid(self, unique_field=None): """ :param unique_field: Unique field :type unique_field: ``bool`` :rtype: :class:`UUID` """ return str(uuid.uuid4()) def list_nodes(self): """ List the nodes known to a particular driver; There are two default nodes created at the beginning >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> node_list=driver.list_nodes() >>> sorted([node.name for node in node_list ]) ['dummy-1', 'dummy-2'] each item in the list returned is a node object from which you can carry out any node actions you wish >>> node_list[0].reboot() True As more nodes are added, list_nodes will return them >>> node=driver.create_node() >>> node.size.id 's1' >>> node.image.id 'i2' >>> sorted([n.name for n in driver.list_nodes()]) ['dummy-1', 'dummy-2', 'dummy-3'] @inherits: :class:`NodeDriver.list_nodes` """ return self.nl def reboot_node(self, node): """ Sets the node state to rebooting; in this dummy driver always returns True as if the reboot had been successful. >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> node=driver.create_node() >>> from libcloud.compute.types import NodeState >>> node.state == NodeState.RUNNING True >>> node.state == NodeState.REBOOTING False >>> driver.reboot_node(node) True >>> node.state == NodeState.REBOOTING True Please note, dummy nodes never recover from the reboot. @inherits: :class:`NodeDriver.reboot_node` """ node.state = NodeState.REBOOTING return True def destroy_node(self, node): """ Sets the node state to terminated and removes it from the node list >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> from libcloud.compute.types import NodeState >>> node = [node for node in driver.list_nodes() if ... node.name == 'dummy-1'][0] >>> node.state == NodeState.RUNNING True >>> driver.destroy_node(node) True >>> node.state == NodeState.RUNNING False >>> [n for n in driver.list_nodes() if n.name == 'dummy-1'] [] @inherits: :class:`NodeDriver.destroy_node` """ node.state = NodeState.TERMINATED self.nl.remove(node) return True def list_images(self, location=None): """ Returns a list of images as a cloud provider might have >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> sorted([image.name for image in driver.list_images()]) ['Slackware 4', 'Ubuntu 9.04', 'Ubuntu 9.10'] @inherits: :class:`NodeDriver.list_images` """ return [ NodeImage(id=1, name="Ubuntu 9.10", driver=self), NodeImage(id=2, name="Ubuntu 9.04", driver=self), NodeImage(id=3, name="Slackware 4", driver=self), ] def list_sizes(self, location=None): """ Returns a list of node sizes as a cloud provider might have >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> sorted([size.ram for size in driver.list_sizes()]) [128, 512, 4096, 8192] @inherits: :class:`NodeDriver.list_images` """ return [ NodeSize(id=1, name="Small", ram=128, disk=4, bandwidth=500, price=4, driver=self), NodeSize(id=2, name="Medium", ram=512, disk=16, bandwidth=1500, price=8, driver=self), NodeSize(id=3, name="Big", ram=4096, disk=32, bandwidth=2500, price=32, driver=self), NodeSize(id=4, name="XXL Big", ram=4096 * 2, disk=32 * 4, bandwidth=2500 * 3, price=32 * 2, driver=self), ] def list_locations(self): """ Returns a list of locations of nodes >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> sorted([loc.name + " in " + loc.country for loc in ... driver.list_locations()]) ['Island Datacenter in FJ', 'London Loft in GB', "Paul's Room in US"] @inherits: :class:`NodeDriver.list_locations` """ return [ NodeLocation(id=1, name="Paul's Room", country='US', driver=self), NodeLocation(id=2, name="London Loft", country='GB', driver=self), NodeLocation(id=3, name="Island Datacenter", country='FJ', driver=self), ] def create_node(self, name, size, image): """ Creates a dummy node; the node id is equal to the number of nodes in the node list >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver(0) >>> sorted([node.name for node in driver.list_nodes()]) ['dummy-1', 'dummy-2'] >>> nodeA = driver.create_node() >>> sorted([node.name for node in driver.list_nodes()]) ['dummy-1', 'dummy-2', 'dummy-3'] >>> driver.create_node().name 'dummy-4' >>> driver.destroy_node(nodeA) True >>> sorted([node.name for node in driver.list_nodes()]) ['dummy-1', 'dummy-2', 'dummy-4'] @inherits: :class:`NodeDriver.create_node` """ num = len(self.nl) + 1 n = Node(id=num, name='dummy-%d' % (num), state=NodeState.RUNNING, public_ips=['127.0.0.%d' % (num)], private_ips=[], driver=self, size=NodeSize(id='s1', name='foo', ram=2048, disk=160, bandwidth=None, price=0.0, driver=self), image=NodeImage(id='i2', name='image', driver=self), extra={'foo': 'bar'}) self.nl.append(n) return n def import_key_pair_from_string(self, name, key_material): key_pair = KeyPair(name=name, public_key=key_material, fingerprint='fingerprint', private_key='private_key', driver=self) return key_pair def _ip_to_int(ip): return socket.htonl(struct.unpack('I', socket.inet_aton(ip))[0]) def _int_to_ip(ip): return socket.inet_ntoa(struct.pack('I', socket.ntohl(ip))) if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/compute/drivers/ec2.py0000664000175000017500000065262713577507766022446 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Amazon EC2, Eucalyptus, Nimbus and Outscale drivers. """ from typing import List import re import base64 import copy import warnings import time from libcloud.utils.py3 import ET from libcloud.utils.py3 import b, basestring, ensure_string from libcloud.utils.xml import fixxpath, findtext, findattr, findall from libcloud.utils.publickey import get_pubkey_ssh2_fingerprint from libcloud.utils.publickey import get_pubkey_comment from libcloud.utils.iso8601 import parse_date from libcloud.common.aws import AWSBaseResponse, SignedAWSConnection from libcloud.common.aws import DEFAULT_SIGNATURE_VERSION from libcloud.common.types import (InvalidCredsError, MalformedResponseError, LibcloudError) from libcloud.compute.providers import Provider from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize from libcloud.compute.base import NodeImage, StorageVolume, VolumeSnapshot from libcloud.compute.base import KeyPair from libcloud.compute.types import NodeState, KeyPairDoesNotExistError, \ StorageVolumeState, VolumeSnapshotState from libcloud.compute.constants import INSTANCE_TYPES, REGION_DETAILS __all__ = [ 'API_VERSION', 'NAMESPACE', 'INSTANCE_TYPES', 'OUTSCALE_INSTANCE_TYPES', 'OUTSCALE_SAS_REGION_DETAILS', 'OUTSCALE_INC_REGION_DETAILS', 'DEFAULT_EUCA_API_VERSION', 'EUCA_NAMESPACE', 'EC2NodeDriver', 'BaseEC2NodeDriver', 'NimbusNodeDriver', 'EucNodeDriver', 'OutscaleSASNodeDriver', 'OutscaleINCNodeDriver', 'EC2NodeLocation', 'EC2ReservedNode', 'EC2SecurityGroup', 'EC2ImportSnapshotTask', 'EC2PlacementGroup', 'EC2Network', 'EC2NetworkSubnet', 'EC2NetworkInterface', 'EC2RouteTable', 'EC2Route', 'EC2SubnetAssociation', 'ExEC2AvailabilityZone', 'IdempotentParamError' ] API_VERSION = '2016-11-15' NAMESPACE = 'http://ec2.amazonaws.com/doc/%s/' % (API_VERSION) # Eucalyptus Constants DEFAULT_EUCA_API_VERSION = '3.3.0' EUCA_NAMESPACE = 'http://msgs.eucalyptus.com/%s' % (DEFAULT_EUCA_API_VERSION) # Outscale Constants DEFAULT_OUTSCALE_API_VERSION = '2016-04-01' OUTSCALE_NAMESPACE = 'http://api.outscale.com/wsdl/fcuext/2014-04-15/' # Add Nimbus region REGION_DETAILS['nimbus'] = { # Nimbus clouds have 3 EC2-style instance types but their particular # RAM allocations are configured by the admin 'country': 'custom', 'signature_version': '2', 'instance_types': [ 'm1.small', 'm1.large', 'm1.xlarge' ] } """ Sizes must be hardcoded because Outscale doesn't provide an API to fetch them. Outscale cloud instances share some names with EC2 but have different specifications so declare them in another constant. """ OUTSCALE_INSTANCE_TYPES = { 't1.micro': { 'id': 't1.micro', 'name': 'Micro Instance', 'ram': 615, 'disk': 0, 'bandwidth': None }, 'm1.small': { 'id': 'm1.small', 'name': 'Standard Small Instance', 'ram': 1740, 'disk': 150, 'bandwidth': None }, 'm1.medium': { 'id': 'm1.medium', 'name': 'Standard Medium Instance', 'ram': 3840, 'disk': 420, 'bandwidth': None }, 'm1.large': { 'id': 'm1.large', 'name': 'Standard Large Instance', 'ram': 7680, 'disk': 840, 'bandwidth': None }, 'm1.xlarge': { 'id': 'm1.xlarge', 'name': 'Standard Extra Large Instance', 'ram': 15360, 'disk': 1680, 'bandwidth': None }, 'c1.medium': { 'id': 'c1.medium', 'name': 'Compute Optimized Medium Instance', 'ram': 1740, 'disk': 340, 'bandwidth': None }, 'c1.xlarge': { 'id': 'c1.xlarge', 'name': 'Compute Optimized Extra Large Instance', 'ram': 7168, 'disk': 1680, 'bandwidth': None }, 'c3.large': { 'id': 'c3.large', 'name': 'Compute Optimized Large Instance', 'ram': 3840, 'disk': 32, 'bandwidth': None }, 'c3.xlarge': { 'id': 'c3.xlarge', 'name': 'Compute Optimized Extra Large Instance', 'ram': 7168, 'disk': 80, 'bandwidth': None }, 'c3.2xlarge': { 'id': 'c3.2xlarge', 'name': 'Compute Optimized Double Extra Large Instance', 'ram': 15359, 'disk': 160, 'bandwidth': None }, 'c3.4xlarge': { 'id': 'c3.4xlarge', 'name': 'Compute Optimized Quadruple Extra Large Instance', 'ram': 30720, 'disk': 320, 'bandwidth': None }, 'c3.8xlarge': { 'id': 'c3.8xlarge', 'name': 'Compute Optimized Eight Extra Large Instance', 'ram': 61440, 'disk': 640, 'bandwidth': None }, 'm2.xlarge': { 'id': 'm2.xlarge', 'name': 'High Memory Extra Large Instance', 'ram': 17510, 'disk': 420, 'bandwidth': None }, 'm2.2xlarge': { 'id': 'm2.2xlarge', 'name': 'High Memory Double Extra Large Instance', 'ram': 35020, 'disk': 840, 'bandwidth': None }, 'm2.4xlarge': { 'id': 'm2.4xlarge', 'name': 'High Memory Quadruple Extra Large Instance', 'ram': 70042, 'disk': 1680, 'bandwidth': None }, 'nv1.small': { 'id': 'nv1.small', 'name': 'GPU Small Instance', 'ram': 1739, 'disk': 150, 'bandwidth': None }, 'nv1.medium': { 'id': 'nv1.medium', 'name': 'GPU Medium Instance', 'ram': 3839, 'disk': 420, 'bandwidth': None }, 'nv1.large': { 'id': 'nv1.large', 'name': 'GPU Large Instance', 'ram': 7679, 'disk': 840, 'bandwidth': None }, 'nv1.xlarge': { 'id': 'nv1.xlarge', 'name': 'GPU Extra Large Instance', 'ram': 15358, 'disk': 1680, 'bandwidth': None }, 'g2.2xlarge': { 'id': 'g2.2xlarge', 'name': 'GPU Double Extra Large Instance', 'ram': 15360, 'disk': 60, 'bandwidth': None }, 'cc1.4xlarge': { 'id': 'cc1.4xlarge', 'name': 'Cluster Compute Quadruple Extra Large Instance', 'ram': 24576, 'disk': 1680, 'bandwidth': None }, 'cc2.8xlarge': { 'id': 'cc2.8xlarge', 'name': 'Cluster Compute Eight Extra Large Instance', 'ram': 65536, 'disk': 3360, 'bandwidth': None }, 'hi1.xlarge': { 'id': 'hi1.xlarge', 'name': 'High Storage Extra Large Instance', 'ram': 15361, 'disk': 1680, 'bandwidth': None }, 'm3.xlarge': { 'id': 'm3.xlarge', 'name': 'High Storage Optimized Extra Large Instance', 'ram': 15357, 'disk': 0, 'bandwidth': None }, 'm3.2xlarge': { 'id': 'm3.2xlarge', 'name': 'High Storage Optimized Double Extra Large Instance', 'ram': 30720, 'disk': 0, 'bandwidth': None }, 'm3s.xlarge': { 'id': 'm3s.xlarge', 'name': 'High Storage Optimized Extra Large Instance', 'ram': 15359, 'disk': 0, 'bandwidth': None }, 'm3s.2xlarge': { 'id': 'm3s.2xlarge', 'name': 'High Storage Optimized Double Extra Large Instance', 'ram': 30719, 'disk': 0, 'bandwidth': None }, 'cr1.8xlarge': { 'id': 'cr1.8xlarge', 'name': 'Memory Optimized Eight Extra Large Instance', 'ram': 249855, 'disk': 240, 'bandwidth': None }, 'os1.2xlarge': { 'id': 'os1.2xlarge', 'name': 'Memory Optimized, High Storage, Passthrough NIC Double Extra ' 'Large Instance', 'ram': 65536, 'disk': 60, 'bandwidth': None }, 'os1.4xlarge': { 'id': 'os1.4xlarge', 'name': 'Memory Optimized, High Storage, Passthrough NIC Quadruple Ext' 'ra Large Instance', 'ram': 131072, 'disk': 120, 'bandwidth': None }, 'os1.8xlarge': { 'id': 'os1.8xlarge', 'name': 'Memory Optimized, High Storage, Passthrough NIC Eight Extra L' 'arge Instance', 'ram': 249856, 'disk': 500, 'bandwidth': None }, 'oc1.4xlarge': { 'id': 'oc1.4xlarge', 'name': 'Outscale Quadruple Extra Large Instance', 'ram': 24575, 'disk': 1680, 'bandwidth': None }, 'oc2.8xlarge': { 'id': 'oc2.8xlarge', 'name': 'Outscale Eight Extra Large Instance', 'ram': 65535, 'disk': 3360, 'bandwidth': None } } """ The function manipulating Outscale cloud regions will be overridden because Outscale instances types are in a separate dict so also declare Outscale cloud regions in some other constants. """ OUTSCALE_SAS_REGION_DETAILS = { 'eu-west-3': { 'endpoint': 'api-ppd.outscale.com', 'api_name': 'osc_sas_eu_west_3', 'country': 'FRANCE', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'eu-west-1': { 'endpoint': 'api.eu-west-1.outscale.com', 'api_name': 'osc_sas_eu_west_1', 'country': 'FRANCE', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'eu-west-2': { 'endpoint': 'fcu.eu-west-2.outscale.com', 'api_name': 'osc_sas_eu_west_2', 'country': 'FRANCE', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'us-east-1': { 'endpoint': 'api.us-east-1.outscale.com', 'api_name': 'osc_sas_us_east_1', 'country': 'USA', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'us-east-2': { 'endpoint': 'fcu.us-east-2.outscale.com', 'api_name': 'osc_sas_us_east_2', 'country': 'USA', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] } } OUTSCALE_INC_REGION_DETAILS = { 'eu-west-1': { 'endpoint': 'api.eu-west-1.outscale.com', 'api_name': 'osc_inc_eu_west_1', 'country': 'FRANCE', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'p2.xlarge', 'p2.8xlarge', 'p2.16xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'eu-west-2': { 'endpoint': 'fcu.eu-west-2.outscale.com', 'api_name': 'osc_inc_eu_west_2', 'country': 'FRANCE', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'eu-west-3': { 'endpoint': 'api-ppd.outscale.com', 'api_name': 'osc_inc_eu_west_3', 'country': 'FRANCE', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'us-east-1': { 'endpoint': 'api.us-east-1.outscale.com', 'api_name': 'osc_inc_us_east_1', 'country': 'USA', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] }, 'us-east-2': { 'endpoint': 'fcu.us-east-2.outscale.com', 'api_name': 'osc_inc_us_east_2', 'country': 'USA', 'instance_types': [ 't1.micro', 'm1.small', 'm1.medium', 'm1.large', 'm1.xlarge', 'c1.medium', 'c1.xlarge', 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', 'nv1.small', 'nv1.medium', 'nv1.large', 'nv1.xlarge', 'cc1.4xlarge', 'cc2.8xlarge', 'm3.xlarge', 'm3.2xlarge', 'cr1.8xlarge', 'os1.8xlarge' ] } } """ Define the extra dictionary for specific resources """ RESOURCE_EXTRA_ATTRIBUTES_MAP = { 'ebs_instance_block_device': { 'attach_time': { 'xpath': 'ebs/attachTime', 'transform_func': parse_date }, 'delete': { 'xpath': 'ebs/deleteOnTermination', 'transform_func': str }, 'status': { 'xpath': 'ebs/status', 'transform_func': str }, 'volume_id': { 'xpath': 'ebs/volumeId', 'transform_func': str } }, 'ebs_volume': { 'snapshot_id': { 'xpath': 'ebs/snapshotId', 'transform_func': str }, 'volume_id': { 'xpath': 'ebs/volumeId', 'transform_func': str }, 'volume_size': { 'xpath': 'ebs/volumeSize', 'transform_func': int }, 'delete': { 'xpath': 'ebs/deleteOnTermination', 'transform_func': str }, 'volume_type': { 'xpath': 'ebs/volumeType', 'transform_func': str }, 'iops': { 'xpath': 'ebs/iops', 'transform_func': int } }, 'elastic_ip': { 'allocation_id': { 'xpath': 'allocationId', 'transform_func': str, }, 'association_id': { 'xpath': 'associationId', 'transform_func': str, }, 'interface_id': { 'xpath': 'networkInterfaceId', 'transform_func': str, }, 'owner_id': { 'xpath': 'networkInterfaceOwnerId', 'transform_func': str, }, 'private_ip': { 'xpath': 'privateIp', 'transform_func': str, } }, 'image': { 'state': { 'xpath': 'imageState', 'transform_func': str }, 'owner_id': { 'xpath': 'imageOwnerId', 'transform_func': str }, 'owner_alias': { 'xpath': 'imageOwnerAlias', 'transform_func': str }, 'is_public': { 'xpath': 'isPublic', 'transform_func': str }, 'architecture': { 'xpath': 'architecture', 'transform_func': str }, 'image_type': { 'xpath': 'imageType', 'transform_func': str }, 'image_location': { 'xpath': 'imageLocation', 'transform_func': str }, 'platform': { 'xpath': 'platform', 'transform_func': str }, 'description': { 'xpath': 'description', 'transform_func': str }, 'root_device_type': { 'xpath': 'rootDeviceType', 'transform_func': str }, 'virtualization_type': { 'xpath': 'virtualizationType', 'transform_func': str }, 'hypervisor': { 'xpath': 'hypervisor', 'transform_func': str }, 'kernel_id': { 'xpath': 'kernelId', 'transform_func': str }, 'ramdisk_id': { 'xpath': 'ramdiskId', 'transform_func': str }, 'ena_support': { 'xpath': 'enaSupport', 'transform_func': str }, 'sriov_net_support': { 'xpath': 'sriovNetSupport', 'transform_func': str } }, 'network': { 'state': { 'xpath': 'state', 'transform_func': str }, 'dhcp_options_id': { 'xpath': 'dhcpOptionsId', 'transform_func': str }, 'instance_tenancy': { 'xpath': 'instanceTenancy', 'transform_func': str }, 'is_default': { 'xpath': 'isDefault', 'transform_func': str } }, 'network_interface': { 'subnet_id': { 'xpath': 'subnetId', 'transform_func': str }, 'vpc_id': { 'xpath': 'vpcId', 'transform_func': str }, 'zone': { 'xpath': 'availabilityZone', 'transform_func': str }, 'description': { 'xpath': 'description', 'transform_func': str }, 'owner_id': { 'xpath': 'ownerId', 'transform_func': str }, 'mac_address': { 'xpath': 'macAddress', 'transform_func': str }, 'private_dns_name': { 'xpath': 'privateIpAddressesSet/privateDnsName', 'transform_func': str }, 'source_dest_check': { 'xpath': 'sourceDestCheck', 'transform_func': str } }, 'network_interface_attachment': { 'attachment_id': { 'xpath': 'attachment/attachmentId', 'transform_func': str }, 'instance_id': { 'xpath': 'attachment/instanceId', 'transform_func': str }, 'owner_id': { 'xpath': 'attachment/instanceOwnerId', 'transform_func': str }, 'device_index': { 'xpath': 'attachment/deviceIndex', 'transform_func': int }, 'status': { 'xpath': 'attachment/status', 'transform_func': str }, 'attach_time': { 'xpath': 'attachment/attachTime', 'transform_func': parse_date }, 'delete': { 'xpath': 'attachment/deleteOnTermination', 'transform_func': str } }, 'node': { 'availability': { 'xpath': 'placement/availabilityZone', 'transform_func': str }, 'architecture': { 'xpath': 'architecture', 'transform_func': str }, 'client_token': { 'xpath': 'clientToken', 'transform_func': str }, 'dns_name': { 'xpath': 'dnsName', 'transform_func': str }, 'hypervisor': { 'xpath': 'hypervisor', 'transform_func': str }, 'iam_profile': { 'xpath': 'iamInstanceProfile/id', 'transform_func': str }, 'image_id': { 'xpath': 'imageId', 'transform_func': str }, 'instance_id': { 'xpath': 'instanceId', 'transform_func': str }, 'instance_lifecycle': { 'xpath': 'instanceLifecycle', 'transform_func': str }, 'instance_tenancy': { 'xpath': 'placement/tenancy', 'transform_func': str }, 'instance_type': { 'xpath': 'instanceType', 'transform_func': str }, 'key_name': { 'xpath': 'keyName', 'transform_func': str }, 'launch_index': { 'xpath': 'amiLaunchIndex', 'transform_func': int }, 'launch_time': { 'xpath': 'launchTime', 'transform_func': str }, 'kernel_id': { 'xpath': 'kernelId', 'transform_func': str }, 'monitoring': { 'xpath': 'monitoring/state', 'transform_func': str }, 'platform': { 'xpath': 'platform', 'transform_func': str }, 'private_dns': { 'xpath': 'privateDnsName', 'transform_func': str }, 'ramdisk_id': { 'xpath': 'ramdiskId', 'transform_func': str }, 'root_device_type': { 'xpath': 'rootDeviceType', 'transform_func': str }, 'root_device_name': { 'xpath': 'rootDeviceName', 'transform_func': str }, 'reason': { 'xpath': 'reason', 'transform_func': str }, 'source_dest_check': { 'xpath': 'sourceDestCheck', 'transform_func': str }, 'status': { 'xpath': 'instanceState/name', 'transform_func': str }, 'subnet_id': { 'xpath': 'subnetId', 'transform_func': str }, 'virtualization_type': { 'xpath': 'virtualizationType', 'transform_func': str }, 'ebs_optimized': { 'xpath': 'ebsOptimized', 'transform_func': str }, 'vpc_id': { 'xpath': 'vpcId', 'transform_func': str } }, 'reserved_node': { 'instance_type': { 'xpath': 'instanceType', 'transform_func': str }, 'availability': { 'xpath': 'availabilityZone', 'transform_func': str }, 'start': { 'xpath': 'start', 'transform_func': str }, 'end': { 'xpath': 'end', 'transform_func': str }, 'duration': { 'xpath': 'duration', 'transform_func': int }, 'usage_price': { 'xpath': 'usagePrice', 'transform_func': float }, 'fixed_price': { 'xpath': 'fixedPrice', 'transform_func': float }, 'instance_count': { 'xpath': 'instanceCount', 'transform_func': int }, 'description': { 'xpath': 'productDescription', 'transform_func': str }, 'instance_tenancy': { 'xpath': 'instanceTenancy', 'transform_func': str }, 'currency_code': { 'xpath': 'currencyCode', 'transform_func': str }, 'offering_type': { 'xpath': 'offeringType', 'transform_func': str } }, 'security_group': { 'vpc_id': { 'xpath': 'vpcId', 'transform_func': str }, 'description': { 'xpath': 'groupDescription', 'transform_func': str }, 'owner_id': { 'xpath': 'ownerId', 'transform_func': str } }, 'snapshot': { 'volume_id': { 'xpath': 'volumeId', 'transform_func': str }, 'state': { 'xpath': 'status', 'transform_func': str }, 'description': { 'xpath': 'description', 'transform_func': str }, 'progress': { 'xpath': 'progress', 'transform_func': str }, 'start_time': { 'xpath': 'startTime', 'transform_func': parse_date } }, 'subnet': { 'cidr_block': { 'xpath': 'cidrBlock', 'transform_func': str }, 'available_ips': { 'xpath': 'availableIpAddressCount', 'transform_func': int }, 'zone': { 'xpath': 'availabilityZone', 'transform_func': str }, 'vpc_id': { 'xpath': 'vpcId', 'transform_func': str } }, 'volume': { 'device': { 'xpath': 'attachmentSet/item/device', 'transform_func': str }, 'snapshot_id': { 'xpath': 'snapshotId', 'transform_func': lambda v: str(v) or None }, 'iops': { 'xpath': 'iops', 'transform_func': int }, 'zone': { 'xpath': 'availabilityZone', 'transform_func': str }, 'create_time': { 'xpath': 'createTime', 'transform_func': parse_date }, 'state': { 'xpath': 'status', 'transform_func': str }, 'encrypted': { 'xpath': 'encrypted', 'transform_func': lambda x: {'true': True, 'false': False}.get(x) }, 'attach_time': { 'xpath': 'attachmentSet/item/attachTime', 'transform_func': parse_date }, 'attachment_status': { 'xpath': 'attachmentSet/item/status', 'transform_func': str }, 'instance_id': { 'xpath': 'attachmentSet/item/instanceId', 'transform_func': str }, 'delete': { 'xpath': 'attachmentSet/item/deleteOnTermination', 'transform_func': str }, 'volume_type': { 'xpath': 'volumeType', 'transform_func': str } }, 'route_table': { 'vpc_id': { 'xpath': 'vpcId', 'transform_func': str } } } VOLUME_MODIFICATION_ATTRIBUTE_MAP = { 'end_time': { 'xpath': 'endTime', 'transform_func': parse_date }, 'modification_state': { 'xpath': 'modificationState', 'transform_func': str }, 'original_iops': { 'xpath': 'originalIops', 'transform_func': int }, 'original_size': { 'xpath': 'originalSize', 'transform_func': int }, 'original_volume_type': { 'xpath': 'originalVolumeType', 'transform_func': str }, 'progress': { 'xpath': 'progress', 'transform_func': int }, 'start_time': { 'xpath': 'startTime', 'transform_func': parse_date }, 'status_message': { 'xpath': 'statusMessage', 'transform_func': str }, 'target_iops': { 'xpath': 'targetIops', 'transform_func': int }, 'target_size': { 'xpath': 'targetSize', 'transform_func': int }, 'target_volume_type': { 'xpath': 'targetVolumeType', 'transform_func': str }, 'volume_id': { 'xpath': 'volumeId', 'transform_func': str } } VALID_EC2_REGIONS = REGION_DETAILS.keys() VALID_EC2_REGIONS = [r for r in VALID_EC2_REGIONS if r != 'nimbus'] VALID_VOLUME_TYPES = ['standard', 'io1', 'gp2', 'st1', 'sc1'] class EC2NodeLocation(NodeLocation): def __init__(self, id, name, country, driver, availability_zone): super(EC2NodeLocation, self).__init__(id, name, country, driver) self.availability_zone = availability_zone def __repr__(self): return (('') % (self.id, self.name, self.country, self.availability_zone, self.driver.name)) class EC2Response(AWSBaseResponse): """ EC2 specific response parsing and error handling. """ def parse_error(self): err_list = [] # Okay, so for Eucalyptus, you can get a 403, with no body, # if you are using the wrong user/password. msg = "Failure: 403 Forbidden" if self.status == 403 and self.body[:len(msg)] == msg: raise InvalidCredsError(msg) try: body = ET.XML(self.body) except Exception: raise MalformedResponseError("Failed to parse XML", body=self.body, driver=EC2NodeDriver) for err in body.findall('Errors/Error'): code, message = list(err) err_list.append('%s: %s' % (code.text, message.text)) if code.text == 'InvalidClientTokenId': raise InvalidCredsError(err_list[-1]) if code.text == 'SignatureDoesNotMatch': raise InvalidCredsError(err_list[-1]) if code.text == 'AuthFailure': raise InvalidCredsError(err_list[-1]) if code.text == 'OptInRequired': raise InvalidCredsError(err_list[-1]) if code.text == 'IdempotentParameterMismatch': raise IdempotentParamError(err_list[-1]) if code.text == 'InvalidKeyPair.NotFound': # TODO: Use connection context instead match = re.match(r'.*\'(.+?)\'.*', message.text) if match: name = match.groups()[0] else: name = None raise KeyPairDoesNotExistError(name=name, driver=self.connection.driver) return '\n'.join(err_list) class EC2Connection(SignedAWSConnection): """ Represents a single connection to the EC2 Endpoint. """ version = API_VERSION host = REGION_DETAILS['us-east-1']['endpoint'] responseCls = EC2Response service_name = 'ec2' class ExEC2AvailabilityZone(object): """ Extension class which stores information about an EC2 availability zone. Note: This class is EC2 specific. """ def __init__(self, name, zone_state, region_name): self.name = name self.zone_state = zone_state self.region_name = region_name def __repr__(self): return (('') % (self.name, self.zone_state, self.region_name)) class EC2ReservedNode(Node): """ Class which stores information about EC2 reserved instances/nodes Inherits from Node and passes in None for name and private/public IPs Note: This class is EC2 specific. """ def __init__(self, id, state, driver, size=None, image=None, extra=None): super(EC2ReservedNode, self).__init__(id=id, name=None, state=state, public_ips=None, private_ips=None, driver=driver, extra=extra) def __repr__(self): return (('') % (self.id)) class EC2SecurityGroup(object): """ Represents information about a Security group Note: This class is EC2 specific. """ def __init__(self, id, name, ingress_rules, egress_rules, extra=None): self.id = id self.name = name self.ingress_rules = ingress_rules self.egress_rules = egress_rules self.extra = extra or {} def __repr__(self): return (('' % (self.name, self.strategy) class EC2Network(object): """ Represents information about a VPC (Virtual Private Cloud) network Note: This class is EC2 specific. """ def __init__(self, id, name, cidr_block, extra=None): self.id = id self.name = name self.cidr_block = cidr_block self.extra = extra or {} def __repr__(self): return (('') % (self.ip, self.domain, self.instance_id)) class VPCInternetGateway(object): """ Class which stores information about VPC Internet Gateways. Note: This class is VPC specific. """ def __init__(self, id, name, vpc_id, state, driver, extra=None): self.id = id self.name = name self.vpc_id = vpc_id self.state = state self.extra = extra or {} def __repr__(self): return (('') % (self.id)) class EC2RouteTable(object): """ Class which stores information about VPC Route Tables. Note: This class is VPC specific. """ def __init__(self, id, name, routes, subnet_associations, propagating_gateway_ids, extra=None): """ :param id: The ID of the route table. :type id: ``str`` :param name: The name of the route table. :type name: ``str`` :param routes: A list of routes in the route table. :type routes: ``list`` of :class:`EC2Route` :param subnet_associations: A list of associations between the route table and one or more subnets. :type subnet_associations: ``list`` of :class:`EC2SubnetAssociation` :param propagating_gateway_ids: The list of IDs of any virtual private gateways propagating the routes. :type propagating_gateway_ids: ``list`` """ self.id = id self.name = name self.routes = routes self.subnet_associations = subnet_associations self.propagating_gateway_ids = propagating_gateway_ids self.extra = extra or {} def __repr__(self): return (('') % (self.id)) class EC2Route(object): """ Class which stores information about a Route. Note: This class is VPC specific. """ def __init__(self, cidr, gateway_id, instance_id, owner_id, interface_id, state, origin, vpc_peering_connection_id): """ :param cidr: The CIDR block used for the destination match. :type cidr: ``str`` :param gateway_id: The ID of a gateway attached to the VPC. :type gateway_id: ``str`` :param instance_id: The ID of a NAT instance in the VPC. :type instance_id: ``str`` :param owner_id: The AWS account ID of the owner of the instance. :type owner_id: ``str`` :param interface_id: The ID of the network interface. :type interface_id: ``str`` :param state: The state of the route (active | blackhole). :type state: ``str`` :param origin: Describes how the route was created. :type origin: ``str`` :param vpc_peering_connection_id: The ID of the VPC peering connection. :type vpc_peering_connection_id: ``str`` """ self.cidr = cidr self.gateway_id = gateway_id self.instance_id = instance_id self.owner_id = owner_id self.interface_id = interface_id self.state = state self.origin = origin self.vpc_peering_connection_id = vpc_peering_connection_id def __repr__(self): return (('') % (self.cidr)) class EC2SubnetAssociation(object): """ Class which stores information about Route Table associated with a given Subnet in a VPC Note: This class is VPC specific. """ def __init__(self, id, route_table_id, subnet_id, main=False): """ :param id: The ID of the subnet association in the VPC. :type id: ``str`` :param route_table_id: The ID of a route table in the VPC. :type route_table_id: ``str`` :param subnet_id: The ID of a subnet in the VPC. :type subnet_id: ``str`` :param main: If true, means this is a main VPC route table. :type main: ``bool`` """ self.id = id self.route_table_id = route_table_id self.subnet_id = subnet_id self.main = main def __repr__(self): return (('') % (self.id)) class EC2VolumeModification(object): """ Describes the modification status of an EBS volume. If the volume has never been modified, some element values will be null. """ def __init__(self, end_time=None, modification_state=None, original_iops=None, original_size=None, original_volume_type=None, progress=None, start_time=None, status_message=None, target_iops=None, target_size=None, target_volume_type=None, volume_id=None): self.end_time = end_time self.modification_state = modification_state self.original_iops = original_iops self.original_size = original_size self.original_volume_type = original_volume_type self.progress = progress self.start_time = start_time self.status_message = status_message self.target_iops = target_iops self.target_size = target_size self.target_volume_type = target_volume_type self.volume_id = volume_id def __repr__(self): return (('') % (self.end_time, self.modification_state, self.original_iops, self.original_size, self.original_volume_type, self.progress, self.start_time, self.status_message, self.target_iops, self.target_size, self.target_volume_type, self.volume_id)) class BaseEC2NodeDriver(NodeDriver): """ Base Amazon EC2 node driver. Used for main EC2 and other derivate driver classes to inherit from it. """ connectionCls = EC2Connection features = {'create_node': ['ssh_key']} path = '/' region_name = '' country = '' signature_version = DEFAULT_SIGNATURE_VERSION NODE_STATE_MAP = { 'pending': NodeState.PENDING, 'running': NodeState.RUNNING, 'shutting-down': NodeState.UNKNOWN, 'terminated': NodeState.TERMINATED } # http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Volume.html VOLUME_STATE_MAP = { 'available': StorageVolumeState.AVAILABLE, 'in-use': StorageVolumeState.INUSE, 'error': StorageVolumeState.ERROR, 'creating': StorageVolumeState.CREATING, 'deleting': StorageVolumeState.DELETING, 'deleted': StorageVolumeState.DELETED, 'error_deleting': StorageVolumeState.ERROR } SNAPSHOT_STATE_MAP = { 'pending': VolumeSnapshotState.CREATING, 'completed': VolumeSnapshotState.AVAILABLE, 'error': VolumeSnapshotState.ERROR, } def list_nodes(self, ex_node_ids=None, ex_filters=None): # type: (str, str) -> List[Node] """ Lists all nodes. Ex_node_ids parameter is used to filter the list of nodes that should be returned. Only the nodes with the corresponding node IDs will be returned. :param ex_node_ids: List of ``node.id`` :type ex_node_ids: ``list`` of ``str`` :param ex_filters: The filters so that the list includes information for certain nodes only. :type ex_filters: ``dict`` :rtype: ``list`` of :class:`Node` """ params = {'Action': 'DescribeInstances'} if ex_node_ids: params.update(self._pathlist('InstanceId', ex_node_ids)) if ex_filters: params.update(self._build_filters(ex_filters)) elem = self.connection.request(self.path, params=params).object nodes = [] for rs in findall(element=elem, xpath='reservationSet/item', namespace=NAMESPACE): nodes += self._to_nodes(rs, 'instancesSet/item') nodes_elastic_ips_mappings = self.ex_describe_addresses(nodes) for node in nodes: ips = nodes_elastic_ips_mappings[node.id] node.public_ips.extend(ips) return nodes def list_sizes(self, location=None): available_types = REGION_DETAILS[self.region_name]['instance_types'] sizes = [] for instance_type in available_types: attributes = INSTANCE_TYPES[instance_type] attributes = copy.deepcopy(attributes) try: price = self._get_size_price(size_id=instance_type) attributes['price'] = price except KeyError: attributes['price'] = None # pricing not available sizes.append(NodeSize(driver=self, **attributes)) return sizes def list_images(self, location=None, ex_image_ids=None, ex_owner=None, ex_executableby=None, ex_filters=None): """ Lists all images @inherits: :class:`NodeDriver.list_images` Ex_image_ids parameter is used to filter the list of images that should be returned. Only the images with the corresponding image IDs will be returned. Ex_owner parameter is used to filter the list of images that should be returned. Only the images with the corresponding owner will be returned. Valid values: amazon|aws-marketplace|self|all|aws id Ex_executableby parameter describes images for which the specified user has explicit launch permissions. The user can be an AWS account ID, self to return images for which the sender of the request has explicit launch permissions, or all to return images with public launch permissions. Valid values: all|self|aws id Ex_filters parameter is used to filter the list of images that should be returned. Only images matching the filter will be returned. :param ex_image_ids: List of ``NodeImage.id`` :type ex_image_ids: ``list`` of ``str`` :param ex_owner: Owner name :type ex_owner: ``str`` :param ex_executableby: Executable by :type ex_executableby: ``str`` :param ex_filters: Filter by :type ex_filters: ``dict`` :rtype: ``list`` of :class:`NodeImage` """ params = {'Action': 'DescribeImages'} if ex_owner: params.update({'Owner.1': ex_owner}) if ex_executableby: params.update({'ExecutableBy.1': ex_executableby}) if ex_image_ids: for index, image_id in enumerate(ex_image_ids): index += 1 params.update({'ImageId.%s' % (index): image_id}) if ex_filters: params.update(self._build_filters(ex_filters)) images = self._to_images( self.connection.request(self.path, params=params).object ) return images def get_image(self, image_id): """ Gets an image based on an image_id. :param image_id: Image identifier :type image_id: ``str`` :return: A NodeImage object :rtype: :class:`NodeImage` """ images = self.list_images(ex_image_ids=[image_id]) image = images[0] return image def list_locations(self): locations = [] iterator = enumerate(self.ex_list_availability_zones()) for index, availability_zone in iterator: locations.append(EC2NodeLocation( index, availability_zone.name, self.country, self, availability_zone) ) return locations def list_volumes(self, node=None, ex_filters=None): """ List volumes that are attached to a node, if specified and those that satisfy the filters, if specified. :param node: The node to which the volumes are attached. :type node: :class:`Node` :param ex_filters: The dictionary of additional filters. :type ex_filters: ``dict`` :return: The list of volumes that match the criteria. :rtype: ``list`` of :class:`StorageVolume` """ params = { 'Action': 'DescribeVolumes', } if not ex_filters: ex_filters = {} if node: ex_filters['attachment.instance-id'] = node.id if node or ex_filters: params.update(self._build_filters(ex_filters)) response = self.connection.request(self.path, params=params).object volumes = [self._to_volume(el) for el in response.findall( fixxpath(xpath='volumeSet/item', namespace=NAMESPACE)) ] return volumes def create_node(self, name, size, image, location=None, auth=None, ex_keyname=None, ex_userdata=None, ex_security_groups=None, ex_securitygroup=None, ex_security_group_ids=None, ex_metadata=None, ex_mincount=1, ex_maxcount=1, ex_clienttoken=None, ex_blockdevicemappings=None, ex_iamprofile=None, ex_ebs_optimized=None, ex_subnet=None, ex_placement_group=None, ex_assign_public_ip=False, ex_terminate_on_shutdown=False): """ Create a new EC2 node. Reference: http://bit.ly/8ZyPSy [docs.amazonwebservices.com] @inherits: :class:`NodeDriver.create_node` :keyword ex_keyname: The name of the key pair :type ex_keyname: ``str`` :keyword ex_userdata: User data :type ex_userdata: ``str`` :keyword ex_security_groups: A list of names of security groups to assign to the node. :type ex_security_groups: ``list`` :keyword ex_security_group_ids: A list of ids of security groups to assign to the node.[for VPC nodes only] :type ex_security_group_ids: ``list`` :keyword ex_metadata: Key/Value metadata to associate with a node :type ex_metadata: ``dict`` :keyword ex_mincount: Minimum number of instances to launch :type ex_mincount: ``int`` :keyword ex_maxcount: Maximum number of instances to launch :type ex_maxcount: ``int`` :keyword ex_clienttoken: Unique identifier to ensure idempotency :type ex_clienttoken: ``str`` :keyword ex_blockdevicemappings: ``list`` of ``dict`` block device mappings. :type ex_blockdevicemappings: ``list`` of ``dict`` :keyword ex_iam_profile: Name or ARN of IAM profile :type ex_iam_profile: ``str`` :keyword ex_ebs_optimized: EBS-Optimized if True :type ex_ebs_optimized: ``bool`` :keyword ex_subnet: The subnet to launch the instance into. :type ex_subnet: :class:`.EC2Subnet` :keyword ex_placement_group: The name of the placement group to launch the instance into. :type ex_placement_group: ``str`` :keyword ex_assign_public_ip: If True, the instance will be assigned a public ip address. Note : It takes takes a short while for the instance to be assigned the public ip so the node returned will NOT have the public ip assigned yet. :type ex_assign_public_ip: ``bool`` :keyword ex_terminate_on_shutdown: Indicates if the instance should be terminated instead of just shut down when using the operating systems command for system shutdown. :type ex_terminate_on_shutdown: ``bool`` """ params = { 'Action': 'RunInstances', 'ImageId': image.id, 'MinCount': str(ex_mincount), 'MaxCount': str(ex_maxcount), 'InstanceType': size.id } if ex_terminate_on_shutdown: params["InstanceInitiatedShutdownBehavior"] = "terminate" if ex_security_groups and ex_securitygroup: raise ValueError('You can only supply ex_security_groups or' ' ex_securitygroup') # ex_securitygroup is here for backward compatibility security_groups = ex_security_groups or ex_securitygroup if security_groups: if not isinstance(security_groups, (tuple, list)): security_groups = [security_groups] for sig in range(len(security_groups)): params['SecurityGroup.%d' % (sig + 1,)] =\ security_groups[sig] if ex_security_group_ids and not ex_subnet: raise ValueError('You can only supply ex_security_group_ids' ' combinated with ex_subnet') security_group_ids = ex_security_group_ids security_group_id_params = {} if security_group_ids: if not isinstance(security_group_ids, (tuple, list)): security_group_ids = [security_group_ids] for sig in range(len(security_group_ids)): security_group_id_params['SecurityGroupId.%d' % (sig + 1,)] =\ security_group_ids[sig] if location: availability_zone = getattr(location, 'availability_zone', None) if availability_zone: if availability_zone.region_name != self.region_name: raise AttributeError('Invalid availability zone: %s' % (availability_zone.name)) params['Placement.AvailabilityZone'] = availability_zone.name if auth and ex_keyname: raise AttributeError('Cannot specify auth and ex_keyname together') if auth: auth = self._get_and_check_auth(auth) # pylint: disable=no-member key = self.ex_find_or_import_keypair_by_key_material(auth.pubkey) params['KeyName'] = key['keyName'] if ex_keyname: params['KeyName'] = ex_keyname if ex_userdata: params['UserData'] = base64.b64encode(b('ex_userdata'))\ .decode('utf-8') if ex_clienttoken: params['ClientToken'] = ex_clienttoken if ex_blockdevicemappings: params.update(self._get_block_device_mapping_params( ex_blockdevicemappings)) if ex_iamprofile: if not isinstance(ex_iamprofile, basestring): raise AttributeError('ex_iamprofile not string') if ex_iamprofile.startswith('arn:aws:iam:'): params['IamInstanceProfile.Arn'] = ex_iamprofile else: params['IamInstanceProfile.Name'] = ex_iamprofile if ex_ebs_optimized: params['EbsOptimized'] = ex_ebs_optimized subnet_id = None if ex_subnet: subnet_id = ex_subnet.id if ex_placement_group: params['Placement.GroupName'] = ex_placement_group assign_public_ip = ex_assign_public_ip # In the event that a public ip is requested a NetworkInterface # needs to be specified. Some properties that would # normally be at the root (security group ids and subnet id) # need to be moved to the level of the NetworkInterface because # the NetworkInterface is no longer created implicitly if assign_public_ip: root_key = 'NetworkInterface.1.' params[root_key + 'AssociatePublicIpAddress'] = "true" # This means that when the instance is terminated, the # NetworkInterface we created for the instance will be # deleted automatically params[root_key + 'DeleteOnTermination'] = "true" # Required to be 0 if we are associating a public ip params[root_key + 'DeviceIndex'] = "0" if subnet_id: params[root_key + 'SubnetId'] = subnet_id for key, security_group_id in security_group_id_params.items(): key = root_key + key params[key] = security_group_id else: params.update(security_group_id_params) if subnet_id: params['SubnetId'] = subnet_id # Specify tags at instance creation time tags = {'Name': name} if ex_metadata: tags.update(ex_metadata) tagspec_root = 'TagSpecification.1.' params[tagspec_root + 'ResourceType'] = 'instance' tag_nr = 1 for k, v in tags.items(): tag_root = tagspec_root + 'Tag.%d.' % tag_nr params[tag_root + 'Key'] = k params[tag_root + 'Value'] = v tag_nr += 1 object = self.connection.request(self.path, params=params).object nodes = self._to_nodes(object, 'instancesSet/item') for node in nodes: node.name = name node.extra.update({'tags': tags}) if len(nodes) == 1: return nodes[0] else: return nodes def reboot_node(self, node): params = {'Action': 'RebootInstances'} params.update(self._pathlist('InstanceId', [node.id])) res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def destroy_node(self, node): params = {'Action': 'TerminateInstances'} params.update(self._pathlist('InstanceId', [node.id])) res = self.connection.request(self.path, params=params).object return self._get_terminate_boolean(res) def create_volume(self, size, name, location=None, snapshot=None, ex_volume_type='standard', ex_iops=None, ex_encrypted=False, ex_kms_key_id=None): """ Create a new volume. :param size: Size of volume in gigabytes (required) :type size: ``int`` :param name: Name of the volume to be created :type name: ``str`` :param location: Which data center to create a volume in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param snapshot: Snapshot from which to create the new volume. (optional) :type snapshot: :class:`.VolumeSnapshot` :param location: Datacenter in which to create a volume in. :type location: :class:`.ExEC2AvailabilityZone` :param ex_volume_type: Type of volume to create. :type ex_volume_type: ``str`` :param iops: The number of I/O operations per second (IOPS) that the volume supports. Only used if ex_volume_type is io1. :type iops: ``int`` :param ex_encrypted: Specifies whether the volume should be encrypted. :type ex_encrypted: ``bool`` :param ex_kms_key_id: The full ARN of the AWS Key Management Service (AWS KMS) customer master key (CMK) to use when creating the encrypted volume. Example: arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123 -456a-a12b-a123b4cd56ef. Only used if encrypted is set to True. :type ex_kms_key_id: ``str`` :return: The newly created volume. :rtype: :class:`StorageVolume` """ params = { 'Action': 'CreateVolume', 'Size': str(size)} if ex_volume_type and ex_volume_type not in VALID_VOLUME_TYPES: raise ValueError('Invalid volume type specified: %s' % (ex_volume_type)) if snapshot: params['SnapshotId'] = snapshot.id if location is not None: params['AvailabilityZone'] = location.availability_zone.name if ex_volume_type: params['VolumeType'] = ex_volume_type if ex_volume_type == 'io1' and ex_iops: params['Iops'] = ex_iops if ex_encrypted: params['Encrypted'] = 1 if ex_kms_key_id is not None: params['KmsKeyId'] = ex_kms_key_id volume = self._to_volume( self.connection.request(self.path, params=params).object, name=name) if self.ex_create_tags(volume, {'Name': name}): volume.extra['tags']['Name'] = name return volume def attach_volume(self, node, volume, device): params = { 'Action': 'AttachVolume', 'VolumeId': volume.id, 'InstanceId': node.id, 'Device': device} self.connection.request(self.path, params=params) return True def detach_volume(self, volume, ex_force=False): params = { 'Action': 'DetachVolume', 'VolumeId': volume.id} if ex_force: params['Force'] = 1 self.connection.request(self.path, params=params) return True def destroy_volume(self, volume): params = { 'Action': 'DeleteVolume', 'VolumeId': volume.id} response = self.connection.request(self.path, params=params).object return self._get_boolean(response) def create_volume_snapshot(self, volume, name=None, ex_metadata=None): """ Create snapshot from volume :param volume: Instance of ``StorageVolume`` :type volume: ``StorageVolume`` :param name: Name of snapshot (optional) :type name: ``str`` :keyword ex_metadata: The Key/Value metadata to associate with a snapshot (optional) :type ex_metadata: ``dict`` :rtype: :class:`VolumeSnapshot` """ params = { 'Action': 'CreateSnapshot', 'VolumeId': volume.id, } if name: params.update({ 'Description': name, }) if ex_metadata is None: ex_metadata = {} response = self.connection.request(self.path, params=params).object snapshot = self._to_snapshot(response, name) ex_metadata.update(**{'Name': name} if name else {}) if self.ex_create_tags(snapshot, ex_metadata): snapshot.extra['tags'] = ex_metadata return snapshot def list_volume_snapshots(self, volume): return [snapshot for snapshot in self.list_snapshots(owner='self') if snapshot.extra["volume_id"] == volume.id] def list_snapshots(self, snapshot=None, owner=None): """ Describes all snapshots. :param snapshot: If provided, only returns snapshot information for the provided snapshot. :param owner: The owner of the snapshot: self|amazon|ID :type owner: ``str`` :rtype: ``list`` of :class:`VolumeSnapshot` """ params = { 'Action': 'DescribeSnapshots', } if snapshot: params.update({ 'SnapshotId.1': snapshot.id, }) if owner: params.update({ 'Owner.1': owner, }) response = self.connection.request(self.path, params=params).object snapshots = self._to_snapshots(response) return snapshots def destroy_volume_snapshot(self, snapshot): params = { 'Action': 'DeleteSnapshot', 'SnapshotId': snapshot.id } response = self.connection.request(self.path, params=params).object return self._get_boolean(response) # Key pair management methods def list_key_pairs(self): params = { 'Action': 'DescribeKeyPairs' } response = self.connection.request(self.path, params=params) elems = findall(element=response.object, xpath='keySet/item', namespace=NAMESPACE) key_pairs = self._to_key_pairs(elems=elems) return key_pairs def get_key_pair(self, name): params = { 'Action': 'DescribeKeyPairs', 'KeyName': name } response = self.connection.request(self.path, params=params) elems = findall(element=response.object, xpath='keySet/item', namespace=NAMESPACE) key_pair = self._to_key_pairs(elems=elems)[0] return key_pair def create_key_pair(self, name): params = { 'Action': 'CreateKeyPair', 'KeyName': name } response = self.connection.request(self.path, params=params) elem = response.object key_pair = self._to_key_pair(elem=elem) return key_pair def import_key_pair_from_string(self, name, key_material): base64key = ensure_string(base64.b64encode(b(key_material))) params = { 'Action': 'ImportKeyPair', 'KeyName': name, 'PublicKeyMaterial': base64key } response = self.connection.request(self.path, params=params) elem = response.object key_pair = self._to_key_pair(elem=elem) return key_pair def delete_key_pair(self, key_pair): params = { 'Action': 'DeleteKeyPair', 'KeyName': key_pair.name } res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def copy_image(self, image, source_region, name=None, description=None): """ Copy an Amazon Machine Image from the specified source region to the current region. @inherits: :class:`NodeDriver.copy_image` :param source_region: The region where the image resides :type source_region: ``str`` :param image: Instance of class NodeImage :type image: :class:`NodeImage` :param name: The name of the new image :type name: ``str`` :param description: The description of the new image :type description: ``str`` :return: Instance of class ``NodeImage`` :rtype: :class:`NodeImage` """ params = {'Action': 'CopyImage', 'SourceRegion': source_region, 'SourceImageId': image.id} if name is not None: params['Name'] = name if description is not None: params['Description'] = description image = self._to_image( self.connection.request(self.path, params=params).object) return image def create_image(self, node, name, description=None, reboot=False, block_device_mapping=None): """ Create an Amazon Machine Image based off of an EBS-backed instance. @inherits: :class:`NodeDriver.create_image` :param node: Instance of ``Node`` :type node: :class: `Node` :param name: The name for the new image :type name: ``str`` :param block_device_mapping: A dictionary of the disk layout An example of this dict is included below. :type block_device_mapping: ``list`` of ``dict`` :param reboot: Whether or not to shutdown the instance before creation. Amazon calls this NoReboot and sets it to false by default to ensure a clean image. :type reboot: ``bool`` :param description: An optional description for the new image :type description: ``str`` An example block device mapping dictionary is included: mapping = [{'VirtualName': None, 'Ebs': {'VolumeSize': 10, 'VolumeType': 'standard', 'DeleteOnTermination': 'true'}, 'DeviceName': '/dev/sda1'}] :return: Instance of class ``NodeImage`` :rtype: :class:`NodeImage` """ params = {'Action': 'CreateImage', 'InstanceId': node.id, 'Name': name, 'NoReboot': not reboot} if description is not None: params['Description'] = description if block_device_mapping is not None: params.update(self._get_block_device_mapping_params( block_device_mapping)) image = self._to_image( self.connection.request(self.path, params=params).object) return image def delete_image(self, image): """ Deletes an image at Amazon given a NodeImage object @inherits: :class:`NodeDriver.delete_image` :param image: Instance of ``NodeImage`` :type image: :class: `NodeImage` :rtype: ``bool`` """ params = {'Action': 'DeregisterImage', 'ImageId': image.id} response = self.connection.request(self.path, params=params).object return self._get_boolean(response) def start_node(self, node): """ Starts the node by passing in the node object, does not work with instance store backed instances. :param node: The node to be used :type node: :class:`Node` :rtype: ``bool`` """ params = {'Action': 'StartInstances'} params.update(self._pathlist('InstanceId', [node.id])) res = self.connection.request(self.path, params=params).object return self._get_state_boolean(res) def stop_node(self, node): """ Stops the node by passing in the node object, does not work with instance store backed instances :param node: The node to be used :type node: :class:`Node` :rtype: ``bool`` """ params = {'Action': 'StopInstances'} params.update(self._pathlist('InstanceId', [node.id])) res = self.connection.request(self.path, params=params).object return self._get_state_boolean(res) def ex_create_placement_group(self, name): """ Creates a new placement group. :param name: The name for the new placement group :type name: ``str`` :rtype: ``bool`` """ params = {'Action': 'CreatePlacementGroup', 'Strategy': 'cluster', 'GroupName': name} response = self.connection.request(self.path, params=params).object return self._get_boolean(response) def ex_delete_placement_group(self, name): """ Deletes a placement group. :param name: The placement group name :type name: ``str`` :rtype: ``bool`` """ params = {'Action': 'DeletePlacementGroup', 'GroupName': name} response = self.connection.request(self.path, params=params).object return self._get_boolean(response) def ex_import_snapshot(self, client_data=None, client_token=None, description=None, disk_container=None, dry_run=None, role_name=None): """ Imports a disk into an EBS snapshot. More information can be found at https://goo.gl/sbXkYA. :param client_data: Describes the client specific data (optional) :type client_data: ``dict`` :param client_token: The token to enable idempotency for VM import requests.(optional) :type client_token: ``str`` :param description: The description string for the import snapshot task.(optional) :type description: ``str`` :param disk_container:The disk container object for the import snapshot request. :type disk_container:``dict`` :param dry_run: Checks whether you have the permission for the action, without actually making the request, and provides an error response.(optional) :type dry_run: ``bool`` :param role_name: The name of the role to use when not using the default role, 'vmimport'.(optional) :type role_name: ``str`` :rtype: :class: ``VolumeSnapshot`` """ params = {'Action': 'ImportSnapshot'} # TODO: This method isn't defined anywhere? # if client_data is not None: # params.update(self._get_client_date_params(client_data)) if client_token is not None: params['ClientToken'] = client_token if description is not None: params['Description'] = description if disk_container is not None: params.update(self._get_disk_container_params(disk_container)) if dry_run is not None: params['DryRun'] = dry_run if role_name is not None: params['RoleName'] = role_name importSnapshot = self.connection.request(self.path, params=params).object importTaskId = findtext(element=importSnapshot, xpath='importTaskId', namespace=NAMESPACE) volumeSnapshot = self._wait_for_import_snapshot_completion( import_task_id=importTaskId, timeout=1800, interval=15) return volumeSnapshot def _wait_for_import_snapshot_completion(self, import_task_id, timeout=1800, interval=15): """ It waits for import snapshot to be completed :param import_task_id: Import task Id for the current Import Snapshot Task :type import_task_id: ``str`` :param timeout: Timeout value for snapshot generation :type timeout: ``float`` :param interval: Time interval for repetative describe import snapshot tasks requests :type interval: ``float`` :rtype: :class:``VolumeSnapshot`` """ start_time = time.time() snapshotId = None while snapshotId is None: if (time.time() - start_time >= timeout): raise Exception('Timeout while waiting ' 'for import task Id %s' % import_task_id) res = self.ex_describe_import_snapshot_tasks(import_task_id) snapshotId = res.snapshotId if snapshotId is None: time.sleep(interval) volumeSnapshot = VolumeSnapshot(snapshotId, driver=self) return volumeSnapshot def ex_describe_import_snapshot_tasks(self, import_task_id, dry_run=None): """ Describes your import snapshot tasks. More information can be found at https://goo.gl/CI0MdS. :param import_task_id: Import task Id for the current Import Snapshot Task :type import_task_id: ``str`` :param dry_run: Checks whether you have the permission for the action, without actually making the request, and provides an error response.(optional) :type dry_run: ``bool`` :rtype: :class:``DescribeImportSnapshotTasks Object`` """ params = {'Action': 'DescribeImportSnapshotTasks'} if dry_run is not None: params['DryRun'] = dry_run # This can be extended for multiple import snapshot tasks params['ImportTaskId.1'] = import_task_id res = self._to_import_snapshot_task( self.connection.request(self.path, params=params).object ) return res def ex_list_placement_groups(self, names=None): """ A list of placement groups. :param names: Placement Group names :type names: ``list`` of ``str`` :rtype: ``list`` of :class:`.EC2PlacementGroup` """ names = names or [] params = {'Action': 'DescribePlacementGroups'} for index, name in enumerate(names): params['GroupName.%s' % index + 1] = name response = self.connection.request(self.path, params=params).object return self._to_placement_groups(response) def ex_register_image(self, name, description=None, architecture=None, image_location=None, root_device_name=None, block_device_mapping=None, kernel_id=None, ramdisk_id=None, virtualization_type=None, ena_support=None, billing_products=None, sriov_net_support=None): """ Registers an Amazon Machine Image based off of an EBS-backed instance. Can also be used to create images from snapshots. More information can be found at http://goo.gl/hqZq0a. :param name: The name for the AMI being registered :type name: ``str`` :param description: The description of the AMI (optional) :type description: ``str`` :param architecture: The architecture of the AMI (i386/x86_64) (optional) :type architecture: ``str`` :param image_location: The location of the AMI within Amazon S3 Required if registering an instance store-backed AMI :type image_location: ``str`` :param root_device_name: The device name for the root device Required if registering an EBS-backed AMI :type root_device_name: ``str`` :param block_device_mapping: A dictionary of the disk layout (optional) :type block_device_mapping: ``dict`` :param kernel_id: Kernel id for AMI (optional) :type kernel_id: ``str`` :param ramdisk_id: RAM disk for AMI (optional) :type ramdisk_id: ``str`` :param virtualization_type: The type of virtualization for the AMI you are registering, paravirt or hvm (optional) :type virtualization_type: ``str`` :param ena_support: Enable enhanced networking with Elastic Network Adapter for the AMI :type ena_support: ``bool`` :param billing_products: The billing product codes :type billing_products: ''list'' :param sriov_net_support: Set to "simple" to enable enhanced networking with the Intel 82599 Virtual Function interface :type sriov_net_support: ``str`` :rtype: :class:`NodeImage` """ params = {'Action': 'RegisterImage', 'Name': name} if description is not None: params['Description'] = description if architecture is not None: params['Architecture'] = architecture if image_location is not None: params['ImageLocation'] = image_location if root_device_name is not None: params['RootDeviceName'] = root_device_name if block_device_mapping is not None: params.update(self._get_block_device_mapping_params( block_device_mapping)) if kernel_id is not None: params['KernelId'] = kernel_id if ramdisk_id is not None: params['RamDiskId'] = ramdisk_id if virtualization_type is not None: params['VirtualizationType'] = virtualization_type if ena_support is not None: params['EnaSupport'] = ena_support if billing_products is not None: params.update(self._get_billing_product_params( billing_products)) if sriov_net_support is not None: params['SriovNetSupport'] = sriov_net_support image = self._to_image( self.connection.request(self.path, params=params).object ) return image def ex_list_networks(self, network_ids=None, filters=None): """ Returns a list of :class:`EC2Network` objects for the current region. :param network_ids: Returns only networks matching the provided network IDs. If not specified, a list of all the networks in the corresponding region is returned. :type network_ids: ``list`` :param filters: The filters so that the list returned includes information for certain networks only. :type filters: ``dict`` :rtype: ``list`` of :class:`EC2Network` """ params = {'Action': 'DescribeVpcs'} if network_ids: params.update(self._pathlist('VpcId', network_ids)) if filters: params.update(self._build_filters(filters)) return self._to_networks( self.connection.request(self.path, params=params).object ) def ex_create_network(self, cidr_block, name=None, instance_tenancy='default'): """ Create a network/VPC :param cidr_block: The CIDR block assigned to the network :type cidr_block: ``str`` :param name: An optional name for the network :type name: ``str`` :param instance_tenancy: The allowed tenancy of instances launched into the VPC. Valid values: default/dedicated :type instance_tenancy: ``str`` :return: Dictionary of network properties :rtype: ``dict`` """ params = {'Action': 'CreateVpc', 'CidrBlock': cidr_block, 'InstanceTenancy': instance_tenancy} response = self.connection.request(self.path, params=params).object element = response.findall(fixxpath(xpath='vpc', namespace=NAMESPACE))[0] network = self._to_network(element, name) if name and self.ex_create_tags(network, {'Name': name}): network.extra['tags']['Name'] = name return network def ex_delete_network(self, vpc): """ Deletes a network/VPC. :param vpc: VPC to delete. :type vpc: :class:`.EC2Network` :rtype: ``bool`` """ params = {'Action': 'DeleteVpc', 'VpcId': vpc.id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_list_subnets(self, subnet_ids=None, filters=None): """ Returns a list of :class:`EC2NetworkSubnet` objects for the current region. :param subnet_ids: Returns only subnets matching the provided subnet IDs. If not specified, a list of all the subnets in the corresponding region is returned. :type subnet_ids: ``list`` :param filters: The filters so that the list returned includes information for certain subnets only. :type filters: ``dict`` :rtype: ``list`` of :class:`EC2NetworkSubnet` """ params = {'Action': 'DescribeSubnets'} if subnet_ids: params.update(self._pathlist('SubnetId', subnet_ids)) if filters: params.update(self._build_filters(filters)) return self._to_subnets( self.connection.request(self.path, params=params).object ) def ex_create_subnet(self, vpc_id, cidr_block, availability_zone, name=None): """ Creates a network subnet within a VPC. :param vpc_id: The ID of the VPC that the subnet should be associated with :type vpc_id: ``str`` :param cidr_block: The CIDR block assigned to the subnet :type cidr_block: ``str`` :param availability_zone: The availability zone where the subnet should reside :type availability_zone: ``str`` :param name: An optional name for the network :type name: ``str`` :rtype: :class: `EC2NetworkSubnet` """ params = {'Action': 'CreateSubnet', 'VpcId': vpc_id, 'CidrBlock': cidr_block, 'AvailabilityZone': availability_zone} response = self.connection.request(self.path, params=params).object element = response.findall(fixxpath(xpath='subnet', namespace=NAMESPACE))[0] subnet = self._to_subnet(element, name) if name and self.ex_create_tags(subnet, {'Name': name}): subnet.extra['tags']['Name'] = name return subnet def ex_modify_subnet_attribute(self, subnet, attribute='auto_public_ip', value=False): """ Modifies a subnet attribute. You can only modify one attribute at a time. :param subnet: The subnet to delete :type subnet: :class:`.EC2NetworkSubnet` :param attribute: The attribute to set on the subnet; one of: ``'auto_public_ip'``: Automatically allocate a public IP address when a server is created ``'auto_ipv6'``: Automatically assign an IPv6 address when a server is created :type attribute: ``str`` :param value: The value to set the subnet attribute to (defaults to ``False``) :type value: ``bool`` :rtype: ``bool`` """ params = {'Action': 'ModifySubnetAttribute', 'SubnetId': subnet.id} if attribute == 'auto_public_ip': params['MapPublicIpOnLaunch.Value'] = value elif attribute == 'auto_ipv6': params['AssignIpv6AddressOnCreation.Value'] = value else: raise ValueError('Unsupported attribute: %s' % (attribute)) res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_delete_subnet(self, subnet): """ Deletes a VPC subnet. :param subnet: The subnet to delete :type subnet: :class:`.EC2NetworkSubnet` :rtype: ``bool`` """ params = {'Action': 'DeleteSubnet', 'SubnetId': subnet.id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_list_security_groups(self): """ Lists existing Security Groups. @note: This is a non-standard extension API, and only works for EC2. :rtype: ``list`` of ``str`` """ params = {'Action': 'DescribeSecurityGroups'} response = self.connection.request(self.path, params=params).object groups = [] for group in findall(element=response, xpath='securityGroupInfo/item', namespace=NAMESPACE): name = findtext(element=group, xpath='groupName', namespace=NAMESPACE) groups.append(name) return groups def ex_get_security_groups(self, group_ids=None, group_names=None, filters=None): """ Returns a list of :class:`EC2SecurityGroup` objects for the current region. :param group_ids: Returns only groups matching the provided group IDs. :type group_ids: ``list`` :param group_names: Returns only groups matching the provided group names. :type group_ids: ``list`` :param filters: The filters so that the list returned includes information for specific security groups only. :type filters: ``dict`` :rtype: ``list`` of :class:`EC2SecurityGroup` """ params = {'Action': 'DescribeSecurityGroups'} if group_ids: params.update(self._pathlist('GroupId', group_ids)) if group_names: for name_idx, group_name in enumerate(group_names): name_idx += 1 # We want 1-based indexes name_key = 'GroupName.%s' % (name_idx) params[name_key] = group_name if filters: params.update(self._build_filters(filters)) response = self.connection.request(self.path, params=params) return self._to_security_groups(response.object) def ex_create_security_group(self, name, description, vpc_id=None): """ Creates a new Security Group in EC2-Classic or a targeted VPC. :param name: The name of the security group to create. This must be unique. :type name: ``str`` :param description: Human readable description of a Security Group. :type description: ``str`` :param vpc_id: Optional identifier for VPC networks :type vpc_id: ``str`` :rtype: ``dict`` """ params = {'Action': 'CreateSecurityGroup', 'GroupName': name, 'GroupDescription': description} if vpc_id is not None: params['VpcId'] = vpc_id response = self.connection.request(self.path, params=params).object group_id = findattr(element=response, xpath='groupId', namespace=NAMESPACE) return { 'group_id': group_id } def ex_delete_security_group_by_id(self, group_id): """ Deletes a new Security Group using the group ID. :param group_id: The ID of the security group :type group_id: ``str`` :rtype: ``bool`` """ params = {'Action': 'DeleteSecurityGroup', 'GroupId': group_id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_delete_security_group_by_name(self, group_name): """ Deletes a new Security Group using the group name. :param group_name: The name of the security group :type group_name: ``str`` :rtype: ``bool`` """ params = {'Action': 'DeleteSecurityGroup', 'GroupName': group_name} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_delete_security_group(self, name): """ A wrapper method which calls ex_delete_security_group_by_name. :param name: The name of the security group :type name: ``str`` :rtype: ``bool`` """ return self.ex_delete_security_group_by_name(name) def ex_authorize_security_group(self, name, from_port, to_port, cidr_ip, protocol='tcp'): """ Edit a Security Group to allow specific traffic. @note: This is a non-standard extension API, and only works for EC2. :param name: The name of the security group to edit :type name: ``str`` :param from_port: The beginning of the port range to open :type from_port: ``str`` :param to_port: The end of the port range to open :type to_port: ``str`` :param cidr_ip: The ip to allow traffic for. :type cidr_ip: ``str`` :param protocol: tcp/udp/icmp :type protocol: ``str`` :rtype: ``bool`` """ params = {'Action': 'AuthorizeSecurityGroupIngress', 'GroupName': name, 'IpProtocol': protocol, 'FromPort': str(from_port), 'ToPort': str(to_port), 'CidrIp': cidr_ip} try: res = self.connection.request( self.path, params=params.copy()).object return self._get_boolean(res) except Exception as e: if e.args[0].find('InvalidPermission.Duplicate') == -1: raise e def ex_authorize_security_group_ingress(self, id, from_port, to_port, cidr_ips=None, group_pairs=None, protocol='tcp', description=None): """ Edit a Security Group to allow specific ingress traffic using CIDR blocks or either a group ID, group name or user ID (account). :param id: The id of the security group to edit :type id: ``str`` :param from_port: The beginning of the port range to open :type from_port: ``int`` :param to_port: The end of the port range to open :type to_port: ``int`` :param cidr_ips: The list of IP ranges to allow traffic for. :type cidr_ips: ``list`` :param group_pairs: Source user/group pairs to allow traffic for. More info can be found at http://goo.gl/stBHJF EC2 Classic Example: To allow access from any system associated with the default group on account 1234567890 [{'group_name': 'default', 'user_id': '1234567890'}] VPC example: To allow access from any system associated with security group sg-47ad482e on your own account [{'group_id': ' sg-47ad482e'}] :type group_pairs: ``list`` of ``dict`` :param protocol: tcp/udp/icmp :type protocol: ``str`` :param description: description to be added to the rules inserted :type description: ``str`` :rtype: ``bool`` """ params = self._get_common_security_group_params(id, protocol, from_port, to_port, cidr_ips, group_pairs, description) params["Action"] = 'AuthorizeSecurityGroupIngress' res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_authorize_security_group_egress(self, id, from_port, to_port, cidr_ips, group_pairs=None, protocol='tcp'): """ Edit a Security Group to allow specific egress traffic using CIDR blocks or either a group ID, group name or user ID (account). This call is not supported for EC2 classic and only works for VPC groups. :param id: The id of the security group to edit :type id: ``str`` :param from_port: The beginning of the port range to open :type from_port: ``int`` :param to_port: The end of the port range to open :type to_port: ``int`` :param cidr_ips: The list of ip ranges to allow traffic for. :type cidr_ips: ``list`` :param group_pairs: Source user/group pairs to allow traffic for. More info can be found at http://goo.gl/stBHJF EC2 Classic Example: To allow access from any system associated with the default group on account 1234567890 [{'group_name': 'default', 'user_id': '1234567890'}] VPC Example: Allow access from any system associated with security group sg-47ad482e on your own account [{'group_id': ' sg-47ad482e'}] :type group_pairs: ``list`` of ``dict`` :param protocol: tcp/udp/icmp :type protocol: ``str`` :rtype: ``bool`` """ params = self._get_common_security_group_params(id, protocol, from_port, to_port, cidr_ips, group_pairs) params["Action"] = 'AuthorizeSecurityGroupEgress' res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_revoke_security_group_ingress(self, id, from_port, to_port, cidr_ips=None, group_pairs=None, protocol='tcp'): """ Edits a Security Group to revoke specific ingress traffic using CIDR blocks or either a group ID, group name or user ID (account). :param id: The ID of the security group to edit :type id: ``str`` :param from_port: The beginning of the port range to open :type from_port: ``int`` :param to_port: The end of the port range to open :type to_port: ``int`` :param cidr_ips: The list of ip ranges to allow traffic for. :type cidr_ips: ``list`` :param group_pairs: Source user/group pairs to allow traffic for. More info can be found at http://goo.gl/stBHJF EC2 Classic Example: To allow access from any system associated with the default group on account 1234567890 [{'group_name': 'default', 'user_id': '1234567890'}] VPC Example: Allow access from any system associated with security group sg-47ad482e on your own account [{'group_id': ' sg-47ad482e'}] :type group_pairs: ``list`` of ``dict`` :param protocol: tcp/udp/icmp :type protocol: ``str`` :rtype: ``bool`` """ params = self._get_common_security_group_params(id, protocol, from_port, to_port, cidr_ips, group_pairs) params["Action"] = 'RevokeSecurityGroupIngress' res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_revoke_security_group_egress(self, id, from_port, to_port, cidr_ips=None, group_pairs=None, protocol='tcp'): """ Edit a Security Group to revoke specific egress traffic using CIDR blocks or either a group ID, group name or user ID (account). This call is not supported for EC2 classic and only works for VPC groups. :param id: The id of the security group to edit :type id: ``str`` :param from_port: The beginning of the port range to open :type from_port: ``int`` :param to_port: The end of the port range to open :type to_port: ``int`` :param cidr_ips: The list of ip ranges to allow traffic for. :type cidr_ips: ``list`` :param group_pairs: Source user/group pairs to allow traffic for. More info can be found at http://goo.gl/stBHJF EC2 Classic Example: To allow access from any system associated with the default group on account 1234567890 [{'group_name': 'default', 'user_id': '1234567890'}] VPC Example: Allow access from any system associated with security group sg-47ad482e on your own account [{'group_id': ' sg-47ad482e'}] :type group_pairs: ``list`` of ``dict`` :param protocol: tcp/udp/icmp :type protocol: ``str`` :rtype: ``bool`` """ params = self._get_common_security_group_params(id, protocol, from_port, to_port, cidr_ips, group_pairs) params['Action'] = 'RevokeSecurityGroupEgress' res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_authorize_security_group_permissive(self, name): """ Edit a Security Group to allow all traffic. @note: This is a non-standard extension API, and only works for EC2. :param name: The name of the security group to edit :type name: ``str`` :rtype: ``list`` of ``str`` """ results = [] params = {'Action': 'AuthorizeSecurityGroupIngress', 'GroupName': name, 'IpProtocol': 'tcp', 'FromPort': '0', 'ToPort': '65535', 'CidrIp': '0.0.0.0/0'} try: results.append( self.connection.request(self.path, params=params.copy()).object ) except Exception as e: if e.args[0].find("InvalidPermission.Duplicate") == -1: raise e params['IpProtocol'] = 'udp' try: results.append( self.connection.request(self.path, params=params.copy()).object ) except Exception as e: if e.args[0].find("InvalidPermission.Duplicate") == -1: raise e params.update({'IpProtocol': 'icmp', 'FromPort': '-1', 'ToPort': '-1'}) try: results.append( self.connection.request(self.path, params=params.copy()).object ) except Exception as e: if e.args[0].find("InvalidPermission.Duplicate") == -1: raise e return results def ex_list_availability_zones(self, only_available=True): """ Returns a list of :class:`ExEC2AvailabilityZone` objects for the current region. Note: This is an extension method and is only available for EC2 driver. :keyword only_available: If true, returns only availability zones with state 'available' :type only_available: ``str`` :rtype: ``list`` of :class:`ExEC2AvailabilityZone` """ params = {'Action': 'DescribeAvailabilityZones'} filters = {'region-name': self.region_name} if only_available: filters['state'] = 'available' params.update(self._build_filters(filters)) result = self.connection.request(self.path, params=params.copy()).object availability_zones = [] for element in findall(element=result, xpath='availabilityZoneInfo/item', namespace=NAMESPACE): name = findtext(element=element, xpath='zoneName', namespace=NAMESPACE) zone_state = findtext(element=element, xpath='zoneState', namespace=NAMESPACE) region_name = findtext(element=element, xpath='regionName', namespace=NAMESPACE) availability_zone = ExEC2AvailabilityZone( name=name, zone_state=zone_state, region_name=region_name ) availability_zones.append(availability_zone) return availability_zones def ex_describe_tags(self, resource): """ Returns a dictionary of tags for a resource (e.g. Node or StorageVolume). :param resource: The resource to be used :type resource: any resource class, such as :class:`Node,` :class:`StorageVolume,` or :class:NodeImage` :return: A dictionary of Node tags :rtype: ``dict`` """ params = {'Action': 'DescribeTags'} filters = { 'resource-id': resource.id } params.update(self._build_filters(filters)) result = self.connection.request(self.path, params=params).object return self._get_resource_tags(result) def ex_create_tags(self, resource, tags): """ Creates tags for a resource (Node or StorageVolume). :param resource: The resource to be tagged :type resource: :class:`Node` or :class:`StorageVolume` or :class:`VolumeSnapshot` :param tags: A dictionary or other mapping of strings to strings, associating tag names with tag values. :type tags: ``dict`` :rtype: ``bool`` """ if not tags: return params = {'Action': 'CreateTags', 'ResourceId.0': resource.id} for i, key in enumerate(tags): params['Tag.%d.Key' % i] = key params['Tag.%d.Value' % i] = tags[key] res = self.connection.request(self.path, params=params.copy()).object return self._get_boolean(res) def ex_delete_tags(self, resource, tags): """ Deletes tags from a resource. :param resource: The resource to be tagged :type resource: :class:`Node` or :class:`StorageVolume` :param tags: A dictionary or other mapping of strings to strings, specifying the tag names and tag values to be deleted. :type tags: ``dict`` :rtype: ``bool`` """ if not tags: return params = {'Action': 'DeleteTags', 'ResourceId.0': resource.id} for i, key in enumerate(tags): params['Tag.%d.Key' % i] = key if tags[key] is not None: params['Tag.%d.Value' % i] = tags[key] res = self.connection.request(self.path, params=params.copy()).object return self._get_boolean(res) def ex_get_metadata_for_node(self, node): """ Returns the metadata associated with the node. :param node: Node instance :type node: :class:`Node` :return: A dictionary or other mapping of strings to strings, associating tag names with tag values. :rtype tags: ``dict`` """ return node.extra['tags'] def ex_allocate_address(self, domain='standard'): """ Allocate a new Elastic IP address for EC2 classic or VPC :param domain: The domain to allocate the new address in (standard/vpc) :type domain: ``str`` :return: Instance of ElasticIP :rtype: :class:`ElasticIP` """ params = {'Action': 'AllocateAddress'} if domain == 'vpc': params['Domain'] = domain response = self.connection.request(self.path, params=params).object return self._to_address(response, only_associated=False) def ex_release_address(self, elastic_ip, domain=None): """ Releases an Elastic IP address using the IP (EC2-Classic) or using the allocation ID (VPC). :param elastic_ip: Elastic IP instance :type elastic_ip: :class:`ElasticIP` :param domain: The domain where the IP resides (vpc only) :type domain: ``str`` :return: True on success, False otherwise. :rtype: ``bool`` """ params = {'Action': 'ReleaseAddress'} if domain is not None and domain != 'vpc': raise AttributeError('Domain can only be set to vpc') if domain is None: params['PublicIp'] = elastic_ip.ip else: params['AllocationId'] = elastic_ip.extra['allocation_id'] response = self.connection.request(self.path, params=params).object return self._get_boolean(response) def ex_describe_all_addresses(self, only_associated=False): """ Returns all the Elastic IP addresses for this account optionally, returns only addresses associated with nodes. :param only_associated: If true, return only the addresses that are associated with an instance. :type only_associated: ``bool`` :return: List of Elastic IP addresses. :rtype: ``list`` of :class:`ElasticIP` """ params = {'Action': 'DescribeAddresses'} response = self.connection.request(self.path, params=params).object # We will send our only_associated boolean over to # shape how the return data is sent back return self._to_addresses(response, only_associated) def ex_associate_address_with_node(self, node, elastic_ip, domain=None): """ Associate an Elastic IP address with a particular node. :param node: Node instance :type node: :class:`Node` :param elastic_ip: Elastic IP instance :type elastic_ip: :class:`ElasticIP` :param domain: The domain where the IP resides (vpc only) :type domain: ``str`` :return: A string representation of the association ID which is required for VPC disassociation. EC2/standard addresses return None :rtype: ``None`` or ``str`` """ params = {'Action': 'AssociateAddress', 'InstanceId': node.id} if domain is not None and domain != 'vpc': raise AttributeError('Domain can only be set to vpc') if domain is None: params.update({'PublicIp': elastic_ip.ip}) else: params.update({'AllocationId': elastic_ip.extra['allocation_id']}) response = self.connection.request(self.path, params=params).object association_id = findtext(element=response, xpath='associationId', namespace=NAMESPACE) return association_id def ex_associate_addresses(self, node, elastic_ip, domain=None): """ Note: This method has been deprecated in favor of the ex_associate_address_with_node method. """ return self.ex_associate_address_with_node(node=node, elastic_ip=elastic_ip, domain=domain) def ex_disassociate_address(self, elastic_ip, domain=None): """ Disassociates an Elastic IP address using the IP (EC2-Classic) or the association ID (VPC). :param elastic_ip: ElasticIP instance :type elastic_ip: :class:`ElasticIP` :param domain: The domain where the IP resides (vpc only) :type domain: ``str`` :return: True on success, False otherwise. :rtype: ``bool`` """ params = {'Action': 'DisassociateAddress'} if domain is not None and domain != 'vpc': raise AttributeError('Domain can only be set to vpc') if domain is None: params['PublicIp'] = elastic_ip.ip else: params['AssociationId'] = elastic_ip.extra['association_id'] res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_describe_addresses(self, nodes): """ Returns Elastic IP addresses for all the nodes in the provided list. :param nodes: A list of :class:`Node` instances :type nodes: ``list`` of :class:`Node` :return: Dictionary where a key is a node ID and the value is a list with the Elastic IP addresses associated with this node. :rtype: ``dict`` """ if not nodes: return {} params = {'Action': 'DescribeAddresses'} if len(nodes) == 1: self._add_instance_filter(params, nodes[0]) result = self.connection.request(self.path, params=params).object node_instance_ids = [node.id for node in nodes] nodes_elastic_ip_mappings = {} # We will set only_associated to True so that we only get back # IPs which are associated with instances only_associated = True for node_id in node_instance_ids: nodes_elastic_ip_mappings.setdefault(node_id, []) for addr in self._to_addresses(result, only_associated): instance_id = addr.instance_id if node_id == instance_id: nodes_elastic_ip_mappings[instance_id].append( addr.ip) return nodes_elastic_ip_mappings def ex_describe_addresses_for_node(self, node): """ Returns a list of Elastic IP Addresses associated with this node. :param node: Node instance :type node: :class:`Node` :return: List Elastic IP Addresses attached to this node. :rtype: ``list`` of ``str`` """ node_elastic_ips = self.ex_describe_addresses([node]) return node_elastic_ips[node.id] # Network interface management methods def ex_list_network_interfaces(self): """ Returns all network interfaces. :return: List of EC2NetworkInterface instances :rtype: ``list`` of :class `EC2NetworkInterface` """ params = {'Action': 'DescribeNetworkInterfaces'} return self._to_interfaces( self.connection.request(self.path, params=params).object ) def ex_create_network_interface(self, subnet, name=None, description=None, private_ip_address=None): """ Create a network interface within a VPC subnet. :param subnet: EC2NetworkSubnet instance :type subnet: :class:`EC2NetworkSubnet` :param name: Optional name of the interface :type name: ``str`` :param description: Optional description of the network interface :type description: ``str`` :param private_ip_address: Optional address to assign as the primary private IP address of the interface. If one is not provided then Amazon will automatically auto-assign an available IP. EC2 allows assignment of multiple IPs, but this will be the primary. :type private_ip_address: ``str`` :return: EC2NetworkInterface instance :rtype: :class `EC2NetworkInterface` """ params = {'Action': 'CreateNetworkInterface', 'SubnetId': subnet.id} if description: params['Description'] = description if private_ip_address: params['PrivateIpAddress'] = private_ip_address response = self.connection.request(self.path, params=params).object element = response.findall(fixxpath(xpath='networkInterface', namespace=NAMESPACE))[0] interface = self._to_interface(element, name) if name and self.ex_create_tags(interface, {'Name': name}): interface.extra['tags']['Name'] = name return interface def ex_delete_network_interface(self, network_interface): """ Deletes a network interface. :param network_interface: EC2NetworkInterface instance :type network_interface: :class:`EC2NetworkInterface` :rtype: ``bool`` """ params = {'Action': 'DeleteNetworkInterface', 'NetworkInterfaceId': network_interface.id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_attach_network_interface_to_node(self, network_interface, node, device_index): """ Attach a network interface to an instance. :param network_interface: EC2NetworkInterface instance :type network_interface: :class:`EC2NetworkInterface` :param node: Node instance :type node: :class:`Node` :param device_index: The interface device index :type device_index: ``int`` :return: String representation of the attachment id. This is required to detach the interface. :rtype: ``str`` """ params = {'Action': 'AttachNetworkInterface', 'NetworkInterfaceId': network_interface.id, 'InstanceId': node.id, 'DeviceIndex': device_index} response = self.connection.request(self.path, params=params).object attachment_id = findattr(element=response, xpath='attachmentId', namespace=NAMESPACE) return attachment_id def ex_detach_network_interface(self, attachment_id, force=False): """ Detach a network interface from an instance. :param attachment_id: The attachment ID associated with the interface :type attachment_id: ``str`` :param force: Forces the detachment. :type force: ``bool`` :return: ``True`` on successful detachment, ``False`` otherwise. :rtype: ``bool`` """ params = {'Action': 'DetachNetworkInterface', 'AttachmentId': attachment_id} if force: params['Force'] = True res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_modify_instance_attribute(self, node, attributes): """ Modify node attributes. A list of valid attributes can be found at http://goo.gl/gxcj8 :param node: Node instance :type node: :class:`Node` :param attributes: Dictionary with node attributes :type attributes: ``dict`` :return: True on success, False otherwise. :rtype: ``bool`` """ attributes = attributes or {} attributes.update({'InstanceId': node.id}) params = {'Action': 'ModifyInstanceAttribute'} params.update(attributes) res = self.connection.request(self.path, params=params.copy()).object return self._get_boolean(res) def ex_modify_snapshot_attribute(self, snapshot, attributes): """ Modify Snapshot attributes. :param snapshot: VolumeSnapshot instance :type snanpshot: :class:`VolumeSnapshot` :param attributes: Dictionary with snapshot attributes :type attributes: ``dict`` :return: True on success, False otherwise. :rtype: ``bool`` """ attributes = attributes or {} attributes.update({'SnapshotId': snapshot.id}) params = {'Action': 'ModifySnapshotAttribute'} params.update(attributes) res = self.connection.request(self.path, params=params.copy()).object return self._get_boolean(res) def ex_modify_image_attribute(self, image, attributes): """ Modifies image attributes. :param image: NodeImage instance :type image: :class:`NodeImage` :param attributes: A dictionary with node attributes :type attributes: ``dict`` :return: True on success, False otherwise. :rtype: ``bool`` """ attributes = attributes or {} attributes.update({'ImageId': image.id}) params = {'Action': 'ModifyImageAttribute'} params.update(attributes) res = self.connection.request(self.path, params=params.copy()).object return self._get_boolean(res) def ex_change_node_size(self, node, new_size): """ Change the node size. Note: Node must be turned of before changing the size. :param node: Node instance :type node: :class:`Node` :param new_size: NodeSize instance :type new_size: :class:`NodeSize` :return: True on success, False otherwise. :rtype: ``bool`` """ if 'instancetype' in node.extra: current_instance_type = node.extra['instancetype'] if current_instance_type == new_size.id: raise ValueError('New instance size is the same as' + 'the current one') attributes = {'InstanceType.Value': new_size.id} return self.ex_modify_instance_attribute(node=node, attributes=attributes) def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_get_console_output(self, node): """ Gets console output for the node. :param node: Node which should be used :type node: :class:`Node` :return: A dictionary with the following keys: - instance_id (``str``) - timestamp (``datetime.datetime``) - last output timestamp - output (``str``) - console output :rtype: ``dict`` """ params = { 'Action': 'GetConsoleOutput', 'InstanceId': node.id } response = self.connection.request(self.path, params=params).object timestamp = findattr(element=response, xpath='timestamp', namespace=NAMESPACE) encoded_string = findattr(element=response, xpath='output', namespace=NAMESPACE) timestamp = parse_date(timestamp) if encoded_string: output = base64.b64decode(b(encoded_string)).decode('utf-8') else: # No console output output = None return {'instance_id': node.id, 'timestamp': timestamp, 'output': output} def ex_list_reserved_nodes(self): """ Lists all reserved instances/nodes which can be purchased from Amazon for one or three year terms. Reservations are made at a region level and reduce the hourly charge for instances. More information can be found at http://goo.gl/ulXCC7. :rtype: ``list`` of :class:`.EC2ReservedNode` """ params = {'Action': 'DescribeReservedInstances'} response = self.connection.request(self.path, params=params).object return self._to_reserved_nodes(response, 'reservedInstancesSet/item') # Account specific methods def ex_get_limits(self): """ Retrieve account resource limits. :rtype: ``dict`` """ attributes = ['max-instances', 'max-elastic-ips', 'vpc-max-elastic-ips'] params = {} params['Action'] = 'DescribeAccountAttributes' for index, attribute in enumerate(attributes): params['AttributeName.%s' % (index)] = attribute response = self.connection.request(self.path, params=params) data = response.object elems = data.findall(fixxpath(xpath='accountAttributeSet/item', namespace=NAMESPACE)) result = {'resource': {}} for elem in elems: name = findtext(element=elem, xpath='attributeName', namespace=NAMESPACE) value = findtext(element=elem, xpath='attributeValueSet/item/attributeValue', namespace=NAMESPACE) result['resource'][name] = int(value) return result # Deprecated extension methods def ex_list_keypairs(self): """ Lists all the keypair names and fingerprints. :rtype: ``list`` of ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'list_key_pairs method') key_pairs = self.list_key_pairs() result = [] for key_pair in key_pairs: item = { 'keyName': key_pair.name, 'keyFingerprint': key_pair.fingerprint, } result.append(item) return result def ex_describe_all_keypairs(self): """ Returns names for all the available key pairs. @note: This is a non-standard extension API, and only works for EC2. :rtype: ``list`` of ``str`` """ names = [key_pair.name for key_pair in self.list_key_pairs()] return names def ex_describe_keypairs(self, name): """ Here for backward compatibility. """ return self.ex_describe_keypair(name=name) def ex_describe_keypair(self, name): """ Describes a keypair by name. @note: This is a non-standard extension API, and only works for EC2. :param name: The name of the keypair to describe. :type name: ``str`` :rtype: ``dict`` """ params = { 'Action': 'DescribeKeyPairs', 'KeyName.1': name } response = self.connection.request(self.path, params=params).object key_name = findattr(element=response, xpath='keySet/item/keyName', namespace=NAMESPACE) fingerprint = findattr(element=response, xpath='keySet/item/keyFingerprint', namespace=NAMESPACE).strip() return { 'keyName': key_name, 'keyFingerprint': fingerprint } def ex_create_keypair(self, name): """ Creates a new keypair @note: This is a non-standard extension API, and only works for EC2. :param name: The name of the keypair to Create. This must be unique, otherwise an InvalidKeyPair.Duplicate exception is raised. :type name: ``str`` :rtype: ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'create_key_pair method') key_pair = self.create_key_pair(name=name) result = { 'keyMaterial': key_pair.private_key, 'keyFingerprint': key_pair.fingerprint } return result def ex_delete_keypair(self, keypair): """ Deletes a key pair by name. @note: This is a non-standard extension API, and only works with EC2. :param keypair: The name of the keypair to delete. :type keypair: ``str`` :rtype: ``bool`` """ warnings.warn('This method has been deprecated in favor of ' 'delete_key_pair method') keypair = KeyPair(name=keypair, public_key=None, fingerprint=None, driver=self) return self.delete_key_pair(keypair) def ex_import_keypair_from_string(self, name, key_material): """ Imports a new public key where the public key is passed in as a string. @note: This is a non-standard extension API, and only works for EC2. :param name: The name of the public key to import. This must be unique, otherwise an InvalidKeyPair.Duplicate exception is raised. :type name: ``str`` :param key_material: The contents of a public key file. :type key_material: ``str`` :rtype: ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'import_key_pair_from_string method') key_pair = self.import_key_pair_from_string(name=name, key_material=key_material) result = { 'keyName': key_pair.name, 'keyFingerprint': key_pair.fingerprint } return result def ex_import_keypair(self, name, keyfile): """ Imports a new public key where the public key is passed via a filename. @note: This is a non-standard extension API, and only works for EC2. :param name: The name of the public key to import. This must be unique, otherwise an InvalidKeyPair. Duplicate exception is raised. :type name: ``str`` :param keyfile: The filename with the path of the public key to import. :type keyfile: ``str`` :rtype: ``dict`` """ warnings.warn('This method has been deprecated in favor of ' 'import_key_pair_from_file method') key_pair = self.import_key_pair_from_file(name=name, key_file_path=keyfile) result = { 'keyName': key_pair.name, 'keyFingerprint': key_pair.fingerprint } return result def ex_find_or_import_keypair_by_key_material(self, pubkey): """ Given a public key, look it up in the EC2 KeyPair database. If it exists, return any information we have about it. Otherwise, create it. Keys that are created are named based on their comment and fingerprint. :rtype: ``dict`` """ key_fingerprint = get_pubkey_ssh2_fingerprint(pubkey) key_comment = get_pubkey_comment(pubkey, default='unnamed') key_name = '%s-%s' % (key_comment, key_fingerprint) key_pairs = self.list_key_pairs() key_pairs = [key_pair for key_pair in key_pairs if key_pair.fingerprint == key_fingerprint] if len(key_pairs) >= 1: key_pair = key_pairs[0] result = { 'keyName': key_pair.name, 'keyFingerprint': key_pair.fingerprint } else: result = self.ex_import_keypair_from_string(key_name, pubkey) return result def ex_list_internet_gateways(self, gateway_ids=None, filters=None): """ Describes available Internet gateways and whether or not they are attached to a VPC. These are required for VPC nodes to communicate over the Internet. :param gateway_ids: Returns only Internet gateways matching the provided Internet gateway IDs. If not specified, a list of all the Internet gateways in the corresponding region is returned. :type gateway_ids: ``list`` :param filters: The filters so the list returned inclues information for certain gateways only. :type filters: ``dict`` :rtype: ``list`` of :class:`.VPCInternetGateway` """ params = {'Action': 'DescribeInternetGateways'} if gateway_ids: params.update(self._pathlist('InternetGatewayId', gateway_ids)) if filters: params.update(self._build_filters(filters)) response = self.connection.request(self.path, params=params).object return self._to_internet_gateways(response, 'internetGatewaySet/item') def ex_create_internet_gateway(self, name=None): """ Delete a VPC Internet gateway :rtype: ``bool`` """ params = {'Action': 'CreateInternetGateway'} resp = self.connection.request(self.path, params=params).object element = resp.findall(fixxpath(xpath='internetGateway', namespace=NAMESPACE)) gateway = self._to_internet_gateway(element[0], name) if name and self.ex_create_tags(gateway, {'Name': name}): gateway.extra['tags']['Name'] = name return gateway def ex_delete_internet_gateway(self, gateway): """ Deletes a VPC Internet gateway. :param gateway: The gateway to delete :type gateway: :class:`.VPCInternetGateway` :rtype: ``bool`` """ params = {'Action': 'DeleteInternetGateway', 'InternetGatewayId': gateway.id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_attach_internet_gateway(self, gateway, network): """ Attach an Internet gateway to a VPC :param gateway: The gateway to attach :type gateway: :class:`.VPCInternetGateway` :param network: The VPC network to attach to :type network: :class:`.EC2Network` :rtype: ``bool`` """ params = {'Action': 'AttachInternetGateway', 'InternetGatewayId': gateway.id, 'VpcId': network.id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_detach_internet_gateway(self, gateway, network): """ Detaches an Internet gateway from a VPC. :param gateway: The gateway to detach :type gateway: :class:`.VPCInternetGateway` :param network: The VPC network to detach from :type network: :class:`.EC2Network` :rtype: ``bool`` """ params = {'Action': 'DetachInternetGateway', 'InternetGatewayId': gateway.id, 'VpcId': network.id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_list_route_tables(self, route_table_ids=None, filters=None): """ Describes one or more of a VPC's route tables. These are used to determine where network traffic is directed. :param route_table_ids: Returns only route tables matching the provided route table IDs. If not specified, a list of all the route tables in the corresponding region is returned. :type route_table_ids: ``list`` :param filters: The filters so that the list returned includes information for certain route tables only. :type filters: ``dict`` :rtype: ``list`` of :class:`.EC2RouteTable` """ params = {'Action': 'DescribeRouteTables'} if route_table_ids: params.update(self._pathlist('RouteTableId', route_table_ids)) if filters: params.update(self._build_filters(filters)) response = self.connection.request(self.path, params=params) return self._to_route_tables(response.object) def ex_create_route_table(self, network, name=None): """ Creates a route table within a VPC. :param vpc_id: The VPC that the subnet should be created in. :type vpc_id: :class:`.EC2Network` :rtype: :class: `.EC2RouteTable` """ params = {'Action': 'CreateRouteTable', 'VpcId': network.id} response = self.connection.request(self.path, params=params).object element = response.findall(fixxpath(xpath='routeTable', namespace=NAMESPACE))[0] route_table = self._to_route_table(element, name=name) if name and self.ex_create_tags(route_table, {'Name': name}): route_table.extra['tags']['Name'] = name return route_table def ex_delete_route_table(self, route_table): """ Deletes a VPC route table. :param route_table: The route table to delete. :type route_table: :class:`.EC2RouteTable` :rtype: ``bool`` """ params = {'Action': 'DeleteRouteTable', 'RouteTableId': route_table.id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_associate_route_table(self, route_table, subnet): """ Associates a route table with a subnet within a VPC. Note: A route table can be associated with multiple subnets. :param route_table: The route table to associate. :type route_table: :class:`.EC2RouteTable` :param subnet: The subnet to associate with. :type subnet: :class:`.EC2Subnet` :return: Route table association ID. :rtype: ``str`` """ params = {'Action': 'AssociateRouteTable', 'RouteTableId': route_table.id, 'SubnetId': subnet.id} result = self.connection.request(self.path, params=params).object association_id = findtext(element=result, xpath='associationId', namespace=NAMESPACE) return association_id def ex_dissociate_route_table(self, subnet_association): """ Dissociates a subnet from a route table. :param subnet_association: The subnet association object or subnet association ID. :type subnet_association: :class:`.EC2SubnetAssociation` or ``str`` :rtype: ``bool`` """ if isinstance(subnet_association, EC2SubnetAssociation): subnet_association_id = subnet_association.id else: subnet_association_id = subnet_association params = {'Action': 'DisassociateRouteTable', 'AssociationId': subnet_association_id} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_replace_route_table_association(self, subnet_association, route_table): """ Changes the route table associated with a given subnet in a VPC. Note: This method can be used to change which table is the main route table in the VPC (Specify the main route table's association ID and the route table to be the new main route table). :param subnet_association: The subnet association object or subnet association ID. :type subnet_association: :class:`.EC2SubnetAssociation` or ``str`` :param route_table: The new route table to associate. :type route_table: :class:`.EC2RouteTable` :return: A new route table association ID. :rtype: ``str`` """ if isinstance(subnet_association, EC2SubnetAssociation): subnet_association_id = subnet_association.id else: subnet_association_id = subnet_association params = {'Action': 'ReplaceRouteTableAssociation', 'AssociationId': subnet_association_id, 'RouteTableId': route_table.id} result = self.connection.request(self.path, params=params).object new_association_id = findtext(element=result, xpath='newAssociationId', namespace=NAMESPACE) return new_association_id def ex_create_route(self, route_table, cidr, internet_gateway=None, node=None, network_interface=None, vpc_peering_connection=None): """ Creates a route entry in the route table. :param route_table: The route table to create the route in. :type route_table: :class:`.EC2RouteTable` :param cidr: The CIDR block used for the destination match. :type cidr: ``str`` :param internet_gateway: The Internet gateway to route traffic through. :type internet_gateway: :class:`.VPCInternetGateway` :param node: The NAT instance to route traffic through. :type node: :class:`Node` :param network_interface: The network interface of the node to route traffic through. :type network_interface: :class:`.EC2NetworkInterface` :param vpc_peering_connection: The VPC peering connection. :type vpc_peering_connection: :class:`.VPCPeeringConnection` :rtype: ``bool`` Note: You must specify one of the following: internet_gateway, node, network_interface, vpc_peering_connection. """ params = {'Action': 'CreateRoute', 'RouteTableId': route_table.id, 'DestinationCidrBlock': cidr} if internet_gateway: params['GatewayId'] = internet_gateway.id if node: params['InstanceId'] = node.id if network_interface: params['NetworkInterfaceId'] = network_interface.id if vpc_peering_connection: params['VpcPeeringConnectionId'] = vpc_peering_connection.id res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_delete_route(self, route_table, cidr): """ Deletes a route entry from the route table. :param route_table: The route table to delete the route from. :type route_table: :class:`.EC2RouteTable` :param cidr: The CIDR block used for the destination match. :type cidr: ``str`` :rtype: ``bool`` """ params = {'Action': 'DeleteRoute', 'RouteTableId': route_table.id, 'DestinationCidrBlock': cidr} res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_replace_route(self, route_table, cidr, internet_gateway=None, node=None, network_interface=None, vpc_peering_connection=None): """ Replaces an existing route entry within a route table in a VPC. :param route_table: The route table to replace the route in. :type route_table: :class:`.EC2RouteTable` :param cidr: The CIDR block used for the destination match. :type cidr: ``str`` :param internet_gateway: The new internet gateway to route traffic through. :type internet_gateway: :class:`.VPCInternetGateway` :param node: The new NAT instance to route traffic through. :type node: :class:`Node` :param network_interface: The new network interface of the node to route traffic through. :type network_interface: :class:`.EC2NetworkInterface` :param vpc_peering_connection: The new VPC peering connection. :type vpc_peering_connection: :class:`.VPCPeeringConnection` :rtype: ``bool`` Note: You must specify one of the following: internet_gateway, node, network_interface, vpc_peering_connection. """ params = {'Action': 'ReplaceRoute', 'RouteTableId': route_table.id, 'DestinationCidrBlock': cidr} if internet_gateway: params['GatewayId'] = internet_gateway.id if node: params['InstanceId'] = node.id if network_interface: params['NetworkInterfaceId'] = network_interface.id if vpc_peering_connection: params['VpcPeeringConnectionId'] = vpc_peering_connection.id res = self.connection.request(self.path, params=params).object return self._get_boolean(res) def ex_modify_volume(self, volume, parameters): """ Modify volume parameters. A list of valid parameters can be found at https://goo.gl/N0rPEQ :param volume: Volume instance :type volume: :class:`Volume` :param parameters: Dictionary with updated volume parameters :type parameters: ``dict`` :return: Volume modification status object :rtype: :class:`VolumeModification """ parameters = parameters or {} volume_type = parameters.get('VolumeType') if volume_type and volume_type not in VALID_VOLUME_TYPES: raise ValueError('Invalid volume type specified: %s' % volume_type) parameters.update({'Action': 'ModifyVolume', 'VolumeId': volume.id}) response = self.connection.request(self.path, params=parameters.copy()).object return self._to_volume_modification(response.findall( fixxpath(xpath='volumeModification', namespace=NAMESPACE))[0]) def ex_describe_volumes_modifications(self, dry_run=False, volume_ids=None, filters=None): """ Describes one or more of your volume modifications. :param dry_run: dry_run :type dry_run: ``bool`` :param volume_ids: The volume_ids so that the response includes information for only said volumes :type volume_ids: ``dict`` :param filters: The filters so that the response includes information for only certain volumes :type filters: ``dict`` :return: List of volume modification status objects :rtype: ``list`` of :class:`VolumeModification """ params = {'Action': 'DescribeVolumesModifications'} if dry_run: params.update({'DryRun': dry_run}) if volume_ids: params.update(self._pathlist('VolumeId', volume_ids)) if filters: params.update(self._build_filters(filters)) response = self.connection.request(self.path, params=params).object return self._to_volume_modifications(response) def _ex_connection_class_kwargs(self): kwargs = super(BaseEC2NodeDriver, self)._ex_connection_class_kwargs() # pylint: disable=no-member if hasattr(self, 'token') and self.token is not None: kwargs['token'] = self.token # Force signature_version 4 for tokens or auth breaks kwargs['signature_version'] = '4' else: kwargs['signature_version'] = self.signature_version return kwargs def _to_nodes(self, object, xpath): return [self._to_node(el) for el in object.findall(fixxpath(xpath=xpath, namespace=NAMESPACE))] def _to_node(self, element): try: state = self.NODE_STATE_MAP[findattr(element=element, xpath="instanceState/name", namespace=NAMESPACE) ] except KeyError: state = NodeState.UNKNOWN created = parse_date(findtext(element=element, xpath='launchTime', namespace=NAMESPACE)) instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) public_ip = findtext(element=element, xpath='ipAddress', namespace=NAMESPACE) public_ips = [public_ip] if public_ip else [] private_ip = findtext(element=element, xpath='privateIpAddress', namespace=NAMESPACE) private_ips = [private_ip] if private_ip else [] product_codes = [] for p in findall(element=element, xpath="productCodesSet/item/productCode", namespace=NAMESPACE): product_codes.append(p) # Get our tags tags = self._get_resource_tags(element) name = tags.get('Name', instance_id) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['node']) # Add additional properties to our extra dictionary extra['block_device_mapping'] = self._to_instance_device_mappings( element) extra['groups'] = self._get_security_groups(element) extra['network_interfaces'] = self._to_interfaces(element) extra['product_codes'] = product_codes extra['tags'] = tags return Node(id=instance_id, name=name, state=state, public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver, created_at=created, extra=extra) def _to_images(self, object): return [self._to_image(el) for el in object.findall( fixxpath(xpath='imagesSet/item', namespace=NAMESPACE)) ] def _to_image(self, element): id = findtext(element=element, xpath='imageId', namespace=NAMESPACE) name = findtext(element=element, xpath='name', namespace=NAMESPACE) # Build block device mapping block_device_mapping = self._to_device_mappings(element) billing_products = [] for p in findall(element=element, xpath="billingProducts/item/billingProduct", namespace=NAMESPACE): billing_products.append(p.text) # Get our tags tags = self._get_resource_tags(element) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['image']) # Add our tags and block device mapping extra['tags'] = tags extra['block_device_mapping'] = block_device_mapping extra['billing_products'] = billing_products return NodeImage(id=id, name=name, driver=self, extra=extra) def _to_volume(self, element, name=None): """ Parse the XML element and return a StorageVolume object. :param name: An optional name for the volume. If not provided then either tag with a key "Name" or volume ID will be used (which ever is available first in that order). :type name: ``str`` :rtype: :class:`StorageVolume` """ volId = findtext(element=element, xpath='volumeId', namespace=NAMESPACE) size = findtext(element=element, xpath='size', namespace=NAMESPACE) raw_state = findtext(element=element, xpath='status', namespace=NAMESPACE) state = self.VOLUME_STATE_MAP.get(raw_state, StorageVolumeState.UNKNOWN) # Get our tags tags = self._get_resource_tags(element) # If name was not passed into the method then # fall back then use the volume id name = name if name else tags.get('Name', volId) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['volume']) extra['tags'] = tags return StorageVolume(id=volId, name=name, size=int(size), driver=self, state=state, extra=extra) def _to_volume_modifications(self, object): return [self._to_volume_modification(el) for el in object.findall( fixxpath(xpath='volumeModificationSet/item', namespace=NAMESPACE)) ] def _to_volume_modification(self, element): """ Parse the XML element and return a StorageVolume object. :rtype: :class:`EC2VolumeModification` """ params = self._get_extra_dict(element, VOLUME_MODIFICATION_ATTRIBUTE_MAP) return EC2VolumeModification(**params) def _to_snapshots(self, response): return [self._to_snapshot(el) for el in response.findall( fixxpath(xpath='snapshotSet/item', namespace=NAMESPACE)) ] def _to_snapshot(self, element, name=None): snapId = findtext(element=element, xpath='snapshotId', namespace=NAMESPACE) size = findtext(element=element, xpath='volumeSize', namespace=NAMESPACE) created = parse_date(findtext(element=element, xpath='startTime', namespace=NAMESPACE)) # Get our tags tags = self._get_resource_tags(element) # If name was not passed into the method then # fall back then use the snapshot id name = name if name else tags.get('Name', snapId) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['snapshot']) # Add tags and name to the extra dict extra['tags'] = tags extra['name'] = name # state state = self.SNAPSHOT_STATE_MAP.get( extra["state"], VolumeSnapshotState.UNKNOWN ) return VolumeSnapshot(snapId, size=int(size), driver=self, extra=extra, created=created, state=state, name=name) def _to_import_snapshot_task(self, element): status = findtext(element=element, xpath='importSnapshotTaskSet/item/' 'snapshotTaskDetail/status', namespace=NAMESPACE) if status != 'completed': snapshotId = None else: xpath = 'importSnapshotTaskSet/item/snapshotTaskDetail/snapshotId' snapshotId = findtext(element=element, xpath=xpath, namespace=NAMESPACE) return EC2ImportSnapshotTask(status, snapshotId=snapshotId) def _to_key_pairs(self, elems): key_pairs = [self._to_key_pair(elem=elem) for elem in elems] return key_pairs def _to_key_pair(self, elem): name = findtext(element=elem, xpath='keyName', namespace=NAMESPACE) fingerprint = findtext(element=elem, xpath='keyFingerprint', namespace=NAMESPACE).strip() private_key = findtext(element=elem, xpath='keyMaterial', namespace=NAMESPACE) key_pair = KeyPair(name=name, public_key=None, fingerprint=fingerprint, private_key=private_key, driver=self) return key_pair def _to_security_groups(self, response): return [self._to_security_group(el) for el in response.findall( fixxpath(xpath='securityGroupInfo/item', namespace=NAMESPACE)) ] def _to_security_group(self, element): # security group id sg_id = findtext(element=element, xpath='groupId', namespace=NAMESPACE) # security group name name = findtext(element=element, xpath='groupName', namespace=NAMESPACE) # Get our tags tags = self._get_resource_tags(element) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['security_group']) # Add tags to the extra dict extra['tags'] = tags # Get ingress rules ingress_rules = self._to_security_group_rules( element, 'ipPermissions/item' ) # Get egress rules egress_rules = self._to_security_group_rules( element, 'ipPermissionsEgress/item' ) return EC2SecurityGroup(sg_id, name, ingress_rules, egress_rules, extra=extra) def _to_security_group_rules(self, element, xpath): return [self._to_security_group_rule(el) for el in element.findall( fixxpath(xpath=xpath, namespace=NAMESPACE)) ] def _to_security_group_rule(self, element): """ Parse the XML element and return a SecurityGroup object. :rtype: :class:`EC2SecurityGroup` """ rule = {} rule['protocol'] = findtext(element=element, xpath='ipProtocol', namespace=NAMESPACE) rule['from_port'] = findtext(element=element, xpath='fromPort', namespace=NAMESPACE) rule['to_port'] = findtext(element=element, xpath='toPort', namespace=NAMESPACE) # get security groups elements = element.findall(fixxpath( xpath='groups/item', namespace=NAMESPACE )) rule['group_pairs'] = [] for element in elements: item = { 'user_id': findtext( element=element, xpath='userId', namespace=NAMESPACE), 'group_id': findtext( element=element, xpath='groupId', namespace=NAMESPACE), 'group_name': findtext( element=element, xpath='groupName', namespace=NAMESPACE) } rule['group_pairs'].append(item) # get ip ranges elements = element.findall(fixxpath( xpath='ipRanges/item', namespace=NAMESPACE )) rule['cidr_ips'] = [ findtext( element=element, xpath='cidrIp', namespace=NAMESPACE ) for element in elements] return rule def _to_networks(self, response): return [self._to_network(el) for el in response.findall( fixxpath(xpath='vpcSet/item', namespace=NAMESPACE)) ] def _to_network(self, element, name=None): # Get the network id vpc_id = findtext(element=element, xpath='vpcId', namespace=NAMESPACE) # Get our tags tags = self._get_resource_tags(element) # Set our name if the Name key/value if available # If we don't get anything back then use the vpc_id name = name if name else tags.get('Name', vpc_id) cidr_block = findtext(element=element, xpath='cidrBlock', namespace=NAMESPACE) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['network']) # Add tags to the extra dict extra['tags'] = tags return EC2Network(vpc_id, name, cidr_block, extra=extra) def _to_addresses(self, response, only_associated): """ Builds a list of dictionaries containing elastic IP properties. :param only_associated: If true, return only those addresses that are associated with an instance. If false, return all addresses. :type only_associated: ``bool`` :rtype: ``list`` of :class:`ElasticIP` """ addresses = [] for el in response.findall(fixxpath(xpath='addressesSet/item', namespace=NAMESPACE)): addr = self._to_address(el, only_associated) if addr is not None: addresses.append(addr) return addresses def _to_address(self, element, only_associated): instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) public_ip = findtext(element=element, xpath='publicIp', namespace=NAMESPACE) domain = findtext(element=element, xpath='domain', namespace=NAMESPACE) # Build our extra dict extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['elastic_ip']) # Return NoneType if only associated IPs are requested if only_associated and not instance_id: return None return ElasticIP(public_ip, domain, instance_id, extra=extra) def _to_placement_groups(self, response): return [self._to_placement_group(el) for el in response.findall( fixxpath(xpath='placementGroupSet/item', namespace=NAMESPACE))] def _to_placement_group(self, element): name = findtext(element=element, xpath='groupName', namespace=NAMESPACE) state = findtext(element=element, xpath='state', namespace=NAMESPACE) strategy = findtext(element=element, xpath='strategy', namespace=NAMESPACE) return EC2PlacementGroup(name, state, strategy) def _to_subnets(self, response): return [self._to_subnet(el) for el in response.findall( fixxpath(xpath='subnetSet/item', namespace=NAMESPACE)) ] def _to_subnet(self, element, name=None): # Get the subnet ID subnet_id = findtext(element=element, xpath='subnetId', namespace=NAMESPACE) # Get our tags tags = self._get_resource_tags(element) # If we don't get anything back then use the subnet_id name = name if name else tags.get('Name', subnet_id) state = findtext(element=element, xpath='state', namespace=NAMESPACE) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['subnet']) # Also include our tags extra['tags'] = tags return EC2NetworkSubnet(subnet_id, name, state, extra=extra) def _to_interfaces(self, response): return [self._to_interface(el) for el in response.findall( fixxpath(xpath='networkInterfaceSet/item', namespace=NAMESPACE)) ] def _to_interface(self, element, name=None): """ Parse the XML element and return an EC2NetworkInterface object. :param name: An optional name for the interface. If not provided then either tag with a key "Name" or the interface ID will be used (whichever is available first in that order). :type name: ``str`` :rtype: :class: `EC2NetworkInterface` """ interface_id = findtext(element=element, xpath='networkInterfaceId', namespace=NAMESPACE) state = findtext(element=element, xpath='status', namespace=NAMESPACE) # Get tags tags = self._get_resource_tags(element) name = name if name else tags.get('Name', interface_id) # Build security groups groups = self._get_security_groups(element) # Build private IPs priv_ips = [] for item in findall(element=element, xpath='privateIpAddressesSet/item', namespace=NAMESPACE): priv_ips.append({'private_ip': findtext(element=item, xpath='privateIpAddress', namespace=NAMESPACE), 'private_dns': findtext(element=item, xpath='privateDnsName', namespace=NAMESPACE), 'primary': findtext(element=item, xpath='primary', namespace=NAMESPACE)}) # Build our attachment dictionary which we will add into extra later attributes_map = \ RESOURCE_EXTRA_ATTRIBUTES_MAP['network_interface_attachment'] attachment = self._get_extra_dict(element, attributes_map) # Build our extra dict attributes_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['network_interface'] extra = self._get_extra_dict(element, attributes_map) # Include our previously built items as well extra['tags'] = tags extra['attachment'] = attachment extra['private_ips'] = priv_ips extra['groups'] = groups return EC2NetworkInterface(interface_id, name, state, extra=extra) def _to_reserved_nodes(self, object, xpath): return [self._to_reserved_node(el) for el in object.findall(fixxpath(xpath=xpath, namespace=NAMESPACE))] def _to_reserved_node(self, element): """ Build an EC2ReservedNode object using the reserved instance properties. Information on these properties can be found at http://goo.gl/ulXCC7. """ # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['reserved_node']) try: size = [size for size in self.list_sizes() if size.id == extra['instance_type']][0] except IndexError: size = None return EC2ReservedNode(id=findtext(element=element, xpath='reservedInstancesId', namespace=NAMESPACE), state=findattr(element=element, xpath='state', namespace=NAMESPACE), driver=self, size=size, extra=extra) def _to_device_mappings(self, object): return [self._to_device_mapping(el) for el in object.findall( fixxpath(xpath='blockDeviceMapping/item', namespace=NAMESPACE)) ] def _to_device_mapping(self, element): """ Parse the XML element and return a dictionary of device properties. Additional information can be found at http://goo.gl/GjWYBf. @note: EBS volumes do not have a virtual name. Only ephemeral disks use this property. :rtype: ``dict`` """ mapping = {} mapping['device_name'] = findattr(element=element, xpath='deviceName', namespace=NAMESPACE) mapping['virtual_name'] = findattr(element=element, xpath='virtualName', namespace=NAMESPACE) # If virtual name does not exist then this is an EBS volume. # Build the EBS dictionary leveraging the _get_extra_dict method. if mapping['virtual_name'] is None: mapping['ebs'] = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['ebs_volume']) return mapping def _to_instance_device_mappings(self, object): return [self._to_instance_device_mapping(el) for el in object.findall( fixxpath(xpath='blockDeviceMapping/item', namespace=NAMESPACE)) ] def _to_instance_device_mapping(self, element): """ Parse the XML element and return a dictionary of device properties. Additional information can be found at https://goo.gl/OGK88a. :rtype: ``dict`` """ mapping = {} mapping['device_name'] = findattr(element=element, xpath='deviceName', namespace=NAMESPACE) mapping['ebs'] = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['ebs_instance_block_device']) return mapping def _to_internet_gateways(self, object, xpath): return [self._to_internet_gateway(el) for el in object.findall(fixxpath(xpath=xpath, namespace=NAMESPACE))] def _to_internet_gateway(self, element, name=None): id = findtext(element=element, xpath='internetGatewayId', namespace=NAMESPACE) vpc_id = findtext(element=element, xpath='attachmentSet/item/vpcId', namespace=NAMESPACE) state = findtext(element=element, xpath='attachmentSet/item/state', namespace=NAMESPACE) # If there's no attachment state, let's # set it to available if not state: state = 'available' # Get our tags tags = self._get_resource_tags(element) # If name was not passed into the method then # fall back then use the gateway id name = name if name else tags.get('Name', id) return VPCInternetGateway(id=id, name=name, vpc_id=vpc_id, state=state, driver=self.connection.driver, extra={'tags': tags}) def _to_route_tables(self, response): return [self._to_route_table(el) for el in response.findall( fixxpath(xpath='routeTableSet/item', namespace=NAMESPACE)) ] def _to_route_table(self, element, name=None): # route table id route_table_id = findtext(element=element, xpath='routeTableId', namespace=NAMESPACE) # Get our tags tags = self._get_resource_tags(element) # Get our extra dictionary extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['route_table']) # Add tags to the extra dict extra['tags'] = tags # Get routes routes = self._to_routes(element, 'routeSet/item') # Get subnet associations subnet_associations = self._to_subnet_associations( element, 'associationSet/item') # Get propagating routes virtual private gateways (VGW) IDs propagating_gateway_ids = [] for el in element.findall(fixxpath(xpath='propagatingVgwSet/item', namespace=NAMESPACE)): propagating_gateway_ids.append(findtext(element=el, xpath='gatewayId', namespace=NAMESPACE)) name = name if name else tags.get('Name', id) return EC2RouteTable(route_table_id, name, routes, subnet_associations, propagating_gateway_ids, extra=extra) def _to_routes(self, element, xpath): return [self._to_route(el) for el in element.findall( fixxpath(xpath=xpath, namespace=NAMESPACE)) ] def _to_route(self, element): """ Parse the XML element and return a route object :rtype: :class: `EC2Route` """ destination_cidr = findtext(element=element, xpath='destinationCidrBlock', namespace=NAMESPACE) gateway_id = findtext(element=element, xpath='gatewayId', namespace=NAMESPACE) instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) owner_id = findtext(element=element, xpath='instanceOwnerId', namespace=NAMESPACE) interface_id = findtext(element=element, xpath='networkInterfaceId', namespace=NAMESPACE) state = findtext(element=element, xpath='state', namespace=NAMESPACE) origin = findtext(element=element, xpath='origin', namespace=NAMESPACE) vpc_peering_connection_id = findtext(element=element, xpath='vpcPeeringConnectionId', namespace=NAMESPACE) return EC2Route(destination_cidr, gateway_id, instance_id, owner_id, interface_id, state, origin, vpc_peering_connection_id) def _to_subnet_associations(self, element, xpath): return [self._to_subnet_association(el) for el in element.findall( fixxpath(xpath=xpath, namespace=NAMESPACE)) ] def _to_subnet_association(self, element): """ Parse the XML element and return a route table association object :rtype: :class: `EC2SubnetAssociation` """ association_id = findtext(element=element, xpath='routeTableAssociationId', namespace=NAMESPACE) route_table_id = findtext(element=element, xpath='routeTableId', namespace=NAMESPACE) subnet_id = findtext(element=element, xpath='subnetId', namespace=NAMESPACE) main = findtext(element=element, xpath='main', namespace=NAMESPACE) main = True if main else False return EC2SubnetAssociation(association_id, route_table_id, subnet_id, main) def _pathlist(self, key, arr): """ Converts a key and an array of values into AWS query param format. """ params = {} i = 0 for value in arr: i += 1 params['%s.%s' % (key, i)] = value return params def _get_boolean(self, element): tag = '{%s}%s' % (NAMESPACE, 'return') return element.findtext(tag) == 'true' def _get_terminate_boolean(self, element): status = element.findtext(".//{%s}%s" % (NAMESPACE, 'name')) return any([term_status == status for term_status in ('shutting-down', 'terminated')]) def _add_instance_filter(self, params, node): """ Add instance filter to the provided params dictionary. """ filters = {'instance-id': node.id} params.update(self._build_filters(filters)) return params def _get_state_boolean(self, element): """ Checks for the instances's state """ state = findall(element=element, xpath='instancesSet/item/currentState/name', namespace=NAMESPACE)[0].text return state in ('stopping', 'pending', 'starting') def _get_extra_dict(self, element, mapping): """ Extract attributes from the element based on rules provided in the mapping dictionary. :param element: Element to parse the values from. :type element: xml.etree.ElementTree.Element. :param mapping: Dictionary with the extra layout :type node: :class:`Node` :rtype: ``dict`` """ extra = {} for attribute, values in mapping.items(): transform_func = values['transform_func'] value = findattr(element=element, xpath=values['xpath'], namespace=NAMESPACE) if value is not None: extra[attribute] = transform_func(value) else: extra[attribute] = None return extra def _get_resource_tags(self, element): """ Parse tags from the provided element and return a dictionary with key/value pairs. :rtype: ``dict`` """ tags = {} # Get our tag set by parsing the element tag_set = findall(element=element, xpath='tagSet/item', namespace=NAMESPACE) for tag in tag_set: key = findtext(element=tag, xpath='key', namespace=NAMESPACE) value = findtext(element=tag, xpath='value', namespace=NAMESPACE) tags[key] = value return tags def _get_block_device_mapping_params(self, block_device_mapping): """ Return a list of dictionaries with query parameters for a valid block device mapping. :param mapping: List of dictionaries with the drive layout :type mapping: ``list`` or ``dict`` :return: Dictionary representation of the drive mapping :rtype: ``dict`` """ if not isinstance(block_device_mapping, (list, tuple)): raise AttributeError( 'block_device_mapping not list or tuple') params = {} for idx, mapping in enumerate(block_device_mapping): idx += 1 # We want 1-based indexes if not isinstance(mapping, dict): raise AttributeError( 'mapping %s in block_device_mapping ' 'not a dict' % mapping) for k, v in mapping.items(): if not isinstance(v, dict): params['BlockDeviceMapping.%d.%s' % (idx, k)] = str(v) else: for key, value in v.items(): params['BlockDeviceMapping.%d.%s.%s' % (idx, k, key)] = str(value) return params def _get_billing_product_params(self, billing_products): """ Return a list of dictionaries with valid param for billing product. :param billing_product: List of billing code values(str) :type billing product: ``list`` :return: Dictionary representation of the billing product codes :rtype: ``dict`` """ if not isinstance(billing_products, (list, tuple)): raise AttributeError( 'billing_products not list or tuple') params = {} for idx, v in enumerate(billing_products): idx += 1 # We want 1-based indexes params['BillingProduct.%d' % (idx)] = str(v) return params def _get_disk_container_params(self, disk_container): """ Return a list of dictionaries with query parameters for a valid disk container. :param disk_container: List of dictionaries with disk_container details :type disk_container: ``list`` or ``dict`` :return: Dictionary representation of the disk_container :rtype: ``dict`` """ if not isinstance(disk_container, (list, tuple)): raise AttributeError('disk_container not list or tuple') params = {} for idx, content in enumerate(disk_container): idx += 1 # We want 1-based indexes if not isinstance(content, dict): raise AttributeError( 'content %s in disk_container not a dict' % content) for k, v in content.items(): if not isinstance(v, dict): params['DiskContainer.%s' % (k)] = str(v) else: for key, value in v.items(): params['DiskContainer.%s.%s' % (k, key)] = str(value) return params def _get_client_data_params(self, client_data): """ Return a dictionary with query parameters for a valid client data. :param client_data: List of dictionaries with the disk upload details :type client_data: ``dict`` :return: Dictionary representation of the client data :rtype: ``dict`` """ if not isinstance(client_data, (list, tuple)): raise AttributeError('client_data not list or tuple') params = {} for idx, content in enumerate(client_data): idx += 1 # We want 1-based indexes if not isinstance(content, dict): raise AttributeError( 'content %s in client_data' 'not a dict' % content) for k, v in content.items(): params['ClientData.%s' % (k)] = str(v) return params def _get_common_security_group_params(self, group_id, protocol, from_port, to_port, cidr_ips, group_pairs, description=None): """ Return a dictionary with common query parameters which are used when operating on security groups. :rtype: ``dict`` """ params = {'GroupId': group_id, 'IpPermissions.1.IpProtocol': protocol, 'IpPermissions.1.FromPort': from_port, 'IpPermissions.1.ToPort': to_port} if cidr_ips is not None: ip_ranges = {} for index, cidr_ip in enumerate(cidr_ips): index += 1 ip_ranges['IpPermissions.1.IpRanges.%s.CidrIp' % (index)] = cidr_ip if description is not None: ip_ranges['IpPermissions.1.IpRanges.%s.Description' % (index)] = description params.update(ip_ranges) if group_pairs is not None: user_groups = {} for index, group_pair in enumerate(group_pairs): index += 1 if 'group_id' in group_pair.keys(): user_groups['IpPermissions.1.Groups.%s.GroupId' % (index)] = group_pair['group_id'] if 'group_name' in group_pair.keys(): user_groups['IpPermissions.1.Groups.%s.GroupName' % (index)] = group_pair['group_name'] if 'user_id' in group_pair.keys(): user_groups['IpPermissions.1.Groups.%s.UserId' % (index)] = group_pair['user_id'] params.update(user_groups) return params def _get_security_groups(self, element): """ Parse security groups from the provided element and return a list of security groups with the id ane name key/value pairs. :rtype: ``list`` of ``dict`` """ groups = [] for item in findall(element=element, xpath='groupSet/item', namespace=NAMESPACE): groups.append({ 'group_id': findtext(element=item, xpath='groupId', namespace=NAMESPACE), 'group_name': findtext(element=item, xpath='groupName', namespace=NAMESPACE) }) return groups def _build_filters(self, filters): """ Return a dictionary with filter query parameters which are used when listing networks, security groups, etc. :param filters: Dict of filter names and filter values :type filters: ``dict`` :rtype: ``dict`` """ filter_entries = {} for filter_idx, filter_data in enumerate(filters.items()): filter_idx += 1 # We want 1-based indexes filter_name, filter_values = filter_data filter_key = 'Filter.%s.Name' % (filter_idx) filter_entries[filter_key] = filter_name if isinstance(filter_values, list): for value_idx, value in enumerate(filter_values): value_idx += 1 # We want 1-based indexes value_key = 'Filter.%s.Value.%s' % (filter_idx, value_idx) filter_entries[value_key] = value else: value_key = 'Filter.%s.Value.1' % (filter_idx) filter_entries[value_key] = filter_values return filter_entries class EC2NodeDriver(BaseEC2NodeDriver): """ Amazon EC2 node driver. """ connectionCls = EC2Connection type = Provider.EC2 name = 'Amazon EC2' website = 'http://aws.amazon.com/ec2/' path = '/' NODE_STATE_MAP = { 'pending': NodeState.PENDING, 'running': NodeState.RUNNING, 'shutting-down': NodeState.UNKNOWN, 'terminated': NodeState.TERMINATED, 'stopped': NodeState.STOPPED } def __init__(self, key, secret=None, secure=True, host=None, port=None, region='us-east-1', token=None, **kwargs): if hasattr(self, '_region'): region = self._region # pylint: disable=no-member valid_regions = self.list_regions() if region not in valid_regions: raise ValueError('Invalid region: %s' % (region)) details = REGION_DETAILS[region] self.region_name = region self.token = token self.api_name = details['api_name'] self.country = details['country'] self.signature_version = details.get('signature_version', DEFAULT_SIGNATURE_VERSION) host = host or details['endpoint'] super(EC2NodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) @classmethod def list_regions(cls): return VALID_EC2_REGIONS class IdempotentParamError(LibcloudError): """ Request used the same client token as a previous, but non-identical request. """ def __str__(self): return repr(self.value) class EucConnection(EC2Connection): """ Connection class for Eucalyptus """ host = None class EucNodeDriver(BaseEC2NodeDriver): """ Driver class for Eucalyptus """ name = 'Eucalyptus' website = 'http://www.eucalyptus.com/' api_name = 'ec2_us_east' region_name = 'us-east-1' connectionCls = EucConnection signature_version = '2' def __init__(self, key, secret=None, secure=True, host=None, path=None, port=None, api_version=DEFAULT_EUCA_API_VERSION): """ @inherits: :class:`EC2NodeDriver.__init__` :param path: The host where the API can be reached. :type path: ``str`` :param api_version: The API version to extend support for Eucalyptus proprietary API calls :type api_version: ``str`` """ super(EucNodeDriver, self).__init__(key, secret, secure, host, port) if path is None: path = '/services/Eucalyptus' self.path = path self.EUCA_NAMESPACE = 'http://msgs.eucalyptus.com/%s' % (api_version) def list_locations(self): raise NotImplementedError( 'list_locations not implemented for this driver') def _to_sizes(self, response): return [self._to_size(el) for el in response.findall( fixxpath(xpath='instanceTypeDetails/item', namespace=self.EUCA_NAMESPACE))] def _to_size(self, el): name = findtext(element=el, xpath='name', namespace=self.EUCA_NAMESPACE) cpu = findtext(element=el, xpath='cpu', namespace=self.EUCA_NAMESPACE) disk = findtext(element=el, xpath='disk', namespace=self.EUCA_NAMESPACE) memory = findtext(element=el, xpath='memory', namespace=self.EUCA_NAMESPACE) return NodeSize(id=name, name=name, ram=int(memory), disk=int(disk), bandwidth=None, price=None, driver=EucNodeDriver, extra={ 'cpu': int(cpu) }) def list_sizes(self): """ Lists available nodes sizes. :rtype: ``list`` of :class:`NodeSize` """ params = {'Action': 'DescribeInstanceTypes'} response = self.connection.request(self.path, params=params).object return self._to_sizes(response) def _add_instance_filter(self, params, node): """ Eucalyptus driver doesn't support filtering on instance id so this is a no-op. """ pass class NimbusConnection(EC2Connection): """ Connection class for Nimbus """ host = None class NimbusNodeDriver(BaseEC2NodeDriver): """ Driver class for Nimbus """ type = Provider.NIMBUS name = 'Nimbus' website = 'http://www.nimbusproject.org/' country = 'Private' api_name = 'nimbus' region_name = 'nimbus' friendly_name = 'Nimbus Private Cloud' connectionCls = NimbusConnection signature_version = '2' def ex_describe_addresses(self, nodes): """ Nimbus doesn't support elastic IPs, so this is a pass-through. @inherits: :class:`EC2NodeDriver.ex_describe_addresses` """ nodes_elastic_ip_mappings = {} for node in nodes: # empty list per node nodes_elastic_ip_mappings[node.id] = [] return nodes_elastic_ip_mappings def ex_create_tags(self, resource, tags): """ Nimbus doesn't support creating tags, so this is a pass-through. @inherits: :class:`EC2NodeDriver.ex_create_tags` """ pass class OutscaleConnection(EC2Connection): """ Connection class for Outscale """ version = DEFAULT_OUTSCALE_API_VERSION host = None class OutscaleNodeDriver(BaseEC2NodeDriver): """ Base Outscale FCU node driver. Outscale per provider driver classes inherit from it. """ connectionCls = OutscaleConnection name = 'Outscale' website = 'http://www.outscale.com' path = '/' signature_version = '2' NODE_STATE_MAP = { 'pending': NodeState.PENDING, 'running': NodeState.RUNNING, 'shutting-down': NodeState.UNKNOWN, 'terminated': NodeState.TERMINATED, 'stopped': NodeState.STOPPED } def __init__(self, key, secret=None, secure=True, host=None, port=None, region='us-east-1', region_details=None, **kwargs): if hasattr(self, '_region'): region = getattr(self, '_region', None) if region_details is None: raise ValueError('Invalid region_details argument') if region not in region_details.keys(): raise ValueError('Invalid region: %s' % (region)) self.region_name = region self.region_details = region_details details = self.region_details[region] self.api_name = details['api_name'] self.country = details['country'] self.connectionCls.host = details['endpoint'] self._not_implemented_msg =\ 'This method is not supported in the Outscale driver' super(OutscaleNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def create_node(self, **kwargs): """ Creates a new Outscale node. The ex_iamprofile keyword is not supported. @inherits: :class:`BaseEC2NodeDriver.create_node` :keyword ex_keyname: The name of the key pair :type ex_keyname: ``str`` :keyword ex_userdata: The user data :type ex_userdata: ``str`` :keyword ex_security_groups: A list of names of security groups to assign to the node. :type ex_security_groups: ``list`` :keyword ex_metadata: The Key/Value metadata to associate with a node. :type ex_metadata: ``dict`` :keyword ex_mincount: The minimum number of nodes to launch :type ex_mincount: ``int`` :keyword ex_maxcount: The maximum number of nodes to launch :type ex_maxcount: ``int`` :keyword ex_clienttoken: A unique identifier to ensure idempotency :type ex_clienttoken: ``str`` :keyword ex_blockdevicemappings: ``list`` of ``dict`` block device mappings. :type ex_blockdevicemappings: ``list`` of ``dict`` :keyword ex_ebs_optimized: EBS-Optimized if True :type ex_ebs_optimized: ``bool`` """ if 'ex_iamprofile' in kwargs: raise NotImplementedError("ex_iamprofile not implemented") return super(OutscaleNodeDriver, self).create_node(**kwargs) def ex_create_network(self, cidr_block, name=None): """ Creates a network/VPC. Outscale does not support instance_tenancy. :param cidr_block: The CIDR block assigned to the network :type cidr_block: ``str`` :param name: An optional name for the network :type name: ``str`` :return: Dictionary of network properties :rtype: ``dict`` """ return super(OutscaleNodeDriver, self).ex_create_network(cidr_block, name=name) def ex_modify_instance_attribute(self, node, disable_api_termination=None, ebs_optimized=None, group_id=None, source_dest_check=None, user_data=None, instance_type=None, attributes=None): """ Modifies node attributes. Ouscale supports the following attributes: 'DisableApiTermination.Value', 'EbsOptimized', 'GroupId.n', 'SourceDestCheck.Value', 'UserData.Value', 'InstanceType.Value' :param node: Node instance :type node: :class:`Node` :param attributes: A dictionary with node attributes :type attributes: ``dict`` :return: True on success, False otherwise. :rtype: ``bool`` """ attributes = attributes or {} if disable_api_termination is not None: attributes['DisableApiTermination.Value'] = disable_api_termination if ebs_optimized is not None: attributes['EbsOptimized'] = ebs_optimized if group_id is not None: attributes['GroupId.n'] = group_id if source_dest_check is not None: attributes['SourceDestCheck.Value'] = source_dest_check if user_data is not None: attributes['UserData.Value'] = user_data if instance_type is not None: attributes['InstanceType.Value'] = instance_type return super(OutscaleNodeDriver, self).ex_modify_instance_attribute( node, attributes) def ex_register_image(self, name, description=None, architecture=None, root_device_name=None, block_device_mapping=None): """ Registers a Machine Image based off of an EBS-backed instance. Can also be used to create images from snapshots. Outscale does not support image_location, kernel_id and ramdisk_id. :param name: The name for the AMI being registered :type name: ``str`` :param description: The description of the AMI (optional) :type description: ``str`` :param architecture: The architecture of the AMI (i386/x86_64) (optional) :type architecture: ``str`` :param root_device_name: The device name for the root device Required if registering an EBS-backed AMI :type root_device_name: ``str`` :param block_device_mapping: A dictionary of the disk layout (optional) :type block_device_mapping: ``dict`` :rtype: :class:`NodeImage` """ return super(OutscaleNodeDriver, self).ex_register_image( name, description=description, architecture=architecture, root_device_name=root_device_name, block_device_mapping=block_device_mapping) def ex_copy_image(self, source_region, image, name=None, description=None): """ Outscale does not support copying images. @inherits: :class:`EC2NodeDriver.ex_copy_image` """ raise NotImplementedError(self._not_implemented_msg) def ex_get_limits(self): """ Outscale does not support getting limits. @inherits: :class:`EC2NodeDriver.ex_get_limits` """ raise NotImplementedError(self._not_implemented_msg) def ex_create_network_interface(self, subnet, name=None, description=None, private_ip_address=None): """ Outscale does not support creating a network interface within a VPC. @inherits: :class:`EC2NodeDriver.ex_create_network_interface` """ raise NotImplementedError(self._not_implemented_msg) def ex_delete_network_interface(self, network_interface): """ Outscale does not support deleting a network interface within a VPC. @inherits: :class:`EC2NodeDriver.ex_delete_network_interface` """ raise NotImplementedError(self._not_implemented_msg) def ex_attach_network_interface_to_node(self, network_interface, node, device_index): """ Outscale does not support attaching a network interface. @inherits: :class:`EC2NodeDriver.ex_attach_network_interface_to_node` """ raise NotImplementedError(self._not_implemented_msg) def ex_detach_network_interface(self, attachment_id, force=False): """ Outscale does not support detaching a network interface @inherits: :class:`EC2NodeDriver.ex_detach_network_interface` """ raise NotImplementedError(self._not_implemented_msg) def list_sizes(self, location=None): """ Lists available nodes sizes. This overrides the EC2 default method in order to use Outscale information or data. :rtype: ``list`` of :class:`NodeSize` """ available_types =\ self.region_details[self.region_name]['instance_types'] sizes = [] for instance_type in available_types: attributes = OUTSCALE_INSTANCE_TYPES[instance_type] attributes = copy.deepcopy(attributes) price = self._get_size_price(size_id=instance_type) attributes.update({'price': price}) sizes.append(NodeSize(driver=self, **attributes)) return sizes def ex_modify_instance_keypair(self, instance_id, key_name=None): """ Modifies the keypair associated with a specified instance. Once the modification is done, you must restart the instance. :param instance_id: The ID of the instance :type instance_id: ``string`` :param key_name: The name of the keypair :type key_name: ``string`` """ params = {'Action': 'ModifyInstanceKeypair'} params.update({'instanceId': instance_id}) if key_name is not None: params.update({'keyName': key_name}) response = self.connection.request(self.path, params=params, method='GET').object return (findtext(element=response, xpath='return', namespace=OUTSCALE_NAMESPACE) == 'true') def _to_quota(self, elem): """ To Quota """ quota = {} for reference_quota_item in findall(element=elem, xpath='referenceQuotaSet/item', namespace=OUTSCALE_NAMESPACE): reference = findtext(element=reference_quota_item, xpath='reference', namespace=OUTSCALE_NAMESPACE) quota_set = [] for quota_item in findall(element=reference_quota_item, xpath='quotaSet/item', namespace=OUTSCALE_NAMESPACE): ownerId = findtext(element=quota_item, xpath='ownerId', namespace=OUTSCALE_NAMESPACE) name = findtext(element=quota_item, xpath='name', namespace=OUTSCALE_NAMESPACE) displayName = findtext(element=quota_item, xpath='displayName', namespace=OUTSCALE_NAMESPACE) description = findtext(element=quota_item, xpath='description', namespace=OUTSCALE_NAMESPACE) groupName = findtext(element=quota_item, xpath='groupName', namespace=OUTSCALE_NAMESPACE) maxQuotaValue = findtext(element=quota_item, xpath='maxQuotaValue', namespace=OUTSCALE_NAMESPACE) usedQuotaValue = findtext(element=quota_item, xpath='usedQuotaValue', namespace=OUTSCALE_NAMESPACE) quota_set.append({'ownerId': ownerId, 'name': name, 'displayName': displayName, 'description': description, 'groupName': groupName, 'maxQuotaValue': maxQuotaValue, 'usedQuotaValue': usedQuotaValue}) quota[reference] = quota_set return quota def ex_describe_quotas(self, dry_run=False, filters=None, max_results=None, marker=None): """ Describes one or more of your quotas. :param dry_run: dry_run :type dry_run: ``bool`` :param filters: The filters so that the response returned includes information for certain quotas only. :type filters: ``dict`` :param max_results: The maximum number of items that can be returned in a single page (by default, 100) :type max_results: ``int`` :param marker: Set quota marker :type marker: ``string`` :return: (is_truncated, quota) tuple :rtype: ``(bool, dict)`` """ if filters: raise NotImplementedError( 'quota filters are not implemented') if marker: raise NotImplementedError( 'quota marker is not implemented') params = {'Action': 'DescribeQuotas'} if dry_run: params.update({'DryRun': dry_run}) if max_results: params.update({'MaxResults': max_results}) response = self.connection.request(self.path, params=params, method='GET').object quota = self._to_quota(response) is_truncated = findtext(element=response, xpath='isTruncated', namespace=OUTSCALE_NAMESPACE) return is_truncated, quota def _to_product_type(self, elem): productTypeId = findtext(element=elem, xpath='productTypeId', namespace=OUTSCALE_NAMESPACE) description = findtext(element=elem, xpath='description', namespace=OUTSCALE_NAMESPACE) return {'productTypeId': productTypeId, 'description': description} def ex_get_product_type(self, image_id, snapshot_id=None): """ Gets the product type of a specified OMI or snapshot. :param image_id: The ID of the OMI :type image_id: ``string`` :param snapshot_id: The ID of the snapshot :type snapshot_id: ``string`` :return: A product type :rtype: ``dict`` """ params = {'Action': 'GetProductType'} params.update({'ImageId': image_id}) if snapshot_id is not None: params.update({'SnapshotId': snapshot_id}) response = self.connection.request(self.path, params=params, method='GET').object product_type = self._to_product_type(response) return product_type def _to_product_types(self, elem): product_types = [] for product_types_item in findall(element=elem, xpath='productTypeSet/item', namespace=OUTSCALE_NAMESPACE): productTypeId = findtext(element=product_types_item, xpath='productTypeId', namespace=OUTSCALE_NAMESPACE) description = findtext(element=product_types_item, xpath='description', namespace=OUTSCALE_NAMESPACE) product_types.append({'productTypeId': productTypeId, 'description': description}) return product_types def ex_describe_product_types(self, filters=None): """ Describes product types. :param filters: The filters so that the list returned includes information for certain quotas only. :type filters: ``dict`` :return: A product types list :rtype: ``list`` """ params = {'Action': 'DescribeProductTypes'} if filters: params.update(self._build_filters(filters)) response = self.connection.request(self.path, params=params, method='GET').object product_types = self._to_product_types(response) return product_types def _to_instance_types(self, elem): instance_types = [] for instance_types_item in findall(element=elem, xpath='instanceTypeSet/item', namespace=OUTSCALE_NAMESPACE): name = findtext(element=instance_types_item, xpath='name', namespace=OUTSCALE_NAMESPACE) vcpu = findtext(element=instance_types_item, xpath='vcpu', namespace=OUTSCALE_NAMESPACE) memory = findtext(element=instance_types_item, xpath='memory', namespace=OUTSCALE_NAMESPACE) storageSize = findtext(element=instance_types_item, xpath='storageSize', namespace=OUTSCALE_NAMESPACE) storageCount = findtext(element=instance_types_item, xpath='storageCount', namespace=OUTSCALE_NAMESPACE) maxIpAddresses = findtext(element=instance_types_item, xpath='maxIpAddresses', namespace=OUTSCALE_NAMESPACE) ebsOptimizedAvailable = findtext(element=instance_types_item, xpath='ebsOptimizedAvailable', namespace=OUTSCALE_NAMESPACE) d = {'name': name, 'vcpu': vcpu, 'memory': memory, 'storageSize': storageSize, 'storageCount': storageCount, 'maxIpAddresses': maxIpAddresses, 'ebsOptimizedAvailable': ebsOptimizedAvailable} instance_types.append(d) return instance_types def ex_describe_instance_types(self, filters=None): """ Describes instance types. :param filters: The filters so that the list returned includes information for instance types only :type filters: ``dict`` :return: A instance types list :rtype: ``list`` """ params = {'Action': 'DescribeInstanceTypes'} if filters: params.update(self._build_filters(filters)) response = self.connection.request(self.path, params=params, method='GET').object instance_types = self._to_instance_types(response) return instance_types class OutscaleSASNodeDriver(OutscaleNodeDriver): """ Outscale SAS node driver """ name = 'Outscale SAS' type = Provider.OUTSCALE_SAS def __init__(self, key, secret=None, secure=True, host=None, port=None, region='us-east-1', region_details=None, **kwargs): super(OutscaleSASNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, region=region, region_details=OUTSCALE_SAS_REGION_DETAILS, **kwargs) class OutscaleINCNodeDriver(OutscaleNodeDriver): """ Outscale INC node driver """ name = 'Outscale INC' type = Provider.OUTSCALE_INC def __init__(self, key, secret=None, secure=True, host=None, port=None, region='us-east-1', region_details=None, **kwargs): super(OutscaleINCNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, region=region, region_details=OUTSCALE_INC_REGION_DETAILS, **kwargs) apache-libcloud-2.8.0/libcloud/compute/drivers/ecp.py0000664000175000017500000002671313577507766022533 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Enomaly ECP driver """ import time import os import socket import binascii from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.utils.py3 import base64_encode_string # JSON is included in the standard library starting with Python 2.6. For 2.5 # and 2.4, there's a simplejson egg at: http://pypi.python.org/pypi/simplejson try: import simplejson as json except ImportError: import json from libcloud.common.base import Response, ConnectionUserAndKey from libcloud.compute.base import NodeDriver, NodeSize, NodeLocation from libcloud.compute.base import NodeImage, Node from libcloud.compute.types import Provider, NodeState, InvalidCredsError from libcloud.utils.networking import is_private_subnet # Defaults API_HOST = '' API_PORT = (80, 443) class ECPResponse(Response): def success(self): if self.status == httplib.OK or self.status == httplib.CREATED: try: j_body = json.loads(self.body) except ValueError: self.error = "JSON response cannot be decoded." return False if j_body['errno'] == 0: return True else: self.error = "ECP error: %s" % j_body['message'] return False elif self.status == httplib.UNAUTHORIZED: raise InvalidCredsError() else: self.error = "HTTP Error Code: %s" % self.status return False def parse_error(self): return self.error # Interpret the json responses - no error checking required def parse_body(self): return json.loads(self.body) def getheaders(self): return self.headers class ECPConnection(ConnectionUserAndKey): """ Connection class for the Enomaly ECP driver """ responseCls = ECPResponse host = API_HOST port = API_PORT def add_default_headers(self, headers): # Authentication username = self.user_id password = self.key base64string = base64_encode_string( b('%s:%s' % (username, password)))[:-1] authheader = "Basic %s" % base64string headers['Authorization'] = authheader return headers def _encode_multipart_formdata(self, fields): """ Based on Wade Leftwich's function: http://code.activestate.com/recipes/146306/ """ # use a random boundary that does not appear in the fields boundary = '' while boundary in ''.join(fields): boundary = binascii.hexlify(os.urandom(16)).decode('utf-8') L = [] for i in fields: L.append('--' + boundary) L.append('Content-Disposition: form-data; name="%s"' % i) L.append('') L.append(fields[i]) L.append('--' + boundary + '--') L.append('') body = '\r\n'.join(L) content_type = 'multipart/form-data; boundary=%s' % boundary header = {'Content-Type': content_type} return header, body class ECPNodeDriver(NodeDriver): """ Enomaly ECP node driver """ name = "Enomaly Elastic Computing Platform" website = 'http://www.enomaly.com/' type = Provider.ECP connectionCls = ECPConnection def list_nodes(self): """ Returns a list of all running Nodes :rtype: ``list`` of :class:`Node` """ # Make the call res = self.connection.request('/rest/hosting/vm/list').parse_body() # Put together a list of node objects nodes = [] for vm in res['vms']: node = self._to_node(vm) if node is not None: nodes.append(node) # And return it return nodes def _to_node(self, vm): """ Turns a (json) dictionary into a Node object. This returns only running VMs. """ # Check state if not vm['state'] == "running": return None # IPs iplist = [interface['ip'] for interface in vm['interfaces'] if interface['ip'] != '127.0.0.1'] public_ips = [] private_ips = [] for ip in iplist: try: socket.inet_aton(ip) except socket.error: # not a valid ip continue if is_private_subnet(ip): private_ips.append(ip) else: public_ips.append(ip) # Create the node object n = Node( id=vm['uuid'], name=vm['name'], state=NodeState.RUNNING, public_ips=public_ips, private_ips=private_ips, driver=self, ) return n def reboot_node(self, node): """ Shuts down a VM and then starts it again. @inherits: :class:`NodeDriver.reboot_node` """ # Turn the VM off # Black magic to make the POST requests work d = self.connection._encode_multipart_formdata({'action': 'stop'}) self.connection.request( '/rest/hosting/vm/%s' % node.id, method='POST', headers=d[0], data=d[1] ).parse_body() node.state = NodeState.REBOOTING # Wait for it to turn off and then continue (to turn it on again) while node.state == NodeState.REBOOTING: # Check if it's off. response = self.connection.request( '/rest/hosting/vm/%s' % node.id ).parse_body() if response['vm']['state'] == 'off': node.state = NodeState.TERMINATED else: time.sleep(5) # Turn the VM back on. # Black magic to make the POST requests work d = self.connection._encode_multipart_formdata({'action': 'start'}) self.connection.request( '/rest/hosting/vm/%s' % node.id, method='POST', headers=d[0], data=d[1] ).parse_body() node.state = NodeState.RUNNING return True def destroy_node(self, node): """ Shuts down and deletes a VM. @inherits: :class:`NodeDriver.destroy_node` """ # Shut down first # Black magic to make the POST requests work d = self.connection._encode_multipart_formdata({'action': 'stop'}) self.connection.request( '/rest/hosting/vm/%s' % node.id, method='POST', headers=d[0], data=d[1] ).parse_body() # Ensure there was no application level error node.state = NodeState.PENDING # Wait for the VM to turn off before continuing while node.state == NodeState.PENDING: # Check if it's off. response = self.connection.request( '/rest/hosting/vm/%s' % node.id ).parse_body() if response['vm']['state'] == 'off': node.state = NodeState.TERMINATED else: time.sleep(5) # Delete the VM # Black magic to make the POST requests work d = self.connection._encode_multipart_formdata({'action': 'delete'}) self.connection.request( '/rest/hosting/vm/%s' % (node.id), method='POST', headers=d[0], data=d[1] ).parse_body() return True def list_images(self, location=None): """ Returns a list of all package templates aka appliances aka images. @inherits: :class:`NodeDriver.list_images` """ # Make the call response = self.connection.request( '/rest/hosting/ptemplate/list').parse_body() # Turn the response into an array of NodeImage objects images = [] for ptemplate in response['packages']: images.append(NodeImage( id=ptemplate['uuid'], name='%s: %s' % (ptemplate['name'], ptemplate['description']), driver=self,) ) return images def list_sizes(self, location=None): """ Returns a list of all hardware templates @inherits: :class:`NodeDriver.list_sizes` """ # Make the call response = self.connection.request( '/rest/hosting/htemplate/list').parse_body() # Turn the response into an array of NodeSize objects sizes = [] for htemplate in response['templates']: sizes.append(NodeSize( id=htemplate['uuid'], name=htemplate['name'], ram=htemplate['memory'], disk=0, # Disk is independent of hardware template. bandwidth=0, # There is no way to keep track of bandwidth. price=0, # The billing system is external. driver=self,) ) return sizes def list_locations(self): """ This feature does not exist in ECP. Returns hard coded dummy location. :rtype: ``list`` of :class:`NodeLocation` """ return [NodeLocation(id=1, name="Cloud", country='', driver=self), ] def create_node(self, name, size, image): """ Creates a virtual machine. :keyword name: String with a name for this new node (required) :type name: ``str`` :keyword size: The size of resources allocated to this node . (required) :type size: :class:`NodeSize` :keyword image: OS Image to boot on node. (required) :type image: :class:`NodeImage` :rtype: :class:`Node` """ # Find out what network to put the VM on. res = self.connection.request( '/rest/hosting/network/list').parse_body() # Use the first / default network because there is no way to specific # which one network = res['networks'][0]['uuid'] # Prepare to make the VM data = { 'name': str(name), 'package': str(image.id), 'hardware': str(size.id), 'network_uuid': str(network), 'disk': '' } # Black magic to make the POST requests work d = self.connection._encode_multipart_formdata(data) response = self.connection.request( '/rest/hosting/vm/', method='PUT', headers=d[0], data=d[1] ).parse_body() # Create a node object and return it. n = Node( id=response['machine_id'], name=data['name'], state=NodeState.PENDING, public_ips=[], private_ips=[], driver=self, ) return n apache-libcloud-2.8.0/libcloud/compute/drivers/ecs.py0000664000175000017500000017451213576514553022526 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Node driver for Aliyun. """ try: import simplejson as json except ImportError: import json import time from libcloud.common.aliyun import AliyunXmlResponse, SignedAliyunConnection from libcloud.common.types import LibcloudError from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeSize, \ StorageVolume, VolumeSnapshot, NodeLocation from libcloud.compute.types import NodeState, StorageVolumeState, \ VolumeSnapshotState from libcloud.utils.py3 import _real_unicode as u from libcloud.utils.xml import findall, findattr, findtext __all__ = [ 'DiskCategory', 'InternetChargeType', 'ECS_API_VERSION', 'ECSDriver', 'ECSSecurityGroup', 'ECSZone' ] ECS_API_VERSION = '2014-05-26' ECS_API_ENDPOINT = 'ecs.aliyuncs.com' DEFAULT_SIGNATURE_VERSION = '1.0' def _parse_bool(value): if isinstance(value, bool): return value if u(value).lower() == 'true': return True return False """ Define the extra dictionary for specific resources """ RESOURCE_EXTRA_ATTRIBUTES_MAP = { 'node': { 'description': { 'xpath': 'Description', 'transform_func': u }, 'image_id': { 'xpath': 'ImageId', 'transform_func': u }, 'zone_id': { 'xpath': 'ZoneId', 'transform_func': u }, 'instance_type': { 'xpath': 'InstanceType', 'transform_func': u }, 'instance_type_family': { 'xpath': 'InstanceTypeFamily', 'transform_func': u }, 'hostname': { 'xpath': 'HostName', 'transform_func': u }, 'serial_number': { 'xpath': 'SerialNumber', 'transform_func': u }, 'internet_charge_type': { 'xpath': 'InternetChargeType', 'transform_func': u }, 'creation_time': { 'xpath': 'CreationTime', 'transform_func': u }, 'instance_network_type': { 'xpath': 'InstanceNetworkType', 'transform_func': u }, 'instance_charge_type': { 'xpath': 'InstanceChargeType', 'transform_func': u }, 'device_available': { 'xpath': 'DeviceAvailable', 'transform_func': u }, 'io_optimized': { 'xpath': 'IoOptimized', 'transform_func': u }, 'expired_time': { 'xpath': 'ExpiredTime', 'transform_func': u } }, 'vpc_attributes': { 'vpc_id': { 'xpath': 'VpcId', 'transform_func': u }, 'vswitch_id': { 'xpath': 'VSwitchId', 'transform_func': u }, 'private_ip_address': { 'xpath': 'PrivateIpAddress/IpAddress', 'transform_func': u }, 'nat_ip_address': { 'xpath': 'NatIpAddress', 'transform_func': u } }, 'eip_address_associate': { 'allocation_id': { 'xpath': 'AllocationId', 'transform_func': u }, 'ip_address': { 'xpath': 'IpAddress', 'transform_func': u }, 'bandwidth': { 'xpath': 'Bandwidth', 'transform_func': int }, 'internet_charge_type': { 'xpath': 'InternetChargeType', 'transform_func': u } }, 'operation_locks': { 'lock_reason': { 'xpath': 'LockReason', 'transform_func': u } }, 'volume': { 'region_id': { 'xpath': 'RegionId', 'transform_func': u }, 'zone_id': { 'xpath': 'ZoneId', 'transform_func': u }, 'description': { 'xpath': 'Description', 'transform_func': u }, 'type': { 'xpath': 'Type', 'transform_func': u }, 'category': { 'xpath': 'Category', 'transform_func': u }, 'image_id': { 'xpath': 'ImageId', 'transform_func': u }, 'source_snapshot_id': { 'xpath': 'SourceSnapshotId', 'transform_func': u }, 'product_code': { 'xpath': 'ProductCode', 'transform_func': u }, 'portable': { 'xpath': 'Portable', 'transform_func': _parse_bool }, 'instance_id': { 'xpath': 'InstanceId', 'transform_func': u }, 'device': { 'xpath': 'Device', 'transform_func': u }, 'delete_with_instance': { 'xpath': 'DeleteWithInstance', 'transform_func': _parse_bool }, 'enable_auto_snapshot': { 'xpath': 'EnableAutoSnapshot', 'transform_func': _parse_bool }, 'creation_time': { 'xpath': 'CreationTime', 'transform_func': u }, 'attached_time': { 'xpath': 'AttachedTime', 'transform_func': u }, 'detached_time': { 'xpath': 'DetachedTime', 'transform_func': u }, 'disk_charge_type': { 'xpath': 'DiskChargeType', 'transform_func': u } }, 'snapshot': { 'snapshot_name': { 'xpath': 'SnapshotName', 'transform_func': u }, 'description': { 'xpath': 'Description', 'transform_func': u }, 'progress': { 'xpath': 'Progress', 'transform_func': u }, 'source_disk_id': { 'xpath': 'SourceDiskId', 'transform_func': u }, 'source_disk_size': { 'xpath': 'SourceDiskSize', 'transform_func': int }, 'source_disk_type': { 'xpath': 'SourceDiskType', 'transform_func': u }, 'product_code': { 'xpath': 'ProductCode', 'transform_func': u }, 'usage': { 'xpath': 'Usage', 'transform_func': u } }, 'image': { 'image_version': { 'xpath': 'ImageVersion', 'transform_func': u }, 'os_type': { 'xpath': 'OSType', 'transform_func': u }, 'platform': { 'xpath': 'Platform', 'transform_func': u }, 'architecture': { 'xpath': 'Architecture', 'transform_func': u }, 'description': { 'xpath': 'Description', 'transform_func': u }, 'size': { 'xpath': 'Size', 'transform_func': int }, 'image_owner_alias': { 'xpath': 'ImageOwnerAlias', 'transform_func': u }, 'os_name': { 'xpath': 'OSName', 'transform_func': u }, 'product_code': { 'xpath': 'ProductCode', 'transform_func': u }, 'is_subscribed': { 'xpath': 'IsSubscribed', 'transform_func': _parse_bool }, 'progress': { 'xpath': 'Progress', 'transform_func': u }, 'creation_time': { 'xpath': 'CreationTime', 'transform_func': u }, 'usage': { 'xpath': 'Usage', 'transform_func': u }, 'is_copied': { 'xpath': 'IsCopied', 'transform_func': _parse_bool } }, 'disk_device_mapping': { 'snapshot_id': { 'xpath': 'SnapshotId', 'transform_func': u }, 'size': { 'xpath': 'Size', 'transform_func': int }, 'device': { 'xpath': 'Device', 'transform_func': u }, 'format': { 'xpath': 'Format', 'transform_func': u }, 'import_oss_bucket': { 'xpath': 'ImportOSSBucket', 'transform_func': u }, 'import_oss_object': { 'xpath': 'ImportOSSObject', 'transform_func': u } } } class ECSConnection(SignedAliyunConnection): """ Represents a single connection to the Aliyun ECS Endpoint. """ api_version = ECS_API_VERSION host = ECS_API_ENDPOINT responseCls = AliyunXmlResponse service_name = 'ecs' class ECSSecurityGroup(object): """ Security group used to control nodes internet and intranet accessibility. """ def __init__(self, id, name, description=None, driver=None, vpc_id=None, creation_time=None): self.id = id self.name = name self.description = description self.driver = driver self.vpc_id = vpc_id self.creation_time = creation_time def __repr__(self): return ('' % (self.id, self.name, self.driver.name)) class ECSSecurityGroupAttribute(object): """ Security group attribute. """ def __init__(self, ip_protocol=None, port_range=None, source_group_id=None, policy=None, nic_type=None): self.ip_protocol = ip_protocol self.port_range = port_range self.source_group_id = source_group_id self.policy = policy self.nic_type = nic_type def __repr__(self): return ('' % (self.ip_protocol)) class ECSZone(object): """ ECSZone used to represent an availability zone in a region. """ def __init__(self, id, name, driver=None, available_resource_types=None, available_instance_types=None, available_disk_categories=None): self.id = id self.name = name self.driver = driver self.available_resource_types = available_resource_types self.available_instance_types = available_instance_types self.available_disk_categories = available_disk_categories def __repr__(self): return ('' % (self.id, self.name, self.driver)) class InternetChargeType(object): """ Internet connection billing types for Aliyun Nodes. """ BY_BANDWIDTH = 'PayByBandwidth' BY_TRAFFIC = 'PayByTraffic' class DiskCategory(object): """ Enum defined disk types supported by Aliyun system and data disks. """ CLOUD = 'cloud' CLOUD_EFFICIENCY = 'cloud_efficiency' CLOUD_SSD = 'cloud_ssd' EPHEMERAL_SSD = 'ephemeral_ssd' class Pagination(object): """ Pagination used to describe the multiple pages results. """ def __init__(self, total, size, current): """ Create a pagination. :param total: the total count of the results :param size: the page size of each page :param current: the current page number, 1-based """ self.total = total self.size = size self.current = current def next(self): """ Switch to the next page. :return: the new pagination or None when no more page :rtype: ``Pagination`` """ if self.total is None or (self.size * self.current >= self.total): return None self.current += 1 return self def to_dict(self): return {'PageNumber': self.current, 'PageSize': self.size} def __repr__(self): return ('' % (self.total, self.size, self.current)) class ECSDriver(NodeDriver): """ Aliyun ECS node driver. Used for Aliyun ECS service. TODO: Get guest OS root password Adjust internet bandwidth settings Manage security groups and rules """ name = 'Aliyun ECS' website = 'https://www.aliyun.com/product/ecs' connectionCls = ECSConnection features = {'create_node': ['password']} namespace = None path = '/' internet_charge_types = InternetChargeType disk_categories = DiskCategory NODE_STATE_MAPPING = { 'Starting': NodeState.PENDING, 'Running': NodeState.RUNNING, 'Stopping': NodeState.PENDING, 'Stopped': NodeState.STOPPED } VOLUME_STATE_MAPPING = { 'In_use': StorageVolumeState.INUSE, 'Available': StorageVolumeState.AVAILABLE, 'Attaching': StorageVolumeState.ATTACHING, 'Detaching': StorageVolumeState.INUSE, 'Creating': StorageVolumeState.CREATING, 'ReIniting': StorageVolumeState.CREATING} SNAPSHOT_STATE_MAPPING = { 'progressing': VolumeSnapshotState.CREATING, 'accomplished': VolumeSnapshotState.AVAILABLE, 'failed': VolumeSnapshotState.ERROR} def list_nodes(self, ex_node_ids=None, ex_filters=None): """ List all nodes. @inherits: :class:`NodeDriver.create_node` :keyword ex_node_ids: a list of node's ids used to filter nodes. Only the nodes which's id in this list will be returned. :type ex_node_ids: ``list`` of ``str`` :keyword ex_filters: node attribute and value pairs to filter nodes. Only the nodes which matchs all the pairs will be returned. If the filter attribute need a json array value, use ``list`` object, the driver will convert it. :type ex_filters: ``dict`` """ params = {'Action': 'DescribeInstances', 'RegionId': self.region} if ex_node_ids: if isinstance(ex_node_ids, list): params['InstanceIds'] = self._list_to_json_array(ex_node_ids) else: raise AttributeError('ex_node_ids should be a list of ' 'node ids.') if ex_filters: if isinstance(ex_filters, dict): params.update(ex_filters) else: raise AttributeError('ex_filters should be a dict of ' 'node attributes.') nodes = self._request_multiple_pages(self.path, params, self._to_nodes) return nodes def list_sizes(self, location=None): params = {'Action': 'DescribeInstanceTypes'} resp_body = self.connection.request(self.path, params).object size_elements = findall(resp_body, 'InstanceTypes/InstanceType', namespace=self.namespace) sizes = [self._to_size(each) for each in size_elements] return sizes def list_locations(self): params = {'Action': 'DescribeRegions'} resp_body = self.connection.request(self.path, params).object location_elements = findall(resp_body, 'Regions/Region', namespace=self.namespace) locations = [self._to_location(each) for each in location_elements] return locations def create_node(self, name, size, image, auth=None, ex_security_group_id=None, ex_description=None, ex_internet_charge_type=None, ex_internet_max_bandwidth_out=None, ex_internet_max_bandwidth_in=None, ex_hostname=None, ex_io_optimized=None, ex_system_disk=None, ex_data_disks=None, ex_vswitch_id=None, ex_private_ip_address=None, ex_client_token=None, **kwargs): """ @inherits: :class:`NodeDriver.create_node` :param name: The name for this new node (required) :type name: ``str`` :param image: The image to use when creating this node (required) :type image: `NodeImage` :param size: The size of the node to create (required) :type size: `NodeSize` :keyword auth: Initial authentication information for the node (optional) :type auth: :class:`NodeAuthSSHKey` or :class:`NodeAuthPassword` :keyword ex_security_group_id: The id of the security group the new created node is attached to. (required) :type ex_security_group_id: ``str`` :keyword ex_description: A description string for this node (optional) :type ex_description: ``str`` :keyword ex_internet_charge_type: The internet charge type (optional) :type ex_internet_charge_type: a ``str`` of 'PayByTraffic' or 'PayByBandwidth' :keyword ex_internet_max_bandwidth_out: The max output bandwidth, in Mbps (optional) Required for 'PayByTraffic' internet charge type :type ex_internet_max_bandwidth_out: a ``int`` in range [0, 100] a ``int`` in range [1, 100] for 'PayByTraffic' internet charge type :keyword ex_internet_max_bandwidth_in: The max input bandwidth, in Mbps (optional) :type ex_internet_max_bandwidth_in: a ``int`` in range [1, 200] default to 200 in server side :keyword ex_hostname: The hostname for the node (optional) :type ex_hostname: ``str`` :keyword ex_io_optimized: Whether the node is IO optimized (optional) :type ex_io_optimized: ``boll`` :keyword ex_system_disk: The system disk for the node (optional) :type ex_system_disk: ``dict`` :keyword ex_data_disks: The data disks for the node (optional) :type ex_data_disks: a `list` of `dict` :keyword ex_vswitch_id: The id of vswitch for a VPC type node (optional) :type ex_vswitch_id: ``str`` :keyword ex_private_ip_address: The IP address in private network (optional) :type ex_private_ip_address: ``str`` :keyword ex_client_token: A token generated by client to keep requests idempotency (optional) :type keyword ex_client_token: ``str`` """ params = {'Action': 'CreateInstance', 'RegionId': self.region, 'ImageId': image.id, 'InstanceType': size.id, 'InstanceName': name} if not ex_security_group_id: raise AttributeError('ex_security_group_id is mandatory') params['SecurityGroupId'] = ex_security_group_id if ex_description: params['Description'] = ex_description inet_params = self._get_internet_related_params( ex_internet_charge_type, ex_internet_max_bandwidth_in, ex_internet_max_bandwidth_out) if inet_params: params.update(inet_params) if ex_hostname: params['HostName'] = ex_hostname if auth: auth = self._get_and_check_auth(auth) params['Password'] = auth.password if ex_io_optimized is not None: optimized = ex_io_optimized if isinstance(optimized, bool): optimized = 'optimized' if optimized else 'none' params['IoOptimized'] = optimized if ex_system_disk: system_disk = self._get_system_disk(ex_system_disk) if system_disk: params.update(system_disk) if ex_data_disks: data_disks = self._get_data_disks(ex_data_disks) if data_disks: params.update(data_disks) if ex_vswitch_id: params['VSwitchId'] = ex_vswitch_id if ex_private_ip_address: if not ex_vswitch_id: raise AttributeError('must provide ex_private_ip_address ' 'and ex_vswitch_id at the same time') else: params['PrivateIpAddress'] = ex_private_ip_address if ex_client_token: params['ClientToken'] = ex_client_token resp = self.connection.request(self.path, params=params) node_id = findtext(resp.object, xpath='InstanceId', namespace=self.namespace) nodes = self.list_nodes(ex_node_ids=[node_id]) if len(nodes) != 1: raise LibcloudError('could not find the new created node ' 'with id %s. ' % node_id, driver=self) node = nodes[0] self.ex_start_node(node) self._wait_until_state(nodes, NodeState.RUNNING) return node def reboot_node(self, node, ex_force_stop=False): """ Reboot the given node @inherits :class:`NodeDriver.reboot_node` :keyword ex_force_stop: if ``True``, stop node force (maybe lose data) otherwise, stop node normally, default to ``False`` :type ex_force_stop: ``bool`` """ params = {'Action': 'RebootInstance', 'InstanceId': node.id, 'ForceStop': u(ex_force_stop).lower()} resp = self.connection.request(self.path, params=params) return resp.success() and \ self._wait_until_state([node], NodeState.RUNNING) def destroy_node(self, node): nodes = self.list_nodes(ex_node_ids=[node.id]) if len(nodes) != 1 and node.id != nodes[0].id: raise LibcloudError('could not find the node with id %s.' % node.id) current = nodes[0] if current.state == NodeState.RUNNING: # stop node first self.ex_stop_node(node) self._wait_until_state(nodes, NodeState.STOPPED) params = {'Action': 'DeleteInstance', 'InstanceId': node.id} resp = self.connection.request(self.path, params) return resp.success() def start_node(self, node): """ Start node to running state. :param node: the ``Node`` object to start :type node: ``Node`` :return: starting operation result. :rtype: ``bool`` """ params = {'Action': 'StartInstance', 'InstanceId': node.id} resp = self.connection.request(self.path, params) return resp.success() and \ self._wait_until_state([node], NodeState.RUNNING) def stop_node(self, node, ex_force_stop=False): """ Stop a running node. :param node: The node to stop :type node: :class:`Node` :keyword ex_force_stop: if ``True``, stop node force (maybe lose data) otherwise, stop node normally, default to ``False`` :type ex_force_stop: ``bool`` :return: stopping operation result. :rtype: ``bool`` """ params = {'Action': 'StopInstance', 'InstanceId': node.id, 'ForceStop': u(ex_force_stop).lower()} resp = self.connection.request(self.path, params) return resp.success() and \ self._wait_until_state([node], NodeState.STOPPED) def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node, ex_force_stop=False): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node, ex_force_stop=ex_force_stop) def ex_create_security_group(self, description=None, client_token=None): """ Create a new security group. :keyword description: security group description :type description: ``unicode`` :keyword client_token: a token generated by client to identify each request. :type client_token: ``str`` """ params = {'Action': 'CreateSecurityGroup', 'RegionId': self.region} if description: params['Description'] = description if client_token: params['ClientToken'] = client_token resp = self.connection.request(self.path, params) return findtext(resp.object, 'SecurityGroupId', namespace=self.namespace) def ex_delete_security_group_by_id(self, group_id=None): """ Delete a new security group. :keyword group_id: security group id :type group_id: ``str`` """ params = {'Action': 'DeleteSecurityGroup', 'RegionId': self.region, 'SecurityGroupId': group_id} resp = self.connection.request(self.path, params) return resp.success() def ex_modify_security_group_by_id( self, group_id=None, name=None, description=None): """ Modify a new security group. :keyword group_id: id of the security group :type group_id: ``str`` :keyword name: new name of the security group :type name: ``unicode`` :keyword description: new description of the security group :type description: ``unicode`` """ params = {'Action': 'ModifySecurityGroupAttribute', 'RegionId': self.region} if not group_id: raise AttributeError('group_id is required') params["SecurityGroupId"] = group_id if name: params["SecurityGroupName"] = name if description: params["Description"] = description resp = self.connection.request(self.path, params) return resp.success() def ex_list_security_groups(self, ex_filters=None): """ List security groups in the current region. :keyword ex_filters: security group attributes to filter results. :type ex_filters: ``dict`` :return: a list of defined security groups :rtype: ``list`` of ``ECSSecurityGroup`` """ params = {'Action': 'DescribeSecurityGroups', 'RegionId': self.region} if ex_filters and isinstance(ex_filters, dict): ex_filters.update(params) params = ex_filters def _parse_response(resp_object): sg_elements = findall(resp_object, 'SecurityGroups/SecurityGroup', namespace=self.namespace) sgs = [self._to_security_group(el) for el in sg_elements] return sgs return self._request_multiple_pages(self.path, params, _parse_response) def ex_list_security_group_attributes(self, group_id=None, nic_type='internet'): """ List security group attributes in the current region. :keyword group_id: security group id. :type group_id: ``str`` :keyword nic_type: internet|intranet. :type nic_type: ``str`` :return: a list of defined security group Attributes :rtype: ``list`` of ``ECSSecurityGroupAttribute`` """ params = {'Action': 'DescribeSecurityGroupAttribute', 'RegionId': self.region, 'NicType': nic_type} if group_id is None: raise AttributeError('group_id is required') params['SecurityGroupId'] = group_id resp_object = self.connection.request(self.path, params).object sga_elements = findall(resp_object, 'Permissions/Permission', namespace=self.namespace) return [self._to_security_group_attribute(el) for el in sga_elements] def ex_join_security_group(self, node, group_id=None): """ Join a node into security group. :param node: The node to join security group :type node: :class:`Node` :param group_id: security group id. :type group_id: ``str`` :return: join operation result. :rtype: ``bool`` """ if group_id is None: raise AttributeError('group_id is required') if node.state != NodeState.RUNNING and \ node.state != NodeState.STOPPED: raise LibcloudError('The node state with id % s need\ be running or stopped .' % node.id) params = {'Action': 'JoinSecurityGroup', 'InstanceId': node.id, 'SecurityGroupId': group_id} resp = self.connection.request(self.path, params) return resp.success() def ex_leave_security_group(self, node, group_id=None): """ Leave a node from security group. :param node: The node to leave security group :type node: :class:`Node` :param group_id: security group id. :type group_id: ``str`` :return: leave operation result. :rtype: ``bool`` """ if group_id is None: raise AttributeError('group_id is required') if node.state != NodeState.RUNNING and \ node.state != NodeState.STOPPED: raise LibcloudError('The node state with id % s need\ be running or stopped .' % node.id) params = {'Action': 'LeaveSecurityGroup', 'InstanceId': node.id, 'SecurityGroupId': group_id} resp = self.connection.request(self.path, params) return resp.success() def ex_list_zones(self, region_id=None): """ List availability zones in the given region or the current region. :keyword region_id: the id of the region to query zones from :type region_id: ``str`` :return: list of zones :rtype: ``list`` of ``ECSZone`` """ params = {'Action': 'DescribeZones'} if region_id: params['RegionId'] = region_id else: params['RegionId'] = self.region resp_body = self.connection.request(self.path, params).object zone_elements = findall(resp_body, 'Zones/Zone', namespace=self.namespace) zones = [self._to_zone(el) for el in zone_elements] return zones ## # Volume and snapshot management methods ## def list_volumes(self, ex_volume_ids=None, ex_filters=None): """ List all volumes. @inherits: :class:`NodeDriver.list_volumes` :keyword ex_volume_ids: a list of volume's ids used to filter volumes. Only the volumes which's id in this list will be returned. :type ex_volume_ids: ``list`` of ``str`` :keyword ex_filters: volume attribute and value pairs to filter volumes. Only the volumes which matchs all will be returned. If the filter attribute need a json array value, use ``list`` object, the driver will convert it. :type ex_filters: ``dict`` """ params = {'Action': 'DescribeDisks', 'RegionId': self.region} if ex_volume_ids: if isinstance(ex_volume_ids, list): params['DiskIds'] = self._list_to_json_array(ex_volume_ids) else: raise AttributeError('ex_volume_ids should be a list of ' 'volume ids.') if ex_filters: if not isinstance(ex_filters, dict): raise AttributeError('ex_filters should be a dict of ' 'volume attributes.') else: for key in ex_filters.keys(): params[key] = ex_filters[key] def _parse_response(resp_object): disk_elements = findall(resp_object, 'Disks/Disk', namespace=self.namespace) volumes = [self._to_volume(each) for each in disk_elements] return volumes return self._request_multiple_pages(self.path, params, _parse_response) def list_volume_snapshots(self, volume, ex_snapshot_ids=[], ex_filters=None): """ List snapshots for a storage volume. @inherites :class:`NodeDriver.list_volume_snapshots` :keyword ex_snapshot_ids: a list of snapshot ids to filter the snapshots returned. :type ex_snapshot_ids: ``list`` of ``str`` :keyword ex_filters: snapshot attribute and value pairs to filter snapshots. Only the snapshot which matchs all the pairs will be returned. If the filter attribute need a json array value, use ``list`` object, the driver will convert it. :type ex_filters: ``dict`` """ params = {'Action': 'DescribeSnapshots', 'RegionId': self.region} if volume: params['DiskId'] = volume.id if ex_snapshot_ids and isinstance(ex_snapshot_ids, list): params['SnapshotIds'] = self._list_to_json_array(ex_snapshot_ids) if ex_filters and isinstance(ex_filters, dict): for key in ex_filters.keys(): params[key] = ex_filters[key] def _parse_response(resp_body): snapshot_elements = findall(resp_body, 'Snapshots/Snapshot', namespace=self.namespace) snapshots = [self._to_snapshot(each) for each in snapshot_elements] return snapshots return self._request_multiple_pages(self.path, params, _parse_response) def create_volume(self, size, name, location=None, snapshot=None, ex_zone_id=None, ex_description=None, ex_disk_category=None, ex_client_token=None): """ Create a new volume. @inherites :class:`NodeDriver.create_volume` :keyword ex_zone_id: the availability zone id (required) :type ex_zone_id: ``str`` :keyword ex_description: volume description :type ex_description: ``unicode`` :keyword ex_disk_category: disk category for data disk :type ex_disk_category: ``str`` :keyword ex_client_token: a token generated by client to identify each request. :type ex_client_token: ``str`` """ params = {'Action': 'CreateDisk', 'RegionId': self.region, 'DiskName': name, 'Size': size} if ex_zone_id is None: raise AttributeError('ex_zone_id is required') params['ZoneId'] = ex_zone_id if snapshot is not None and isinstance(snapshot, VolumeSnapshot): params['SnapshotId'] = snapshot.id if ex_description: params['Description'] = ex_description if ex_disk_category: params['DiskCategory'] = ex_disk_category if ex_client_token: params['ClientToken'] = ex_client_token resp = self.connection.request(self.path, params).object volume_id = findtext(resp, 'DiskId', namespace=self.namespace) volumes = self.list_volumes(ex_volume_ids=[volume_id]) if len(volumes) != 1: raise LibcloudError('could not find the new create volume ' 'with id %s.' % volume_id, driver=self) return volumes[0] def create_volume_snapshot(self, volume, name=None, ex_description=None, ex_client_token=None): """ Creates a snapshot of the storage volume. @inherits :class:`NodeDriver.create_volume_snapshot` :keyword ex_description: description of the snapshot. :type ex_description: ``unicode`` :keyword ex_client_token: a token generated by client to identify each request. :type ex_client_token: ``str`` """ params = {'Action': 'CreateSnapshot', 'DiskId': volume.id} if name: params['SnapshotName'] = name if ex_description: params['Description'] = ex_description if ex_client_token: params['ClientToken'] = ex_client_token snapshot_elements = self.connection.request(self.path, params).object snapshot_id = findtext(snapshot_elements, 'SnapshotId', namespace=self.namespace) snapshots = self.list_volume_snapshots(volume=None, ex_snapshot_ids=[snapshot_id]) if len(snapshots) != 1: raise LibcloudError('could not find new created snapshot with ' 'id %s.' % snapshot_id, driver=self) return snapshots[0] def attach_volume(self, node, volume, device=None, ex_delete_with_instance=None): """ Attaches volume to node. @inherits :class:`NodeDriver.attach_volume` :keyword device: device path allocated for this attached volume :type device: ``str`` between /dev/xvdb to xvdz, if empty, allocated by the system :keyword ex_delete_with_instance: if to delete this volume when the instance is deleted. :type ex_delete_with_instance: ``bool`` """ params = {'Action': 'AttachDisk', 'InstanceId': node.id, 'DiskId': volume.id} if device: params['Device'] = device if ex_delete_with_instance: params['DeleteWithInstance'] = \ str(bool(ex_delete_with_instance)).lower() resp = self.connection.request(self.path, params) return resp.success() def detach_volume(self, volume, ex_instance_id=None): """ Detaches a volume from a node. @inherits :class:`NodeDriver.detach_volume` :keyword ex_instance_id: the id of the instance from which the volume is detached. :type ex_instance_id: ``str`` """ params = {'Action': 'DetachDisk', 'DiskId': volume.id} if ex_instance_id: params['InstanceId'] = ex_instance_id else: volumes = self.list_volumes(ex_volume_ids=[volume.id]) if len(volumes) != 1: raise AttributeError('could not find the instance id ' 'the volume %s attached to, ' 'ex_instance_id is required.' % volume.id) params['InstanceId'] = volumes[0].extra['instance_id'] resp = self.connection.request(self.path, params) return resp.success() def destroy_volume(self, volume): params = {'Action': 'DeleteDisk', 'DiskId': volume.id} volumes = self.list_volumes(ex_volume_ids=[volume.id]) if len(volumes) != 1: raise LibcloudError('could not find the volume with id %s.' % volume.id, driver=self) if volumes[0].state != StorageVolumeState.AVAILABLE: raise LibcloudError('only volume in AVAILABLE state could be ' 'destroyed.', driver=self) resp = self.connection.request(self.path, params) return resp.success() def destroy_volume_snapshot(self, snapshot): params = {'Action': 'DeleteSnapshot'} if snapshot and isinstance(snapshot, VolumeSnapshot): params['SnapshotId'] = snapshot.id else: raise AttributeError('snapshot is required and must be a ' 'VolumeSnapshot') resp = self.connection.request(self.path, params) return resp.success() ## # Image management methods ## def list_images(self, location=None, ex_image_ids=None, ex_filters=None): """ List images on a provider. @inherits :class:`NodeDriver.list_images` :keyword ex_image_ids: a list of image ids to filter the images to be returned. :type ex_image_ids: ``list`` of ``str`` :keyword ex_filters: image attribute and value pairs to filter images. Only the image which matchs all the pairs will be returned. If the filter attribute need a json array value, use ``list`` object, the driver will convert it. :type ex_filters: ``dict`` """ if location and isinstance(location, NodeLocation): region = location.id else: region = self.region params = {'Action': 'DescribeImages', 'RegionId': region} if ex_image_ids: if isinstance(ex_image_ids, list): params['ImageId'] = ','.join(ex_image_ids) else: raise AttributeError('ex_image_ids should be a list of ' 'image ids') if ex_filters and isinstance(ex_filters, dict): for key in ex_filters.keys(): params[key] = ex_filters[key] def _parse_response(resp_body): image_elements = findall(resp_body, 'Images/Image', namespace=self.namespace) images = [self._to_image(each) for each in image_elements] return images return self._request_multiple_pages(self.path, params, _parse_response) def create_image(self, node, name, description=None, ex_snapshot_id=None, ex_image_version=None, ex_client_token=None): """ Creates an image from a system disk snapshot. @inherits :class:`NodeDriver.create_image` :keyword ex_snapshot_id: the id of the snapshot to create the image. (required) :type ex_snapshot_id: ``str`` :keyword ex_image_version: the version number of the image :type ex_image_version: ``str`` :keyword ex_client_token: a token generated by client to identify each request. :type ex_client_token: ``str`` """ params = {'Action': 'CreateImage', 'RegionId': self.region} if name: params['ImageName'] = name if description: params['Description'] = description if ex_snapshot_id: params['SnapshotId'] = ex_snapshot_id else: raise AttributeError('ex_snapshot_id is required') if ex_image_version: params['ImageVersion'] = ex_image_version if ex_client_token: params['ClientToken'] = ex_client_token resp = self.connection.request(self.path, params) image_id = findtext(resp.object, 'ImageId', namespace=self.namespace) return self.get_image(image_id=image_id) def delete_image(self, node_image): params = {'Action': 'DeleteImage', 'RegionId': self.region, 'ImageId': node_image.id} resp = self.connection.request(self.path, params) return resp.success() def get_image(self, image_id, ex_region_id=None): if ex_region_id: region = ex_region_id else: region = self.region location = NodeLocation(id=region, name=None, country=None, driver=self) images = self.list_images(location, ex_image_ids=[image_id]) if len(images) != 1: raise LibcloudError('could not find the image with id %s' % image_id, driver=self) return images[0] def copy_image(self, source_region, node_image, name, description=None, ex_destination_region_id=None, ex_client_token=None): """ Copies an image from a source region to the destination region. If not provide a destination region, default to the current region. @inherits :class:`NodeDriver.copy_image` :keyword ex_destination_region_id: id of the destination region :type ex_destination_region_id: ``str`` :keyword ex_client_token: a token generated by client to identify each request. :type ex_client_token: ``str`` """ params = {'Action': 'CopyImage', 'RegionId': source_region, 'ImageId': node_image.id} if ex_destination_region_id is not None: params['DestinationRegionId'] = ex_destination_region_id else: params['DestinationRegionId'] = self.region if name: params['DestinationImageName'] = name if description: params['DestinationDescription'] = description if ex_client_token: params['ClientToken'] = ex_client_token resp = self.connection.request(self.path, params) image_id = findtext(resp.object, 'ImageId', namespace=self.namespace) return self.get_image(image_id=image_id) def create_public_ip(self, instance_id): """ Create public ip. :keyword instance_id: instance id for allocating public ip. :type instance_id: ``str`` :return public ip :rtype ``str`` """ params = {'Action': 'AllocatePublicIpAddress', 'InstanceId': instance_id} resp = self.connection.request(self.path, params=params) return findtext(resp.object, 'IpAddress', namespace=self.namespace) def _to_nodes(self, object): """ Convert response to Node object list :param object: parsed response object :return: a list of ``Node`` :rtype: ``list`` """ node_elements = findall(object, 'Instances/Instance', self.namespace) return [self._to_node(el) for el in node_elements] def _to_node(self, instance): """ Convert an InstanceAttributesType object to ``Node`` object :param instance: a xml element represents an instance :return: a ``Node`` object :rtype: ``Node`` """ _id = findtext(element=instance, xpath='InstanceId', namespace=self.namespace) name = findtext(element=instance, xpath='InstanceName', namespace=self.namespace) instance_status = findtext(element=instance, xpath='Status', namespace=self.namespace) state = self.NODE_STATE_MAPPING.get(instance_status, NodeState.UNKNOWN) def _get_ips(ip_address_els): return [each.text for each in ip_address_els] public_ip_els = findall(element=instance, xpath='PublicIpAddress/IpAddress', namespace=self.namespace) public_ips = _get_ips(public_ip_els) private_ip_els = findall(element=instance, xpath='InnerIpAddress/IpAddress', namespace=self.namespace) private_ips = _get_ips(private_ip_els) # Extra properties extra = self._get_extra_dict(instance, RESOURCE_EXTRA_ATTRIBUTES_MAP['node']) extra['vpc_attributes'] = self._get_vpc_attributes(instance) extra['eip_address'] = self._get_eip_address(instance) extra['operation_locks'] = self._get_operation_locks(instance) node = Node(id=_id, name=name, state=state, public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver, extra=extra) return node def _get_extra_dict(self, element, mapping): """ Extract attributes from the element based on rules provided in the mapping dictionary. :param element: Element to parse the values from. :type element: xml.etree.ElementTree.Element. :param mapping: Dictionary with the extra layout :type node: :class:`Node` :rtype: ``dict`` """ extra = {} for attribute, values in mapping.items(): transform_func = values['transform_func'] value = findattr(element=element, xpath=values['xpath'], namespace=self.namespace) if value: try: extra[attribute] = transform_func(value) except Exception: extra[attribute] = None else: extra[attribute] = value return extra def _get_internet_related_params(self, ex_internet_charge_type, ex_internet_max_bandwidth_in, ex_internet_max_bandwidth_out): params = {} if ex_internet_charge_type: params['InternetChargeType'] = ex_internet_charge_type if ex_internet_charge_type.lower() == 'paybytraffic': if ex_internet_max_bandwidth_out: params['InternetMaxBandwidthOut'] = \ ex_internet_max_bandwidth_out else: raise AttributeError('ex_internet_max_bandwidth_out is ' 'mandatory for PayByTraffic internet' ' charge type.') elif ex_internet_max_bandwidth_out: params['InternetMaxBandwidthOut'] = \ ex_internet_max_bandwidth_out if ex_internet_max_bandwidth_in: params['InternetMaxBandwidthIn'] = \ ex_internet_max_bandwidth_in return params def _get_system_disk(self, ex_system_disk): if not isinstance(ex_system_disk, dict): raise AttributeError('ex_system_disk is not a dict') sys_disk_dict = ex_system_disk key_base = 'SystemDisk.' # TODO(samsong8610): Use a type instead of dict mappings = {'category': 'Category', 'disk_name': 'DiskName', 'description': 'Description'} params = {} for attr in mappings.keys(): if attr in sys_disk_dict: params[key_base + mappings[attr]] = sys_disk_dict[attr] return params def _get_data_disks(self, ex_data_disks): if isinstance(ex_data_disks, dict): data_disks = [ex_data_disks] elif isinstance(ex_data_disks, list): data_disks = ex_data_disks else: raise AttributeError('ex_data_disks should be a list of dict') # TODO(samsong8610): Use a type instead of dict mappings = {'size': 'Size', 'category': 'Category', 'snapshot_id': 'SnapshotId', 'disk_name': 'DiskName', 'description': 'Description', 'device': 'Device', 'delete_with_instance': 'DeleteWithInstance'} params = {} for idx, disk in enumerate(data_disks): key_base = 'DataDisk.{0}.'.format(idx + 1) for attr in mappings.keys(): if attr in disk: if attr == 'delete_with_instance': # Convert bool value to str value = str(disk[attr]).lower() else: value = disk[attr] params[key_base + mappings[attr]] = value return params def _get_vpc_attributes(self, instance): vpcs = findall(instance, xpath='VpcAttributes', namespace=self.namespace) if len(vpcs) <= 0: return None return self._get_extra_dict( vpcs[0], RESOURCE_EXTRA_ATTRIBUTES_MAP['vpc_attributes']) def _get_eip_address(self, instance): eips = findall(instance, xpath='EipAddress', namespace=self.namespace) if len(eips) <= 0: return None return self._get_extra_dict( eips[0], RESOURCE_EXTRA_ATTRIBUTES_MAP['eip_address_associate']) def _get_operation_locks(self, instance): locks = findall(instance, xpath='OperationLocks', namespace=self.namespace) if len(locks) <= 0: return None return self._get_extra_dict( locks[0], RESOURCE_EXTRA_ATTRIBUTES_MAP['operation_locks']) def _wait_until_state(self, nodes, state, wait_period=3, timeout=600): """ Block until the provided nodes are in the desired state. :param nodes: List of nodes to wait for :type nodes: ``list`` of :class:`.Node` :param state: desired state :type state: ``NodeState`` :param wait_period: How many seconds to wait between each loop iteration. (default is 3) :type wait_period: ``int`` :param timeout: How many seconds to wait before giving up. (default is 600) :type timeout: ``int`` :return: if the nodes are in the desired state. :rtype: ``bool`` """ start = time.time() end = start + timeout node_ids = [node.id for node in nodes] while(time.time() < end): matched_nodes = self.list_nodes(ex_node_ids=node_ids) if len(matched_nodes) > len(node_ids): found_ids = [node.id for node in matched_nodes] msg = ('found multiple nodes with same ids, ' 'desired ids: %(ids)s, found ids: %(found_ids)s' % {'ids': node_ids, 'found_ids': found_ids}) raise LibcloudError(value=msg, driver=self) desired_nodes = [node for node in matched_nodes if node.state == state] if len(desired_nodes) == len(node_ids): return True else: time.sleep(wait_period) continue raise LibcloudError(value='Timed out after %s seconds' % (timeout), driver=self) def _to_volume(self, element): _id = findtext(element, 'DiskId', namespace=self.namespace) name = findtext(element, 'DiskName', namespace=self.namespace) size = int(findtext(element, 'Size', namespace=self.namespace)) status_str = findtext(element, 'Status', namespace=self.namespace) status = self.VOLUME_STATE_MAPPING.get(status_str, StorageVolumeState.UNKNOWN) extra = self._get_extra_dict(element, RESOURCE_EXTRA_ATTRIBUTES_MAP['volume']) extra['operation_locks'] = self._get_operation_locks(element) return StorageVolume(_id, name, size, self, state=status, extra=extra) def _list_to_json_array(self, value): try: return json.dumps(value) except Exception: raise AttributeError('could not convert list to json array') def _to_snapshot(self, element): _id = findtext(element, 'SnapshotId', namespace=self.namespace) created = findtext(element, 'CreationTime', namespace=self.namespace) status_str = findtext(element, 'Status', namespace=self.namespace) state = self.SNAPSHOT_STATE_MAPPING.get(status_str, VolumeSnapshotState.UNKNOWN) extra = self._get_extra_dict(element, RESOURCE_EXTRA_ATTRIBUTES_MAP['snapshot']) return VolumeSnapshot(id=_id, driver=self, extra=extra, created=created, state=state) def _to_size(self, element): _id = findtext(element, 'InstanceTypeId', namespace=self.namespace) ram = float(findtext(element, 'MemorySize', namespace=self.namespace)) extra = {} extra['cpu_core_count'] = int(findtext(element, 'CpuCoreCount', namespace=self.namespace)) extra['instance_type_family'] = findtext(element, 'InstanceTypeFamily', namespace=self.namespace) return NodeSize(id=_id, name=_id, ram=ram, disk=None, bandwidth=None, price=None, driver=self, extra=extra) def _to_location(self, element): _id = findtext(element, 'RegionId', namespace=self.namespace) localname = findtext(element, 'LocalName', namespace=self.namespace) return NodeLocation(id=_id, name=localname, country=None, driver=self) def _to_image(self, element): _id = findtext(element, 'ImageId', namespace=self.namespace) name = findtext(element, 'ImageName', namespace=self.namespace) extra = self._get_extra_dict(element, RESOURCE_EXTRA_ATTRIBUTES_MAP['image']) extra['disk_device_mappings'] = self._get_disk_device_mappings( element.find('DiskDeviceMappings')) return NodeImage(id=_id, name=name, driver=self, extra=extra) def _get_disk_device_mappings(self, element): if element is None: return None mapping_element = element.find('DiskDeviceMapping') if mapping_element is not None: return self._get_extra_dict( mapping_element, RESOURCE_EXTRA_ATTRIBUTES_MAP['disk_device_mapping']) return None def _to_security_group(self, element): _id = findtext(element, 'SecurityGroupId', namespace=self.namespace) name = findtext(element, 'SecurityGroupName', namespace=self.namespace) description = findtext(element, 'Description', namespace=self.namespace) vpc_id = findtext(element, 'VpcId', namespace=self.namespace) creation_time = findtext(element, 'CreationTime', namespace=self.namespace) return ECSSecurityGroup(_id, name, description=description, driver=self, vpc_id=vpc_id, creation_time=creation_time) def _to_security_group_attribute(self, element): ip_protocol = findtext(element, 'IpProtocol', namespace=self.namespace) port_range = findtext(element, 'PortRange', namespace=self.namespace) source_group_id = findtext(element, 'SourceGroupId', namespace=self.namespace) policy = findtext(element, 'Policy', namespace=self.namespace) nic_type = findtext(element, 'NicType', namespace=self.namespace) return ECSSecurityGroupAttribute(ip_protocol=ip_protocol, port_range=port_range, source_group_id=source_group_id, policy=policy, nic_type=nic_type) def _to_zone(self, element): _id = findtext(element, 'ZoneId', namespace=self.namespace) local_name = findtext(element, 'LocalName', namespace=self.namespace) resource_types = findall(element, 'AvailableResourceCreation/ResourceTypes', namespace=self.namespace) instance_types = findall(element, 'AvailableInstanceTypes/InstanceTypes', namespace=self.namespace) disk_categories = findall(element, 'AvailableDiskCategories/DiskCategories', namespace=self.namespace) def _text(element): return element.text return ECSZone(id=_id, name=local_name, driver=self, available_resource_types=list( map(_text, resource_types)), available_instance_types=list( map(_text, instance_types)), available_disk_categories=list( map(_text, disk_categories))) def _get_pagination(self, element): page_number = int(findtext(element, 'PageNumber')) total_count = int(findtext(element, 'TotalCount')) page_size = int(findtext(element, 'PageSize')) return Pagination(total=total_count, size=page_size, current=page_number) def _request_multiple_pages(self, path, params, parse_func): """ Request all resources by multiple pages. :param path: the resource path :type path: ``str`` :param params: the query parameters :type params: ``dict`` :param parse_func: the function object to parse the response body :param type: ``function`` :return: list of resource object, if not found any, return [] :rtype: ``list`` """ results = [] while True: one_page = self.connection.request(path, params).object resources = parse_func(one_page) results += resources pagination = self._get_pagination(one_page) if pagination.next() is None: break params.update(pagination.to_dict()) return results apache-libcloud-2.8.0/libcloud/compute/drivers/elastichosts.py0000664000175000017500000001625713600144066024444 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ ElasticHosts Driver """ from libcloud.compute.types import Provider from libcloud.compute.drivers.elasticstack import ElasticStackBaseNodeDriver # API end-points API_ENDPOINTS = { 'lon-p': { 'name': 'London Peer 1', 'country': 'United Kingdom', 'host': 'api-lon-p.elastichosts.com' }, 'lon-b': { 'name': 'London BlueSquare', 'country': 'United Kingdom', 'host': 'api-lon-b.elastichosts.com' }, 'sat-p': { 'name': 'San Antonio Peer 1', 'country': 'United States', 'host': 'api-sat-p.elastichosts.com' }, 'lax-p': { 'name': 'Los Angeles Peer 1', 'country': 'United States', 'host': 'api-lax-p.elastichosts.com' }, 'sjc-c': { 'name': 'San Jose (Silicon Valley)', 'country': 'United States', 'host': 'api-sjc-c.elastichosts.com' }, 'tor-p': { 'name': 'Toronto Peer 1', 'country': 'Canada', 'host': 'api-tor-p.elastichosts.com' }, 'syd-y': { 'name': 'Sydney', 'country': 'Australia', 'host': 'api-syd-v.elastichosts.com' }, 'cn-1': { 'name': 'Hong Kong', 'country': 'China', 'host': 'api-hkg-e.elastichosts.com' } } # Default API end-point for the base connection class. DEFAULT_REGION = 'sat-p' # Retrieved from http://www.elastichosts.com/cloud-hosting/api STANDARD_DRIVES = { '38df0986-4d85-4b76-b502-3878ffc80161': { 'uuid': '38df0986-4d85-4b76-b502-3878ffc80161', 'description': 'CentOS Linux 5.5', 'size_gunzipped': '3GB', 'supports_deployment': True, }, '980cf63c-f21e-4382-997b-6541d5809629': { 'uuid': '980cf63c-f21e-4382-997b-6541d5809629', 'description': 'Debian Linux 5.0', 'size_gunzipped': '1GB', 'supports_deployment': True, }, 'aee5589a-88c3-43ef-bb0a-9cab6e64192d': { 'uuid': 'aee5589a-88c3-43ef-bb0a-9cab6e64192d', 'description': 'Ubuntu Linux 10.04', 'size_gunzipped': '1GB', 'supports_deployment': True, }, '62f512cd-82c7-498e-88d8-a09ac2ef20e7': { 'uuid': '62f512cd-82c7-498e-88d8-a09ac2ef20e7', 'description': 'Ubuntu Linux 12.04', 'size_gunzipped': '1GB', 'supports_deployment': True, }, 'b9d0eb72-d273-43f1-98e3-0d4b87d372c0': { 'uuid': 'b9d0eb72-d273-43f1-98e3-0d4b87d372c0', 'description': 'Windows Web Server 2008', 'size_gunzipped': '13GB', 'supports_deployment': False, }, '30824e97-05a4-410c-946e-2ba5a92b07cb': { 'uuid': '30824e97-05a4-410c-946e-2ba5a92b07cb', 'description': 'Windows Web Server 2008 R2', 'size_gunzipped': '13GB', 'supports_deployment': False, }, '9ecf810e-6ad1-40ef-b360-d606f0444671': { 'uuid': '9ecf810e-6ad1-40ef-b360-d606f0444671', 'description': 'Windows Web Server 2008 R2 + SQL Server', 'size_gunzipped': '13GB', 'supports_deployment': False, }, '10a88d1c-6575-46e3-8d2c-7744065ea530': { 'uuid': '10a88d1c-6575-46e3-8d2c-7744065ea530', 'description': 'Windows Server 2008 Standard R2', 'size_gunzipped': '13GB', 'supports_deployment': False, }, '2567f25c-8fb8-45c7-95fc-bfe3c3d84c47': { 'uuid': '2567f25c-8fb8-45c7-95fc-bfe3c3d84c47', 'description': 'Windows Server 2008 Standard R2 + SQL Server', 'size_gunzipped': '13GB', 'supports_deployment': False, }, } class ElasticHostsException(Exception): def __str__(self): return self.args[0] def __repr__(self): return "" % (self.args[0]) class ElasticHostsNodeDriver(ElasticStackBaseNodeDriver): """ Node Driver class for ElasticHosts """ type = Provider.ELASTICHOSTS api_name = 'elastichosts' name = 'ElasticHosts' website = 'http://www.elastichosts.com/' features = {"create_node": ["generates_password"]} _standard_drives = STANDARD_DRIVES def __init__(self, key, secret=None, secure=True, host=None, port=None, region=DEFAULT_REGION, **kwargs): if hasattr(self, '_region'): region = getattr(self, '_region', None) if region not in API_ENDPOINTS: raise ValueError('Invalid region: %s' % (region)) self._host_argument_set = host is not None super(ElasticHostsNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) def _ex_connection_class_kwargs(self): """ Return the host value based on the user supplied region. """ kwargs = {} if not self._host_argument_set: kwargs['host'] = API_ENDPOINTS[self.region]['host'] return kwargs class ElasticHostsUK1NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the London Peer 1 end-point """ name = 'ElasticHosts (lon-p)' _region = 'lon-p' class ElasticHostsUK2NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the London Bluesquare end-point """ name = 'ElasticHosts (lon-b)' _region = 'lon-b' class ElasticHostsUS1NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the San Antonio Peer 1 end-point """ name = 'ElasticHosts (sat-p)' _region = 'sat-p' class ElasticHostsUS2NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the Los Angeles Peer 1 end-point """ name = 'ElasticHosts (lax-p)' _region = 'lax-p' class ElasticHostsUS3NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the San Jose (Silicon Valley) end-point """ name = 'ElasticHosts (sjc-c)' _region = 'sjc-c' class ElasticHostsCA1NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the Toronto Peer 1 end-point """ name = 'ElasticHosts (tor-p)' _region = 'tor-p' class ElasticHostsAU1NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the Sydney end-point """ name = 'ElasticHosts (syd-y)' _region = 'syd-y' class ElasticHostsCN1NodeDriver(ElasticHostsNodeDriver): """ ElasticHosts node driver for the Hong Kong end-point """ name = 'ElasticHosts (cn-1)' _region = 'cn-1' apache-libcloud-2.8.0/libcloud/compute/drivers/elasticstack.py0000664000175000017500000003757213600144066024414 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Base driver for the providers based on the ElasticStack platform - http://www.elasticstack.com. """ import re import time import base64 from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b try: import simplejson as json except ImportError: import json from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.common.types import InvalidCredsError from libcloud.compute.types import NodeState from libcloud.compute.base import NodeDriver, NodeSize, Node from libcloud.compute.base import NodeImage from libcloud.compute.deployment import ScriptDeployment, SSHKeyDeployment from libcloud.compute.deployment import MultiStepDeployment NODE_STATE_MAP = { 'active': NodeState.RUNNING, 'dead': NodeState.TERMINATED, 'dumped': NodeState.TERMINATED, } # Default timeout (in seconds) for the drive imaging process IMAGING_TIMEOUT = 10 * 60 # ElasticStack doesn't specify special instance types, so I just specified # some plans based on the other provider offerings. # # Basically for CPU any value between 500Mhz and 20000Mhz should work, # 256MB to 8192MB for ram and 1GB to 2TB for disk. INSTANCE_TYPES = { 'small': { 'id': 'small', 'name': 'Small instance', 'cpu': 2000, 'memory': 1700, 'disk': 160, 'bandwidth': None, }, 'medium': { 'id': 'medium', 'name': 'Medium instance', 'cpu': 3000, 'memory': 4096, 'disk': 500, 'bandwidth': None, }, 'large': { 'id': 'large', 'name': 'Large instance', 'cpu': 4000, 'memory': 7680, 'disk': 850, 'bandwidth': None, }, 'extra-large': { 'id': 'extra-large', 'name': 'Extra Large instance', 'cpu': 8000, 'memory': 8192, 'disk': 1690, 'bandwidth': None, }, 'high-cpu-medium': { 'id': 'high-cpu-medium', 'name': 'High-CPU Medium instance', 'cpu': 5000, 'memory': 1700, 'disk': 350, 'bandwidth': None, }, 'high-cpu-extra-large': { 'id': 'high-cpu-extra-large', 'name': 'High-CPU Extra Large instance', 'cpu': 20000, 'memory': 7168, 'disk': 1690, 'bandwidth': None, }, } class ElasticStackException(Exception): def __str__(self): return self.args[0] def __repr__(self): return "" % (self.args[0]) class ElasticStackResponse(JsonResponse): def success(self): if self.status == 401: raise InvalidCredsError() return 200 <= self.status <= 299 def parse_error(self): error_header = self.headers.get('x-elastic-error', '') return 'X-Elastic-Error: %s (%s)' % (error_header, self.body.strip()) class ElasticStackNodeSize(NodeSize): def __init__(self, id, name, cpu, ram, disk, bandwidth, price, driver): self.id = id self.name = name self.cpu = cpu self.ram = ram self.disk = disk self.bandwidth = bandwidth self.price = price self.driver = driver def __repr__(self): return (('') % (self.id, self.name, self.cpu, self.ram, self.disk, self.bandwidth, self.price, self.driver.name)) class ElasticStackBaseConnection(ConnectionUserAndKey): """ Base connection class for the ElasticStack driver """ host = None responseCls = ElasticStackResponse def add_default_headers(self, headers): headers['Accept'] = 'application/json' headers['Content-Type'] = 'application/json' headers['Authorization'] = \ ('Basic %s' % (base64.b64encode(b('%s:%s' % (self.user_id, self.key)))) .decode('utf-8')) return headers class ElasticStackBaseNodeDriver(NodeDriver): website = 'http://www.elasticstack.com' connectionCls = ElasticStackBaseConnection features = {"create_node": ["generates_password"]} # Dynamically populated by sub-classes _standard_drives = {} def reboot_node(self, node): # Reboots the node response = self.connection.request( action='/servers/%s/reset' % (node.id), method='POST' ) return response.status == 204 def destroy_node(self, node): # Kills the server immediately response = self.connection.request( action='/servers/%s/destroy' % (node.id), method='POST' ) return response.status == 204 def list_images(self, location=None): # Returns a list of available pre-installed system drive images images = [] for key, value in self._standard_drives.items(): image = NodeImage( id=value['uuid'], name=value['description'], driver=self.connection.driver, extra={ 'size_gunzipped': value['size_gunzipped'] } ) images.append(image) return images def list_sizes(self, location=None): sizes = [] for key, value in INSTANCE_TYPES.items(): size = ElasticStackNodeSize( id=value['id'], name=value['name'], cpu=value['cpu'], ram=value['memory'], disk=value['disk'], bandwidth=value['bandwidth'], price=self._get_size_price(size_id=value['id']), driver=self.connection.driver ) sizes.append(size) return sizes def list_nodes(self): # Returns a list of active (running) nodes response = self.connection.request(action='/servers/info').object nodes = [] for data in response: node = self._to_node(data) nodes.append(node) return nodes def create_node(self, name, size, image, smp='auto', nic_model='e1000', vnc_password=None, drive_type='hdd'): """Creates an ElasticStack instance @inherits: :class:`NodeDriver.create_node` :keyword name: String with a name for this new node (required) :type name: ``str`` :keyword smp: Number of virtual processors or None to calculate based on the cpu speed :type smp: ``int`` :keyword nic_model: e1000, rtl8139 or virtio (if not specified, e1000 is used) :type nic_model: ``str`` :keyword vnc_password: If set, the same password is also used for SSH access with user toor, otherwise VNC access is disabled and no SSH login is possible. :type vnc_password: ``str`` """ ssh_password = vnc_password if nic_model not in ('e1000', 'rtl8139', 'virtio'): raise ElasticStackException('Invalid NIC model specified') # check that drive size is not smaller than pre installed image size # First we create a drive with the specified size drive_data = {} drive_data.update({'name': name, 'size': '%sG' % (size.disk)}) response = self.connection.request(action='/drives/create', data=json.dumps(drive_data), method='POST').object if not response: raise ElasticStackException('Drive creation failed') drive_uuid = response['drive'] # Then we image the selected pre-installed system drive onto it response = self.connection.request( action='/drives/%s/image/%s/gunzip' % (drive_uuid, image.id), method='POST' ) if response.status not in (200, 204): raise ElasticStackException('Drive imaging failed') # We wait until the drive is imaged and then boot up the node # (in most cases, the imaging process shouldn't take longer # than a few minutes) response = self.connection.request( action='/drives/%s/info' % (drive_uuid) ).object imaging_start = time.time() while 'imaging' in response: response = self.connection.request( action='/drives/%s/info' % (drive_uuid) ).object elapsed_time = time.time() - imaging_start if ('imaging' in response and elapsed_time >= IMAGING_TIMEOUT): raise ElasticStackException('Drive imaging timed out') time.sleep(1) node_data = {} node_data.update({'name': name, 'cpu': size.cpu, 'mem': size.ram, 'ide:0:0': drive_uuid, 'boot': 'ide:0:0', 'smp': smp}) node_data.update({'nic:0:model': nic_model, 'nic:0:dhcp': 'auto'}) if vnc_password: node_data.update({'vnc': 'auto', 'vnc:password': vnc_password}) response = self.connection.request( action='/servers/create', data=json.dumps(node_data), method='POST' ).object if isinstance(response, list): nodes = [self._to_node(node, ssh_password) for node in response] else: nodes = self._to_node(response, ssh_password) return nodes # Extension methods def ex_set_node_configuration(self, node, **kwargs): """ Changes the configuration of the running server :param node: Node which should be used :type node: :class:`Node` :param kwargs: keyword arguments :type kwargs: ``dict`` :rtype: ``bool`` """ valid_keys = ('^name$', '^parent$', '^cpu$', '^smp$', '^mem$', '^boot$', '^nic:0:model$', '^nic:0:dhcp', '^nic:1:model$', '^nic:1:vlan$', '^nic:1:mac$', '^vnc:ip$', '^vnc:password$', '^vnc:tls', '^ide:[0-1]:[0-1](:media)?$', '^scsi:0:[0-7](:media)?$', '^block:[0-7](:media)?$') invalid_keys = [] keys = list(kwargs.keys()) for key in keys: matches = False for regex in valid_keys: if re.match(regex, key): matches = True break if not matches: invalid_keys.append(key) if invalid_keys: raise ElasticStackException( 'Invalid configuration key specified: %s' % (',' .join(invalid_keys)) ) response = self.connection.request( action='/servers/%s/set' % (node.id), data=json.dumps(kwargs), method='POST' ) return (response.status == httplib.OK and response.body != '') def deploy_node(self, **kwargs): """ Create a new node, and start deployment. @inherits: :class:`NodeDriver.deploy_node` :keyword enable_root: If true, root password will be set to vnc_password (this will enable SSH access) and default 'toor' account will be deleted. :type enable_root: ``bool`` """ image = kwargs['image'] vnc_password = kwargs.get('vnc_password', None) enable_root = kwargs.get('enable_root', False) if not vnc_password: raise ValueError('You need to provide vnc_password argument ' 'if you want to use deployment') if (image in self._standard_drives and not self._standard_drives[image]['supports_deployment']): raise ValueError('Image %s does not support deployment' % (image.id)) if enable_root: script = ("unset HISTFILE;" "echo root:%s | chpasswd;" "sed -i '/^toor.*$/d' /etc/passwd /etc/shadow;" "history -c") % vnc_password root_enable_script = ScriptDeployment(script=script, delete=True) deploy = kwargs.get('deploy', None) if deploy: if (isinstance(deploy, ScriptDeployment) or isinstance(deploy, SSHKeyDeployment)): deployment = MultiStepDeployment([deploy, root_enable_script]) elif isinstance(deploy, MultiStepDeployment): deployment = deploy deployment.add(root_enable_script) else: deployment = root_enable_script kwargs['deploy'] = deployment if not kwargs.get('ssh_username', None): kwargs['ssh_username'] = 'toor' return super(ElasticStackBaseNodeDriver, self).deploy_node(**kwargs) def ex_shutdown_node(self, node): """ Sends the ACPI power-down event :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ response = self.connection.request( action='/servers/%s/shutdown' % (node.id), method='POST' ) return response.status == 204 def ex_destroy_drive(self, drive_uuid): """ Deletes a drive :param drive_uuid: Drive uuid which should be used :type drive_uuid: ``str`` :rtype: ``bool`` """ response = self.connection.request( action='/drives/%s/destroy' % (drive_uuid), method='POST' ) return response.status == 204 # Helper methods def _to_node(self, data, ssh_password=None): try: state = NODE_STATE_MAP[data['status']] except KeyError: state = NodeState.UNKNOWN if 'nic:0:dhcp:ip' in data: if isinstance(data['nic:0:dhcp:ip'], list): public_ip = data['nic:0:dhcp:ip'] else: public_ip = [data['nic:0:dhcp:ip']] else: public_ip = [] extra = {'cpu': data['cpu'], 'mem': data['mem']} if 'started' in data: extra['started'] = data['started'] if 'smp' in data: extra['smp'] = data['smp'] if 'vnc:ip' in data: extra['vnc:ip'] = data['vnc:ip'] if 'vnc:password' in data: extra['vnc:password'] = data['vnc:password'] boot_device = data['boot'] if isinstance(boot_device, list): for device in boot_device: extra[device] = data[device] else: extra[boot_device] = data[boot_device] if ssh_password: extra.update({'password': ssh_password}) node = Node(id=data['server'], name=data['name'], state=state, public_ips=public_ip, private_ips=None, driver=self.connection.driver, extra=extra) return node apache-libcloud-2.8.0/libcloud/compute/drivers/exoscale.py0000664000175000017500000000220713535474530023541 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.providers import Provider from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver __all__ = [ 'ExoscaleNodeDriver' ] class ExoscaleNodeDriver(CloudStackNodeDriver): type = Provider.EXOSCALE name = 'Exoscale' website = 'https://www.exoscale.com/' # API endpoint info host = 'api.exoscale.com' path = '/compute' apache-libcloud-2.8.0/libcloud/compute/drivers/gandi.py0000664000175000017500000006330113577507766023040 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Gandi driver for compute """ from datetime import datetime from libcloud.common.gandi import BaseGandiDriver, GandiException,\ NetworkInterface, IPAddress, Disk from libcloud.compute.base import KeyPair from libcloud.compute.base import StorageVolume from libcloud.compute.types import NodeState, Provider from libcloud.compute.base import Node, NodeDriver from libcloud.compute.base import NodeSize, NodeImage, NodeLocation NODE_STATE_MAP = { 'running': NodeState.RUNNING, 'halted': NodeState.TERMINATED, 'paused': NodeState.TERMINATED, 'locked': NodeState.TERMINATED, 'being_created': NodeState.PENDING, 'invalid': NodeState.UNKNOWN, 'legally_locked': NodeState.PENDING, 'deleted': NodeState.TERMINATED } NODE_PRICE_HOURLY_USD = 0.02 INSTANCE_TYPES = { 'small': { 'id': 'small', 'name': 'Small instance', 'cpu': 1, 'memory': 256, 'disk': 3, 'bandwidth': 10240, }, 'medium': { 'id': 'medium', 'name': 'Medium instance', 'cpu': 1, 'memory': 1024, 'disk': 20, 'bandwidth': 10240, }, 'large': { 'id': 'large', 'name': 'Large instance', 'cpu': 2, 'memory': 2048, 'disk': 50, 'bandwidth': 10240, }, 'x-large': { 'id': 'x-large', 'name': 'Extra Large instance', 'cpu': 4, 'memory': 4096, 'disk': 100, 'bandwidth': 10240, }, } class GandiNodeDriver(BaseGandiDriver, NodeDriver): """ Gandi node driver """ api_name = 'gandi' friendly_name = 'Gandi.net' website = 'http://www.gandi.net/' country = 'FR' type = Provider.GANDI # TODO : which features to enable ? features = {} def __init__(self, *args, **kwargs): """ @inherits: :class:`NodeDriver.__init__` """ super(GandiNodeDriver, self).__init__(*args, **kwargs) def _resource_info(self, type, id): try: obj = self.connection.request('hosting.%s.info' % type, int(id)) return obj.object except Exception as e: raise GandiException(1003, e) def _node_info(self, id): return self._resource_info('vm', id) def _volume_info(self, id): return self._resource_info('disk', id) # Generic methods for driver def _to_node(self, vm): return Node( id=vm['id'], name=vm['hostname'], state=NODE_STATE_MAP.get( vm['state'], NodeState.UNKNOWN ), public_ips=vm.get('ips', []), private_ips=[], driver=self, extra={ 'ai_active': vm.get('ai_active'), 'datacenter_id': vm.get('datacenter_id'), 'description': vm.get('description') } ) def _to_nodes(self, vms): return [self._to_node(v) for v in vms] def _to_volume(self, disk): extra = {'can_snapshot': disk['can_snapshot']} return StorageVolume( id=disk['id'], name=disk['name'], size=int(disk['size']), driver=self, extra=extra) def _to_volumes(self, disks): return [self._to_volume(d) for d in disks] def list_nodes(self): """ Return a list of nodes in the current zone or all zones. :return: List of Node objects :rtype: ``list`` of :class:`Node` """ vms = self.connection.request('hosting.vm.list').object ips = self.connection.request('hosting.ip.list').object for vm in vms: vm['ips'] = [] for ip in ips: if vm['ifaces_id'][0] == ip['iface_id']: ip = ip.get('ip', None) if ip: vm['ips'].append(ip) nodes = self._to_nodes(vms) return nodes def ex_get_node(self, node_id): """ Return a Node object based on a node id. :param name: The ID of the node :type name: ``int`` :return: A Node object for the node :rtype: :class:`Node` """ vm = self.connection.request('hosting.vm.info', int(node_id)).object ips = self.connection.request('hosting.ip.list').object vm['ips'] = [] for ip in ips: if vm['ifaces_id'][0] == ip['iface_id']: ip = ip.get('ip', None) if ip: vm['ips'].append(ip) node = self._to_node(vm) return node def reboot_node(self, node): """ Reboot a node. :param node: Node to be rebooted :type node: :class:`Node` :return: True if successful, False if not :rtype: ``bool`` """ op = self.connection.request('hosting.vm.reboot', int(node.id)) self._wait_operation(op.object['id']) vm = self._node_info(int(node.id)) if vm['state'] == 'running': return True return False def destroy_node(self, node): """ Destroy a node. :param node: Node object to destroy :type node: :class:`Node` :return: True if successful :rtype: ``bool`` """ vm = self._node_info(node.id) if vm['state'] == 'running': # Send vm_stop and wait for accomplish op_stop = self.connection.request('hosting.vm.stop', int(node.id)) if not self._wait_operation(op_stop.object['id']): raise GandiException(1010, 'vm.stop failed') # Delete op = self.connection.request('hosting.vm.delete', int(node.id)) if self._wait_operation(op.object['id']): return True return False def deploy_node(self, **kwargs): """ deploy_node is not implemented for gandi driver :rtype: ``bool`` """ raise NotImplementedError( 'deploy_node not implemented for gandi driver') def create_node(self, name, size, image, location=None, login=None, password=None, inet_family=4, keypairs=None): """ Create a new Gandi node :keyword name: String with a name for this new node (required) :type name: ``str`` :keyword image: OS Image to boot on node. (required) :type image: :class:`NodeImage` :keyword location: Which data center to create a node in. If empty, undefined behavior will be selected. (optional) :type location: :class:`NodeLocation` :keyword size: The size of resources allocated to this node. (required) :type size: :class:`NodeSize` :keyword login: user name to create for login on machine (required) :type login: ``str`` :keyword password: password for user that'll be created (required) :type password: ``str`` :keyword inet_family: version of ip to use, default 4 (optional) :type inet_family: ``int`` :keyword keypairs: IDs of keypairs or Keypairs object :type keypairs: list of ``int`` or :class:`.KeyPair` :rtype: :class:`Node` """ keypairs = keypairs or [] if not login and not keypairs: raise GandiException(1020, "Login and password or ssh keypair " "must be defined for node creation") if location and isinstance(location, NodeLocation): dc_id = int(location.id) else: raise GandiException( 1021, 'location must be a subclass of NodeLocation') if not size and not isinstance(size, NodeSize): raise GandiException( 1022, 'size must be a subclass of NodeSize') keypair_ids = [ k if isinstance(k, int) else k.extra['id'] for k in keypairs ] # If size name is in INSTANCE_TYPE we use new rating model instance = INSTANCE_TYPES.get(size.id) cores = instance['cpu'] if instance else int(size.id) src_disk_id = int(image.id) disk_spec = { 'datacenter_id': dc_id, 'name': 'disk_%s' % name } vm_spec = { 'datacenter_id': dc_id, 'hostname': name, 'memory': int(size.ram), 'cores': cores, 'bandwidth': int(size.bandwidth), 'ip_version': inet_family, } if login and password: vm_spec.update({ 'login': login, 'password': password, # TODO : use NodeAuthPassword }) if keypair_ids: vm_spec['keys'] = keypair_ids # Call create_from helper api. Return 3 operations : disk_create, # iface_create,vm_create (op_disk, op_iface, op_vm) = self.connection.request( 'hosting.vm.create_from', vm_spec, disk_spec, src_disk_id ).object # We wait for vm_create to finish if self._wait_operation(op_vm['id']): # after successful operation, get ip information # thru first interface node = self._node_info(op_vm['vm_id']) ifaces = node.get('ifaces') if len(ifaces) > 0: ips = ifaces[0].get('ips') if len(ips) > 0: node['ip'] = ips[0]['ip'] return self._to_node(node) return None def _to_image(self, img): return NodeImage( id=img['disk_id'], name=img['label'], driver=self.connection.driver ) def list_images(self, location=None): """ Return a list of image objects. :keyword location: Which data center to filter a images in. :type location: :class:`NodeLocation` :return: List of GCENodeImage objects :rtype: ``list`` of :class:`GCENodeImage` """ try: if location: filtering = {'datacenter_id': int(location.id)} else: filtering = {} images = self.connection.request('hosting.image.list', filtering) return [self._to_image(i) for i in images.object] except Exception as e: raise GandiException(1011, e) def _to_size(self, id, size): return NodeSize( id=id, name='%s cores' % id, ram=size['memory'], disk=size['disk'], bandwidth=size['bandwidth'], price=(self._get_size_price(size_id='1') * id), driver=self.connection.driver, ) def _instance_type_to_size(self, instance): return NodeSize( id=instance['id'], name=instance['name'], ram=instance['memory'], disk=instance['disk'], bandwidth=instance['bandwidth'], price=self._get_size_price(size_id=instance['id']), driver=self.connection.driver, ) def list_instance_type(self, location=None): return [self._instance_type_to_size(instance) for name, instance in INSTANCE_TYPES.items()] def list_sizes(self, location=None): """ Return a list of sizes (machineTypes) in a zone. :keyword location: Which data center to filter a sizes in. :type location: :class:`NodeLocation` or ``None`` :return: List of NodeSize objects :rtype: ``list`` of :class:`NodeSize` """ account = self.connection.request('hosting.account.info').object if account.get('rating_enabled'): # This account use new rating model return self.list_instance_type(location) # Look for available shares, and return a list of share_definition available_res = account['resources']['available'] if available_res['shares'] == 0: return None else: share_def = account['share_definition'] available_cores = available_res['cores'] # 0.75 core given when creating a server max_core = int(available_cores + 0.75) shares = [] if available_res['servers'] < 1: # No server quota, no way return shares for i in range(1, max_core + 1): share = {id: i} share_is_available = True for k in ['memory', 'disk', 'bandwidth']: if share_def[k] * i > available_res[k]: # We run out for at least one resource inside share_is_available = False else: share[k] = share_def[k] * i if share_is_available: nb_core = i shares.append(self._to_size(nb_core, share)) return shares def _to_loc(self, loc): return NodeLocation( id=loc['id'], name=loc['dc_code'], country=loc['country'], driver=self ) def list_locations(self): """ Return a list of locations (datacenters). :return: List of NodeLocation objects :rtype: ``list`` of :class:`NodeLocation` """ res = self.connection.request('hosting.datacenter.list') return [self._to_loc(l) for l in res.object] def list_volumes(self): """ Return a list of volumes. :return: A list of volume objects. :rtype: ``list`` of :class:`StorageVolume` """ res = self.connection.request('hosting.disk.list', {}) return self._to_volumes(res.object) def ex_get_volume(self, volume_id): """ Return a Volume object based on a volume ID. :param volume_id: The ID of the volume :type volume_id: ``int`` :return: A StorageVolume object for the volume :rtype: :class:`StorageVolume` """ res = self.connection.request('hosting.disk.info', volume_id) return self._to_volume(res.object) def create_volume(self, size, name, location=None, snapshot=None): """ Create a volume (disk). :param size: Size of volume to create (in GB). :type size: ``int`` :param name: Name of volume to create :type name: ``str`` :keyword location: Location (zone) to create the volume in :type location: :class:`NodeLocation` or ``None`` :keyword snapshot: Snapshot to create image from :type snapshot: :class:`Snapshot` :return: Storage Volume object :rtype: :class:`StorageVolume` """ disk_param = { 'name': name, 'size': int(size), 'datacenter_id': int(location.id) } if snapshot: op = self.connection.request('hosting.disk.create_from', disk_param, int(snapshot.id)) else: op = self.connection.request('hosting.disk.create', disk_param) if self._wait_operation(op.object['id']): disk = self._volume_info(op.object['disk_id']) return self._to_volume(disk) return None def attach_volume(self, node, volume, device=None): """ Attach a volume to a node. :param node: The node to attach the volume to :type node: :class:`Node` :param volume: The volume to attach. :type volume: :class:`StorageVolume` :keyword device: Not used in this cloud. :type device: ``None`` :return: True if successful :rtype: ``bool`` """ op = self.connection.request('hosting.vm.disk_attach', int(node.id), int(volume.id)) if self._wait_operation(op.object['id']): return True return False def detach_volume(self, node, volume): """ Detaches a volume from a node. :param node: Node which should be used :type node: :class:`Node` :param volume: Volume to be detached :type volume: :class:`StorageVolume` :rtype: ``bool`` """ op = self.connection.request('hosting.vm.disk_detach', int(node.id), int(volume.id)) if self._wait_operation(op.object['id']): return True return False def destroy_volume(self, volume): """ Destroy a volume. :param volume: Volume object to destroy :type volume: :class:`StorageVolume` :return: True if successful :rtype: ``bool`` """ op = self.connection.request('hosting.disk.delete', int(volume.id)) if self._wait_operation(op.object['id']): return True return False def _to_iface(self, iface): ips = [] for ip in iface.get('ips', []): new_ip = IPAddress( ip['id'], NODE_STATE_MAP.get( ip['state'], NodeState.UNKNOWN ), ip['ip'], self.connection.driver, version=ip.get('version'), extra={'reverse': ip['reverse']} ) ips.append(new_ip) return NetworkInterface( iface['id'], NODE_STATE_MAP.get( iface['state'], NodeState.UNKNOWN ), mac_address=None, driver=self.connection.driver, ips=ips, node_id=iface.get('vm_id'), extra={'bandwidth': iface['bandwidth']}, ) def _to_ifaces(self, ifaces): return [self._to_iface(i) for i in ifaces] def ex_list_interfaces(self): """ Specific method to list network interfaces :rtype: ``list`` of :class:`GandiNetworkInterface` """ ifaces = self.connection.request('hosting.iface.list').object ips = self.connection.request('hosting.ip.list').object for iface in ifaces: iface['ips'] = list( filter(lambda i: i['iface_id'] == iface['id'], ips)) return self._to_ifaces(ifaces) def _to_disk(self, element): disk = Disk( id=element['id'], state=NODE_STATE_MAP.get( element['state'], NodeState.UNKNOWN ), name=element['name'], driver=self.connection.driver, size=element['size'], extra={'can_snapshot': element['can_snapshot']} ) return disk def _to_disks(self, elements): return [self._to_disk(el) for el in elements] def ex_list_disks(self): """ Specific method to list all disk :rtype: ``list`` of :class:`GandiDisk` """ res = self.connection.request('hosting.disk.list', {}) return self._to_disks(res.object) def ex_node_attach_disk(self, node, disk): """ Specific method to attach a disk to a node :param node: Node which should be used :type node: :class:`Node` :param disk: Disk which should be used :type disk: :class:`GandiDisk` :rtype: ``bool`` """ op = self.connection.request('hosting.vm.disk_attach', int(node.id), int(disk.id)) if self._wait_operation(op.object['id']): return True return False def ex_node_detach_disk(self, node, disk): """ Specific method to detach a disk from a node :param node: Node which should be used :type node: :class:`Node` :param disk: Disk which should be used :type disk: :class:`GandiDisk` :rtype: ``bool`` """ op = self.connection.request('hosting.vm.disk_detach', int(node.id), int(disk.id)) if self._wait_operation(op.object['id']): return True return False def ex_node_attach_interface(self, node, iface): """ Specific method to attach an interface to a node :param node: Node which should be used :type node: :class:`Node` :param iface: Network interface which should be used :type iface: :class:`GandiNetworkInterface` :rtype: ``bool`` """ op = self.connection.request('hosting.vm.iface_attach', int(node.id), int(iface.id)) if self._wait_operation(op.object['id']): return True return False def ex_node_detach_interface(self, node, iface): """ Specific method to detach an interface from a node :param node: Node which should be used :type node: :class:`Node` :param iface: Network interface which should be used :type iface: :class:`GandiNetworkInterface` :rtype: ``bool`` """ op = self.connection.request('hosting.vm.iface_detach', int(node.id), int(iface.id)) if self._wait_operation(op.object['id']): return True return False def ex_snapshot_disk(self, disk, name=None): """ Specific method to make a snapshot of a disk :param disk: Disk which should be used :type disk: :class:`GandiDisk` :param name: Name which should be used :type name: ``str`` :rtype: ``bool`` """ if not disk.extra.get('can_snapshot'): raise GandiException(1021, 'Disk %s can\'t snapshot' % disk.id) if not name: suffix = datetime.today().strftime('%Y%m%d') name = 'snap_%s' % (suffix) op = self.connection.request( 'hosting.disk.create_from', {'name': name, 'type': 'snapshot', }, int(disk.id), ) if self._wait_operation(op.object['id']): return True return False def ex_update_disk(self, disk, new_size=None, new_name=None): """Specific method to update size or name of a disk WARNING: if a server is attached it'll be rebooted :param disk: Disk which should be used :type disk: :class:`GandiDisk` :param new_size: New size :type new_size: ``int`` :param new_name: New name :type new_name: ``str`` :rtype: ``bool`` """ params = {} if new_size: params.update({'size': new_size}) if new_name: params.update({'name': new_name}) op = self.connection.request('hosting.disk.update', int(disk.id), params) if self._wait_operation(op.object['id']): return True return False def _to_key_pair(self, data): key_pair = KeyPair(name=data['name'], fingerprint=data['fingerprint'], public_key=data.get('value', None), private_key=data.get('privatekey', None), driver=self, extra={'id': data['id']}) return key_pair def _to_key_pairs(self, data): return [self._to_key_pair(k) for k in data] def list_key_pairs(self): """ List registered key pairs. :return: A list of key par objects. :rtype: ``list`` of :class:`libcloud.compute.base.KeyPair` """ kps = self.connection.request('hosting.ssh.list').object return self._to_key_pairs(kps) def get_key_pair(self, name): """ Retrieve a single key pair. :param name: Name of the key pair to retrieve. :type name: ``str`` :rtype: :class:`.KeyPair` """ filter_params = {'name': name} kps = self.connection.request('hosting.ssh.list', filter_params).object return self._to_key_pair(kps[0]) def import_key_pair_from_string(self, name, key_material): """ Create a new key pair object. :param name: Key pair name. :type name: ``str`` :param key_material: Public key material. :type key_material: ``str`` :return: Imported key pair object. :rtype: :class:`.KeyPair` """ params = {'name': name, 'value': key_material} kp = self.connection.request('hosting.ssh.create', params).object return self._to_key_pair(kp) def delete_key_pair(self, key_pair): """ Delete an existing key pair. :param key_pair: Key pair object or ID. :type key_pair: :class.KeyPair` or ``int`` :return: True of False based on success of Keypair deletion :rtype: ``bool`` """ key_id = key_pair if isinstance(key_pair, int) \ else key_pair.extra['id'] success = self.connection.request('hosting.ssh.delete', key_id).object return success apache-libcloud-2.8.0/libcloud/compute/drivers/gce.py0000664000175000017500000136376213577507766022533 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Module for Google Compute Engine Driver. """ from __future__ import with_statement import datetime import time import sys from libcloud.common.base import LazyObject from libcloud.common.google import GoogleOAuth2Credential from libcloud.common.google import GoogleResponse from libcloud.common.google import GoogleBaseConnection from libcloud.common.google import GoogleBaseError from libcloud.common.google import ResourceNotFoundError from libcloud.common.google import ResourceExistsError from libcloud.common.types import LibcloudError from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation from libcloud.compute.base import NodeSize, StorageVolume, VolumeSnapshot from libcloud.compute.base import UuidMixin from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState from libcloud.utils.iso8601 import parse_date API_VERSION = 'v1' DEFAULT_TASK_COMPLETION_TIMEOUT = 180 def timestamp_to_datetime(timestamp): """ Return a datetime object that corresponds to the time in an RFC3339 timestamp. :param timestamp: RFC3339 timestamp string :type timestamp: ``str`` :return: Datetime object corresponding to timestamp :rtype: :class:`datetime.datetime` """ # We remove timezone offset and microseconds (Python 2.5 strptime doesn't # support %f) ts = datetime.datetime.strptime(timestamp[:-10], '%Y-%m-%dT%H:%M:%S') tz_hours = int(timestamp[-5:-3]) tz_mins = int(timestamp[-2:]) * int(timestamp[-6:-5] + '1') tz_delta = datetime.timedelta(hours=tz_hours, minutes=tz_mins) return ts + tz_delta class GCEResponse(GoogleResponse): pass class GCEConnection(GoogleBaseConnection): """ Connection class for the GCE driver. GCEConnection extends :class:`google.GoogleBaseConnection` for 3 reasons: 1. modify request_path for GCE URI. 2. Implement gce_params functionality described below. 3. Add request_aggregated_items method for making aggregated API calls. If the parameter gce_params is set to a dict prior to calling request(), the URL parameters will be updated to include those key/values FOR A SINGLE REQUEST. If the response contains a nextPageToken, gce_params['pageToken'] will be set to its value. This can be used to implement paging in list: >>> params, more_results = {'maxResults': 2}, True >>> while more_results: ... driver.connection.gce_params=params ... driver.ex_list_urlmaps() ... more_results = 'pageToken' in params ... [, ] [] """ host = 'www.googleapis.com' responseCls = GCEResponse def __init__(self, user_id, key, secure, auth_type=None, credential_file=None, project=None, **kwargs): super(GCEConnection, self).__init__( user_id, key, secure=secure, auth_type=auth_type, credential_file=credential_file, **kwargs) self.request_path = '/compute/%s/projects/%s' % (API_VERSION, project) self.gce_params = None def pre_connect_hook(self, params, headers): """ Update URL parameters with values from self.gce_params. @inherits: :class:`GoogleBaseConnection.pre_connect_hook` """ params, headers = super(GCEConnection, self).pre_connect_hook(params, headers) if self.gce_params: params.update(self.gce_params) return params, headers def request(self, *args, **kwargs): """ Perform request then do GCE-specific processing of URL params. @inherits: :class:`GoogleBaseConnection.request` """ response = super(GCEConnection, self).request(*args, **kwargs) # If gce_params has been set, then update the pageToken with the # nextPageToken so it can be used in the next request. if self.gce_params: if 'nextPageToken' in response.object: self.gce_params['pageToken'] = response.object['nextPageToken'] elif 'pageToken' in self.gce_params: del self.gce_params['pageToken'] self.gce_params = None return response def request_aggregated_items(self, api_name): """ Perform request(s) to obtain all results from 'api_name'. This method will make requests to the aggregated 'api_name' until all results are received. It will then, through a helper function, combine all results and return a single 'items' dictionary. :param api_name: Name of API to call. Consult API docs for valid names. :type api_name: ``str`` :return: dict in the format of the API response. format: { 'items': {'key': {api_name: []}} } ex: { 'items': {'zones/us-central1-a': {disks: []}} } :rtype: ``dict`` """ request_path = "/aggregated/%s" % api_name api_responses = [] params = {'maxResults': 500} more_results = True while more_results: self.gce_params = params response = self.request(request_path, method='GET').object if 'items' in response: api_responses.append(response) more_results = 'pageToken' in params return self._merge_response_items(api_name, api_responses) def _merge_response_items(self, list_name, response_list): """ Take a list of API responses ("item"-portion only) and combine them. Helper function to combine multiple aggegrated responses into a single dictionary that resembles an API response. Note: keys that don't have a 'list_name" key (including warnings) are omitted. :param list_name: Name of list in dict. Practically, this is the name of the API called (e.g. 'disks'). :type list_name: ``str`` :param response_list: list of API responses (e.g. resp['items']). Each entry in the list is the result of a single API call. Expected format is: [ { items: { key1: { api_name:[]}, key2: { api_name:[]} }}, ... ] :type response_list: ``dict`` :return: dict in the format of: { items: {key: {api_name:[]}, key2: {api_name:[]}} } ex: { items: { 'us-east1-a': {'disks': []}, 'us-east1-b': {'disks': []} }} :rtype: ``dict`` """ merged_items = {} for resp in response_list: if 'items' in resp: # example k would be a zone or region name # example v would be { "disks" : [], "otherkey" : "..." } for k, v in resp['items'].items(): if list_name in v: merged_items.setdefault(k, {}).setdefault( list_name, []) # Combine the list with the existing list. merged_items[k][list_name] += v[list_name] return {'items': merged_items} class GCEList(object): """ An Iterator that wraps list functions to provide additional features. GCE enforces a limit on the number of objects returned by a list operation, so users with more than 500 objects of a particular type will need to use filter(), page() or both. >>> l=GCEList(driver, driver.ex_list_urlmaps) >>> for sublist in l.filter('name eq ...-map').page(1): ... sublist ... [] [] One can create a GCEList manually, but it's slightly easier to use the ex_list() method of :class:`GCENodeDriver`. """ def __init__(self, driver, list_fn, **kwargs): """ :param driver: An initialized :class:``GCENodeDriver`` :type driver: :class:``GCENodeDriver`` :param list_fn: A bound list method from :class:`GCENodeDriver`. :type list_fn: ``instancemethod`` """ self.driver = driver self.list_fn = list_fn self.kwargs = kwargs self.params = {} def __iter__(self): list_fn = self.list_fn more_results = True while more_results: self.driver.connection.gce_params = self.params yield list_fn(**self.kwargs) more_results = 'pageToken' in self.params def __repr__(self): return '' % (self.list_fn.__name__, repr(self.params)) def filter(self, expression): """ Filter results of a list operation. GCE supports server-side filtering of resources returned by a list operation. Syntax of the filter expression is fully described in the GCE API reference doc, but in brief it is:: FIELD_NAME COMPARISON_STRING LITERAL_STRING where FIELD_NAME is the resource's property name, COMPARISON_STRING is 'eq' or 'ne', and LITERAL_STRING is a regular expression in RE2 syntax. >>> for sublist in l.filter('name eq ...-map'): ... sublist ... [, \ ] API reference: https://cloud.google.com/compute/docs/reference/latest/ RE2 syntax: https://github.com/google/re2/blob/master/doc/syntax.txt :param expression: Filter expression described above. :type expression: ``str`` :return: This :class:`GCEList` instance :rtype: :class:`GCEList` """ self.params['filter'] = expression return self def page(self, max_results=500): """ Limit the number of results by each iteration. This implements the paging functionality of the GCE list methods and returns this GCEList instance so that results can be chained: >>> for sublist in GCEList(driver, driver.ex_list_urlmaps).page(2): ... sublist ... [, \ ] [] :keyword max_results: Maximum number of results to return per iteration. Defaults to the GCE default of 500. :type max_results: ``int`` :return: This :class:`GCEList` instance :rtype: :class:`GCEList` """ self.params['maxResults'] = max_results return self class GCELicense(UuidMixin, LazyObject): """A GCE License used to track software usage in GCE nodes.""" def __init__(self, name, project, driver): UuidMixin.__init__(self) self.id = name self.name = name self.project = project self.driver = driver self.charges_use_fee = None # init in _request self.extra = None # init in _request self._request() def _request(self): # TODO(crunkleton@google.com): create new connection? or make # connection thread-safe? Saving, modifying, and restoring # driver.connection.request_path is really hacky and thread-unsafe. saved_request_path = self.driver.connection.request_path try: new_request_path = saved_request_path.replace(self.driver.project, self.project) self.driver.connection.request_path = new_request_path request = '/global/licenses/%s' % self.name response = self.driver.connection.request(request, method='GET').object except Exception: raise finally: # Restore the connection request_path self.driver.connection.request_path = saved_request_path self.extra = { 'selfLink': response.get('selfLink'), 'kind': response.get('kind') } self.charges_use_fee = response['chargesUseFee'] def destroy(self): raise LibcloudError("Can not destroy a License resource.") def __repr__(self): return '' % ( self.id, self.name, self.charges_use_fee) class GCEDiskType(UuidMixin): """A GCE DiskType resource.""" def __init__(self, id, name, zone, driver, extra=None): self.id = str(id) self.name = name self.zone = zone self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): raise LibcloudError("Can not destroy a DiskType resource.") def __repr__(self): return '' % ( self.id, self.name, self.zone) class GCEAcceleratorType(UuidMixin): """A GCE AcceleratorType resource.""" def __init__(self, id, name, zone, driver, extra=None): self.id = str(id) self.name = name self.zone = zone self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): raise LibcloudError("Can not destroy an AcceleratorType resource.") def __repr__(self): return '' % ( self.id, self.name, self.zone) class GCEAddress(UuidMixin): """A GCE Static address.""" def __init__(self, id, name, address, region, driver, extra=None): self.id = str(id) self.name = name self.address = address self.region = region self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this address. :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_address(address=self) def __repr__(self): return '' % ( self.id, self.name, self.address, (hasattr(self.region, "name") and self.region.name or self.region)) class GCEBackend(UuidMixin): """A GCE Backend. Only used for creating Backend Services.""" def __init__(self, instance_group, balancing_mode='UTILIZATION', max_utilization=None, max_rate=None, max_rate_per_instance=None, capacity_scaler=1, description=None): if isinstance(instance_group, GCEInstanceGroup): self.instance_group = instance_group elif isinstance(instance_group, GCEInstanceGroupManager): self.instance_group = instance_group.instance_group else: raise ValueError('instance_group must be of type GCEInstanceGroup' 'or of type GCEInstanceGroupManager') self.instance_group = instance_group self.balancing_mode = balancing_mode self.max_utilization = max_utilization self.max_rate = max_rate self.max_rate_per_instance = max_rate_per_instance self.capacity_scaler = capacity_scaler # 'id' and 'name' aren't actually used or provided by the GCE API. # We create them for convenience. self.id = self._gen_id() self.name = self.id self.description = description or self.name UuidMixin.__init__(self) def _gen_id(self): """ Use the Instance Group information to fill in name and id fields. :return: id in the format of: ZONE/instanceGroups/INSTANCEGROUPNAME Ex: us-east1-c/instanceGroups/my-instance-group :rtype: ``str`` """ zone_name = self.instance_group.zone.name return "%s/instanceGroups/%s" % (zone_name, self.instance_group.name) def to_backend_dict(self): """ Returns dict formatted for inclusion in Backend Service Request. :return: dict formatted as a list entry for Backend Service 'backend'. :rtype: ``dict`` """ d = {} d['group'] = self.instance_group.extra['selfLink'] if self.balancing_mode: d['balancingMode'] = self.balancing_mode if self.max_utilization: d['maxUtilization'] = self.max_utilization if self.max_rate: d['maxRate'] = self.max_rate if self.max_rate_per_instance: d['maxRatePerInstance'] = self.max_rate_per_instance if self.capacity_scaler: d['capacityScaler'] = self.capacity_scaler return d def __repr__(self): return '' % ( self.id, self.balancing_mode) class GCEBackendService(UuidMixin): """A GCE Backend Service.""" def __init__(self, id, name, backends, healthchecks, port, port_name, protocol, timeout, driver, extra=None): self.id = str(id) self.name = name self.backends = backends or [] self.healthchecks = healthchecks or [] self.port = port self.port_name = port_name self.protocol = protocol self.timeout = timeout self.driver = driver self.extra = extra or {} UuidMixin.__init__(self) def __repr__(self): return '' % (self.id, self.name) def destroy(self): """ Destroy this Backend Service. :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_backendservice(backendservice=self) class GCEFailedDisk(object): """Dummy Node object for disks that are not created.""" def __init__(self, name, error, code): self.name = name self.error = error self.code = code def __repr__(self): return '' % (self.name, self.code) class GCEFailedNode(object): """Dummy Node object for nodes that are not created.""" def __init__(self, name, error, code): self.name = name self.error = error self.code = code def __repr__(self): return '' % (self.name, self.code) class GCEHealthCheck(UuidMixin): """A GCE Http Health Check class.""" def __init__(self, id, name, path, port, interval, timeout, unhealthy_threshold, healthy_threshold, driver, extra=None): self.id = str(id) self.name = name self.path = path self.port = port self.interval = interval self.timeout = timeout self.unhealthy_threshold = unhealthy_threshold self.healthy_threshold = healthy_threshold self.driver = driver self.extra = extra or {} UuidMixin.__init__(self) def destroy(self): """ Destroy this Health Check. :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_healthcheck(healthcheck=self) def update(self): """ Commit updated healthcheck values. :return: Updated Healthcheck object :rtype: :class:`GCEHealthcheck` """ return self.driver.ex_update_healthcheck(healthcheck=self) def __repr__(self): return '' % ( self.id, self.name, self.path, self.port) class GCEFirewall(UuidMixin): """A GCE Firewall rule class.""" def __init__(self, id, name, allowed, denied, direction, network, source_ranges, source_tags, priority, source_service_accounts, target_service_accounts, target_tags, target_ranges, driver, extra=None): self.id = str(id) self.name = name self.network = network self.allowed = allowed self.denied = denied self.direction = direction self.priority = priority self.source_ranges = source_ranges self.source_tags = source_tags self.source_service_accounts = source_service_accounts self.target_tags = target_tags self.target_service_accounts = target_service_accounts self.target_ranges = target_ranges self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this firewall. :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_firewall(firewall=self) def update(self): """ Commit updated firewall values. :return: Updated Firewall object :rtype: :class:`GCEFirewall` """ return self.driver.ex_update_firewall(firewall=self) def __repr__(self): return '' % ( self.id, self.name, self.network.name) class GCEForwardingRule(UuidMixin): def __init__(self, id, name, region, address, protocol, targetpool, driver, extra=None): self.id = str(id) self.name = name self.region = region self.address = address self.protocol = protocol # TODO: 'targetpool' should more correctly be 'target' since a # forwarding rule's target can be something besides a targetpool self.targetpool = targetpool self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this Forwarding Rule :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_forwarding_rule(forwarding_rule=self) def __repr__(self): return '' % ( self.id, self.name, self.address) class GCENodeImage(NodeImage): """A GCE Node Image class.""" def __init__(self, id, name, driver, extra=None): super(GCENodeImage, self).__init__(id, name, driver, extra=extra) def delete(self): """ Delete this image :return: True if successful :rtype: ``bool`` """ return self.driver.ex_delete_image(image=self) def deprecate(self, replacement, state, deprecated=None, obsolete=None, deleted=None): """ Deprecate this image :param replacement: Image to use as a replacement :type replacement: ``str`` or :class: `GCENodeImage` :param state: Deprecation state of this image. Possible values include \'ACTIVE\', \'DELETED\', \'DEPRECATED\' or \'OBSOLETE\'. :type state: ``str`` :param deprecated: RFC3339 timestamp to mark DEPRECATED :type deprecated: ``str`` or ``None`` :param obsolete: RFC3339 timestamp to mark OBSOLETE :type obsolete: ``str`` or ``None`` :param deleted: RFC3339 timestamp to mark DELETED :type deleted: ``str`` or ``None`` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_deprecate_image(self, replacement, state, deprecated, obsolete, deleted) class GCESslCertificate(UuidMixin): """ GCESslCertificate represents the SslCertificate resource. """ def __init__(self, id, name, certificate, driver, extra, private_key=None, description=None): """ :param name: Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. :type name: ``str`` :param certificate: A local certificate file. The certificate must be in PEM format. The certificate chain must be no greater than 5 certs long. The chain must include at least one intermediate cert. :type certificate: ``str`` :param private_key: A write-only private key in PEM format. Only insert RPCs will include this field. :type private_key: ``str`` :keyword description: An optional description of this resource. Provide this property when you create the resource. :type description: ``str`` :keyword driver: An initialized :class: `GCENodeDriver` :type driver: :class:`:class: `GCENodeDriver`` :keyword extra: A dictionary of extra information. :type extra: ``:class: ``dict```` """ self.name = name self.certificate = certificate self.private_key = private_key self.description = description self.driver = driver self.extra = extra UuidMixin.__init__(self) def __repr__(self): return '' % (self.name) def destroy(self): """ Destroy this SslCertificate. :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_destroy_sslcertificate(sslcertificate=self) class GCESubnetwork(UuidMixin): """A GCE Subnetwork object class.""" def __init__(self, id, name, cidr, network, region, driver, extra=None): self.id = str(id) self.name = name self.cidr = cidr self.network = network self.region = region self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this subnetwork :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_subnetwork(self) def __repr__(self): return '' % (self.id, self.name, self.region.name, self.network.name, self.cidr) class GCENetwork(UuidMixin): """A GCE Network object class.""" def __init__(self, id, name, cidr, driver, extra=None): self.id = str(id) self.name = name self.cidr = cidr self.driver = driver self.extra = extra self.mode = 'legacy' self.subnetworks = [] if 'mode' in extra and extra['mode'] != 'legacy': self.mode = extra['mode'] self.subnetworks = extra['subnetworks'] UuidMixin.__init__(self) def destroy(self): """ Destroy this network :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_network(network=self) def __repr__(self): return '' % ( self.id, self.name, self.cidr, self.mode) class GCERoute(UuidMixin): """A GCE Route object class.""" def __init__(self, id, name, dest_range, priority, network="default", tags=None, driver=None, extra=None): self.id = str(id) self.name = name self.dest_range = dest_range self.priority = priority self.network = network self.tags = tags self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this route :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_route(route=self) def __repr__(self): network_name = getattr(self.network, 'name', self.network) return '' % ( self.id, self.name, self.dest_range, network_name) class GCENodeSize(NodeSize): """A GCE Node Size (MachineType) class.""" def __init__(self, id, name, ram, disk, bandwidth, price, driver, extra=None): self.extra = extra super(GCENodeSize, self).__init__(id, name, ram, disk, bandwidth, price, driver, extra=extra) class GCEProject(UuidMixin): """GCE Project information.""" def __init__(self, id, name, metadata, quotas, driver, extra=None): self.id = str(id) self.name = name self.metadata = metadata self.quotas = quotas self.driver = driver self.extra = extra UuidMixin.__init__(self) def set_common_instance_metadata(self, metadata=None, force=False): """ Set common instance metadata for the project. Common uses are for setting 'sshKeys', or setting a project-wide 'startup-script' for all nodes (instances). Passing in ``None`` for the 'metadata' parameter will clear out all common instance metadata *except* for 'sshKeys'. If you also want to update 'sshKeys', set the 'force' parameter to ``True``. :param metadata: Dictionary of metadata. Can be either a standard python dictionary, or the format expected by GCE (e.g. {'items': [{'key': k1, 'value': v1}, ...}] :type metadata: ``dict`` or ``None`` :param force: Force update of 'sshKeys'. If force is ``False`` (the default), existing sshKeys will be retained. Setting force to ``True`` will either replace sshKeys if a new a new value is supplied, or deleted if no new value is supplied. :type force: ``bool`` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_set_common_instance_metadata(metadata=metadata, force=force) def set_usage_export_bucket(self, bucket, prefix=None): """ Used to retain Compute Engine resource usage, storing the CSV data in a Google Cloud Storage bucket. See the `docs `_ for more information. Please ensure you have followed the necessary setup steps prior to enabling this feature (e.g. bucket exists, ACLs are in place, etc.) :param bucket: Name of the Google Cloud Storage bucket. Specify the name in either 'gs://' or the full URL 'https://storage.googleapis.com/'. :type bucket: ``str`` :param prefix: Optional prefix string for all reports. :type prefix: ``str`` or ``None`` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_set_usage_export_bucket(bucket=bucket, prefix=prefix) def __repr__(self): return '' % (self.id, self.name) class GCERegion(UuidMixin): def __init__(self, id, name, status, zones, quotas, deprecated, driver, extra=None): self.id = str(id) self.name = name self.status = status self.zones = zones self.quotas = quotas self.deprecated = deprecated self.driver = driver self.extra = extra UuidMixin.__init__(self) def __repr__(self): return '' % ( self.id, self.name, self.status) class GCESnapshot(VolumeSnapshot): def __init__(self, id, name, size, status, driver, extra=None, created=None): self.status = status super(GCESnapshot, self).__init__(id, driver, size, extra, created, name=name) class GCETargetHttpProxy(UuidMixin): def __init__(self, id, name, urlmap, driver, extra=None): self.id = str(id) self.name = name self.urlmap = urlmap self.driver = driver self.extra = extra or {} UuidMixin.__init__(self) def __repr__(self): return '' % (self.id, self.name) def destroy(self): """ Destroy this Target HTTP Proxy. :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_targethttpproxy(targethttpproxy=self) class GCETargetHttpsProxy(UuidMixin): """ GCETargetHttpsProxy represents the TargetHttpsProxy resource. """ def __init__(self, id, name, description=None, sslcertificates=None, urlmap=None, driver=None, extra=None): """ :param name: Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. :type name: ``str`` :param description: An optional description of this resource. Provide this property when you create the resource. :type description: ``str`` :param sslcertificates: URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. Currently, exactly one SSL certificate must be specified. :type sslcertificates: ``list`` of :class:`GCESslcertificates` :param urlmap: A fully-qualified or valid partial URL to the UrlMap resource that defines the mapping from URL to the BackendService. For example, the following are all valid URLs for specifying a URL map: - ht tps://www.googleapis.compute/v1/projects/project/gl obal/urlMaps/url-map - projects/project/global/urlMaps/url-map - global/urlMaps/url-map :type urlmap: :class:`GCEUrlMap` :keyword driver: An initialized :class: `GCENodeDriver` :type driver: :class:`:class: `GCENodeDriver`` :keyword extra: A dictionary of extra information. :type extra: ``:class: ``dict```` """ self.name = name self.description = description self.sslcertificates = sslcertificates self.urlmap = urlmap self.driver = driver self.extra = extra UuidMixin.__init__(self) def __repr__(self): return '' % (self.name) def set_sslcertificates(self, sslcertificates): """ Set the SSL Certificates for this TargetHTTPSProxy :param sslcertificates: SSL Certificates to set. :type sslcertificates: ``list`` of :class:`GCESslCertificate` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_targethttpsproxy_set_sslcertificates( targethttpsproxy=self, sslcertificates=sslcertificates) def set_urlmap(self, urlmap): """ Changes the URL map for TargetHttpsProxy. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param targethttpsproxy: Name of the TargetHttpsProxy resource whose URL map is to be set. :type targethttpsproxy: ``str`` :param urlmap: UrlMap to set. :type urlmap: :class:`GCEUrlMap` :return: True :rtype: ``bool`` """ return self.driver.ex_targethttpsproxy_set_urlmap( targethttpsproxy=self, urlmap=urlmap) def destroy(self): """ Destroy this TargetHttpsProxy. :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_destroy_targethttpsproxy(targethttpsproxy=self) class GCETargetInstance(UuidMixin): def __init__(self, id, name, zone, node, driver, extra=None): self.id = str(id) self.name = name self.zone = zone self.node = node self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this Target Instance :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_targetinstance(targetinstance=self) def __repr__(self): return '' % ( self.id, self.name, self.zone.name, (hasattr(self.node, 'name') and self.node.name or self.node)) class GCEAutoscaler(UuidMixin): """Represents a autoscaling policy object used to scale Instance Groups.""" def __init__(self, id, name, zone, target, policy, driver, extra=None): self.id = str(id) self.name = name self.zone = zone self.target = target self.policy = policy self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this Autoscaler. :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_autoscaler(autoscaler=self) def __repr__(self): return '' % ( self.id, self.name, self.zone.name, self.target.name) class GCEInstanceTemplate(UuidMixin): """Represents a machine configuration used in creating Instance Groups.""" def __init__(self, id, name, driver, extra=None): self.id = str(id) self.name = name self.driver = driver self.extra = extra UuidMixin.__init__(self) def __repr__(self): return '' % ( self.id, self.name, self.extra['properties'].get('machineType', 'UNKNOWN')) def destroy(self): """ Destroy this InstanceTemplate. :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_destroy_instancetemplate(instancetemplate=self) class GCEInstanceGroup(UuidMixin): """ GCEInstanceGroup represents the InstanceGroup resource. """ def __init__(self, id, name, zone, driver, extra=None, network=None, subnetwork=None, named_ports=None): """ :param name: Required. The name of the instance group. The name must be 1-63 characters long, and comply with RFC1035. :type name: ``str`` :param zone: The URL of the zone where the instance group is located. :type zone: :class:`GCEZone` :param network: The URL of the network to which all instances in the instance group belong. :type network: :class:`GCENetwork` :param subnetwork: The URL of the subnetwork to which all instances in the instance group belong. :type subnetwork: :class:`GCESubnetwork` :param named_ports: Assigns a name to a port number. For example: {name: "http", port: 80} This allows the system to reference ports by the assigned name instead of a port number. Named ports can also contain multiple ports. For example: [{name: "http", port: 80},{name: "http", port: 8080}] Named ports apply to all instances in this instance group. :type named_ports: ``""`` """ self.name = name self.zone = zone self.network = network self.subnetwork = subnetwork self.named_ports = named_ports self.driver = driver self.extra = extra UuidMixin.__init__(self) def __repr__(self): return '' % (self.name, self.zone.name) def destroy(self): """ Destroy this InstanceGroup. :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_destroy_instancegroup(instancegroup=self) def add_instances(self, node_list): """ Adds a list of instances to the specified instance group. All of the instances in the instance group must be in the same network/subnetwork. Read Adding instances for more information. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param instancegroup: The Instance Group where you are adding instances. :type instancegroup: :class:``GCEInstanceGroup`` :param node_list: List of nodes to add. :type node_list: ``list`` of :class:`Node` or ``list`` of :class:`GCENode` :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_instancegroup_add_instances(instancegroup=self, node_list=node_list) def list_instances(self): """ Lists the instances in the specified instance group. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :return: List of :class:`GCENode` objects. :rtype: ``list`` of :class:`GCENode` objects. """ return self.driver.ex_instancegroup_list_instances(instancegroup=self) def remove_instances(self, node_list): """ Removes one or more instances from the specified instance group, but does not delete those instances. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param instancegroup: The Instance Group where you are removng instances. :type instancegroup: :class:``GCEInstanceGroup`` :param node_list: List of nodes to add. :type node_list: ``list`` of :class:`Node` or ``list`` of :class:`GCENode` :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_instancegroup_remove_instances( instancegroup=self, node_list=node_list) def set_named_ports(self, named_ports): """ Sets the named ports for the specified instance group. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param named_ports: Assigns a name to a port number. For example: {name: "http", port: 80} This allows the system to reference ports by the assigned name instead of a port number. Named ports can also contain multiple ports. For example: [{name: "http", port: 80},{name: "http", port: 8080}] Named ports apply to all instances in this instance group. :type named_ports: ``list`` of {'name': ``str``, 'port`: ``int``} :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_instancegroup_set_named_ports( instancegroup=self, named_ports=named_ports) class GCEInstanceGroupManager(UuidMixin): """ GCE Instance Groups Manager class. Handles 'managed' Instance Groups. For more information on Instance Groups, see: https://cloud.google.com/compute/docs/instance-groups """ def __init__(self, id, name, zone, size, template, instance_group, driver, extra=None): """ :param id: Internal identifier of Instance Group. Display only. :type id: ``str`` :param name: The name of this Instance Group. :type name: ``str`` :param zone: Zone in witch the Instance Group belongs :type zone: :class: ``GCEZone`` :param size: Number of instances in this Instance Group. :type size: ``int`` :param template: An initialized :class:``GCEInstanceTemplate`` :type driver: :class:``GCEInstanceTemplate`` :param instance_group: An initialized :class:``GCEInstanceGroup`` :type driver: :class:``GCEInstanceGroup`` :param driver: An initialized :class:``GCENodeDriver`` :type driver: :class:``GCENodeDriver`` :param extra: A dictionary of extra information. :type extra: ``dict`` """ self.id = str(id) self.name = name self.zone = zone self.size = size or 0 self.template = template self.instance_group = instance_group self.driver = driver self.extra = extra UuidMixin.__init__(self) def destroy(self): """ Destroy this Instance Group. Destroys all instances managed by the Instance Group. :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_instancegroupmanager(manager=self) def list_managed_instances(self): """ Lists all of the instances in this managed instance group. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :return: ``list`` of ``dict`` containing instance URI and currentAction. See ex_instancegroupmanager_list_managed_instances for more details. :rtype: ``list`` """ return self.driver.ex_instancegroupmanager_list_managed_instances( manager=self) def set_instancetemplate(self, instancetemplate): """ Set the Instance Template for this Instance Group. :param instancetemplate: Instance Template to set. :type instancetemplate: :class:`GCEInstanceTemplate` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_instancegroupmanager_set_instancetemplate( manager=self, instancetemplate=instancetemplate) def recreate_instances(self): """ Recreate instances in a Managed Instance Group. :return: ``list`` of ``dict`` containing instance URI and currentAction. See ex_instancegroupmanager_list_managed_instances for more details. :rtype: ``list`` """ return self.driver.ex_instancegroupmanager_recreate_instances( manager=self) def delete_instances(self, node_list): """ Removes one or more instances from the specified instance group, and delete those instances. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param node_list: List of nodes to delete. :type node_list: ``list`` of :class:`Node` or ``list`` of :class:`GCENode` :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_instancegroupmanager_delete_instances( manager=self, node_list=node_list) def resize(self, size): """ Set the number of instances for this Instance Group. An increase in num_instances will result in VMs being created. A decrease will result in VMs being destroyed. :param size: Number to instances to resize to. :type size: ``int`` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_instancegroupmanager_resize(manager=self, size=size) def set_named_ports(self, named_ports): """ Sets the named ports for the instance group controlled by this manager. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param named_ports: Assigns a name to a port number. For example: {name: "http", port: 80} This allows the system to reference ports by the assigned name instead of a port number. Named ports can also contain multiple ports. For example: [{name: "http", port: 80},{name: "http", port: 8080}] Named ports apply to all instances in this instance group. :type named_ports: ``list`` of {'name': ``str``, 'port`: ``int``} :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_instancegroup_set_named_ports( instancegroup=self.instance_group, named_ports=named_ports) def set_autohealingpolicies(self, healthcheck, initialdelaysec): """ Sets the autohealing policies for the instance for the instance group controlled by this manager. :param healthcheck: Healthcheck to add :type healthcheck: :class:`GCEHealthCheck` :param initialdelaysec: The time to allow an instance to boot and applications to fully start before the first health check :type initialdelaysec: ``int`` :return: Return True if successful. :rtype: ``bool`` """ return self.driver.ex_instancegroupmanager_set_autohealingpolicies( manager=self, healthcheck=healthcheck, initialdelaysec=initialdelaysec) def __repr__(self): return '' % ( self.name, self.zone.name, self.size) class GCETargetPool(UuidMixin): def __init__(self, id, name, region, healthchecks, nodes, driver, extra=None): self.id = str(id) self.name = name self.region = region self.healthchecks = healthchecks self.nodes = nodes self.driver = driver self.extra = extra UuidMixin.__init__(self) def add_node(self, node): """ Add a node to this target pool. :param node: Node to add :type node: ``str`` or :class:`Node` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_targetpool_add_node(targetpool=self, node=node) def remove_node(self, node): """ Remove a node from this target pool. :param node: Node to remove :type node: ``str`` or :class:`Node` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_targetpool_remove_node(targetpool=self, node=node) def add_healthcheck(self, healthcheck): """ Add a healthcheck to this target pool. :param healthcheck: Healthcheck to add :type healthcheck: ``str`` or :class:`GCEHealthCheck` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_targetpool_add_healthcheck( targetpool=self, healthcheck=healthcheck) def remove_healthcheck(self, healthcheck): """ Remove a healthcheck from this target pool. :param healthcheck: Healthcheck to remove :type healthcheck: ``str`` or :class:`GCEHealthCheck` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_targetpool_remove_healthcheck( targetpool=self, healthcheck=healthcheck) def set_backup_targetpool(self, backup_targetpool, failover_ratio=0.1): """ Set a backup targetpool. :param backup_targetpool: The existing targetpool to use for failover traffic. :type backup_targetpool: :class:`GCETargetPool` :param failover_ratio: The percentage of healthy VMs must fall at or below this value before traffic will be sent to the backup targetpool (default 0.10) :type failover_ratio: ``float`` :return: True if successful :rtype: ``bool`` """ return self.driver.ex_targetpool_set_backup_targetpool( targetpool=self, backup_targetpool=backup_targetpool, failover_ratio=failover_ratio) def get_health(self, node=None): """ Return a hash of target pool instances and their health. :param node: Optional node to specify if only a specific node's health status should be returned :type node: ``str``, ``Node``, or ``None`` :return: List of hashes of nodes and their respective health :rtype: ``list`` of ``dict`` """ return self.driver.ex_targetpool_get_health(targetpool=self, node=node) def destroy(self): """ Destroy this Target Pool :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_targetpool(targetpool=self) def __repr__(self): return '' % ( self.id, self.name, self.region.name) class GCEUrlMap(UuidMixin): """A GCE URL Map.""" def __init__(self, id, name, default_service, host_rules, path_matchers, tests, driver, extra=None): self.id = str(id) self.name = name self.default_service = default_service self.host_rules = host_rules or [] self.path_matchers = path_matchers or [] self.tests = tests or [] self.driver = driver self.extra = extra or {} UuidMixin.__init__(self) def __repr__(self): return '' % (self.id, self.name) def destroy(self): """ Destroy this URL Map :return: True if successful :rtype: ``bool`` """ return self.driver.ex_destroy_urlmap(urlmap=self) class GCEZone(NodeLocation): """Subclass of NodeLocation to provide additional information.""" def __init__(self, id, name, status, maintenance_windows, deprecated, driver, extra=None): self.status = status self.maintenance_windows = maintenance_windows self.deprecated = deprecated self.extra = extra country = name.split('-')[0] super(GCEZone, self).__init__(id=str(id), name=name, country=country, driver=driver, extra=extra) @property def time_until_mw(self): """ Returns the time until the next Maintenance Window as a datetime.timedelta object. """ return self._get_time_until_mw() @property def next_mw_duration(self): """ Returns the duration of the next Maintenance Window as a datetime.timedelta object. """ return self._get_next_mw_duration() def _now(self): """ Returns current UTC time. Can be overridden in unittests. """ return datetime.datetime.utcnow() def _get_next_maint(self): """ Returns the next Maintenance Window. :return: A dictionary containing maintenance window info (or None if no maintenance windows are scheduled) The dictionary contains 4 keys with values of type ``str`` - name: The name of the maintenance window - description: Description of the maintenance window - beginTime: RFC3339 Timestamp - endTime: RFC3339 Timestamp :rtype: ``dict`` or ``None`` """ begin = None next_window = None if not self.maintenance_windows: return None if len(self.maintenance_windows) == 1: return self.maintenance_windows[0] for mw in self.maintenance_windows: begin_next = timestamp_to_datetime(mw['beginTime']) if (not begin) or (begin_next < begin): begin = begin_next next_window = mw return next_window def _get_time_until_mw(self): """ Returns time until next maintenance window. :return: Time until next maintenance window (or None if no maintenance windows are scheduled) :rtype: :class:`datetime.timedelta` or ``None`` """ next_window = self._get_next_maint() if not next_window: return None now = self._now() next_begin = timestamp_to_datetime(next_window['beginTime']) return next_begin - now def _get_next_mw_duration(self): """ Returns the duration of the next maintenance window. :return: Duration of next maintenance window (or None if no maintenance windows are scheduled) :rtype: :class:`datetime.timedelta` or ``None`` """ next_window = self._get_next_maint() if not next_window: return None next_begin = timestamp_to_datetime(next_window['beginTime']) next_end = timestamp_to_datetime(next_window['endTime']) return next_end - next_begin def __repr__(self): return '' % (self.id, self.name, self.status) class GCENodeDriver(NodeDriver): """ GCE Node Driver class. This is the primary driver for interacting with Google Compute Engine. It contains all of the standard libcloud methods, plus additional ex_* methods for more features. Note that many methods allow either objects or strings (or lists of objects/strings). In most cases, passing strings instead of objects will result in additional GCE API calls. """ connectionCls = GCEConnection api_name = 'google' name = "Google Compute Engine" type = Provider.GCE website = 'https://cloud.google.com/' features = {'create_node': ['ssh_key']} # Google Compute Engine node states are mapped to Libcloud node states # per the following dict. GCE does not have an actual 'stopped' state # but instead uses a 'terminated' state to indicate the node exists # but is not running. In order to better match libcloud, GCE maps this # 'terminated' state to 'STOPPED'. # Also, when a node is deleted from GCE, it no longer exists and instead # will result in a ResourceNotFound error versus returning a placeholder # node in a 'terminated' state. # For more details, please see GCE's docs, # https://cloud.google.com/compute/docs/instances#checkmachinestatus NODE_STATE_MAP = { "PROVISIONING": NodeState.PENDING, "STAGING": NodeState.PENDING, "RUNNING": NodeState.RUNNING, "STOPPING": NodeState.PENDING, "SUSPENDED": NodeState.SUSPENDED, "TERMINATED": NodeState.STOPPED, "UNKNOWN": NodeState.UNKNOWN } AUTH_URL = "https://www.googleapis.com/auth/" SA_SCOPES_MAP = { # list derived from 'gcloud compute instances create --help' "bigquery": "bigquery", "cloud-platform": "cloud-platform", "compute-ro": "compute.readonly", "compute-rw": "compute", "datastore": "datastore", "logging-write": "logging.write", "monitoring": "monitoring", "monitoring-write": "monitoring.write", "service-control": "servicecontrol", "service-management": "service.management", "sql": "sqlservice", "sql-admin": "sqlservice.admin", "storage-full": "devstorage.full_control", "storage-ro": "devstorage.read_only", "storage-rw": "devstorage.read_write", "taskqueue": "taskqueue", "useraccounts-ro": "cloud.useraccounts.readonly", "useraccounts-rw": "cloud.useraccounts", "userinfo-email": "userinfo.email" } IMAGE_PROJECTS = { "centos-cloud": [ "centos-6", "centos-7", "centos-8", ], "cos-cloud": ["cos-beta", "cos-dev", "cos-stable"], "coreos-cloud": ["coreos-alpha", "coreos-beta", "coreos-stable"], "debian-cloud": [ "debian-8", "debian-9", "debian-10", ], "opensuse-cloud": ["opensuse-leap"], "rhel-cloud": [ "rhel-6", "rhel-7", "rhel-8", ], "suse-cloud": [ "sles-11", "sles-12", "sles-15", ], "suse-byos-cloud": [ "sles-11-byos", "sles-12-byos", "sles-12-sp2-sap-byos", "sles-12-sp3-sap-byos", "suse-manager-proxy-byos", "suse-manager-server-byos" ], "suse-sap-cloud": [ "sles-12-sp2-sap", "sles-12-sp3-sap", "sles-12-sp4-sap", "sles-15-sap", ], "ubuntu-os-cloud": [ "ubuntu-1404-lts", "ubuntu-1604-lts", "ubuntu-minimal-1604-lts", "ubuntu-1710", "ubuntu-1804-lts", "ubuntu-minimal-1804-lts", "ubuntu-1810", "ubuntu-minimal-1810", "ubuntu-1904", "ubuntu-minimal-1904", ], "windows-cloud": [ "windows-1709-core-for-containers", "windows-1709-core", "windows-2008-r2", "windows-2012-r2-core", "windows-2012-r2", "windows-2016-core", "windows-2016" ], "windows-sql-cloud": [ "sql-ent-2012-win-2012-r2", "sql-std-2012-win-2012-r2", "sql-web-2012-win-2012-r2", "sql-ent-2014-win-2012-r2", "sql-ent-2014-win-2016", "sql-std-2014-win-2012-r2", "sql-web-2014-win-2012-r2", "sql-ent-2016-win-2012-r2", "sql-ent-2016-win-2016", "sql-std-2016-win-2012-r2", "sql-std-2016-win-2016", "sql-web-2016-win-2012-r2", "sql-web-2016-win-2016", "sql-ent-2017-win-2016", "sql-exp-2017-win-2012-r2", "sql-exp-2017-win-2016", "sql-std-2017-win-2016", "sql-web-2017-win-2016" ], } BACKEND_SERVICE_PROTOCOLS = ['HTTP', 'HTTPS', 'HTTP2', 'TCP', 'SSL'] def __init__(self, user_id, key=None, datacenter=None, project=None, auth_type=None, scopes=None, credential_file=None, **kwargs): """ :param user_id: The email address (for service accounts) or Client ID (for installed apps) to be used for authentication. :type user_id: ``str`` :param key: The RSA Key (for service accounts) or file path containing key or Client Secret (for installed apps) to be used for authentication. :type key: ``str`` :keyword datacenter: The name of the datacenter (zone) used for operations. :type datacenter: ``str`` :keyword project: Your GCE project name. (required) :type project: ``str`` :keyword auth_type: Accepted values are "SA" or "IA" or "GCE" ("Service Account" or "Installed Application" or "GCE" if libcloud is being used on a GCE instance with service account enabled). If not supplied, auth_type will be guessed based on value of user_id or if the code is being executed in a GCE instance. :type auth_type: ``str`` :keyword scopes: List of authorization URLs. Default is empty and grants read/write to Compute, Storage, DNS. :type scopes: ``list`` :keyword credential_file: Path to file for caching authentication information used by GCEConnection. :type credential_file: ``str`` """ if not project: raise ValueError('Project name must be specified using ' '"project" keyword.') self.auth_type = auth_type self.project = project self.scopes = scopes self.credential_file = credential_file or \ GoogleOAuth2Credential.default_credential_file + '.' + self.project super(GCENodeDriver, self).__init__(user_id, key, **kwargs) # Cache Zone and Region information to reduce API calls and # increase speed self.base_path = '/compute/%s/projects/%s' % (API_VERSION, self.project) self.zone_list = self.ex_list_zones() self.zone_dict = {} for zone in self.zone_list: self.zone_dict[zone.name] = zone if datacenter: self.zone = self.ex_get_zone(datacenter) else: self.zone = None self.region_list = self.ex_list_regions() self.region_dict = {} for region in self.region_list: self.region_dict[region.name] = region if self.zone: self.region = self._get_region_from_zone(self.zone) else: self.region = None # Volume details are looked up in this name-zone dict. # It is populated if the volume name is not found or the dict is empty. self._ex_volume_dict = {} def ex_add_access_config(self, node, name, nic, nat_ip=None, config_type=None): """ Add a network interface access configuration to a node. :keyword node: The existing target Node (instance) that will receive the new access config. :type node: ``Node`` :keyword name: Name of the new access config. :type node: ``str`` :keyword nat_ip: The external existing static IP Address to use for the access config. If not provided, an ephemeral IP address will be allocated. :type nat_ip: ``str`` or ``None`` :keyword config_type: The type of access config to create. Currently the only supported type is 'ONE_TO_ONE_NAT'. :type config_type: ``str`` or ``None`` :return: True if successful :rtype: ``bool`` """ if not isinstance(node, Node): raise ValueError("Must specify a valid libcloud node object.") node_name = node.name zone_name = node.extra['zone'].name config = {'name': name} if config_type is None: config_type = 'ONE_TO_ONE_NAT' config['type'] = config_type if nat_ip is not None: config['natIP'] = nat_ip params = {'networkInterface': nic} request = '/zones/%s/instances/%s/addAccessConfig' % (zone_name, node_name) self.connection.async_request(request, method='POST', data=config, params=params) return True def ex_delete_access_config(self, node, name, nic): """ Delete a network interface access configuration from a node. :keyword node: The existing target Node (instance) for the request. :type node: ``Node`` :keyword name: Name of the access config. :type name: ``str`` :keyword nic: Name of the network interface. :type nic: ``str`` :return: True if successful :rtype: ``bool`` """ if not isinstance(node, Node): raise ValueError("Must specify a valid libcloud node object.") node_name = node.name zone_name = node.extra['zone'].name params = {'accessConfig': name, 'networkInterface': nic} request = '/zones/%s/instances/%s/deleteAccessConfig' % (zone_name, node_name) self.connection.async_request(request, method='POST', params=params) return True def ex_set_node_metadata(self, node, metadata): """ Set metadata for the specified node. :keyword node: The existing target Node (instance) for the request. :type node: ``Node`` :keyword metadata: Set (or clear with None) metadata for this particular node. :type metadata: ``dict`` or ``None`` :return: True if successful :rtype: ``bool`` """ if not isinstance(node, Node): raise ValueError("Must specify a valid libcloud node object.") node_name = node.name zone_name = node.extra['zone'].name if 'metadata' in node.extra and \ 'fingerprint' in node.extra['metadata']: current_fp = node.extra['metadata']['fingerprint'] else: current_fp = 'absent' body = self._format_metadata(current_fp, metadata) request = '/zones/%s/instances/%s/setMetadata' % (zone_name, node_name) self.connection.async_request(request, method='POST', data=body) return True def ex_set_node_labels(self, node, labels): """ Set labels for the specified node. :keyword node: The existing target Node (instance) for the request. :type node: ``Node`` :keyword labels: Set (or clear with None) labels for this node. :type labels: ``dict`` or ``None`` :return: True if successful :rtype: ``bool`` """ if not isinstance(node, Node): raise ValueError("Must specify a valid libcloud node object.") node_name = node.name zone_name = node.extra['zone'].name current_fp = node.extra['labelFingerprint'] body = {'labels': labels, 'labelFingerprint': current_fp} request = '/zones/%s/instances/%s/setLabels' % (zone_name, node_name) self.connection.async_request(request, method='POST', data=body) return True def ex_set_image_labels(self, image, labels): """ Set labels for the specified image. :keyword image: The existing target Image for the request. :type image: ``NodeImage`` :keyword labels: Set (or clear with None) labels for this image. :type labels: ``dict`` or ``None`` :return: True if successful :rtype: ``bool`` """ if not isinstance(image, NodeImage): raise ValueError("Must specify a valid libcloud image object.") current_fp = image.extra['labelFingerprint'] body = {'labels': labels, 'labelFingerprint': current_fp} request = '/global/%s/setLabels' % (image.name) self.connection.async_request(request, method='POST', data=body) return True def ex_set_volume_labels(self, volume, labels): """ Set labels for the specified volume (disk). :keyword volume: The existing target StorageVolume for the request. :type volume: ``StorageVolume`` :keyword labels: Set (or clear with None) labels for this image. :type labels: ``dict`` or ``None`` :return: True if successful :rtype: ``bool`` """ if not isinstance(volume, StorageVolume): raise ValueError("Must specify a valid libcloud volume object.") volume_name = volume.name zone_name = volume.extra['zone'].name current_fp = volume.extra['labelFingerprint'] body = {'labels': labels, 'labelFingerprint': current_fp} request = '/zones/%s/disks/%s/setLabels' % (zone_name, volume_name) self.connection.async_request(request, method='POST', data=body) return True def ex_get_serial_output(self, node): """ Fetch the console/serial port output from the node. :keyword node: The existing target Node (instance) for the request. :type node: ``Node`` :return: A string containing serial port output of the node. :rtype: ``str`` """ if not isinstance(node, Node): raise ValueError("Must specify a valid libcloud node object.") node_name = node.name zone_name = node.extra['zone'].name request = '/zones/%s/instances/%s/serialPort' % (zone_name, node_name) response = self.connection.request(request, method='GET').object return response['contents'] def ex_list(self, list_fn, **kwargs): """ Wrap a list method in a :class:`GCEList` iterator. >>> for sublist in driver.ex_list(driver.ex_list_urlmaps).page(1): ... sublist ... [] [] [] :param list_fn: A bound list method from :class:`GCENodeDriver`. :type list_fn: ``instancemethod`` :return: An iterator that returns sublists from list_fn. :rtype: :class:`GCEList` """ return GCEList(driver=self, list_fn=list_fn, **kwargs) def ex_list_disktypes(self, zone=None): """ Return a list of DiskTypes for a zone or all. :keyword zone: The zone to return DiskTypes from. For example: 'us-central1-a'. If None, will return DiskTypes from self.zone. If 'all', will return all DiskTypes. :type zone: ``str`` or ``None`` :return: A list of static DiskType objects. :rtype: ``list`` of :class:`GCEDiskType` """ list_disktypes = [] zone = self._set_zone(zone) if zone is None: request = '/aggregated/diskTypes' else: request = '/zones/%s/diskTypes' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each region if zone is None: for v in response['items'].values(): zone_disktypes = [self._to_disktype(a) for a in v.get('diskTypes', [])] list_disktypes.extend(zone_disktypes) else: list_disktypes = [self._to_disktype(a) for a in response['items']] return list_disktypes def ex_set_usage_export_bucket(self, bucket, prefix=None): """ Used to retain Compute Engine resource usage, storing the CSV data in a Google Cloud Storage bucket. See the `docs `_ for more information. Please ensure you have followed the necessary setup steps prior to enabling this feature (e.g. bucket exists, ACLs are in place, etc.) :param bucket: Name of the Google Cloud Storage bucket. Specify the name in either 'gs://' or the full URL 'https://storage.googleapis.com/'. :type bucket: ``str`` :param prefix: Optional prefix string for all reports. :type prefix: ``str`` or ``None`` :return: True if successful :rtype: ``bool`` """ if bucket.startswith('https://www.googleapis.com/') or \ bucket.startswith('gs://'): data = {'bucketName': bucket} else: raise ValueError("Invalid bucket name: %s" % bucket) if prefix: data['reportNamePrefix'] = prefix request = '/setUsageExportBucket' self.connection.async_request(request, method='POST', data=data) return True def ex_set_common_instance_metadata(self, metadata=None, force=False): """ Set common instance metadata for the project. Common uses are for setting 'sshKeys', or setting a project-wide 'startup-script' for all nodes (instances). Passing in ``None`` for the 'metadata' parameter will clear out all common instance metadata *except* for 'sshKeys'. If you also want to update 'sshKeys', set the 'force' parameter to ``True``. :param metadata: Dictionary of metadata. Can be either a standard python dictionary, or the format expected by GCE (e.g. {'items': [{'key': k1, 'value': v1}, ...}] :type metadata: ``dict`` or ``None`` :param force: Force update of 'sshKeys'. If force is ``False`` (the default), existing sshKeys will be retained. Setting force to ``True`` will either replace sshKeys if a new a new value is supplied, or deleted if no new value is supplied. :type force: ``bool`` :return: True if successful :rtype: ``bool`` """ if metadata: metadata = self._format_metadata('na', metadata) request = '/setCommonInstanceMetadata' project = self.ex_get_project() current_metadata = project.extra['commonInstanceMetadata'] fingerprint = current_metadata['fingerprint'] md_items = [] if 'items' in current_metadata: md_items = current_metadata['items'] # grab copy of current 'sshKeys' in case we want to retain them current_keys = "" for md in md_items: if md['key'] == 'sshKeys': current_keys = md['value'] new_md = self._set_project_metadata(metadata, force, current_keys) md = {'fingerprint': fingerprint, 'items': new_md} self.connection.async_request(request, method='POST', data=md) return True def ex_list_addresses(self, region=None): """ Return a list of static addresses for a region, 'global', or all. :keyword region: The region to return addresses from. For example: 'us-central1'. If None, will return addresses from region of self.zone. If 'all', will return all addresses. If 'global', it will return addresses in the global namespace. :type region: ``str`` or ``None`` :return: A list of static address objects. :rtype: ``list`` of :class:`GCEAddress` """ list_addresses = [] if region != 'global': region = self._set_region(region) if region is None: request = '/aggregated/addresses' elif region == 'global': request = '/global/addresses' else: request = '/regions/%s/addresses' % (region.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each region if region is None: for v in response['items'].values(): region_addresses = [self._to_address(a) for a in v.get('addresses', [])] list_addresses.extend(region_addresses) else: list_addresses = [self._to_address(a) for a in response['items']] return list_addresses def ex_list_backendservices(self): """ Return a list of backend services. :return: A list of backend service objects. :rtype: ``list`` of :class:`GCEBackendService` """ list_backendservices = [] response = self.connection.request('/global/backendServices', method='GET').object list_backendservices = [self._to_backendservice(d) for d in response.get('items', [])] return list_backendservices def ex_list_healthchecks(self): """ Return the list of health checks. :return: A list of health check objects. :rtype: ``list`` of :class:`GCEHealthCheck` """ list_healthchecks = [] request = '/global/httpHealthChecks' response = self.connection.request(request, method='GET').object list_healthchecks = [self._to_healthcheck(h) for h in response.get('items', [])] return list_healthchecks def ex_list_firewalls(self): """ Return the list of firewalls. :return: A list of firewall objects. :rtype: ``list`` of :class:`GCEFirewall` """ list_firewalls = [] request = '/global/firewalls' response = self.connection.request(request, method='GET').object list_firewalls = [self._to_firewall(f) for f in response.get('items', [])] return list_firewalls def ex_list_forwarding_rules(self, region=None, global_rules=False): """ Return the list of forwarding rules for a region or all. :keyword region: The region to return forwarding rules from. For example: 'us-central1'. If None, will return forwarding rules from the region of self.region (which is based on self.zone). If 'all', will return forwarding rules for all regions, which does not include the global forwarding rules. :type region: ``str`` or :class:`GCERegion` or ``None`` :keyword global_rules: List global forwarding rules instead of per-region rules. Setting True will cause 'region' parameter to be ignored. :type global_rules: ``bool`` :return: A list of forwarding rule objects. :rtype: ``list`` of :class:`GCEForwardingRule` """ list_forwarding_rules = [] if global_rules: region = None request = '/global/forwardingRules' else: region = self._set_region(region) if region is None: request = '/aggregated/forwardingRules' else: request = '/regions/%s/forwardingRules' % (region.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each region if not global_rules and region is None: for v in response['items'].values(): region_forwarding_rules = [ self._to_forwarding_rule(f) for f in v.get('forwardingRules', []) ] list_forwarding_rules.extend(region_forwarding_rules) else: list_forwarding_rules = [self._to_forwarding_rule(f) for f in response['items']] return list_forwarding_rules def list_images(self, ex_project=None, ex_include_deprecated=False): """ Return a list of image objects. If no project is specified, a list of all non-deprecated global and vendor images images is returned. By default, only non-deprecated images are returned. :keyword ex_project: Optional alternate project name. :type ex_project: ``str``, ``list`` of ``str``, or ``None`` :keyword ex_include_deprecated: If True, even DEPRECATED images will be returned. :type ex_include_deprecated: ``bool`` :return: List of GCENodeImage objects :rtype: ``list`` of :class:`GCENodeImage` """ dep = ex_include_deprecated if ex_project is not None: return self.ex_list_project_images(ex_project=ex_project, ex_include_deprecated=dep) image_list = self.ex_list_project_images(ex_project=None, ex_include_deprecated=dep) for img_proj in list(self.IMAGE_PROJECTS.keys()): try: image_list.extend( self.ex_list_project_images(ex_project=img_proj, ex_include_deprecated=dep)) except Exception: # do not break if an OS type is invalid pass return image_list def ex_list_project_images(self, ex_project=None, ex_include_deprecated=False): """ Return a list of image objects for a project. If no project is specified, only a list of 'global' images is returned. :keyword ex_project: Optional alternate project name. :type ex_project: ``str``, ``list`` of ``str``, or ``None`` :keyword ex_include_deprecated: If True, even DEPRECATED images will be returned. :type ex_include_deprecated: ``bool`` :return: List of GCENodeImage objects :rtype: ``list`` of :class:`GCENodeImage` """ list_images = [] request = '/global/images' if ex_project is None: response = self.connection.request(request, method='GET').object for img in response.get('items', []): if 'deprecated' not in img: list_images.append(self._to_node_image(img)) else: if ex_include_deprecated: list_images.append(self._to_node_image(img)) else: list_images = [] # Save the connection request_path save_request_path = self.connection.request_path if isinstance(ex_project, str): ex_project = [ex_project] for proj in ex_project: # Override the connection request path new_request_path = save_request_path.replace(self.project, proj) self.connection.request_path = new_request_path try: response = self.connection.request(request, method='GET').object except Exception: raise finally: # Restore the connection request_path self.connection.request_path = save_request_path for img in response.get('items', []): if 'deprecated' not in img: list_images.append(self._to_node_image(img)) else: if ex_include_deprecated: list_images.append(self._to_node_image(img)) return list_images def list_locations(self): """ Return a list of locations (zones). The :class:`ex_list_zones` method returns more comprehensive results, but this is here for compatibility. :return: List of NodeLocation objects :rtype: ``list`` of :class:`NodeLocation` """ list_locations = [] request = '/zones' response = self.connection.request(request, method='GET').object list_locations = [self._to_node_location(l) for l in response['items']] return list_locations def ex_list_routes(self): """ Return the list of routes. :return: A list of route objects. :rtype: ``list`` of :class:`GCERoute` """ list_routes = [] request = '/global/routes' response = self.connection.request(request, method='GET').object list_routes = [self._to_route(n) for n in response.get('items', [])] return list_routes def ex_list_sslcertificates(self): """ Retrieves the list of SslCertificate resources available to the specified project. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :return: A list of SSLCertificate objects. :rtype: ``list`` of :class:`GCESslCertificate` """ list_data = [] request = '/global/sslCertificates' response = self.connection.request(request, method='GET').object list_data = [self._to_sslcertificate(a) for a in response.get('items', [])] return list_data def ex_list_subnetworks(self, region=None): """ Return the list of subnetworks. :keyword region: Region for the subnetwork. Specify 'all' to return the aggregated list of subnetworks. :type region: ``str`` or :class:`GCERegion` :return: A list of subnetwork objects. :rtype: ``list`` of :class:`GCESubnetwork` """ region = self._set_region(region) if region is None: request = '/aggregated/subnetworks' else: request = '/regions/%s/subnetworks' % (region.name) list_subnetworks = [] response = self.connection.request(request, method='GET').object if 'items' in response: if region is None: for v in response['items'].values(): for i in v.get('subnetworks', []): try: list_subnetworks.append(self._to_subnetwork(i)) except ResourceNotFoundError: pass else: for i in response['items']: try: list_subnetworks.append(self._to_subnetwork(i)) except ResourceNotFoundError: pass return list_subnetworks def ex_list_networks(self): """ Return the list of networks. :return: A list of network objects. :rtype: ``list`` of :class:`GCENetwork` """ list_networks = [] request = '/global/networks' response = self.connection.request(request, method='GET').object list_networks = [self._to_network(n) for n in response.get('items', [])] return list_networks def list_nodes(self, ex_zone=None, ex_use_disk_cache=True): """ Return a list of nodes in the current zone or all zones. :keyword ex_zone: Optional zone name or 'all' :type ex_zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :keyword ex_use_disk_cache: Disk information for each node will retrieved from a dictionary rather than making a distinct API call for it. :type ex_use_disk_cache: ``bool`` :return: List of Node objects :rtype: ``list`` of :class:`Node` """ list_nodes = [] zone = self._set_zone(ex_zone) if zone is None: request = '/aggregated/instances' else: request = '/zones/%s/instances' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated response returns a dict for each zone if zone is None: # Create volume cache now for fast lookups of disk info. self._ex_populate_volume_dict() for v in response['items'].values(): for i in v.get('instances', []): try: list_nodes.append( self._to_node(i, use_disk_cache=ex_use_disk_cache) ) # If a GCE node has been deleted between # - is was listed by `request('.../instances', 'GET') # - it is converted by `self._to_node(i)` # `_to_node()` will raise a ResourceNotFoundError. # # Just ignore that node and return the list of the # other nodes. except ResourceNotFoundError: pass else: for i in response['items']: try: list_nodes.append( self._to_node(i, use_disk_cache=ex_use_disk_cache) ) # If a GCE node has been deleted between # - is was listed by `request('.../instances', 'GET') # - it is converted by `self._to_node(i)` # `_to_node()` will raise a ResourceNotFoundError. # # Just ignore that node and return the list of the # other nodes. except ResourceNotFoundError: pass # Clear the volume cache as lookups are complete. self._ex_volume_dict = {} return list_nodes def ex_list_regions(self): """ Return the list of regions. :return: A list of region objects. :rtype: ``list`` of :class:`GCERegion` """ list_regions = [] request = '/regions' response = self.connection.request(request, method='GET').object list_regions = [self._to_region(r) for r in response['items']] return list_regions def list_sizes(self, location=None): """ Return a list of sizes (machineTypes) in a zone. :keyword location: Location or Zone for sizes :type location: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :return: List of GCENodeSize objects :rtype: ``list`` of :class:`GCENodeSize` """ list_sizes = [] zone = self._set_zone(location) if zone is None: request = '/aggregated/machineTypes' else: request = '/zones/%s/machineTypes' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated response returns a dict for each zone if zone is None: for v in response['items'].values(): zone_sizes = [self._to_node_size(s) for s in v.get('machineTypes', [])] list_sizes.extend(zone_sizes) else: list_sizes = [self._to_node_size(s) for s in response['items']] return list_sizes def ex_list_snapshots(self): """ Return the list of disk snapshots in the project. :return: A list of snapshot objects :rtype: ``list`` of :class:`GCESnapshot` """ list_snapshots = [] request = '/global/snapshots' response = self.connection.request(request, method='GET').object list_snapshots = [self._to_snapshot(s) for s in response.get('items', [])] return list_snapshots def ex_list_targethttpproxies(self): """ Return the list of target HTTP proxies. :return: A list of target http proxy objects :rtype: ``list`` of :class:`GCETargetHttpProxy` """ request = '/global/targetHttpProxies' response = self.connection.request(request, method='GET').object return [self._to_targethttpproxy(u) for u in response.get('items', [])] def ex_list_targethttpsproxies(self): """ Return the list of target HTTPs proxies. :return: A list of target https proxy objects :rtype: ``list`` of :class:`GCETargetHttpsProxy` """ request = '/global/targetHttpsProxies' response = self.connection.request(request, method='GET').object return [self._to_targethttpsproxy(x) for x in response.get('items', [])] def ex_list_targetinstances(self, zone=None): """ Return the list of target instances. :return: A list of target instance objects :rtype: ``list`` of :class:`GCETargetInstance` """ list_targetinstances = [] zone = self._set_zone(zone) if zone is None: request = '/aggregated/targetInstances' else: request = '/zones/%s/targetInstances' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each region if zone is None: for v in response['items'].values(): zone_targetinstances = [ self._to_targetinstance(t) for t in v.get('targetInstances', []) ] list_targetinstances.extend(zone_targetinstances) else: list_targetinstances = [self._to_targetinstance(t) for t in response['items']] return list_targetinstances def ex_list_targetpools(self, region=None): """ Return the list of target pools. :return: A list of target pool objects :rtype: ``list`` of :class:`GCETargetPool` """ list_targetpools = [] region = self._set_region(region) if region is None: request = '/aggregated/targetPools' else: request = '/regions/%s/targetPools' % (region.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each region if region is None: for v in response['items'].values(): region_targetpools = [self._to_targetpool(t) for t in v.get('targetPools', [])] list_targetpools.extend(region_targetpools) else: list_targetpools = [self._to_targetpool(t) for t in response['items']] return list_targetpools def ex_list_urlmaps(self): """ Return the list of URL Maps in the project. :return: A list of url map objects :rtype: ``list`` of :class:`GCEUrlMap` """ request = '/global/urlMaps' response = self.connection.request(request, method='GET').object return [self._to_urlmap(u) for u in response.get('items', [])] def ex_list_instancegroups(self, zone): """ Retrieves the list of instance groups that are located in the specified project and zone. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :param zone: The name of the zone where the instance group is located. :type zone: ``str`` :return: A list of instance group mgr objects. :rtype: ``list`` of :class:`GCEInstanceGroupManagers` """ list_data = [] zone = self._set_zone(zone) if zone is None: request = '/aggregated/instanceGroups' else: request = '/zones/%s/instanceGroups' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each region if zone is None: for v in response['items'].values(): zone_data = [self._to_instancegroup(a) for a in v.get('instanceGroups', [])] list_data.extend(zone_data) else: list_data = [self._to_instancegroup(a) for a in response['items']] return list_data def ex_list_instancegroupmanagers(self, zone=None): """ Return a list of Instance Group Managers. :keyword zone: The zone to return InstanceGroupManagers from. For example: 'us-central1-a'. If None, will return InstanceGroupManagers from self.zone. If 'all', will return all InstanceGroupManagers. :type zone: ``str`` or ``None`` :return: A list of instance group mgr objects. :rtype: ``list`` of :class:`GCEInstanceGroupManagers` """ list_managers = [] zone = self._set_zone(zone) if zone is None: request = '/aggregated/instanceGroupManagers' else: request = '/zones/%s/instanceGroupManagers' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each region if zone is None: for v in response['items'].values(): zone_managers = [ self._to_instancegroupmanager(a) for a in v.get('instanceGroupManagers', []) ] list_managers.extend(zone_managers) else: list_managers = [self._to_instancegroupmanager(a) for a in response['items']] return list_managers def ex_list_instancetemplates(self): """ Return the list of Instance Templates. :return: A list of Instance Template Objects :rtype: ``list`` of :class:`GCEInstanceTemplate` """ request = '/global/instanceTemplates' response = self.connection.request(request, method='GET').object return [self._to_instancetemplate(u) for u in response.get('items', [])] def ex_list_autoscalers(self, zone=None): """ Return the list of AutoScalers. :keyword zone: The zone to return InstanceGroupManagers from. For example: 'us-central1-a'. If None, will return InstanceGroupManagers from self.zone. If 'all', will return all InstanceGroupManagers. :type zone: ``str`` or ``None`` :return: A list of AutoScaler Objects :rtype: ``list`` of :class:`GCEAutoScaler` """ list_autoscalers = [] zone = self._set_zone(zone) if zone is None: request = '/aggregated/autoscalers' else: request = '/zones/%s/autoscalers' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated result returns dictionaries for each zone. if zone is None: for v in response['items'].values(): zone_as = [self._to_autoscaler(a) for a in v.get('autoscalers', [])] list_autoscalers.extend(zone_as) else: list_autoscalers = [self._to_autoscaler(a) for a in response['items']] return list_autoscalers def list_volumes(self, ex_zone=None): """ Return a list of volumes for a zone or all. Will return list from provided zone, or from the default zone unless given the value of 'all'. :keyword ex_zone: The zone to return volumes from. :type ex_zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :return: A list of volume objects. :rtype: ``list`` of :class:`StorageVolume` """ list_volumes = [] zone = self._set_zone(ex_zone) if zone is None: request = '/aggregated/disks' else: request = '/zones/%s/disks' % (zone.name) response = self.connection.request(request, method='GET').object if 'items' in response: # The aggregated response returns a dict for each zone if zone is None: for v in response['items'].values(): zone_volumes = [self._to_storage_volume(d) for d in v.get('disks', [])] list_volumes.extend(zone_volumes) else: list_volumes = [self._to_storage_volume(d) for d in response['items']] return list_volumes def ex_list_zones(self): """ Return the list of zones. :return: A list of zone objects. :rtype: ``list`` of :class:`GCEZone` """ list_zones = [] request = '/zones' response = self.connection.request(request, method='GET').object list_zones = [self._to_zone(z) for z in response['items']] return list_zones def ex_create_address(self, name, region=None, address=None, description=None, address_type='EXTERNAL', subnetwork=None): """ Create a static address in a region, or a global address. :param name: Name of static address :type name: ``str`` :keyword region: Name of region for the address (e.g. 'us-central1') Use 'global' to create a global address. :type region: ``str`` or :class:`GCERegion` :keyword address: Ephemeral IP address to promote to a static one (e.g. 'xxx.xxx.xxx.xxx') :type address: ``str`` or ``None`` :keyword description: Optional descriptive comment. :type description: ``str`` or ``None`` :keyword address_type: Optional The type of address to reserve, either INTERNAL or EXTERNAL. If unspecified, defaults to EXTERNAL. :type description: ``str`` :keyword subnetwork: Optional The URL of the subnetwork in which to reserve the address. If an IP address is specified, it must be within the subnetwork's IP range. This field can only be used with INTERNAL type with GCE_ENDPOINT/DNS_RESOLVER purposes. :type description: ``str`` :return: Static Address object :rtype: :class:`GCEAddress` """ region = region or self.region if region is None: raise ValueError('REGION_NOT_SPECIFIED', 'Region must be provided for an address') if region != 'global' and not hasattr(region, 'name'): region = self.ex_get_region(region) address_data = {'name': name} if address: address_data['address'] = address if description: address_data['description'] = description if address_type: if address_type not in ['EXTERNAL', 'INTERNAL']: raise ValueError('ADDRESS_TYPE_WRONG', 'Address type must be either EXTERNAL or \ INTERNAL') else: address_data['addressType'] = address_type if subnetwork and address_type != 'INTERNAL': raise ValueError('INVALID_ARGUMENT_COMBINATION', 'Address type must be internal if subnetwork \ provided') if subnetwork and not hasattr(subnetwork, 'name'): subnetwork = \ self.ex_get_subnetwork(subnetwork, region) if region == 'global': request = '/global/addresses' else: request = '/regions/%s/addresses' % (region.name) self.connection.async_request(request, method='POST', data=address_data) return self.ex_get_address(name, region=region) def ex_create_autoscaler(self, name, zone, instance_group, policy, description=None): """ Create an Autoscaler for an Instance Group. :param name: The name of the Autoscaler :type name: ``str`` :param zone: The zone to which the Instance Group belongs :type zone: ``str`` or :class:`GCEZone` :param instance_group: An Instance Group Manager object. :type: :class:`GCEInstanceGroupManager` :param policy: A dict containing policy configuration. See the API documentation for Autoscalers for more details. :type: ``dict`` :return: An Autoscaler object. :rtype: :class:`GCEAutoscaler` """ zone = zone or self.zone autoscaler_data = {} autoscaler_data = {'name': name} if not hasattr(zone, 'name'): zone = self.ex_get_zone(zone) autoscaler_data['zone'] = zone.extra['selfLink'] # TODO(supertom): we should validate the policy autoscaler_data['autoscalingPolicy'] = policy request = '/zones/%s/autoscalers' % zone.name autoscaler_data['target'] = instance_group.extra['selfLink'] self.connection.async_request(request, method='POST', data=autoscaler_data) return self.ex_get_autoscaler(name, zone) def ex_create_backend(self, instance_group, balancing_mode='UTILIZATION', max_utilization=None, max_rate=None, max_rate_per_instance=None, capacity_scaler=1, description=None): """ Helper Object to create a backend. :param instance_group: The Instance Group for this Backend. :type instance_group: :class: `GCEInstanceGroup` :param balancing_mode: Specifies the balancing mode for this backend. For global HTTP(S) load balancing, the valid values are UTILIZATION (default) and RATE. For global SSL load balancing, the valid values are UTILIZATION (default) and CONNECTION. :type balancing_mode: ``str`` :param max_utilization: Used when balancingMode is UTILIZATION. This ratio defines the CPU utilization target for the group. The default is 0.8. Valid range is [0.0, 1.0]. :type max_utilization: ``float`` :param max_rate: The max requests per second (RPS) of the group. Can be used with either RATE or UTILIZATION balancing modes, but required if RATE mode. For RATE mode, either maxRate or maxRatePerInstance must be set. :type max_rate: ``int`` :param max_rate_per_instance: The max requests per second (RPS) that a single backend instance can handle. This is used to calculate the capacity of the group. Can be used in either balancing mode. For RATE mode, either maxRate or maxRatePerInstance must be set. :type max_rate_per_instance: ``float`` :param capacity_scaler: A multiplier applied to the group's maximum servicing capacity (based on UTILIZATION, RATE, or CONNECTION). Default value is 1, which means the group will serve up to 100% of its configured capacity (depending on balancingMode). A setting of 0 means the group is completely drained, offering 0% of its available capacity. Valid range is [0.0,1.0]. :type capacity_scaler: ``float`` :param description: An optional description of this resource. Provide this property when you create the resource. :type description: ``str`` :return: A GCEBackend object. :rtype: :class: `GCEBackend` """ return GCEBackend( instance_group=instance_group, balancing_mode=balancing_mode, max_utilization=max_utilization, max_rate=max_rate, max_rate_per_instance=max_rate_per_instance, capacity_scaler=capacity_scaler, description=description) def ex_create_backendservice(self, name, healthchecks, backends=[], protocol=None, description=None, timeout_sec=None, enable_cdn=False, port=None, port_name=None): """ Create a global Backend Service. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param name: Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. :type name: ``str`` :param healthchecks: A list of HTTP Health Checks to use for this service. There must be at least one. :type healthchecks: ``list`` of (``str`` or :class:`GCEHealthCheck`) :keyword backends: The list of backends that serve this BackendService. :type backends: ``list`` of :class `GCEBackend` or list of ``dict`` :keyword timeout_sec: How many seconds to wait for the backend before considering it a failed request. Default is 30 seconds. :type timeout_sec: ``integer`` :keyword enable_cdn: If true, enable Cloud CDN for this BackendService. When the load balancing scheme is INTERNAL, this field is not used. :type enable_cdn: ``bool`` :keyword port: Deprecated in favor of port_name. The TCP port to connect on the backend. The default value is 80. This cannot be used for internal load balancing. :type port: ``integer`` :keyword port_name: Name of backend port. The same name should appear in the instance groups referenced by this service. :type port_name: ``str`` :keyword protocol: The protocol this Backend Service uses to communicate with backends. Possible values are HTTP, HTTPS, HTTP2, TCP and SSL. :type protocol: ``str`` :return: A Backend Service object. :rtype: :class:`GCEBackendService` """ backendservice_data = {'name': name, 'healthChecks': [], 'backends': [], 'enableCDN': enable_cdn} for hc in healthchecks: if not hasattr(hc, 'extra'): hc = self.ex_get_healthcheck(name=hc) backendservice_data['healthChecks'].append(hc.extra['selfLink']) for be in backends: if isinstance(be, GCEBackend): backendservice_data['backends'].append(be.to_backend_dict()) else: backendservice_data['backends'].append(be) if port: backendservice_data['port'] = port if port_name: backendservice_data['portName'] = port_name if timeout_sec: backendservice_data['timeoutSec'] = timeout_sec if protocol: if protocol in self.BACKEND_SERVICE_PROTOCOLS: backendservice_data['protocol'] = protocol else: raise ValueError('Protocol must be one of %s' % ','.join(self.BACKEND_SERVICE_PROTOCOLS)) if description: backendservice_data['description'] = description request = '/global/backendServices' self.connection.async_request(request, method='POST', data=backendservice_data) return self.ex_get_backendservice(name) def ex_create_healthcheck(self, name, host=None, path=None, port=None, interval=None, timeout=None, unhealthy_threshold=None, healthy_threshold=None, description=None): """ Create an Http Health Check. :param name: Name of health check :type name: ``str`` :keyword host: Hostname of health check request. Defaults to empty and public IP is used instead. :type host: ``str`` :keyword path: The request path for the check. Defaults to /. :type path: ``str`` :keyword port: The TCP port number for the check. Defaults to 80. :type port: ``int`` :keyword interval: How often (in seconds) to check. Defaults to 5. :type interval: ``int`` :keyword timeout: How long to wait before failing. Defaults to 5. :type timeout: ``int`` :keyword unhealthy_threshold: How many failures before marking unhealthy. Defaults to 2. :type unhealthy_threshold: ``int`` :keyword healthy_threshold: How many successes before marking as healthy. Defaults to 2. :type healthy_threshold: ``int`` :keyword description: The description of the check. Defaults to None. :type description: ``str`` or ``None`` :return: Health Check object :rtype: :class:`GCEHealthCheck` """ hc_data = {} hc_data['name'] = name if host: hc_data['host'] = host if description: hc_data['description'] = description # As of right now, the 'default' values aren't getting set when called # through the API, so set them explicitly hc_data['requestPath'] = path or '/' hc_data['port'] = port or 80 hc_data['checkIntervalSec'] = interval or 5 hc_data['timeoutSec'] = timeout or 5 hc_data['unhealthyThreshold'] = unhealthy_threshold or 2 hc_data['healthyThreshold'] = healthy_threshold or 2 request = '/global/httpHealthChecks' self.connection.async_request(request, method='POST', data=hc_data) return self.ex_get_healthcheck(name) def ex_create_firewall(self, name, allowed=None, denied=None, network='default', target_ranges=None, direction='INGRESS', priority=1000, source_service_accounts=None, target_service_accounts=None, source_ranges=None, source_tags=None, target_tags=None, description=None): """ Create a firewall rule on a network. Rules can be for Ingress or Egress, and they may Allow or Deny traffic. They are also applied in order based on action (Deny, Allow) and Priority. Rules can be applied using various Source and Target filters. Firewall rules should be supplied in the "allowed" or "denied" field. This is a list of dictionaries formatted like so ("ports" is optional): [{"IPProtocol": "", "ports": ""}] For example, to allow tcp on port 8080 and udp on all ports, 'allowed' would be:: [{"IPProtocol": "tcp", "ports": ["8080"]}, {"IPProtocol": "udp"}] Note that valid inputs vary by direction (INGRESS vs EGRESS), action (allow/deny), and source/target filters (tag vs range etc). See `Firewall Reference `_ for more information. :param name: Name of the firewall to be created :type name: ``str`` :param description: Optional description of the rule. :type description: ``str`` :param direction: Direction of the FW rule - "INGRESS" or "EGRESS" Defaults to 'INGRESS'. :type direction: ``str`` :param priority: Priority integer of the rule - lower is applied first. Defaults to 1000 :type priority: ``int`` :param allowed: List of dictionaries with rules for type INGRESS :type allowed: ``list`` of ``dict`` :param denied: List of dictionaries with rules for type EGRESS :type denied: ``list`` of ``dict`` :keyword network: The network that the firewall applies to. :type network: ``str`` or :class:`GCENetwork` :keyword source_ranges: A list of IP ranges in CIDR format that the firewall should apply to. Defaults to ['0.0.0.0/0'] :type source_ranges: ``list`` of ``str`` :keyword source_service_accounts: A list of source service accounts the rules apply to. :type source_service_accounts: ``list`` of ``str`` :keyword source_tags: A list of source instance tags the rules apply to. :type source_tags: ``list`` of ``str`` :keyword target_tags: A list of target instance tags the rules apply to. :type target_tags: ``list`` of ``str`` :keyword target_service_accounts: A list of target service accounts the rules apply to. :type target_service_accounts: ``list`` of ``str`` :keyword target_ranges: A list of IP ranges in CIDR format that the EGRESS type rule should apply to. Defaults to ['0.0.0.0/0'] :type target_ranges: ``list`` of ``str`` :return: Firewall object :rtype: :class:`GCEFirewall` """ firewall_data = {} if not hasattr(network, 'name'): nw = self.ex_get_network(network) else: nw = network firewall_data['name'] = name firewall_data['direction'] = direction firewall_data['priority'] = priority firewall_data['description'] = description if direction == 'INGRESS': firewall_data['allowed'] = allowed elif direction == 'EGRESS': firewall_data['denied'] = denied firewall_data['network'] = nw.extra['selfLink'] if source_ranges is None and source_tags is None \ and source_service_accounts is None: source_ranges = ['0.0.0.0/0'] if source_ranges is not None: firewall_data['sourceRanges'] = source_ranges if source_tags is not None: firewall_data['sourceTags'] = source_tags if source_service_accounts is not None: firewall_data['sourceServiceAccounts'] = source_service_accounts if target_tags is not None: firewall_data['targetTags'] = target_tags if target_service_accounts is not None: firewall_data['targetServiceAccounts'] = target_service_accounts if target_ranges is not None: firewall_data['destinationRanges'] = target_ranges request = '/global/firewalls' self.connection.async_request(request, method='POST', data=firewall_data) return self.ex_get_firewall(name) def ex_create_forwarding_rule(self, name, target=None, region=None, protocol='tcp', port_range=None, address=None, description=None, global_rule=False, targetpool=None, lb_scheme=None): """ Create a forwarding rule. :param name: Name of forwarding rule to be created :type name: ``str`` :keyword target: The target of this forwarding rule. For global forwarding rules this must be a global TargetHttpProxy. For regional rules this may be either a TargetPool or TargetInstance. If passed a string instead of the object, it will be the name of a TargetHttpProxy for global rules or a TargetPool for regional rules. A TargetInstance must be passed by object. (required) :type target: ``str`` or :class:`GCETargetHttpProxy` or :class:`GCETargetInstance` or :class:`GCETargetPool` :keyword region: Region to create the forwarding rule in. Defaults to self.region. Ignored if global_rule is True. :type region: ``str`` or :class:`GCERegion` :keyword protocol: Should be 'tcp' or 'udp' :type protocol: ``str`` :keyword port_range: Single port number or range separated by a dash. Examples: '80', '5000-5999'. Required for global forwarding rules, optional for regional rules. :type port_range: ``str`` :keyword address: Optional static address for forwarding rule. Must be in same region. :type address: ``str`` or :class:`GCEAddress` :keyword description: The description of the forwarding rule. Defaults to None. :type description: ``str`` or ``None`` :keyword targetpool: Deprecated parameter for backwards compatibility. Use target instead. :type targetpool: ``str`` or :class:`GCETargetPool` :keyword lb_scheme: Load balancing scheme, can be 'EXTERNAL' or 'INTERNAL'. Defaults to 'EXTERNAL'. :type lb_scheme: ``str`` or ``None`` :return: Forwarding Rule object :rtype: :class:`GCEForwardingRule` """ forwarding_rule_data = {'name': name} if global_rule: if not hasattr(target, 'name'): target = self.ex_get_targethttpproxy(target) else: region = region or self.region if not hasattr(region, 'name'): region = self.ex_get_region(region) forwarding_rule_data['region'] = region.extra['selfLink'] if not target: target = targetpool # Backwards compatibility if not hasattr(target, 'name'): target = self.ex_get_targetpool(target, region) forwarding_rule_data['target'] = target.extra['selfLink'] forwarding_rule_data['IPProtocol'] = protocol.upper() if address: if not hasattr(address, 'name'): address = self.ex_get_address(address, 'global' if global_rule else region) forwarding_rule_data['IPAddress'] = address.address if port_range: forwarding_rule_data['portRange'] = port_range if description: forwarding_rule_data['description'] = description if lb_scheme: forwarding_rule_data['loadBalancingScheme'] = lb_scheme if global_rule: request = '/global/forwardingRules' else: request = '/regions/%s/forwardingRules' % (region.name) self.connection.async_request(request, method='POST', data=forwarding_rule_data) return self.ex_get_forwarding_rule(name, global_rule=global_rule) def ex_create_image(self, name, volume, description=None, family=None, guest_os_features=None, use_existing=True, wait_for_completion=True, ex_licenses=None, ex_labels=None): """ Create an image from the provided volume. :param name: The name of the image to create. :type name: ``str`` :param volume: The volume to use to create the image, or the Google Cloud Storage URI :type volume: ``str`` or :class:`StorageVolume` :keyword description: Description of the new Image :type description: ``str`` :keyword family: The name of the image family to which this image belongs. If you create resources by specifying an image family instead of a specific image name, the resource uses the latest non-deprecated image that is set with that family name. :type family: ``str`` :keyword guest_os_features: Features of the guest operating system, valid for bootable images only. :type guest_os_features: ``list`` of ``str`` or ``None`` :keyword ex_licenses: List of strings representing licenses to be associated with the image. :type ex_licenses: ``list`` of ``str`` :keyword ex_labels: Labels dictionary for image. :type ex_labels: ``dict`` or ``None`` :keyword use_existing: If True and an image with the given name already exists, return an object for that image instead of attempting to create a new image. :type use_existing: ``bool`` :keyword wait_for_completion: If True, wait until the new image is created before returning a new NodeImage Otherwise, return a new NodeImage instance, and let the user track the creation progress :type wait_for_completion: ``bool`` :return: A GCENodeImage object for the new image :rtype: :class:`GCENodeImage` """ image_data = {} image_data['name'] = name image_data['description'] = description image_data['family'] = family if isinstance(volume, StorageVolume): image_data['sourceDisk'] = volume.extra['selfLink'] image_data['zone'] = volume.extra['zone'].name elif (isinstance(volume, str) and volume.startswith('https://') and volume.endswith('tar.gz')): image_data['rawDisk'] = {'source': volume, 'containerType': 'TAR'} else: raise ValueError('Source must be instance of StorageVolume or URI') if ex_licenses: if isinstance(ex_licenses, str): ex_licenses = [ex_licenses] image_data['licenses'] = ex_licenses if ex_labels: image_data['labels'] = ex_labels if guest_os_features: image_data['guestOsFeatures'] = [] if isinstance(guest_os_features, str): guest_os_features = [guest_os_features] for feature in guest_os_features: image_data['guestOsFeatures'].append({'type': feature}) request = '/global/images' try: if wait_for_completion: self.connection.async_request(request, method='POST', data=image_data) else: self.connection.request(request, method='POST', data=image_data) except ResourceExistsError as e: if not use_existing: raise e return self.ex_get_image(name) def ex_copy_image(self, name, url, description=None, family=None, guest_os_features=None): """ Copy an image to your image collection. :param name: The name of the image :type name: ``str`` :param url: The URL to the image. The URL can start with `gs://` :type url: ``str`` :param description: The description of the image :type description: ``str`` :param family: The family of the image :type family: ``str`` :param guest_os_features: The features of the guest operating system. :type guest_os_features: ``list`` of ``str`` or ``None`` :return: NodeImage object based on provided information or None if an image with that name is not found. :rtype: :class:`NodeImage` or ``None`` """ # The URL for an image can start with gs:// if url.startswith('gs://'): url = url.replace('gs://', 'https://storage.googleapis.com/', 1) image_data = { 'name': name, 'description': description, 'family': family, 'sourceType': 'RAW', 'rawDisk': { 'source': url, }, } if guest_os_features: image_data['guestOsFeatures'] = [] if isinstance(guest_os_features, str): guest_os_features = [guest_os_features] for feature in guest_os_features: image_data['guestOsFeatures'].append({'type': feature}) request = '/global/images' self.connection.async_request(request, method='POST', data=image_data) return self.ex_get_image(name) def ex_create_instancegroup(self, name, zone, description=None, network=None, subnetwork=None, named_ports=None): """ Creates an instance group in the specified project using the parameters that are included in the request. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param name: Required. The name of the instance group. The name must be 1-63 characters long, and comply with RFC1035. :type name: ``str`` :param zone: The URL of the zone where the instance group is located. :type zone: :class:`GCEZone` :keyword description: An optional description of this resource. Provide this property when you create the resource. :type description: ``str`` :keyword network: The URL of the network to which all instances in the instance group belong. :type network: :class:`GCENetwork` :keyword subnetwork: The URL of the subnetwork to which all instances in the instance group belong. :type subnetwork: :class:`GCESubnetwork` :keyword named_ports: Assigns a name to a port number. For example: {name: "http", port: 80} This allows the system to reference ports by the assigned name instead of a port number. Named ports can also contain multiple ports. For example: [{name: "http", port: 80},{name: "http", port: 8080}] Named ports apply to all instances in this instance group. :type named_ports: ``list`` of {'name': ``str``, 'port`: ``int``} :return: `GCEInstanceGroup` object. :rtype: :class:`GCEInstanceGroup` """ zone = zone or self.zone if not hasattr(zone, 'name'): zone = self.ex_get_zone(zone) request = "/zones/%s/instanceGroups" % (zone.name) request_data = {} request_data['name'] = name request_data['zone'] = zone.extra['selfLink'] if description: request_data['description'] = description if network: request_data['network'] = network.extra['selfLink'] if subnetwork: request_data['subnetwork'] = subnetwork.extra['selfLink'] if named_ports: request_data['namedPorts'] = named_ports self.connection.async_request(request, method='POST', data=request_data) return self.ex_get_instancegroup(name, zone) def ex_create_instancegroupmanager(self, name, zone, template, size, base_instance_name=None, description=None): """ Create a Managed Instance Group. :param name: Name of the Instance Group. :type name: ``str`` :param zone: The zone to which the Instance Group belongs :type zone: ``str`` or :class:`GCEZone` or ``None`` :param template: The Instance Template. Should be an instance of GCEInstanceTemplate or a string. :type template: ``str`` or :class:`GCEInstanceTemplate` :param base_instance_name: The prefix for each instance created. If None, Instance Group name will be used. :type base_instance_name: ``str`` :param description: User-supplied text about the Instance Group. :type description: ``str`` :return: An Instance Group Manager object. :rtype: :class:`GCEInstanceGroupManager` """ zone = zone or self.zone if not hasattr(zone, 'name'): zone = self.ex_get_zone(zone) request = '/zones/%s/instanceGroupManagers' % (zone.name) manager_data = {} # If the user gave us a name, we fetch the GCEInstanceTemplate for it. if not hasattr(template, 'name'): template = self.ex_get_instancetemplate(template) manager_data['instanceTemplate'] = template.extra['selfLink'] # If base_instance_name is not set, we use name. manager_data['baseInstanceName'] = name if base_instance_name is not None: manager_data['baseInstanceName'] = base_instance_name manager_data['name'] = name manager_data['targetSize'] = size manager_data['description'] = description self.connection.async_request(request, method='POST', data=manager_data) return self.ex_get_instancegroupmanager(name, zone) def ex_create_route(self, name, dest_range, priority=500, network="default", tags=None, next_hop=None, description=None): """ Create a route. :param name: Name of route to be created :type name: ``str`` :param dest_range: Address range of route in CIDR format. :type dest_range: ``str`` :param priority: Priority value, lower values take precedence :type priority: ``int`` :param network: The network the route belongs to. Can be either the full URL of the network, the name of the network or a libcloud object. :type network: ``str`` or ``GCENetwork`` :param tags: List of instance-tags for routing, empty for all nodes :type tags: ``list`` of ``str`` or ``None`` :param next_hop: Next traffic hop. Use ``None`` for the default Internet gateway, or specify an instance or IP address. :type next_hop: ``str``, ``Node``, or ``None`` :param description: Custom description for the route. :type description: ``str`` or ``None`` :return: Route object :rtype: :class:`GCERoute` """ route_data = {} route_data['name'] = name route_data['destRange'] = dest_range route_data['priority'] = priority route_data['description'] = description if isinstance(network, str) and network.startswith('https://'): network_uri = network elif isinstance(network, str): network = self.ex_get_network(network) network_uri = network.extra['selfLink'] else: network_uri = network.extra['selfLink'] route_data['network'] = network_uri route_data['tags'] = tags if next_hop is None: url = 'https://www.googleapis.com/compute/%s/projects/%s/%s' % ( API_VERSION, self.project, "global/gateways/default-internet-gateway") route_data['nextHopGateway'] = url elif isinstance(next_hop, str): route_data['nextHopIp'] = next_hop else: route_data['nextHopInstance'] = next_hop.extra['selfLink'] request = '/global/routes' self.connection.async_request(request, method='POST', data=route_data) return self.ex_get_route(name) def ex_create_sslcertificate(self, name, certificate=None, private_key=None, description=None): """ Creates a SslCertificate resource in the specified project using the data included in the request. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param name: Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. :type name: ``str`` :param certificate: A string containing local certificate file in PEM format. The certificate chain must be no greater than 5 certs long. The chain must include at least one intermediate cert. :type certificate: ``str`` :param private_key: A string containing a write-only private key in PEM format. Only insert RPCs will include this field. :type private_key: ``str`` :keyword description: An optional description of this resource. Provide this property when you create the resource. :type description: ``str`` :return: `GCESslCertificate` object. :rtype: :class:`GCESslCertificate` """ request = "/global/sslCertificates" % () request_data = {} request_data['name'] = name request_data['certificate'] = certificate request_data['privateKey'] = private_key request_data['description'] = description self.connection.async_request(request, method='POST', data=request_data) return self.ex_get_sslcertificate(name) def ex_create_subnetwork(self, name, cidr=None, network=None, region=None, description=None, privateipgoogleaccess=None, secondaryipranges=None): """ Create a subnetwork. :param name: Name of subnetwork to be created :type name: ``str`` :param cidr: Address range of network in CIDR format. :type cidr: ``str`` :param network: The network name or object this subnet belongs to. :type network: ``str`` or :class:`GCENetwork` :param region: The region the subnetwork belongs to. :type region: ``str`` or :class:`GCERegion` :param description: Custom description for the network. :type description: ``str`` or ``None`` :param privateipgoogleaccess: Allow access to Google services without assigned external IP addresses. :type privateipgoogleaccess: ``bool` or ``None`` :param secondaryipranges: List of dicts of secondary or "alias" IP ranges for this subnetwork in [{"rangeName": "second1", "ipCidrRange": "192.168.168.0/24"}, {k:v, k:v}] format. :type secondaryipranges: ``list`` of ``dict`` or ``None`` :return: Subnetwork object :rtype: :class:`GCESubnetwork` """ if not cidr: raise ValueError("Must provide an IP network in CIDR notation.") if not network: raise ValueError("Must provide a network for the subnetwork.") else: if isinstance(network, GCENetwork): network_url = network.extra['selfLink'] else: if network.startswith('https://'): network_url = network else: network_obj = self.ex_get_network(network) network_url = network_obj.extra['selfLink'] if not region: raise ValueError("Must provide a region for the subnetwork.") else: if isinstance(region, GCERegion): region_url = region.extra['selfLink'] else: if region.startswith('https://'): region_url = region else: region_obj = self.ex_get_region(region) region_url = region_obj.extra['selfLink'] subnet_data = {} subnet_data['name'] = name subnet_data['description'] = description subnet_data['ipCidrRange'] = cidr subnet_data['network'] = network_url subnet_data['region'] = region_url subnet_data['privateIpGoogleAccess'] = privateipgoogleaccess subnet_data['secondaryIpRanges'] = secondaryipranges region_name = region_url.split('/')[-1] request = '/regions/%s/subnetworks' % (region_name) self.connection.async_request(request, method='POST', data=subnet_data) return self.ex_get_subnetwork(name, region_name) def ex_create_network(self, name, cidr, description=None, mode="legacy", routing_mode=None): """ Create a network. In November 2015, Google introduced Subnetworks and suggests using networks with 'auto' generated subnetworks. See, the `subnet docs `_ for more details. Note that libcloud follows the usability pattern from the Cloud SDK (e.g. 'gcloud compute' command-line utility) and uses 'mode' to specify 'auto', 'custom', or 'legacy'. :param name: Name of network to be created :type name: ``str`` :param cidr: Address range of network in CIDR format. :type cidr: ``str`` or ``None`` :param description: Custom description for the network. :type description: ``str`` or ``None`` :param mode: Create a 'auto', 'custom', or 'legacy' network. :type mode: ``str`` :param routing_mode: Create network with 'Global' or 'Regional' routing mode for BGP advertisements. Defaults to 'Regional' :type routing_mode: ``str`` or ``None`` :return: Network object :rtype: :class:`GCENetwork` """ network_data = {} network_data['name'] = name network_data['description'] = description if mode.lower() not in ['auto', 'custom', 'legacy']: raise ValueError("Invalid network mode: '%s'. Must be 'auto', " "'custom', or 'legacy'." % mode) if cidr and mode in ['auto', 'custom']: raise ValueError("Can only specify IPv4Range with 'legacy' mode.") if mode == 'legacy': if not cidr: raise ValueError("Must specify IPv4Range with 'legacy' mode.") network_data['IPv4Range'] = cidr else: network_data['autoCreateSubnetworks'] = (mode.lower() == 'auto') if routing_mode: if routing_mode.lower() not in ['regional', 'global']: raise ValueError("Invalid Routing Mode: '%s'. Must be " "'REGIONAL', or 'GLOBAL'." % routing_mode) else: network_data['routingConfig'] = { 'routingMode': routing_mode.upper() } request = '/global/networks' self.connection.async_request(request, method='POST', data=network_data) return self.ex_get_network(name) def create_node( self, name, size, image, location=None, ex_network='default', ex_subnetwork=None, ex_tags=None, ex_metadata=None, ex_boot_disk=None, use_existing_disk=True, external_ip='ephemeral', internal_ip=None, ex_disk_type='pd-standard', ex_disk_auto_delete=True, ex_service_accounts=None, description=None, ex_can_ip_forward=None, ex_disks_gce_struct=None, ex_nic_gce_struct=None, ex_on_host_maintenance=None, ex_automatic_restart=None, ex_preemptible=None, ex_image_family=None, ex_labels=None, ex_accelerator_type=None, ex_accelerator_count=None, ex_disk_size=None): """ Create a new node and return a node object for the node. :param name: The name of the node to create. :type name: ``str`` :param size: The machine type to use. :type size: ``str`` or :class:`GCENodeSize` :param image: The image to use to create the node (or, if attaching a persistent disk, the image used to create the disk) :type image: ``str`` or :class:`GCENodeImage` or ``None`` :keyword location: The location (zone) to create the node in. :type location: ``str`` or :class:`NodeLocation` or :class:`GCEZone` or ``None`` :keyword ex_network: The network to associate with the node. :type ex_network: ``str`` or :class:`GCENetwork` :keyword ex_subnetwork: The subnetwork to associate with the node. :type ex_subnetwork: ``str`` or :class:`GCESubnetwork` :keyword ex_tags: A list of tags to associate with the node. :type ex_tags: ``list`` of ``str`` or ``None`` :keyword ex_metadata: Metadata dictionary for instance. :type ex_metadata: ``dict`` or ``None`` :keyword ex_boot_disk: The boot disk to attach to the instance. :type ex_boot_disk: :class:`StorageVolume` or ``str`` or ``None`` :keyword use_existing_disk: If True and if an existing disk with the same name/location is found, use that disk instead of creating a new one. :type use_existing_disk: ``bool`` :keyword external_ip: The external IP address to use. If 'ephemeral' (default), a new non-static address will be used. If 'None', then no external address will be used. To use an existing static IP address, a GCEAddress object should be passed in. :type external_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword internal_ip: The private IP address to use. :type internal_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword ex_disk_type: Specify a pd-standard (default) disk or pd-ssd for an SSD disk. :type ex_disk_type: ``str`` or :class:`GCEDiskType` :keyword ex_disk_auto_delete: Indicate that the boot disk should be deleted when the Node is deleted. Set to True by default. :type ex_disk_auto_delete: ``bool`` :keyword ex_service_accounts: Specify a list of serviceAccounts when creating the instance. The format is a list of dictionaries containing email and list of scopes, e.g. [{'email':'default', 'scopes':['compute', ...]}, ...] Scopes can either be full URLs or short names. If not provided, use the 'default' service account email and a scope of 'devstorage.read_only'. Also accepts the aliases defined in 'gcloud compute'. :type ex_service_accounts: ``list`` :keyword description: The description of the node (instance). :type description: ``str`` or ``None`` :keyword ex_can_ip_forward: Set to ``True`` to allow this node to send/receive non-matching src/dst packets. :type ex_can_ip_forward: ``bool`` or ``None`` :keyword ex_disks_gce_struct: Support for passing in the GCE-specific formatted disks[] structure. No attempt is made to ensure proper formatting of the disks[] structure. Using this structure obviates the need of using other disk params like 'ex_boot_disk', etc. See the GCE docs for specific details. :type ex_disks_gce_struct: ``list`` or ``None`` :keyword ex_nic_gce_struct: Support passing in the GCE-specific formatted networkInterfaces[] structure. No attempt is made to ensure proper formatting of the networkInterfaces[] data. Using this structure obviates the need of using 'external_ip' and 'ex_network'. See the GCE docs for details. :type ex_nic_gce_struct: ``list`` or ``None`` :keyword ex_on_host_maintenance: Defines whether node should be terminated or migrated when host machine goes down. Acceptable values are: 'MIGRATE' or 'TERMINATE' (If not supplied, value will be reset to GCE default value for the instance type.) :type ex_on_host_maintenance: ``str`` or ``None`` :keyword ex_automatic_restart: Defines whether the instance should be automatically restarted when it is terminated by Compute Engine. (If not supplied, value will be set to the GCE default value for the instance type.) :type ex_automatic_restart: ``bool`` or ``None`` :keyword ex_preemptible: Defines whether the instance is preemptible. (If not supplied, the instance will not be preemptible) :type ex_preemptible: ``bool`` or ``None`` :keyword ex_image_family: Determine image from an 'Image Family' instead of by name. 'image' should be None to use this keyword. :type ex_image_family: ``str`` or ``None`` :keyword ex_labels: Labels dictionary for instance. :type ex_labels: ``dict`` or ``None`` :keyword ex_accelerator_type: Defines the accelerator to use with this node. Must set 'ex_on_host_maintenance' to 'TERMINATE'. Must include a count of accelerators to use in 'ex_accelerator_count'. :type ex_accelerator_type: ``str`` or ``None`` :keyword ex_accelerator_count: The number of 'ex_accelerator_type' accelerators to attach to the node. :type ex_accelerator_count: ``int`` or ``None`` :keyword ex_disk_size: Defines size of the boot disk. Integer in gigabytes. :type ex_disk_size: ``int`` or ``None`` :return: A Node object for the new node. :rtype: :class:`Node` """ if ex_boot_disk and ex_disks_gce_struct: raise ValueError("Cannot specify both 'ex_boot_disk' and " "'ex_disks_gce_struct'") if image and ex_image_family: raise ValueError("Cannot specify both 'image' and " "'ex_image_family'") if not (image or ex_image_family or ex_boot_disk or ex_disks_gce_struct): raise ValueError("Missing root device or image. Must specify an " "'image', 'ex_image_family', existing " "'ex_boot_disk', or use the " "'ex_disks_gce_struct'.") location = location or self.zone if not hasattr(location, 'name'): location = self.ex_get_zone(location) if not hasattr(size, 'name'): size = self.ex_get_size(size, location) if not hasattr(ex_network, 'name'): ex_network = self.ex_get_network(ex_network) if ex_subnetwork and not hasattr(ex_subnetwork, 'name'): ex_subnetwork = \ self.ex_get_subnetwork(ex_subnetwork, region=self._get_region_from_zone( location)) if ex_image_family: image = self.ex_get_image_from_family(ex_image_family) if image and not hasattr(image, 'name'): image = self.ex_get_image(image) if not hasattr(ex_disk_type, 'name'): ex_disk_type = self.ex_get_disktype(ex_disk_type, zone=location) if ex_boot_disk and not hasattr(ex_boot_disk, 'name'): ex_boot_disk = self.ex_get_volume(ex_boot_disk, zone=location) if ex_accelerator_type and not hasattr(ex_accelerator_type, 'name'): if ex_accelerator_count is None: raise ValueError("Missing accelerator count. Must specify an " "'ex_accelerator_count' when using " "'ex_accelerator_type'.") ex_accelerator_type = self.ex_get_accelerator_type( ex_accelerator_type, zone=location) # Use disks[].initializeParams to auto-create the boot disk if not ex_disks_gce_struct and not ex_boot_disk: ex_disks_gce_struct = [{ 'autoDelete': ex_disk_auto_delete, 'boot': True, 'type': 'PERSISTENT', 'mode': 'READ_WRITE', 'deviceName': name, 'initializeParams': { 'diskName': name, 'diskSizeGb': ex_disk_size, 'diskType': ex_disk_type.extra['selfLink'], 'sourceImage': image.extra['selfLink'] } }] request, node_data = self._create_node_req( name, size, image, location, network=ex_network, tags=ex_tags, metadata=ex_metadata, boot_disk=ex_boot_disk, external_ip=external_ip, internal_ip=internal_ip, ex_disk_type=ex_disk_type, ex_disk_auto_delete=ex_disk_auto_delete, ex_service_accounts=ex_service_accounts, description=description, ex_can_ip_forward=ex_can_ip_forward, ex_disks_gce_struct=ex_disks_gce_struct, ex_nic_gce_struct=ex_nic_gce_struct, ex_on_host_maintenance=ex_on_host_maintenance, ex_automatic_restart=ex_automatic_restart, ex_preemptible=ex_preemptible, ex_subnetwork=ex_subnetwork, ex_labels=ex_labels, ex_accelerator_type=ex_accelerator_type, ex_accelerator_count=ex_accelerator_count) self.connection.async_request(request, method='POST', data=node_data) return self.ex_get_node(name, location.name) def ex_create_instancetemplate( self, name, size, source=None, image=None, disk_type='pd-standard', disk_auto_delete=True, network='default', subnetwork=None, can_ip_forward=None, external_ip='ephemeral', internal_ip=None, service_accounts=None, on_host_maintenance=None, automatic_restart=None, preemptible=None, tags=None, metadata=None, description=None, disks_gce_struct=None, nic_gce_struct=None): """ Creates an instance template in the specified project using the data that is included in the request. If you are creating a new template to update an existing instance group, your new instance template must use the same network or, if applicable, the same subnetwork as the original template. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param name: The name of the node to create. :type name: ``str`` :param size: The machine type to use. :type size: ``str`` or :class:`GCENodeSize` :param image: The image to use to create the node (or, if attaching a persistent disk, the image used to create the disk) :type image: ``str`` or :class:`GCENodeImage` or ``None`` :keyword network: The network to associate with the template. :type network: ``str`` or :class:`GCENetwork` :keyword subnetwork: The subnetwork to associate with the node. :type subnetwork: ``str`` or :class:`GCESubnetwork` :keyword tags: A list of tags to associate with the node. :type tags: ``list`` of ``str`` or ``None`` :keyword metadata: Metadata dictionary for instance. :type metadata: ``dict`` or ``None`` :keyword external_ip: The external IP address to use. If 'ephemeral' (default), a new non-static address will be used. If 'None', then no external address will be used. To use an existing static IP address, a GCEAddress object should be passed in. :type external_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword internal_ip: The private IP address to use. :type internal_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword disk_type: Specify a pd-standard (default) disk or pd-ssd for an SSD disk. :type disk_type: ``str`` or :class:`GCEDiskType` :keyword disk_auto_delete: Indicate that the boot disk should be deleted when the Node is deleted. Set to True by default. :type disk_auto_delete: ``bool`` :keyword service_accounts: Specify a list of serviceAccounts when creating the instance. The format is a list of dictionaries containing email and list of scopes, e.g. [{'email':'default', 'scopes':['compute', ...]}, ...] Scopes can either be full URLs or short names. If not provided, use the 'default' service account email and a scope of 'devstorage.read_only'. Also accepts the aliases defined in 'gcloud compute'. :type service_accounts: ``list`` :keyword description: The description of the node (instance). :type description: ``str`` or ``None`` :keyword can_ip_forward: Set to ``True`` to allow this node to send/receive non-matching src/dst packets. :type can_ip_forward: ``bool`` or ``None`` :keyword disks_gce_struct: Support for passing in the GCE-specific formatted disks[] structure. No attempt is made to ensure proper formatting of the disks[] structure. Using this structure obviates the need of using other disk params like 'ex_boot_disk', etc. See the GCE docs for specific details. :type disks_gce_struct: ``list`` or ``None`` :keyword nic_gce_struct: Support passing in the GCE-specific formatted networkInterfaces[] structure. No attempt is made to ensure proper formatting of the networkInterfaces[] data. Using this structure obviates the need of using 'external_ip' and 'ex_network'. See the GCE docs for details. :type nic_gce_struct: ``list`` or ``None`` :keyword on_host_maintenance: Defines whether node should be terminated or migrated when host machine goes down. Acceptable values are: 'MIGRATE' or 'TERMINATE' (If not supplied, value will be reset to GCE default value for the instance type.) :type ex_on_host_maintenance: ``str`` or ``None`` :keyword automatic_restart: Defines whether the instance should be automatically restarted when it is terminated by Compute Engine. (If not supplied, value will be set to the GCE default value for the instance type.) :type automatic_restart: ``bool`` or ``None`` :keyword preemptible: Defines whether the instance is preemptible. (If not supplied, the instance will not be preemptible) :type preemptible: ``bool`` or ``None`` :return: An Instance Template object. :rtype: :class:`GCEInstanceTemplate` """ request = "/global/instanceTemplates" properties = self._create_instance_properties( name, node_size=size, source=source, image=image, disk_type=disk_type, disk_auto_delete=True, external_ip=external_ip, network=network, subnetwork=subnetwork, can_ip_forward=can_ip_forward, service_accounts=service_accounts, on_host_maintenance=on_host_maintenance, internal_ip=internal_ip, automatic_restart=automatic_restart, preemptible=preemptible, tags=tags, metadata=metadata, description=description, disks_gce_struct=disks_gce_struct, nic_gce_struct=nic_gce_struct, use_selflinks=False) request_data = {'name': name, 'description': description, 'properties': properties} self.connection.async_request(request, method='POST', data=request_data) return self.ex_get_instancetemplate(name) def _create_instance_properties( self, name, node_size, source=None, image=None, disk_type='pd-standard', disk_auto_delete=True, network='default', subnetwork=None, external_ip='ephemeral', internal_ip=None, can_ip_forward=None, service_accounts=None, on_host_maintenance=None, automatic_restart=None, preemptible=None, tags=None, metadata=None, description=None, disks_gce_struct=None, nic_gce_struct=None, use_selflinks=True, labels=None, accelerator_type=None, accelerator_count=None, disk_size=None): """ Create the GCE instance properties needed for instance templates. :param node_size: The machine type to use. :type node_size: ``str`` or :class:`GCENodeSize` :keyword source: A source disk to attach to the instance. Cannot specify both 'image' and 'source'. :type source: :class:`StorageVolume` or ``str`` or ``None`` :param image: The image to use to create the node. Cannot specify both 'image' and 'source'. :type image: ``str`` or :class:`GCENodeImage` or ``None`` :keyword disk_type: Specify a pd-standard (default) disk or pd-ssd for an SSD disk. :type disk_type: ``str`` or :class:`GCEDiskType` :keyword disk_auto_delete: Indicate that the boot disk should be deleted when the Node is deleted. Set to True by default. :type disk_auto_delete: ``bool`` :keyword network: The network to associate with the node. :type network: ``str`` or :class:`GCENetwork` :keyword subnetwork: The Subnetwork resource for this instance. If the network resource is in legacy mode, do not provide this property. If the network is in auto subnet mode, providing the subnetwork is optional. If the network is in custom subnet mode, then this field should be specified. :type subnetwork: :class: `GCESubnetwork` or None :keyword external_ip: The external IP address to use. If 'ephemeral' (default), a new non-static address will be used. If 'None', then no external address will be used. To use an existing static IP address, a GCEAddress object should be passed in. :type external_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword internal_ip: The private IP address to use. :type internal_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword can_ip_forward: Set to ``True`` to allow this node to send/receive non-matching src/dst packets. :type can_ip_forward: ``bool`` or ``None`` :keyword service_accounts: Specify a list of serviceAccounts when creating the instance. The format is a list of dictionaries containing email and list of scopes, e.g. [{'email':'default', 'scopes':['compute', ...]}, ...] Scopes can either be full URLs or short names. If not provided, use the 'default' service account email and a scope of 'devstorage.read_only'. Also accepts the aliases defined in 'gcloud compute'. :type service_accounts: ``list`` :keyword on_host_maintenance: Defines whether node should be terminated or migrated when host machine goes down. Acceptable values are: 'MIGRATE' or 'TERMINATE' (If not supplied, value will be reset to GCE default value for the instance type.) :type on_host_maintenance: ``str`` or ``None`` :keyword automatic_restart: Defines whether the instance should be automatically restarted when it is terminated by Compute Engine. (If not supplied, value will be set to the GCE default value for the instance type.) :type automatic_restart: ``bool`` or ``None`` :keyword preemptible: Defines whether the instance is preemptible. (If not supplied, the instance will not be preemptible) :type preemptible: ``bool`` or ``None`` :keyword tags: A list of tags to associate with the node. :type tags: ``list`` of ``str`` or ``None`` :keyword metadata: Metadata dictionary for instance. :type metadata: ``dict`` or ``None`` :keyword description: The description of the node (instance). :type description: ``str`` or ``None`` :keyword disks_gce_struct: Support for passing in the GCE-specific formatted disks[] structure. No attempt is made to ensure proper formatting of the disks[] structure. Using this structure obviates the need of using other disk params like 'boot_disk', etc. See the GCE docs for specific details. :type disks_gce_struct: ``list`` or ``None`` :keyword nic_gce_struct: Support passing in the GCE-specific formatted networkInterfaces[] structure. No attempt is made to ensure proper formatting of the networkInterfaces[] data. Using this structure obviates the need of using 'external_ip' and 'network'. See the GCE docs for details. :type nic_gce_struct: ``list`` or ``None`` :type labels: Labels dict for instance :type labels: ``dict`` or ``None`` :keyword accelerator_type: Support for passing in the GCE-specifc accelerator type to request for the VM. :type accelerator_type: :class:`GCEAcceleratorType` or ``None`` :keyword accelerator_count: Support for passing in the number of requested 'accelerator_type' accelerators attached to the VM. Will only pay atention to this field if 'accelerator_type' is not None. :type accelerator_count: ``int`` or ``None`` :keyword disk_size: Specify size of the boot disk. Integer in gigabytes. :type disk_size: ``int`` or ``None`` :return: A dictionary formatted for use with the GCE API. :rtype: ``dict`` """ instance_properties = {} # build disks if not image and not source and not disks_gce_struct: raise ValueError("Missing root device or image. Must specify an " "'image', source, or use the " "'disks_gce_struct'.") if source and disks_gce_struct: raise ValueError("Cannot specify both 'source' and " "'disks_gce_struct'. Use one or the other.") if disks_gce_struct: instance_properties['disks'] = disks_gce_struct else: disk_name = None device_name = None if source: disk_name = source.name # TODO(supertom): what about device name? device_name = source.name image = None instance_properties['disks'] = [self._build_disk_gce_struct( device_name, source=source, disk_type=disk_type, image=image, disk_name=disk_name, usage_type='PERSISTENT', mount_mode='READ_WRITE', auto_delete=disk_auto_delete, is_boot=True, use_selflinks=use_selflinks, disk_size=disk_size)] # build network interfaces if nic_gce_struct is not None: if hasattr(external_ip, 'address'): raise ValueError("Cannot specify both a static IP address " "and 'nic_gce_struct'. Use one or the " "other.") if hasattr(network, 'name'): if network.name == 'default': # pylint: disable=no-member # assume this is just the default value from create_node() # and since the user specified ex_nic_gce_struct, the # struct should take precedence network = None else: raise ValueError("Cannot specify both 'network' and " "'nic_gce_struct'. Use one or the " "other.") instance_properties['networkInterfaces'] = nic_gce_struct else: instance_properties['networkInterfaces'] = [ self._build_network_gce_struct( network=network, subnetwork=subnetwork, external_ip=external_ip, use_selflinks=True, internal_ip=internal_ip) ] # build scheduling scheduling = self._build_scheduling_gce_struct( on_host_maintenance, automatic_restart, preemptible) if scheduling: instance_properties['scheduling'] = scheduling # build service accounts/scopes instance_properties[ 'serviceAccounts'] = self._build_service_accounts_gce_list( service_accounts) # build accelerators if accelerator_type is not None: instance_properties['guestAccelerators'] = \ self._format_guest_accelerators(accelerator_type, accelerator_count) # include general properties if description: instance_properties['description'] = str(description) if tags: instance_properties['tags'] = {'items': tags} if metadata: instance_properties['metadata'] = self._format_metadata( fingerprint='na', metadata=metadata) if labels: instance_properties['labels'] = labels if can_ip_forward: instance_properties['canIpForward'] = True instance_properties['machineType'] = self._get_selflink_or_name( obj=node_size, get_selflinks=use_selflinks, objname='size') return instance_properties def _build_disk_gce_struct( self, device_name, source=None, disk_type=None, disk_size=None, image=None, disk_name=None, is_boot=True, mount_mode='READ_WRITE', usage_type='PERSISTENT', auto_delete=True, use_selflinks=True): """ Generates the GCP dict for a disk. :param device_name: Specifies a unique device name of your choice that is reflected into the /dev/disk/by-id/google-* tree of a Linux operating system running within the instance. This name can be used to reference the device for mounting, resizing, and so on, from within the instance. Defaults to disk_name. :type device_name: ``str`` :keyword source: The disk to attach to the instance. :type source: ``str`` of selfLink, :class:`StorageVolume` or None :keyword disk_type: Specify a URL or DiskType object. :type disk_type: ``str`` or :class:`GCEDiskType` or ``None`` :keyword image: The image to use to create the disk. :type image: :class:`GCENodeImage` or ``None`` :keyword disk_size: Integer in gigabytes. :type disk_size: ``int`` :param disk_name: Specifies the disk name. If not specified, the default is to use the device_name. :type disk_name: ``str`` :keyword mount_mode: The mode in which to attach this disk, either READ_WRITE or READ_ONLY. If not specified, the default is to attach the disk in READ_WRITE mode. :type mount_mode: ``str`` :keyword usage_type: Specifies the type of the disk, either SCRATCH or PERSISTENT. If not specified, the default is PERSISTENT. :type usage_type: ``str`` :keyword auto_delete: Indicate that the boot disk should be deleted when the Node is deleted. Set to True by default. :type auto_delete: ``bool`` :return: Dictionary to be used in disk-portion of instance API call. :rtype: ``dict`` """ # validation if source is None and image is None: raise ValueError( "Either the 'source' or 'image' argument must be specified.") if not isinstance(auto_delete, bool): raise ValueError("auto_delete field is not a bool.") if (disk_size is not None and not (isinstance(disk_size, int) or disk_size.isdigit())): raise ValueError("disk_size must be a digit, '%s' provided." % str(disk_size)) mount_modes = ['READ_WRITE', 'READ_ONLY'] if mount_mode not in mount_modes: raise ValueError("mount mode must be one of: %s." % (','.join(mount_modes))) usage_types = ['PERSISTENT', 'SCRATCH'] if usage_type not in usage_types: raise ValueError("usage type must be one of: %s." % (','.join(usage_types))) disk = {} if not disk_name: disk_name = device_name if source is not None: disk['source'] = self._get_selflink_or_name( obj=source, get_selflinks=use_selflinks, objname='volume') else: # create new disk # we need the URL of the image, always. image = self._get_selflink_or_name(obj=image, get_selflinks=True, objname='image') disk_type = self._get_selflink_or_name( obj=disk_type, get_selflinks=use_selflinks, objname='disktype') disk['initializeParams'] = { 'diskName': disk_name, 'diskType': disk_type, 'sourceImage': image, } if disk_size is not None: disk['initializeParams']['diskSizeGb'] = disk_size # add in basic attributes disk.update({'boot': is_boot, 'type': usage_type, 'mode': mount_mode, 'deviceName': device_name, 'autoDelete': auto_delete}) return disk def _get_selflink_or_name(self, obj, get_selflinks=True, objname=None): """ Return the selflink or name, given a name or object. Will try to fetch the appropriate object if necessary (assumes we only need one parameter to fetch the object, no introspection is performed). :param obj: object to test. :type obj: ``str`` or ``object`` :param get_selflinks: Inform if we should return selfLinks or just the name. Default is True. :param get_selflinks: ``bool`` :param objname: string to use in constructing method call :type objname: ``str`` or None :return: URL from extra['selfLink'] or name :rtype: ``str`` """ if get_selflinks: if not hasattr(obj, 'name'): if objname: getobj = getattr(self, 'ex_get_%s' % (objname)) obj = getobj(obj) else: raise ValueError( "objname must be set if selflinks is True.") return obj.extra['selfLink'] else: if not hasattr(obj, 'name'): return obj else: return obj.name def _build_network_gce_struct(self, network, subnetwork=None, external_ip=None, use_selflinks=True, internal_ip=None): """ Build network interface dict for use in the GCE API. Note: Must be wrapped in a list before passing to the GCE API. :param network: The network to associate with the node. :type network: :class:`GCENetwork` :keyword subnetwork: The subnetwork to include. :type subnetwork: :class:`GCESubNetwork` :keyword external_ip: The external IP address to use. If 'ephemeral' (default), a new non-static address will be used. If 'None', then no external address will be used. To use an existing static IP address, a GCEAddress object should be passed in. :type external_ip: :class:`GCEAddress` :keyword internal_ip: The private IP address to use. :type internal_ip: :class:`GCEAddress` or ``str`` :return: network interface dict :rtype: ``dict`` """ ni = {} ni = {'kind': 'compute#instanceNetworkInterface'} if network is None: network = 'default' ni['network'] = self._get_selflink_or_name( obj=network, get_selflinks=use_selflinks, objname='network') if subnetwork: ni['subnetwork'] = self._get_selflink_or_name( obj=subnetwork, get_selflinks=use_selflinks, objname='subnetwork') if external_ip: access_configs = [{'name': 'External NAT', 'type': 'ONE_TO_ONE_NAT'}] if hasattr(external_ip, 'address'): access_configs[0]['natIP'] = external_ip.address ni['accessConfigs'] = access_configs if internal_ip: ni['networkIP'] = internal_ip return ni def _build_service_account_gce_struct( self, service_account, default_email='default', default_scope='devstorage.read_only'): """ Helper to create Service Account dict. Use _build_service_accounts_gce_list to create a list ready for the GCE API. :param: service_account: dictionarie containing email and list of scopes, e.g. [{'email':'default', 'scopes':['compute', ...]}, ...] Scopes can either be full URLs or short names. If not provided, use the 'default' service account email and a scope of 'devstorage.read_only'. Also accepts the aliases defined in 'gcloud compute'. :type service_account: ``dict`` or None :return: dict usable in GCE API call. :rtype: ``dict`` """ if not isinstance(service_account, dict): raise ValueError( "service_account not in the correct format," "'%s - %s'" % (str(type(service_account)), str(service_account))) sa = {} if 'email' not in service_account: sa['email'] = default_email else: sa['email'] = service_account['email'] if 'scopes' not in service_account: sa['scopes'] = [self.AUTH_URL + default_scope] else: ps = [] for scope in service_account['scopes']: if scope.startswith(self.AUTH_URL): ps.append(scope) elif scope in self.SA_SCOPES_MAP: ps.append(self.AUTH_URL + self.SA_SCOPES_MAP[scope]) else: ps.append(self.AUTH_URL + scope) sa['scopes'] = ps return sa def _build_service_accounts_gce_list(self, service_accounts=None, default_email='default', default_scope='devstorage.read_only'): """ Helper to create service account list for GCE API. :keyword service_accounts: Specify a list of serviceAccounts when creating the instance. The format is a list of dictionaries containing email and list of scopes, e.g. [{'email':'default', 'scopes':['compute', ...]}, ...] Scopes can either be full URLs or short names. If not provided, use the 'default' service account email and a scope of 'devstorage.read_only'. Also accepts the aliases defined in 'gcloud compute'. :type service_accounts: ``list`` of ``dict`` or None :return: list of dictionaries usable in the GCE API. :rtype: ``list`` of ``dict`` """ gce_service_accounts = [] if not service_accounts: gce_service_accounts = [{ 'email': default_email, 'scopes': [self.AUTH_URL + default_scope] }] elif not isinstance(service_accounts, list): raise ValueError("service_accounts field is not a list.") else: for sa in service_accounts: gce_service_accounts.append( self._build_service_account_gce_struct(service_account=sa)) return gce_service_accounts def _build_scheduling_gce_struct(self, on_host_maintenance=None, automatic_restart=None, preemptible=None): """ Build the scheduling dict suitable for use with the GCE API. :param on_host_maintenance: Defines whether node should be terminated or migrated when host machine goes down. Acceptable values are: 'MIGRATE' or 'TERMINATE' (If not supplied, value will be reset to GCE default value for the instance type.) :type on_host_maintenance: ``str`` or ``None`` :param automatic_restart: Defines whether the instance should be automatically restarted when it is terminated by Compute Engine. (If not supplied, value will be set to the GCE default value for the instance type.) :type automatic_restart: ``bool`` or ``None`` :param preemptible: Defines whether the instance is preemptible. (If not supplied, the instance will not be preemptible) :type preemptible: ``bool`` or ``None`` :return: A dictionary of scheduling options for the GCE API. :rtype: ``dict`` """ scheduling = {} if preemptible is not None: if isinstance(preemptible, bool): scheduling['preemptible'] = preemptible else: raise ValueError("boolean expected for preemptible") if on_host_maintenance is not None: maint_opts = ['MIGRATE', 'TERMINATE'] if isinstance(on_host_maintenance, str) and on_host_maintenance in maint_opts: if preemptible is True and on_host_maintenance == 'MIGRATE': raise ValueError(("host maintenance cannot be 'MIGRATE' " "if instance is preemptible.")) scheduling['onHostMaintenance'] = on_host_maintenance else: raise ValueError("host maintenance must be one of %s" % (','.join(maint_opts))) if automatic_restart is not None: if isinstance(automatic_restart, bool): if automatic_restart is True and preemptible is True: raise ValueError( "instance cannot be restarted if it is preemptible.") scheduling['automaticRestart'] = automatic_restart else: raise ValueError("boolean expected for automatic") return scheduling def ex_create_multiple_nodes( self, base_name, size, image, number, location=None, ex_network='default', ex_subnetwork=None, ex_tags=None, ex_metadata=None, ignore_errors=True, use_existing_disk=True, poll_interval=2, external_ip='ephemeral', internal_ip=None, ex_disk_type='pd-standard', ex_disk_auto_delete=True, ex_service_accounts=None, timeout=DEFAULT_TASK_COMPLETION_TIMEOUT, description=None, ex_can_ip_forward=None, ex_disks_gce_struct=None, ex_nic_gce_struct=None, ex_on_host_maintenance=None, ex_automatic_restart=None, ex_image_family=None, ex_preemptible=None, ex_labels=None, ex_disk_size=None): """ Create multiple nodes and return a list of Node objects. Nodes will be named with the base name and a number. For example, if the base name is 'libcloud' and you create 3 nodes, they will be named:: libcloud-000 libcloud-001 libcloud-002 :param base_name: The base name of the nodes to create. :type base_name: ``str`` :param size: The machine type to use. :type size: ``str`` or :class:`GCENodeSize` :param image: The image to use to create the nodes. :type image: ``str`` or :class:`GCENodeImage` :param number: The number of nodes to create. :type number: ``int`` :keyword location: The location (zone) to create the nodes in. :type location: ``str`` or :class:`NodeLocation` or :class:`GCEZone` or ``None`` :keyword ex_network: The network to associate with the nodes. :type ex_network: ``str`` or :class:`GCENetwork` :keyword ex_tags: A list of tags to associate with the nodes. :type ex_tags: ``list`` of ``str`` or ``None`` :keyword ex_metadata: Metadata dictionary for instances. :type ex_metadata: ``dict`` or ``None`` :keyword ignore_errors: If True, don't raise Exceptions if one or more nodes fails. :type ignore_errors: ``bool`` :keyword use_existing_disk: If True and if an existing disk with the same name/location is found, use that disk instead of creating a new one. :type use_existing_disk: ``bool`` :keyword poll_interval: Number of seconds between status checks. :type poll_interval: ``int`` :keyword external_ip: The external IP address to use. If 'ephemeral' (default), a new non-static address will be used. If 'None', then no external address will be used. (Static addresses are not supported for multiple node creation.) :type external_ip: ``str`` or None :keyword internal_ip: The private IP address to use. :type internal_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword ex_disk_type: Specify a pd-standard (default) disk or pd-ssd for an SSD disk. :type ex_disk_type: ``str`` or :class:`GCEDiskType` :keyword ex_disk_auto_delete: Indicate that the boot disk should be deleted when the Node is deleted. Set to True by default. :type ex_disk_auto_delete: ``bool`` :keyword ex_service_accounts: Specify a list of serviceAccounts when creating the instance. The format is a list of dictionaries containing email and list of scopes, e.g. [{'email':'default', 'scopes':['compute', ...]}, ...] Scopes can either be full URLs or short names. If not provided, use the 'default' service account email and a scope of 'devstorage.read_only'. Also accepts the aliases defined in 'gcloud compute'. :type ex_service_accounts: ``list`` :keyword timeout: The number of seconds to wait for all nodes to be created before timing out. :type timeout: ``int`` :keyword description: The description of the node (instance). :type description: ``str`` or ``None`` :keyword ex_can_ip_forward: Set to ``True`` to allow this node to send/receive non-matching src/dst packets. :type ex_can_ip_forward: ``bool`` or ``None`` :keyword ex_preemptible: Defines whether the instance is preemptible. (If not supplied, the instance will not be preemptible) :type ex_preemptible: ``bool`` or ``None`` :keyword ex_disks_gce_struct: Support for passing in the GCE-specific formatted disks[] structure. No attempt is made to ensure proper formatting of the disks[] structure. Using this structure obviates the need of using other disk params like 'ex_boot_disk', etc. See the GCE docs for specific details. :type ex_disks_gce_struct: ``list`` or ``None`` :keyword ex_nic_gce_struct: Support passing in the GCE-specific formatted networkInterfaces[] structure. No attempt is made to ensure proper formatting of the networkInterfaces[] data. Using this structure obviates the need of using 'external_ip' and 'ex_network'. See the GCE docs for details. :type ex_nic_gce_struct: ``list`` or ``None`` :keyword ex_on_host_maintenance: Defines whether node should be terminated or migrated when host machine goes down. Acceptable values are: 'MIGRATE' or 'TERMINATE' (If not supplied, value will be reset to GCE default value for the instance type.) :type ex_on_host_maintenance: ``str`` or ``None`` :keyword ex_automatic_restart: Defines whether the instance should be automatically restarted when it is terminated by Compute Engine. (If not supplied, value will be set to the GCE default value for the instance type.) :type ex_automatic_restart: ``bool`` or ``None`` :keyword ex_image_family: Determine image from an 'Image Family' instead of by name. 'image' should be None to use this keyword. :type ex_image_family: ``str`` or ``None`` :param ex_labels: Label dict for node. :type ex_labels: ``dict`` :keyword ex_disk_size: Defines size of the boot disk. Integer in gigabytes. :type ex_disk_size: ``int`` or ``None`` :return: A list of Node objects for the new nodes. :rtype: ``list`` of :class:`Node` """ if image and ex_disks_gce_struct: raise ValueError("Cannot specify both 'image' and " "'ex_disks_gce_struct'.") if image and ex_image_family: raise ValueError("Cannot specify both 'image' and " "'ex_image_family'") location = location or self.zone if not hasattr(location, 'name'): location = self.ex_get_zone(location) if not hasattr(size, 'name'): size = self.ex_get_size(size, location) if not hasattr(ex_network, 'name'): ex_network = self.ex_get_network(ex_network) if ex_subnetwork and not hasattr(ex_subnetwork, 'name'): ex_subnetwork = \ self.ex_get_subnetwork(ex_subnetwork, region=self._get_region_from_zone( location)) if ex_image_family: image = self.ex_get_image_from_family(ex_image_family) if image and not hasattr(image, 'name'): image = self.ex_get_image(image) if not hasattr(ex_disk_type, 'name'): ex_disk_type = self.ex_get_disktype(ex_disk_type, zone=location) node_attrs = {'size': size, 'image': image, 'location': location, 'network': ex_network, 'subnetwork': ex_subnetwork, 'tags': ex_tags, 'metadata': ex_metadata, 'ignore_errors': ignore_errors, 'use_existing_disk': use_existing_disk, 'external_ip': external_ip, 'internal_ip': internal_ip, 'ex_disk_type': ex_disk_type, 'ex_disk_auto_delete': ex_disk_auto_delete, 'ex_service_accounts': ex_service_accounts, 'description': description, 'ex_can_ip_forward': ex_can_ip_forward, 'ex_disks_gce_struct': ex_disks_gce_struct, 'ex_nic_gce_struct': ex_nic_gce_struct, 'ex_on_host_maintenance': ex_on_host_maintenance, 'ex_automatic_restart': ex_automatic_restart, 'ex_preemptible': ex_preemptible, 'ex_labels': ex_labels, 'ex_disk_size': ex_disk_size} # List for holding the status information for disk/node creation. status_list = [] for i in range(number): name = '%s-%03d' % (base_name, i) status = {'name': name, 'node_response': None, 'node': None} status_list.append(status) start_time = time.time() complete = False while not complete: if (time.time() - start_time >= timeout): raise Exception("Timeout (%s sec) while waiting for multiple " "instances") complete = True time.sleep(poll_interval) for status in status_list: # Create the node or check status if already in progress. if not status['node']: if not status['node_response']: self._multi_create_node(status, node_attrs) else: self._multi_check_node(status, node_attrs) # If any of the nodes have not been created (or failed) we are # not done yet. if not status['node']: complete = False # Return list of nodes node_list = [] for status in status_list: node_list.append(status['node']) return node_list def ex_create_targethttpproxy(self, name, urlmap): """ Create a target HTTP proxy. :param name: Name of target HTTP proxy :type name: ``str`` :keyword urlmap: URL map defining the mapping from URl to the backendservice. :type healthchecks: ``str`` or :class:`GCEUrlMap` :return: Target Pool object :rtype: :class:`GCETargetPool` """ targetproxy_data = {'name': name} if not hasattr(urlmap, 'name'): urlmap = self.ex_get_urlmap(urlmap) targetproxy_data['urlMap'] = urlmap.extra['selfLink'] request = '/global/targetHttpProxies' self.connection.async_request(request, method='POST', data=targetproxy_data) return self.ex_get_targethttpproxy(name) def ex_create_targethttpsproxy(self, name, urlmap, sslcertificates, description=None): """ Creates a TargetHttpsProxy resource in the specified project using the data included in the request. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param name: Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long, and comply with RFC1035. Specifically, the name must be 1-63 characters long and match the regular expression [a-z]([-a-z0-9]*[a-z0-9])? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. :type name: ``str`` :param sslcertificates: URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. Currently, exactly one SSL certificate must be specified. :type sslcertificates: ``list`` of :class:`GCESslcertificates` :param urlmap: A fully-qualified or valid partial URL to the UrlMap resource that defines the mapping from URL to the BackendService. :type urlmap: :class:`GCEUrlMap` :keyword description: An optional description of this resource. Provide this property when you create the resource. :type description: ``str`` :return: `GCETargetHttpsProxy` object. :rtype: :class:`GCETargetHttpsProxy` """ request = "/global/targetHttpsProxies" % () request_data = {} request_data['name'] = name request_data['description'] = description request_data['sslCertificates'] = [x.extra['selfLink'] for x in sslcertificates] request_data['urlMap'] = urlmap.extra['selfLink'] self.connection.async_request(request, method='POST', data=request_data) return self.ex_get_targethttpsproxy(name) def ex_create_targetinstance(self, name, zone=None, node=None, description=None, nat_policy="NO_NAT"): """ Create a target instance. :param name: Name of target instance :type name: ``str`` :keyword region: Zone to create the target pool in. Defaults to self.zone :type region: ``str`` or :class:`GCEZone` or ``None`` :keyword node: The actual instance to be used as the traffic target. :type node: ``str`` or :class:`Node` :keyword description: A text description for the target instance :type description: ``str`` or ``None`` :keyword nat_policy: The NAT option for how IPs are NAT'd to the node. :type nat_policy: ``str`` :return: Target Instance object :rtype: :class:`GCETargetInstance` """ zone = zone or self.zone targetinstance_data = {} targetinstance_data['name'] = name if not hasattr(zone, 'name'): zone = self.ex_get_zone(zone) targetinstance_data['zone'] = zone.extra['selfLink'] if node is not None: if not hasattr(node, 'name'): node = self.ex_get_node(node, zone) targetinstance_data['instance'] = node.extra['selfLink'] targetinstance_data['natPolicy'] = nat_policy if description: targetinstance_data['description'] = description request = '/zones/%s/targetInstances' % (zone.name) self.connection.async_request(request, method='POST', data=targetinstance_data) return self.ex_get_targetinstance(name, zone) def ex_create_targetpool(self, name, region=None, healthchecks=None, nodes=None, session_affinity=None, backup_pool=None, failover_ratio=None): """ Create a target pool. :param name: Name of target pool :type name: ``str`` :keyword region: Region to create the target pool in. Defaults to self.region :type region: ``str`` or :class:`GCERegion` or ``None`` :keyword healthchecks: Optional list of health checks to attach :type healthchecks: ``list`` of ``str`` or :class:`GCEHealthCheck` :keyword nodes: Optional list of nodes to attach to the pool :type nodes: ``list`` of ``str`` or :class:`Node` :keyword session_affinity: Optional algorithm to use for session affinity. :type session_affinity: ``str`` :keyword backup_pool: Optional backup targetpool to take over traffic if the failover_ratio is exceeded. :type backup_pool: ``GCETargetPool`` or ``None`` :keyword failover_ratio: The percentage of healthy VMs must fall at or below this value before traffic will be sent to the backup_pool. :type failover_ratio: :class:`GCETargetPool` or ``None`` :return: Target Pool object :rtype: :class:`GCETargetPool` """ targetpool_data = {} region = region or self.region if backup_pool and not failover_ratio: failover_ratio = 0.1 targetpool_data['failoverRatio'] = failover_ratio targetpool_data['backupPool'] = backup_pool.extra['selfLink'] if failover_ratio and not backup_pool: e = "Must supply a backup targetPool when setting failover_ratio" raise ValueError(e) targetpool_data['name'] = name if not hasattr(region, 'name'): region = self.ex_get_region(region) targetpool_data['region'] = region.extra['selfLink'] if healthchecks: if not hasattr(healthchecks[0], 'name'): hc_list = [self.ex_get_healthcheck(h).extra['selfLink'] for h in healthchecks] else: hc_list = [h.extra['selfLink'] for h in healthchecks] targetpool_data['healthChecks'] = hc_list if nodes: if not hasattr(nodes[0], 'name'): node_list = [self.ex_get_node(n, 'all').extra['selfLink'] for n in nodes] else: node_list = [n.extra['selfLink'] for n in nodes] targetpool_data['instances'] = node_list if session_affinity: targetpool_data['sessionAffinity'] = session_affinity request = '/regions/%s/targetPools' % (region.name) self.connection.async_request(request, method='POST', data=targetpool_data) return self.ex_get_targetpool(name, region) def ex_create_urlmap(self, name, default_service): """ Create a URL Map. :param name: Name of the URL Map. :type name: ``str`` :keyword default_service: Default backend service for the map. :type default_service: ``str`` or :class:`GCEBackendService` :return: URL Map object :rtype: :class:`GCEUrlMap` """ urlmap_data = {'name': name} # TODO: support hostRules, pathMatchers, tests if not hasattr(default_service, 'name'): default_service = self.ex_get_backendservice(default_service) urlmap_data['defaultService'] = default_service.extra['selfLink'] request = '/global/urlMaps' self.connection.async_request(request, method='POST', data=urlmap_data) return self.ex_get_urlmap(name) def create_volume(self, size, name, location=None, snapshot=None, image=None, use_existing=True, ex_disk_type='pd-standard', ex_image_family=None): """ Create a volume (disk). :param size: Size of volume to create (in GB). Can be None if image or snapshot is supplied. :type size: ``int`` or ``str`` or ``None`` :param name: Name of volume to create :type name: ``str`` :keyword location: Location (zone) to create the volume in :type location: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :keyword snapshot: Snapshot to create image from :type snapshot: :class:`GCESnapshot` or ``str`` or ``None`` :keyword image: Image to create disk from. :type image: :class:`GCENodeImage` or ``str`` or ``None`` :keyword use_existing: If True and a disk with the given name already exists, return an object for that disk instead of attempting to create a new disk. :type use_existing: ``bool`` :keyword ex_disk_type: Specify a pd-standard (default) disk or pd-ssd for an SSD disk. :type ex_disk_type: ``str`` or :class:`GCEDiskType` :keyword ex_image_family: Determine image from an 'Image Family' instead of by name. 'image' should be None to use this keyword. :type ex_image_family: ``str`` or ``None`` :return: Storage Volume object :rtype: :class:`StorageVolume` """ if image and ex_image_family: raise ValueError("Cannot specify both 'image' and " "'ex_image_family'") if ex_image_family: image = self.ex_get_image_from_family(ex_image_family) request, volume_data, params = self._create_vol_req( size, name, location, snapshot, image, ex_disk_type) try: self.connection.async_request(request, method='POST', data=volume_data, params=params) except ResourceExistsError as e: if not use_existing: raise e return self.ex_get_volume(name, location) def create_volume_snapshot(self, volume, name): """ Create a snapshot of the provided Volume. :param volume: A StorageVolume object :type volume: :class:`StorageVolume` :return: A GCE Snapshot object :rtype: :class:`GCESnapshot` """ snapshot_data = {} snapshot_data['name'] = name request = '/zones/%s/disks/%s/createSnapshot' % ( volume.extra['zone'].name, volume.name) self.connection.async_request(request, method='POST', data=snapshot_data) return self.ex_get_snapshot(name) def list_volume_snapshots(self, volume): """ List snapshots created from the provided volume. For GCE, snapshots are global, but while the volume they were created from still exists, the source disk for the snapshot is tracked. :param volume: A StorageVolume object :type volume: :class:`StorageVolume` :return: A list of Snapshot objects :rtype: ``list`` of :class:`GCESnapshot` """ volume_snapshots = [] volume_link = volume.extra['selfLink'] all_snapshots = self.ex_list_snapshots() for snapshot in all_snapshots: if snapshot.extra['sourceDisk'] == volume_link: volume_snapshots.append(snapshot) return volume_snapshots def ex_update_autoscaler(self, autoscaler): """ Update an autoscaler with new values. To update, change the attributes of the autoscaler object and pass the updated object to the method. :param autoscaler: An Autoscaler object with updated values. :type autoscaler: :class:`GCEAutoscaler` :return: An Autoscaler object representing the new state. :rtype: :class:`GCEAutoscaler`` """ request = '/zones/%s/autoscalers' % (autoscaler.zone.name) as_data = {} as_data['name'] = autoscaler.name as_data['autoscalingPolicy'] = autoscaler.policy as_data['target'] = autoscaler.target.extra['selfLink'] self.connection.async_request(request, method='PUT', data=as_data) return self.ex_get_autoscaler(autoscaler.name, autoscaler.zone) def ex_update_healthcheck(self, healthcheck): """ Update a health check with new values. To update, change the attributes of the health check object and pass the updated object to the method. :param healthcheck: A healthcheck object with updated values. :type healthcheck: :class:`GCEHealthCheck` :return: An object representing the new state of the health check. :rtype: :class:`GCEHealthCheck` """ hc_data = {} hc_data['name'] = healthcheck.name hc_data['requestPath'] = healthcheck.path hc_data['port'] = healthcheck.port hc_data['checkIntervalSec'] = healthcheck.interval hc_data['timeoutSec'] = healthcheck.timeout hc_data['unhealthyThreshold'] = healthcheck.unhealthy_threshold hc_data['healthyThreshold'] = healthcheck.healthy_threshold if healthcheck.extra['host']: hc_data['host'] = healthcheck.extra['host'] if healthcheck.extra['description']: hc_data['description'] = healthcheck.extra['description'] request = '/global/httpHealthChecks/%s' % (healthcheck.name) self.connection.async_request(request, method='PUT', data=hc_data) return self.ex_get_healthcheck(healthcheck.name) def ex_update_firewall(self, firewall): """ Update a firewall with new values. To update, change the attributes of the firewall object and pass the updated object to the method. :param firewall: A firewall object with updated values. :type firewall: :class:`GCEFirewall` :return: An object representing the new state of the firewall. :rtype: :class:`GCEFirewall` """ firewall_data = {} firewall_data['name'] = firewall.name firewall_data['allowed'] = firewall.allowed firewall_data['denied'] = firewall.denied # Priority updates not yet exposed via API firewall_data['network'] = firewall.network.extra['selfLink'] if firewall.source_ranges: firewall_data['sourceRanges'] = firewall.source_ranges if firewall.source_tags: firewall_data['sourceTags'] = firewall.source_tags if firewall.source_service_accounts: firewall_data['sourceServiceAccounts'] = \ firewall.source_service_accounts if firewall.target_tags: firewall_data['targetTags'] = firewall.target_tags if firewall.target_service_accounts: firewall_data['targetServiceAccounts'] = \ firewall.target_service_accounts if firewall.target_ranges: firewall_data['destinationRanges'] = firewall.target_ranges if firewall.extra['description']: firewall_data['description'] = firewall.extra['description'] request = '/global/firewalls/%s' % (firewall.name) self.connection.async_request(request, method='PUT', data=firewall_data) return self.ex_get_firewall(firewall.name) def ex_targethttpsproxy_set_sslcertificates(self, targethttpsproxy, sslcertificates): """ Replaces SslCertificates for TargetHttpsProxy. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param targethttpsproxy: Name of the TargetHttpsProxy resource to set an SslCertificates resource for. :type targethttpsproxy: ``str`` :param sslcertificates: sslcertificates to set. :type sslcertificates: ``list`` of :class:`GCESslCertificates` :return: True :rtype: ``bool`` """ request = "/targetHttpsProxies/%s/setSslCertificates" % ( targethttpsproxy.name) request_data = {'sslCertificates': [x.extra['selfLink'] for x in sslcertificates]} self.connection.async_request(request, method='POST', data=request_data) return True def ex_targethttpsproxy_set_urlmap(self, targethttpsproxy, urlmap): """ Changes the URL map for TargetHttpsProxy. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param targethttpsproxy: Name of the TargetHttpsProxy resource whose URL map is to be set. :type targethttpsproxy: ``str`` :param urlmap: urlmap to set. :type urlmap: :class:`GCEUrlMap` :return: True :rtype: ``bool`` """ request = "/targetHttpsProxies/%s/setUrlMap" % (targethttpsproxy.name) request_data = {'urlMap': urlmap.extra['selfLink']} self.connection.async_request(request, method='POST', data=request_data) return True def ex_targetpool_get_health(self, targetpool, node=None): """ Return a hash of target pool instances and their health. :param targetpool: Targetpool containing healthchecked instances. :type targetpool: :class:`GCETargetPool` :param node: Optional node to specify if only a specific node's health status should be returned :type node: ``str``, ``Node``, or ``None`` :return: List of hashes of instances and their respective health, e.g. [{'node': ``Node``, 'health': 'UNHEALTHY'}, ...] :rtype: ``list`` of ``dict`` """ health = [] region_name = targetpool.region.name request = '/regions/%s/targetPools/%s/getHealth' % (region_name, targetpool.name) if node is not None: if hasattr(node, 'name'): node_name = node.name else: node_name = node nodes = targetpool.nodes for node_object in nodes: if node: if node_name == node_object.name: body = {'instance': node_object.extra['selfLink']} resp = self.connection.request(request, method='POST', data=body).object status = resp['healthStatus'][0]['healthState'] health.append({'node': node_object, 'health': status}) else: body = {'instance': node_object.extra['selfLink']} resp = self.connection.request(request, method='POST', data=body).object status = resp['healthStatus'][0]['healthState'] health.append({'node': node_object, 'health': status}) return health def ex_targetpool_set_backup_targetpool( self, targetpool, backup_targetpool, failover_ratio=0.1): """ Set a backup targetpool. :param targetpool: The existing primary targetpool :type targetpool: :class:`GCETargetPool` :param backup_targetpool: The existing targetpool to use for failover traffic. :type backup_targetpool: :class:`GCETargetPool` :param failover_ratio: The percentage of healthy VMs must fall at or below this value before traffic will be sent to the backup targetpool (default 0.10) :type failover_ratio: ``float`` :return: True if successful :rtype: ``bool`` """ region = targetpool.region.name name = targetpool.name req_data = {'target': backup_targetpool.extra['selfLink']} params = {'failoverRatio': failover_ratio} request = '/regions/%s/targetPools/%s/setBackup' % (region, name) self.connection.async_request(request, method='POST', data=req_data, params=params) return True def ex_targetpool_add_node(self, targetpool, node): """ Add a node to a target pool. :param targetpool: The targetpool to add node to :type targetpool: ``str`` or :class:`GCETargetPool` :param node: The node to add :type node: ``str`` or :class:`Node` :return: True if successful :rtype: ``bool`` """ if not hasattr(targetpool, 'name'): targetpool = self.ex_get_targetpool(targetpool) if hasattr(node, 'name'): node_uri = node.extra['selfLink'] else: if node.startswith('https://'): node_uri = node else: node = self.ex_get_node(node, 'all') node_uri = node.extra['selfLink'] targetpool_data = {'instances': [{'instance': node_uri}]} request = '/regions/%s/targetPools/%s/addInstance' % ( targetpool.region.name, targetpool.name) self.connection.async_request(request, method='POST', data=targetpool_data) if all((node_uri != n) and (not hasattr(n, 'extra') or n.extra['selfLink'] != node_uri) for n in targetpool.nodes): targetpool.nodes.append(node) return True def ex_targetpool_add_healthcheck(self, targetpool, healthcheck): """ Add a health check to a target pool. :param targetpool: The targetpool to add health check to :type targetpool: ``str`` or :class:`GCETargetPool` :param healthcheck: The healthcheck to add :type healthcheck: ``str`` or :class:`GCEHealthCheck` :return: True if successful :rtype: ``bool`` """ if not hasattr(targetpool, 'name'): targetpool = self.ex_get_targetpool(targetpool) if not hasattr(healthcheck, 'name'): healthcheck = self.ex_get_healthcheck(healthcheck) targetpool_data = { 'healthChecks': [{'healthCheck': healthcheck.extra['selfLink']}] } request = '/regions/%s/targetPools/%s/addHealthCheck' % ( targetpool.region.name, targetpool.name) self.connection.async_request(request, method='POST', data=targetpool_data) targetpool.healthchecks.append(healthcheck) return True def ex_targetpool_remove_node(self, targetpool, node): """ Remove a node from a target pool. :param targetpool: The targetpool to remove node from :type targetpool: ``str`` or :class:`GCETargetPool` :param node: The node to remove :type node: ``str`` or :class:`Node` :return: True if successful :rtype: ``bool`` """ if not hasattr(targetpool, 'name'): targetpool = self.ex_get_targetpool(targetpool) if hasattr(node, 'name'): node_uri = node.extra['selfLink'] else: if node.startswith('https://'): node_uri = node else: node = self.ex_get_node(node, 'all') node_uri = node.extra['selfLink'] targetpool_data = {'instances': [{'instance': node_uri}]} request = '/regions/%s/targetPools/%s/removeInstance' % ( targetpool.region.name, targetpool.name) self.connection.async_request(request, method='POST', data=targetpool_data) # Remove node object from node list index = None for i, nd in enumerate(targetpool.nodes): if nd == node_uri or (hasattr(nd, 'extra') and nd.extra['selfLink'] == node_uri): index = i break if index is not None: targetpool.nodes.pop(index) return True def ex_targetpool_remove_healthcheck(self, targetpool, healthcheck): """ Remove a health check from a target pool. :param targetpool: The targetpool to remove health check from :type targetpool: ``str`` or :class:`GCETargetPool` :param healthcheck: The healthcheck to remove :type healthcheck: ``str`` or :class:`GCEHealthCheck` :return: True if successful :rtype: ``bool`` """ if not hasattr(targetpool, 'name'): targetpool = self.ex_get_targetpool(targetpool) if not hasattr(healthcheck, 'name'): healthcheck = self.ex_get_healthcheck(healthcheck) targetpool_data = { 'healthChecks': [{'healthCheck': healthcheck.extra['selfLink']}] } request = '/regions/%s/targetPools/%s/removeHealthCheck' % ( targetpool.region.name, targetpool.name) self.connection.async_request(request, method='POST', data=targetpool_data) # Remove healthcheck object from healthchecks list index = None for i, hc in enumerate(targetpool.healthchecks): if hc.name == healthcheck.name: index = i if index is not None: targetpool.healthchecks.pop(index) return True def ex_instancegroup_add_instances(self, instancegroup, node_list): """ Adds a list of instances to the specified instance group. All of the instances in the instance group must be in the same network/subnetwork. Read Adding instances for more information. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param instancegroup: The Instance Group where you are adding instances. :type instancegroup: :class:``GCEInstanceGroup`` :param node_list: List of nodes to add. :type node_list: ``list`` of :class:`Node` or ``list`` of :class:`GCENode` :return: Return True if successful. :rtype: ``bool`` """ request = "/zones/%s/instanceGroups/%s/addInstances" % ( instancegroup.zone.name, instancegroup.name) request_data = {'instances': [{'instance': x.extra['selfLink']} for x in node_list]} self.connection.async_request(request, method='POST', data=request_data) return True def ex_instancegroup_remove_instances(self, instancegroup, node_list): """ Removes one or more instances from the specified instance group, but does not delete those instances. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param instancegroup: The Instance Group where the specified instances will be removed. :type instancegroup: :class:``GCEInstanceGroup`` :param node_list: List of nodes to add. :type node_list: ``list`` of :class:`Node` or ``list`` of :class:`GCENode` :return: True if successful. :rtype: ``bool`` """ request = "/zones/%s/instanceGroups/%s/removeInstances" % ( instancegroup.zone.name, instancegroup.name) request_data = {'instances': [{'instance': x.extra['selfLink']} for x in node_list]} self.connection.async_request(request, method='POST', data=request_data) return True def ex_instancegroup_list_instances(self, instancegroup): """ Lists the instances in the specified instance group. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :param instancegroup: The Instance Group where from which you want to generate a list of included instances. :type instancegroup: :class:`GCEInstanceGroup` :return: List of :class:`GCENode` objects. :rtype: ``list`` of :class:`GCENode` objects. """ request = "/zones/%s/instanceGroups/%s/listInstances" % ( instancegroup.zone.name, instancegroup.name) # Note: This API requires a 'POST'. response = self.connection.request(request, method='POST').object list_data = [] if 'items' in response: for v in response['items']: instance_info = self._get_components_from_path(v['instance']) list_data.append( self.ex_get_node(instance_info['name'], instance_info[ 'zone'])) return list_data def ex_instancegroup_set_named_ports(self, instancegroup, named_ports=[]): """ Sets the named ports for the specified instance group. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param instancegroup: The Instance Group where where the named ports are updated. :type instancegroup: :class:`GCEInstanceGroup` :param named_ports: Assigns a name to a port number. For example: {name: "http", port: 80} This allows the system to reference ports by the assigned name instead of a port number. Named ports can also contain multiple ports. For example: [{name: "http", port: 80},{name: "http", port: 8080}] Named ports apply to all instances in this instance group. :type named_ports: ``list`` of {'name': ``str``, 'port`: ``int``} :return: Return True if successful. :rtype: ``bool`` """ if not isinstance(named_ports, list): raise ValueError("'named_ports' must be a list of name/port" " dictionaries.") request = "/zones/%s/instanceGroups/%s/setNamedPorts" % ( instancegroup.zone.name, instancegroup.name) request_data = {'namedPorts': named_ports, 'fingerprint': instancegroup.extra['fingerprint']} self.connection.async_request(request, method='POST', data=request_data) return True def ex_destroy_instancegroup(self, instancegroup): """ Deletes the specified instance group. The instances in the group are not deleted. Note that instance group must not belong to a backend service. Read Deleting an instance group for more information. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param instancegroup: The name of the instance group to delete. :type instancegroup: :class:`GCEInstanceGroup` :return: Return True if successful. :rtype: ``bool`` """ request = "/zones/%s/instanceGroups/%s" % (instancegroup.zone.name, instancegroup.name) request_data = {} self.connection.async_request(request, method='DELETE', data=request_data) return True def ex_instancegroupmanager_list_managed_instances(self, manager): """ Lists all of the instances in the Managed Instance Group. Each instance in the list has a currentAction, which indicates the action that the managed instance group is performing on the instance. For example, if the group is still creating an instance, the currentAction is 'CREATING'. Note that 'instanceStatus' might not be available, for example, if currentAction is 'CREATING' or 'RECREATING'. If a previous action failed, the list displays the errors for that failed action. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly 'currentAction' values are one of: 'ABANDONING', 'CREATING', 'DELETING', 'NONE', 'RECREATING', 'REFRESHING', 'RESTARTING' :param manager: Instance Group Manager to operate on. :type manager: :class:`GCEInstanceGroupManager` :return: ``list`` of ``dict`` containing 'name', 'zone', 'lastAttempt', 'currentAction', 'instance' and 'instanceStatus'. :rtype: ``list`` """ request = "/zones/%s/instanceGroupManagers/%s/listManagedInstances" % ( manager.zone.name, manager.name) # Note: This API requires a 'POST'. response = self.connection.request(request, method='POST').object instance_data = [] if 'managedInstances' in response: for i in response['managedInstances']: i['name'] = self._get_components_from_path(i['instance'])[ 'name'] i['zone'] = manager.zone.name instance_data.append(i) return instance_data def ex_instancegroupmanager_set_autohealingpolicies(self, manager, healthcheck, initialdelaysec): """ Set the Autohealing Policies for this Instance Group. :param healthcheck: Healthcheck to add :type healthcheck: :class:`GCEHealthCheck` :param initialdelaysec: The time to allow an instance to boot and applications to fully start before the first health check :type initialdelaysec: ``int`` :return: True if successful :rtype: ``bool`` """ request_data = {} request_data['autoHealingPolicies'] = [{ 'healthCheck': healthcheck.path, 'initialDelaySec': initialdelaysec }] request = "/zones/%s/instanceGroupManagers/%s/" % ( manager.zone.name, manager.name) self.connection.async_request(request, method='PATCH', data=request_data) return True def ex_instancegroupmanager_set_instancetemplate(self, manager, instancetemplate): """ Set the Instance Template for this Instance Group. Existing VMs are not recreated by setting a new InstanceTemplate. :param manager: Instance Group Manager to operate on. :type manager: :class:`GCEInstanceGroupManager` :param instancetemplate: Instance Template to set. :type instancetemplate: :class:`GCEInstanceTemplate` :return: True if successful :rtype: ``bool`` """ req_data = {'instanceTemplate': instancetemplate.extra['selfLink']} request = '/zones/%s/instanceGroupManagers/' \ '%s/setInstanceTemplate' % (manager.zone.name, manager.name) self.connection.async_request(request, method='POST', data=req_data) return True def ex_instancegroupmanager_recreate_instances(self, manager, instances=None): """ Schedules a group action to recreate the specified instances in the managed instance group. The instances are deleted and recreated using the current instance template for the managed instance group. This operation is marked as DONE when the action is scheduled even if the instances have not yet been recreated. You must separately verify the status of the recreating action with the listmanagedinstances method or querying the managed instance group directly. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param manager: Required. The name of the managed instance group. The name must be 1-63 characters long, and comply with RFC1035. :type manager: ``str`` or :class: `GCEInstanceGroupManager` :keyword instances: list of Node objects to be recreated. If equal to None, all instances in the managed instance group are recreated. :type instances: ``list`` of :class: `Node`, ``list`` of instance names (only), ``list`` of instance URIs, or None. :return: Dictionary containing instance URI and currentAction. See ex_instancegroupmanager_list_managed_instances for more details. :rtype: ``dict`` """ instance_uris = [] if not isinstance(manager, GCEInstanceGroupManager) and not isinstance( manager, str): raise ValueError("InstanceGroupManager must be of type str or " "GCEInstanceGroupManager. Type '%s' provided" % (type(manager))) if isinstance(manager, str): manager = self.ex_get_instancegroupmanager(manager) if instances is None: il = self.ex_instancegroupmanager_list_managed_instances(manager) instance_uris = [x['instance'] for x in il] elif isinstance(instances, list): for i in instances: if i.startswith('https://'): instance_uris.append(i) else: instance_uris.append( self.ex_get_node(i, manager.zone).extra['selfLink']) else: raise ValueError("instances must be 'None or " "a list of instance URIs, instance names, or" "Node objects") request = "/zones/%s/instanceGroupManagers/%s/recreateInstances" % ( manager.zone.name, manager.name) request_data = {'instances': instance_uris} self.connection.request(request, method='POST', data=request_data).object return self.ex_instancegroupmanager_list_managed_instances(manager) def ex_instancegroupmanager_delete_instances(self, manager, node_list): """ Remove instances from GCEInstanceGroupManager and destroy the instance Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param manager: Required. The name of the managed instance group. The name must be 1-63 characters long, and comply with RFC1035. :type manager: ``str`` or :class: `GCEInstanceGroupManager` :param node_list: list of Node objects to delete. :type node_list: ``list`` of :class:`Node` :return: True if successful :rtype: ``bool`` """ request = "/zones/%s/instanceGroupManagers/%s/deleteInstances" % ( manager.zone.name, manager.name) request_data = {'instances': [x.extra['selfLink'] for x in node_list]} self.connection.request(request, method='POST', data=request_data).object return True def ex_instancegroupmanager_resize(self, manager, size): """ Set the Instance Template for this Instance Group. :param manager: Instance Group Manager to operate on. :type manager: :class:`GCEInstanceGroupManager` :param size: New size of Managed Instance Group. :type size: ``int`` :return: True if successful :rtype: ``bool`` """ req_params = {'size': size} request = '/zones/%s/instanceGroupManagers/%s/resize' % ( manager.zone.name, manager.name) self.connection.async_request(request, method='POST', params=req_params) return True def reboot_node(self, node): """ Reboot a node. :param node: Node to be rebooted :type node: :class:`Node` :return: True if successful, False if not :rtype: ``bool`` """ request = '/zones/%s/instances/%s/reset' % (node.extra['zone'].name, node.name) self.connection.async_request(request, method='POST', data='ignored') return True def ex_set_node_tags(self, node, tags): """ Set the tags on a Node instance. Note that this updates the node object directly. :param node: Node object :type node: :class:`Node` :param tags: List of tags to apply to the object :type tags: ``list`` of ``str`` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/instances/%s/setTags' % (node.extra['zone'].name, node.name) tags_data = {} tags_data['items'] = tags tags_data['fingerprint'] = node.extra['tags_fingerprint'] self.connection.async_request(request, method='POST', data=tags_data) new_node = self.ex_get_node(node.name, node.extra['zone']) node.extra['tags'] = new_node.extra['tags'] node.extra['tags_fingerprint'] = new_node.extra['tags_fingerprint'] return True def ex_set_node_scheduling(self, node, on_host_maintenance=None, automatic_restart=None): """Set the maintenance behavior for the node. See `Scheduling `_ documentation for more info. :param node: Node object :type node: :class:`Node` :keyword on_host_maintenance: Defines whether node should be terminated or migrated when host machine goes down. Acceptable values are: 'MIGRATE' or 'TERMINATE' (If not supplied, value will be reset to GCE default value for the instance type.) :type on_host_maintenance: ``str`` :keyword automatic_restart: Defines whether the instance should be automatically restarted when it is terminated by Compute Engine. (If not supplied, value will be set to the GCE default value for the instance type.) :type automatic_restart: ``bool`` :return: True if successful. :rtype: ``bool`` """ if not hasattr(node, 'name'): node = self.ex_get_node(node, 'all') if on_host_maintenance is not None: on_host_maintenance = on_host_maintenance.upper() ohm_values = ['MIGRATE', 'TERMINATE'] if on_host_maintenance not in ohm_values: raise ValueError('on_host_maintenance must be one of %s' % ','.join(ohm_values)) request = '/zones/%s/instances/%s/setScheduling' % ( node.extra['zone'].name, node.name) scheduling_data = {} if on_host_maintenance is not None: scheduling_data['onHostMaintenance'] = on_host_maintenance if automatic_restart is not None: scheduling_data['automaticRestart'] = automatic_restart self.connection.async_request(request, method='POST', data=scheduling_data) new_node = self.ex_get_node(node.name, node.extra['zone']) node.extra['scheduling'] = new_node.extra['scheduling'] ohm = node.extra['scheduling'].get('onHostMaintenance') ar = node.extra['scheduling'].get('automaticRestart') success = True if on_host_maintenance not in [None, ohm]: success = False if automatic_restart not in [None, ar]: success = False return success def attach_volume(self, node, volume, device=None, ex_mode=None, ex_boot=False, ex_type=None, ex_source=None, ex_auto_delete=None, ex_initialize_params=None, ex_licenses=None, ex_interface=None): """ Attach a volume to a node. If volume is None, an ex_source URL must be provided. :param node: The node to attach the volume to :type node: :class:`Node` or ``None`` :param volume: The volume to attach. :type volume: :class:`StorageVolume` or ``None`` :keyword device: The device name to attach the volume as. Defaults to volume name. :type device: ``str`` :keyword ex_mode: Either 'READ_WRITE' or 'READ_ONLY' :type ex_mode: ``str`` :keyword ex_boot: If true, disk will be attached as a boot disk :type ex_boot: ``bool`` :keyword ex_type: Specify either 'PERSISTENT' (default) or 'SCRATCH'. :type ex_type: ``str`` :keyword ex_source: URL (full or partial) of disk source. Must be present if not using an existing StorageVolume. :type ex_source: ``str`` or ``None`` :keyword ex_auto_delete: If set, the disk will be auto-deleted if the parent node/instance is deleted. :type ex_auto_delete: ``bool`` or ``None`` :keyword ex_initialize_params: Allow user to pass in full JSON struct of `initializeParams` as documented in GCE's API. :type ex_initialize_params: ``dict`` or ``None`` :keyword ex_licenses: List of strings representing licenses associated with the volume/disk. :type ex_licenses: ``list`` of ``str`` :keyword ex_interface: User can specify either 'SCSI' (default) or 'NVME'. :type ex_interface: ``str`` or ``None`` :return: True if successful :rtype: ``bool`` """ if volume is None and ex_source is None: raise ValueError("Must supply either a StorageVolume or " "set `ex_source` URL for an existing disk.") if volume is None and device is None: raise ValueError("Must supply either a StorageVolume or " "set `device` name.") volume_data = {} if ex_source: volume_data['source'] = ex_source if ex_initialize_params: volume_data['initialzeParams'] = ex_initialize_params if ex_licenses: volume_data['licenses'] = ex_licenses if ex_interface: volume_data['interface'] = ex_interface if ex_type: volume_data['type'] = ex_type if ex_auto_delete: volume_data['autoDelete'] = ex_auto_delete volume_data['source'] = ex_source or volume.extra['selfLink'] volume_data['mode'] = ex_mode or 'READ_WRITE' if device: volume_data['deviceName'] = device else: volume_data['deviceName'] = volume.name volume_data['boot'] = ex_boot request = '/zones/%s/instances/%s/attachDisk' % ( node.extra['zone'].name, node.name) self.connection.async_request(request, method='POST', data=volume_data) return True def ex_resize_volume(self, volume, size): """ Resize a volume to the specified size. :param volume: Volume object to resize :type volume: :class:`StorageVolume` :param size: The size in GB of the volume to resize to. :type size: ``int`` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/disks/%s/resize' % ( volume.extra['zone'].name, volume.name) request_data = {'sizeGb': int(size)} self.connection.async_request( request, method='POST', data=request_data ) return True def detach_volume(self, volume, ex_node=None): """ Detach a volume from a node. :param volume: Volume object to detach :type volume: :class:`StorageVolume` :keyword ex_node: Node object to detach volume from (required) :type ex_node: :class:`Node` :return: True if successful :rtype: ``bool`` """ if not ex_node: return False request = '/zones/%s/instances/%s/detachDisk?deviceName=%s' % ( ex_node.extra['zone'].name, ex_node.name, volume.name) self.connection.async_request(request, method='POST', data='ignored') return True def ex_set_volume_auto_delete(self, volume, node, auto_delete=True): """ Sets the auto-delete flag for a volume attached to a node. :param volume: Volume object to auto-delete :type volume: :class:`StorageVolume` :param ex_node: Node object to auto-delete volume from :type ex_node: :class:`Node` :keyword auto_delete: Flag to set for the auto-delete value :type auto_delete: ``bool`` (default True) :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/instances/%s/setDiskAutoDelete' % ( node.extra['zone'].name, node.name) delete_params = { 'deviceName': volume.name, 'autoDelete': auto_delete, } self.connection.async_request(request, method='POST', params=delete_params) return True def ex_destroy_address(self, address): """ Destroy a static address. :param address: Address object to destroy :type address: ``str`` or :class:`GCEAddress` :return: True if successful :rtype: ``bool`` """ if not hasattr(address, 'name'): address = self.ex_get_address(address) if hasattr(address.region, 'name'): request = '/regions/%s/addresses/%s' % (address.region.name, address.name) else: request = '/global/addresses/%s' % (address.name) self.connection.async_request(request, method='DELETE') return True def ex_destroy_backendservice(self, backendservice): """ Destroy a Backend Service. :param backendservice: BackendService object to destroy :type backendservice: :class:`GCEBackendService` :return: True if successful :rtype: ``bool`` """ request = '/global/backendServices/%s' % backendservice.name self.connection.async_request(request, method='DELETE') return True def ex_delete_image(self, image): """ Delete a specific image resource. :param image: Image object to delete :type image: ``str`` or :class:`GCENodeImage` :return: True if successful :rtype: ``bool`` """ if not hasattr(image, 'name'): image = self.ex_get_image(image) request = '/global/images/%s' % (image.name) self.connection.async_request(request, method='DELETE') return True def ex_deprecate_image(self, image, replacement, state=None, deprecated=None, obsolete=None, deleted=None): """ Deprecate a specific image resource. :param image: Image object to deprecate :type image: ``str`` or :class: `GCENodeImage` :param replacement: Image object to use as a replacement :type replacement: ``str`` or :class: `GCENodeImage` :param state: State of the image :type state: ``str`` :param deprecated: RFC3339 timestamp to mark DEPRECATED :type deprecated: ``str`` or ``None`` :param obsolete: RFC3339 timestamp to mark OBSOLETE :type obsolete: ``str`` or ``None`` :param deleted: RFC3339 timestamp to mark DELETED :type deleted: ``str`` or ``None`` :return: True if successful :rtype: ``bool`` """ if not hasattr(image, 'name'): image = self.ex_get_image(image) if not hasattr(replacement, 'name'): replacement = self.ex_get_image(replacement) if state is None: state = 'DEPRECATED' possible_states = ['ACTIVE', 'DELETED', 'DEPRECATED', 'OBSOLETE'] if state not in possible_states: raise ValueError('state must be one of %s' % ','.join(possible_states)) if state == 'ACTIVE': image_data = {} else: image_data = { 'state': state, 'replacement': replacement.extra['selfLink'], } for attribute, value in [('deprecated', deprecated), ('obsolete', obsolete), ('deleted', deleted)]: if value is None: continue try: timestamp_to_datetime(value) except Exception: raise ValueError('%s must be an RFC3339 timestamp' % attribute) image_data[attribute] = value request = '/global/images/%s/deprecate' % (image.name) self.connection.request(request, method='POST', data=image_data).object return True def ex_destroy_healthcheck(self, healthcheck): """ Destroy a healthcheck. :param healthcheck: Health check object to destroy :type healthcheck: :class:`GCEHealthCheck` :return: True if successful :rtype: ``bool`` """ request = '/global/httpHealthChecks/%s' % (healthcheck.name) self.connection.async_request(request, method='DELETE') return True def ex_destroy_firewall(self, firewall): """ Destroy a firewall. :param firewall: Firewall object to destroy :type firewall: :class:`GCEFirewall` :return: True if successful :rtype: ``bool`` """ request = '/global/firewalls/%s' % (firewall.name) self.connection.async_request(request, method='DELETE') return True def ex_destroy_forwarding_rule(self, forwarding_rule): """ Destroy a forwarding rule. :param forwarding_rule: Forwarding Rule object to destroy :type forwarding_rule: :class:`GCEForwardingRule` :return: True if successful :rtype: ``bool`` """ if forwarding_rule.region: request = '/regions/%s/forwardingRules/%s' % ( forwarding_rule.region.name, forwarding_rule.name) else: request = '/global/forwardingRules/%s' % forwarding_rule.name self.connection.async_request(request, method='DELETE') return True def ex_destroy_route(self, route): """ Destroy a route. :param route: Route object to destroy :type route: :class:`GCERoute` :return: True if successful :rtype: ``bool`` """ request = '/global/routes/%s' % (route.name) self.connection.async_request(request, method='DELETE') return True def ex_destroy_network(self, network): """ Destroy a network. :param network: Network object to destroy :type network: :class:`GCENetwork` :return: True if successful :rtype: ``bool`` """ request = '/global/networks/%s' % (network.name) self.connection.async_request(request, method='DELETE') return True def ex_set_machine_type(self, node, machine_type='n1-standard-1'): """ Set the machine type of the stopped instance. Can be the short-name, a full, or partial URL. :param node: Target node object to change :type node: :class:`Node` :param machine_type: Desired machine type :type machine_type: ``str`` :return: True if successful :rtype: ``bool`` """ request = mt_url = '/zones/%s' % node.extra['zone'].name mt = machine_type.split('/')[-1] mt_url = '%s/machineTypes/%s' % (mt_url, mt) request = '%s/instances/%s/setMachineType' % (request, node.name) body = {"machineType": mt_url} self.connection.async_request(request, method='POST', data=body) return True def start_node(self, node, ex_sync=True): """ Start a node that is stopped and in TERMINATED state. :param node: Node object to start :type node: :class:`Node` :keyword sync: If true, do not return until destroyed or timeout :type sync: ``bool`` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/instances/%s/start' % (node.extra['zone'].name, node.name) if ex_sync: self.connection.async_request(request, method='POST') else: self.connection.request(request, method='POST') return True def stop_node(self, node, ex_sync=True): """ Stop a running node. :param node: Node object to stop :type node: :class:`Node` :keyword sync: If true, do not return until destroyed or timeout :type sync: ``bool`` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/instances/%s/stop' % (node.extra['zone'].name, node.name) if ex_sync: self.connection.async_request(request, method='POST') else: self.connection.request(request, method='POST') return True def ex_start_node(self, node, sync=True): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node, ex_sync=sync) def ex_stop_node(self, node, sync=True): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node, ex_sync=sync) def ex_destroy_instancegroupmanager(self, manager): """ Destroy a managed instance group. This will destroy all instances that belong to the instance group. :param manager: InstanceGroup object to destroy. :type manager: :class:`GCEInstanceGroup` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/instanceGroupManagers/%s' % (manager.zone.name, manager.name) self.connection.async_request(request, method='DELETE') return True def ex_destroy_instancetemplate(self, instancetemplate): """ Deletes the specified instance template. If you delete an instance template that is being referenced from another instance group, the instance group will not be able to create or recreate virtual machine instances. Deleting an instance template is permanent and cannot be undone. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param instancetemplate: The name of the instance template to delete. :type instancetemplate: ``str`` :return instanceTemplate: Return True if successful. :rtype instanceTemplate: ````bool```` """ request = "/global/instanceTemplates/%s" % (instancetemplate.name) request_data = {} self.connection.async_request(request, method='DELETE', data=request_data) return True def ex_destroy_autoscaler(self, autoscaler): """ Destroy an Autoscaler. :param autoscaler: Autoscaler object to destroy. :type autoscaler: :class:`GCEAutoscaler` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/autoscalers/%s' % (autoscaler.zone.name, autoscaler.name) self.connection.async_request(request, method='DELETE') return True def destroy_node(self, node, destroy_boot_disk=False, ex_sync=True): """ Destroy a node. :param node: Node object to destroy :type node: :class:`Node` :keyword destroy_boot_disk: If true, also destroy the node's boot disk. (Note that this keyword is not accessible from the node's .destroy() method.) :type destroy_boot_disk: ``bool`` :keyword ex_sync: If true, do not return until destroyed or timeout :type ex_sync: ``bool`` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/instances/%s' % (node.extra['zone'].name, node.name) if ex_sync: self.connection.async_request(request, method='DELETE') else: self.connection.request(request, method='DELETE') if destroy_boot_disk and node.extra['boot_disk']: node.extra['boot_disk'].destroy() return True def ex_destroy_multiple_nodes(self, node_list, ignore_errors=True, destroy_boot_disk=False, poll_interval=2, timeout=DEFAULT_TASK_COMPLETION_TIMEOUT): """ Destroy multiple nodes at once. :param node_list: List of nodes to destroy :type node_list: ``list`` of :class:`Node` :keyword ignore_errors: If true, don't raise an exception if one or more nodes fails to be destroyed. :type ignore_errors: ``bool`` :keyword destroy_boot_disk: If true, also destroy the nodes' boot disks. :type destroy_boot_disk: ``bool`` :keyword poll_interval: Number of seconds between status checks. :type poll_interval: ``int`` :keyword timeout: Number of seconds to wait for all nodes to be destroyed. :type timeout: ``int`` :return: A list of boolean values. One for each node. True means that the node was successfully destroyed. :rtype: ``list`` of ``bool`` """ status_list = [] complete = False start_time = time.time() for node in node_list: request = '/zones/%s/instances/%s' % (node.extra['zone'].name, node.name) try: response = self.connection.request(request, method='DELETE').object except GoogleBaseError: self._catch_error(ignore_errors=ignore_errors) response = None status = {'node': node, 'node_success': False, 'node_response': response, 'disk_success': not destroy_boot_disk, 'disk_response': None} status_list.append(status) while not complete: if (time.time() - start_time >= timeout): raise Exception("Timeout (%s sec) while waiting to delete " "multiple instances") complete = True for status in status_list: # If one of the operations is running, check the status operation = status['node_response'] or status['disk_response'] delete_disk = False if operation: no_errors = True try: response = self.connection.request(operation[ 'selfLink']).object except GoogleBaseError: self._catch_error(ignore_errors=ignore_errors) no_errors = False response = {'status': 'DONE'} if response['status'] == 'DONE': # If a node was deleted, update status and indicate # that the disk is ready to be deleted. if status['node_response']: status['node_response'] = None status['node_success'] = no_errors delete_disk = True else: status['disk_response'] = None status['disk_success'] = no_errors # If we are destroying disks, and the node has been deleted, # destroy the disk. if delete_disk and destroy_boot_disk: boot_disk = status['node'].extra['boot_disk'] if boot_disk: request = '/zones/%s/disks/%s' % ( boot_disk.extra['zone'].name, boot_disk.name) try: response = self.connection.request( request, method='DELETE').object except GoogleBaseError: self._catch_error(ignore_errors=ignore_errors) no_errors = False response = None status['disk_response'] = response else: # If there is no boot disk, ignore status['disk_success'] = True operation = status['node_response'] or status['disk_response'] if operation: time.sleep(poll_interval) complete = False success = [] for status in status_list: s = status['node_success'] and status['disk_success'] success.append(s) return success def ex_destroy_targethttpproxy(self, targethttpproxy): """ Destroy a target HTTP proxy. :param targethttpproxy: TargetHttpProxy object to destroy :type targethttpproxy: :class:`GCETargetHttpProxy` :return: True if successful :rtype: ``bool`` """ request = '/global/targetHttpProxies/%s' % targethttpproxy.name self.connection.async_request(request, method='DELETE') return True def ex_destroy_targethttpsproxy(self, targethttpsproxy): """ Deletes the specified TargetHttpsProxy resource. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param targethttpsproxy: Name of the TargetHttpsProxy resource to delete. :type targethttpsproxy: ``str`` :return targetHttpsProxy: Return True if successful. :rtype targetHttpsProxy: ````bool```` """ request = "/global/targetHttpsProxies/%s" % (targethttpsproxy.name) request_data = {} self.connection.async_request(request, method='DELETE', data=request_data) return True def ex_destroy_targetinstance(self, targetinstance): """ Destroy a target instance. :param targetinstance: TargetInstance object to destroy :type targetinstance: :class:`GCETargetInstance` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/targetInstances/%s' % (targetinstance.zone.name, targetinstance.name) self.connection.async_request(request, method='DELETE') return True def ex_destroy_targetpool(self, targetpool): """ Destroy a target pool. :param targetpool: TargetPool object to destroy :type targetpool: :class:`GCETargetPool` :return: True if successful :rtype: ``bool`` """ request = '/regions/%s/targetPools/%s' % (targetpool.region.name, targetpool.name) self.connection.async_request(request, method='DELETE') return True def ex_destroy_urlmap(self, urlmap): """ Destroy a URL map. :param urlmap: UrlMap object to destroy :type urlmap: :class:`GCEUrlMap` :return: True if successful :rtype: ``bool`` """ request = '/global/urlMaps/%s' % urlmap.name self.connection.async_request(request, method='DELETE') return True def destroy_volume(self, volume): """ Destroy a volume. :param volume: Volume object to destroy :type volume: :class:`StorageVolume` :return: True if successful :rtype: ``bool`` """ request = '/zones/%s/disks/%s' % (volume.extra['zone'].name, volume.name) self.connection.async_request(request, method='DELETE') return True def destroy_volume_snapshot(self, snapshot): """ Destroy a snapshot. :param snapshot: Snapshot object to destroy :type snapshot: :class:`GCESnapshot` :return: True if successful :rtype: ``bool`` """ request = '/global/snapshots/%s' % (snapshot.name) self.connection.async_request(request, method='DELETE') return True def ex_get_license(self, project, name): """ Return a License object for specified project and name. :param project: The project to reference when looking up the license. :type project: ``str`` :param name: The name of the License :type name: ``str`` :return: A License object for the name :rtype: :class:`GCELicense` """ return GCELicense.lazy(name, project, self) def ex_get_disktype(self, name, zone=None): """ Return a DiskType object based on a name and optional zone. :param name: The name of the DiskType :type name: ``str`` :keyword zone: The zone to search for the DiskType in (set to 'all' to search all zones) :type zone: ``str`` :class:`GCEZone` or ``None`` :return: A DiskType object for the name :rtype: :class:`GCEDiskType` """ zone = self._set_zone(zone) request = '/zones/%s/diskTypes/%s' % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_disktype(response) def ex_get_accelerator_type(self, name, zone=None): """ Return an AcceleratorType object based on a name and zone. :param name: The name of the AcceleratorType :type name: ``str`` :param zone: The zone to search for the AcceleratorType in. :type zone: :class:`GCEZone` :return: An AcceleratorType object for the name :rtype: :class:`GCEAcceleratorType` """ zone = self._set_zone(zone) request = '/zones/%s/acceleratorTypes/%s' % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_accelerator_type(response) def ex_get_address(self, name, region=None): """ Return an Address object based on an address name and optional region. :param name: The name of the address :type name: ``str`` :keyword region: The region to search for the address in (set to 'all' to search all regions) :type region: ``str`` :class:`GCERegion` or ``None`` :return: An Address object for the address :rtype: :class:`GCEAddress` """ if region == 'global': request = '/global/addresses/%s' % (name) else: region = self._set_region(region) or self._find_zone_or_region( name, 'addresses', region=True, res_name='Address') request = '/regions/%s/addresses/%s' % (region.name, name) response = self.connection.request(request, method='GET').object return self._to_address(response) def ex_get_backendservice(self, name): """ Return a Backend Service object based on name :param name: The name of the backend service :type name: ``str`` :return: A BackendService object for the backend service :rtype: :class:`GCEBackendService` """ request = '/global/backendServices/%s' % name response = self.connection.request(request, method='GET').object return self._to_backendservice(response) def ex_get_healthcheck(self, name): """ Return a HealthCheck object based on the healthcheck name. :param name: The name of the healthcheck :type name: ``str`` :return: A GCEHealthCheck object :rtype: :class:`GCEHealthCheck` """ request = '/global/httpHealthChecks/%s' % (name) response = self.connection.request(request, method='GET').object return self._to_healthcheck(response) def ex_get_firewall(self, name): """ Return a Firewall object based on the firewall name. :param name: The name of the firewall :type name: ``str`` :return: A GCEFirewall object :rtype: :class:`GCEFirewall` """ request = '/global/firewalls/%s' % (name) response = self.connection.request(request, method='GET').object return self._to_firewall(response) def ex_get_forwarding_rule(self, name, region=None, global_rule=False): """ Return a Forwarding Rule object based on the forwarding rule name. :param name: The name of the forwarding rule :type name: ``str`` :keyword region: The region to search for the rule in (set to 'all' to search all regions). :type region: ``str`` or ``None`` :keyword global_rule: Set to True to get a global forwarding rule. Region will be ignored if True. :type global_rule: ``bool`` :return: A GCEForwardingRule object :rtype: :class:`GCEForwardingRule` """ if global_rule: request = '/global/forwardingRules/%s' % name else: region = self._set_region(region) or self._find_zone_or_region( name, 'forwardingRules', region=True, res_name='ForwardingRule') request = '/regions/%s/forwardingRules/%s' % (region.name, name) response = self.connection.request(request, method='GET').object return self._to_forwarding_rule(response) def ex_get_image(self, partial_name, ex_project_list=None, ex_standard_projects=True): """ Return an GCENodeImage object based on the name or link provided. :param partial_name: The name, partial name, or full path of a GCE image. :type partial_name: ``str`` :param ex_project_list: The name of the project to list for images. Examples include: 'debian-cloud'. :type ex_project_list: ``str`` or ``list`` of ``str`` or ``None`` :param ex_standard_projects: If true, check in standard projects if the image is not found. :type ex_standard_projects: ``bool`` :return: GCENodeImage object based on provided information or None if an image with that name is not found. :rtype: :class:`GCENodeImage` or raise ``ResourceNotFoundError`` """ if partial_name.startswith('https://'): response = self.connection.request(partial_name, method='GET') return self._to_node_image(response.object) image = self._match_images(ex_project_list, partial_name) if not image and ex_standard_projects: for img_proj, short_list in self.IMAGE_PROJECTS.items(): for short_name in short_list: if partial_name.startswith(short_name): image = self._match_images(img_proj, partial_name) if not image: raise ResourceNotFoundError('Could not find image \'%s\'' % (partial_name), None, None) return image def ex_get_image_from_family(self, image_family, ex_project_list=None, ex_standard_projects=True): """ Return an GCENodeImage object based on an image family name. :param image_family: The name of the 'Image Family' to return the latest image from. :type image_family: ``str`` :param ex_project_list: The name of the project to list for images. Examples include: 'debian-cloud'. :type ex_project_list: ``list`` of ``str``, or ``None`` :param ex_standard_projects: If true, check in standard projects if the image is not found. :type ex_standard_projects: ``bool`` :return: GCENodeImage object based on provided information or ResourceNotFoundError if the image family is not found. :rtype: :class:`GCENodeImage` or raise ``ResourceNotFoundError`` """ def _try_image_family(image_family, project=None): request = '/global/images/family/%s' % (image_family) save_request_path = self.connection.request_path if project: new_request_path = save_request_path.replace(self.project, project) self.connection.request_path = new_request_path try: response = self.connection.request(request, method='GET') image = self._to_node_image(response.object) except ResourceNotFoundError: image = None finally: self.connection.request_path = save_request_path return image image = None if image_family.startswith('https://'): response = self.connection.request(image_family, method='GET') return self._to_node_image(response.object) if not ex_project_list: image = _try_image_family(image_family) else: for img_proj in ex_project_list: image = _try_image_family(image_family, project=img_proj) if image: break if not image and ex_standard_projects: for img_proj, short_list in self.IMAGE_PROJECTS.items(): for short_name in short_list: if image_family.startswith(short_name): image = _try_image_family(image_family, project=img_proj) if image: break if not image: raise ResourceNotFoundError('Could not find image for family ' '\'%s\'' % (image_family), None, None) return image def ex_get_route(self, name): """ Return a Route object based on a route name. :param name: The name of the route :type name: ``str`` :return: A Route object for the named route :rtype: :class:`GCERoute` """ request = '/global/routes/%s' % (name) response = self.connection.request(request, method='GET').object return self._to_route(response) def ex_destroy_sslcertificate(self, sslcertificate): """ Deletes the specified SslCertificate resource. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute :param sslcertificate: Name of the SslCertificate resource to delete. :type sslcertificate: ``str`` :return sslCertificate: Return True if successful. :rtype sslCertificate: ````bool```` """ request = "/global/sslCertificates/%s" % (sslcertificate.name) request_data = {} self.connection.async_request(request, method='DELETE', data=request_data) return True def ex_destroy_subnetwork(self, name, region=None): """ Delete a Subnetwork object based on name and region. :param name: The name, URL or object of the subnetwork :type name: ``str`` or :class:`GCESubnetwork` :keyword region: The region object, name, or URL of the subnetwork :type region: ``str`` or :class:`GCERegion` or ``None`` :return: True if successful :rtype: ``bool`` """ region_name = None subnet_name = None if region: if isinstance(region, GCERegion): region_name = region.name else: if region.startswith('https://'): region_name = region.split('/')[-1] else: region_name = region if isinstance(name, GCESubnetwork): subnet_name = name.name if not region_name: region_name = name.region.name else: if name.startswith('https://'): url_parts = self._get_components_from_path(name) subnet_name = url_parts['name'] if not region_name: region_name = url_parts['region'] else: subnet_name = name if not region_name: region = self._set_region(region) if not region: raise ValueError("Could not determine region for subnetwork.") else: region_name = region.name request = '/regions/%s/subnetworks/%s' % (region_name, subnet_name) self.connection.async_request(request, method='DELETE').object return True def ex_get_subnetwork(self, name, region=None): """ Return a Subnetwork object based on name and region. :param name: The name or URL of the subnetwork :type name: ``str`` :keyword region: The region of the subnetwork :type region: ``str`` or :class:`GCERegion` or ``None`` :return: A Subnetwork object :rtype: :class:`GCESubnetwork` """ region_name = None if name.startswith('https://'): request = name else: if isinstance(region, GCERegion): region_name = region.name elif isinstance(region, str): if region.startswith('https://'): region_name = region.split('/')[-1] else: region_name = region if not region_name: region = self._set_region(region) if not region: raise ValueError( "Could not determine region for subnetwork.") else: region_name = region.name request = '/regions/%s/subnetworks/%s' % (region_name, name) response = self.connection.request(request, method='GET').object return self._to_subnetwork(response) def ex_get_network(self, name): """ Return a Network object based on a network name. :param name: The name or URL of the network :type name: ``str`` :return: A Network object for the network :rtype: :class:`GCENetwork` """ if name.startswith('https://'): request = name else: request = '/global/networks/%s' % (name) response = self.connection.request(request, method='GET').object return self._to_network(response) def ex_get_node(self, name, zone=None): """ Return a Node object based on a node name and optional zone. :param name: The name of the node :type name: ``str`` :keyword zone: The zone to search for the node in. If set to 'all', search all zones for the instance. :type zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :return: A Node object for the node :rtype: :class:`Node` """ zone = self._set_zone(zone) or self._find_zone_or_region( name, 'instances', res_name='Node') request = '/zones/%s/instances/%s' % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_node(response) def ex_get_project(self): """ Return a Project object with project-wide information. :return: A GCEProject object :rtype: :class:`GCEProject` """ response = self.connection.request('', method='GET').object return self._to_project(response) def ex_get_size(self, name, zone=None): """ Return a size object based on a machine type name and zone. :param name: The name of the node :type name: ``str`` :keyword zone: The zone to search for the machine type in :type zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :return: A GCENodeSize object for the machine type :rtype: :class:`GCENodeSize` """ zone = zone or self.zone if not hasattr(zone, 'name'): zone = self.ex_get_zone(zone) request = '/zones/%s/machineTypes/%s' % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_node_size(response) def ex_get_snapshot(self, name): """ Return a Snapshot object based on snapshot name. :param name: The name of the snapshot :type name: ``str`` :return: A GCESnapshot object for the snapshot :rtype: :class:`GCESnapshot` """ request = '/global/snapshots/%s' % (name) response = self.connection.request(request, method='GET').object return self._to_snapshot(response) def ex_get_volume(self, name, zone=None, use_cache=False): """ Return a Volume object based on a volume name and optional zone. To improve performance, we request all disks and allow the user to consult the cache dictionary rather than making an API call. :param name: The name of the volume :type name: ``str`` :keyword zone: The zone to search for the volume in (set to 'all' to search all zones) :type zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :keyword use_cache: Search for the volume in the existing cache of volumes. If True, we omit the API call and search self.volumes_dict. If False, a call to disks/aggregatedList is made prior to searching self._ex_volume_dict. :type use_cache: ``bool`` :return: A StorageVolume object for the volume :rtype: :class:`StorageVolume` """ if not self._ex_volume_dict or use_cache is False: # Make the API call and build volume dictionary self._ex_populate_volume_dict() try: # if zone is of class GCEZone or NodeLocation, get name instead zone = zone.name except AttributeError: pass return self._ex_lookup_volume(name, zone) def ex_get_region(self, name): """ Return a Region object based on the region name. :param name: The name of the region. :type name: ``str`` :return: A GCERegion object for the region :rtype: :class:`GCERegion` """ if name.startswith('https://'): short_name = self._get_components_from_path(name)['name'] request = name else: short_name = name request = '/regions/%s' % (name) # Check region cache first if short_name in self.region_dict: return self.region_dict[short_name] # Otherwise, look up region information response = self.connection.request(request, method='GET').object return self._to_region(response) def ex_get_sslcertificate(self, name): """ Returns the specified SslCertificate resource. Get a list of available SSL certificates by making a list() request. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :param name: Name of the SslCertificate resource to return. :type name: ``str`` :return: `GCESslCertificate` object. :rtype: :class:`GCESslCertificate` """ request = "/global/sslCertificates/%s" % (name) response = self.connection.request(request, method='GET').object return self._to_sslcertificate(response) def ex_get_targethttpproxy(self, name): """ Return a Target HTTP Proxy object based on its name. :param name: The name of the target HTTP proxy. :type name: ``str`` :return: A Target HTTP Proxy object for the pool :rtype: :class:`GCETargetHttpProxy` """ request = '/global/targetHttpProxies/%s' % name response = self.connection.request(request, method='GET').object return self._to_targethttpproxy(response) def ex_get_targethttpsproxy(self, name): """ Returns the specified TargetHttpsProxy resource. Get a list of available target HTTPS proxies by making a list() request. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :param name: Name of the TargetHttpsProxy resource to return. :type name: ``str`` :return: `GCETargetHttpsProxy` object. :rtype: :class:`GCETargetHttpsProxy` """ request = "/global/targetHttpsProxies/%s" % (name) response = self.connection.request(request, method='GET').object return self._to_targethttpsproxy(response) def ex_get_targetinstance(self, name, zone=None): """ Return a TargetInstance object based on a name and optional zone. :param name: The name of the target instance :type name: ``str`` :keyword zone: The zone to search for the target instance in (set to 'all' to search all zones). :type zone: ``str`` or :class:`GCEZone` or ``None`` :return: A TargetInstance object for the instance :rtype: :class:`GCETargetInstance` """ zone = self._set_zone(zone) or self._find_zone_or_region( name, 'targetInstances', res_name='TargetInstance') request = '/zones/%s/targetInstances/%s' % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_targetinstance(response) def ex_get_targetpool(self, name, region=None): """ Return a TargetPool object based on a name and optional region. :param name: The name of the target pool :type name: ``str`` :keyword region: The region to search for the target pool in (set to 'all' to search all regions). :type region: ``str`` or :class:`GCERegion` or ``None`` :return: A TargetPool object for the pool :rtype: :class:`GCETargetPool` """ region = self._set_region(region) or self._find_zone_or_region( name, 'targetPools', region=True, res_name='TargetPool') request = '/regions/%s/targetPools/%s' % (region.name, name) response = self.connection.request(request, method='GET').object return self._to_targetpool(response) def ex_get_urlmap(self, name): """ Return a URL Map object based on name :param name: The name of the url map :type name: ``str`` :return: A URL Map object for the backend service :rtype: :class:`GCEUrlMap` """ request = '/global/urlMaps/%s' % name response = self.connection.request(request, method='GET').object return self._to_urlmap(response) def ex_get_instancegroup(self, name, zone=None): """ Returns the specified Instance Group. Get a list of available instance groups by making a list() request. Scopes needed - one of the following: * https://www.googleapis.com/auth/cloud-platform * https://www.googleapis.com/auth/compute * https://www.googleapis.com/auth/compute.readonly :param name: The name of the instance group. :type name: ``str`` :param zone: The name of the zone where the instance group is located. :type zone: ``str`` :return: `GCEInstanceGroup` object. :rtype: :class:`GCEInstanceGroup` """ zone = self._set_zone(zone) or self._find_zone_or_region( name, 'instanceGroups', region=False, res_name='Instancegroup') request = "/zones/%s/instanceGroups/%s" % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_instancegroup(response) def ex_get_instancegroupmanager(self, name, zone=None): """ Return a InstanceGroupManager object based on a name and optional zone. :param name: The name of the Instance Group Manager. :type name: ``str`` :keyword zone: The zone to search for the Instance Group Manager. Set to 'all' to search all zones. :type zone: ``str`` or :class:`GCEZone` or ``None`` :return: An Instance Group Manager object. :rtype: :class:`GCEInstanceGroupManager` """ zone = self._set_zone(zone) or self._find_zone_or_region( name, 'instanceGroupManagers', region=False, res_name='Instancegroupmanager') request = '/zones/%s/instanceGroupManagers/%s' % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_instancegroupmanager(response) def ex_get_instancetemplate(self, name): """ Return an InstanceTemplate object based on a name and optional zone. :param name: The name of the Instance Template. :type name: ``str`` :return: An Instance Template object. :rtype: :class:`GCEInstanceTemplate` """ request = '/global/instanceTemplates/%s' % (name) response = self.connection.request(request, method='GET').object return self._to_instancetemplate(response) def ex_get_autoscaler(self, name, zone=None): """ Return an Autoscaler object based on a name and optional zone. :param name: The name of the Autoscaler. :type name: ``str`` :keyword zone: The zone to search for the Autoscaler. Set to 'all' to search all zones. :type zone: ``str`` or :class:`GCEZone` or ``None`` :return: An Autoscaler object. :rtype: :class:`GCEAutoscaler` """ zone = self._set_zone(zone) or self._find_zone_or_region( name, 'Autoscalers', region=False, res_name='Autoscalers') request = '/zones/%s/autoscalers/%s' % (zone.name, name) response = self.connection.request(request, method='GET').object return self._to_autoscaler(response) def ex_get_zone(self, name): """ Return a Zone object based on the zone name. :param name: The name of the zone. :type name: ``str`` :return: A GCEZone object for the zone or None if not found :rtype: :class:`GCEZone` or ``None`` """ if name.startswith('https://'): short_name = self._get_components_from_path(name)['name'] request = name else: short_name = name request = '/zones/%s' % (name) # Check zone cache first if short_name in self.zone_dict: return self.zone_dict[short_name] # Otherwise, look up zone information try: response = self.connection.request(request, method='GET').object except ResourceNotFoundError: return None return self._to_zone(response) def _ex_connection_class_kwargs(self): return {'auth_type': self.auth_type, 'project': self.project, 'scopes': self.scopes, 'credential_file': self.credential_file} def _build_volume_dict(self, zone_dict): """ Build a dictionary in [name][zone]=disk format. :param zone_dict: dict in the format of: { items: {key: {api_name:[], key2: api_name:[]}} } :type zone_dict: ``dict`` :return: dict of volumes, organized by name, then zone Format: { 'disk_name': {'zone_name1': disk_info, 'zone_name2': disk_info} } :rtype: ``dict`` """ name_zone_dict = {} for k, v in zone_dict.items(): zone_name = k.replace('zones/', '') disks = v.get('disks', []) for disk in disks: n = disk['name'] name_zone_dict.setdefault(n, {}) name_zone_dict[n].update({zone_name: disk}) return name_zone_dict def _ex_lookup_volume(self, volume_name, zone=None): """ Look up volume by name and zone in volume dict. If zone isn't specified or equals 'all', we return the volume for the first zone, as determined alphabetically. :param volume_name: The name of the volume. :type volume_name: ``str`` :keyword zone: The zone to search for the volume in (set to 'all' to search all zones) :type zone: ``str`` or ``None`` :return: A StorageVolume object for the volume. :rtype: :class:`StorageVolume` or raise ``ResourceNotFoundError``. """ if volume_name not in self._ex_volume_dict: # Possibly added through another thread/process, so re-populate # _volume_dict and try again. If still not found, raise exception. self._ex_populate_volume_dict() if volume_name not in self._ex_volume_dict: raise ResourceNotFoundError( 'Volume name: \'%s\' not found. Zone: %s' % ( volume_name, zone), None, None) # Disk names are not unique across zones, so if zone is None or # 'all', we return the first one we find for that disk name. For # consistency, we sort by keys and set the zone to the first key. if zone is None or zone == 'all': zone = sorted(self._ex_volume_dict[volume_name])[0] volume = self._ex_volume_dict[volume_name].get(zone, None) if not volume: raise ResourceNotFoundError( 'Volume \'%s\' not found for zone %s.' % (volume_name, zone), None, None) return self._to_storage_volume(volume) def _ex_populate_volume_dict(self): """ Fetch the volume information using disks/aggregatedList and store it in _ex_volume_dict. return: ``None`` """ # fill the volume dict by making an aggegatedList call to disks. aggregated_items = self.connection.request_aggregated_items( "disks") # _ex_volume_dict is in the format of: # { 'disk_name' : { 'zone1': disk, 'zone2': disk, ... }} self._ex_volume_dict = self._build_volume_dict( aggregated_items['items']) return None def _catch_error(self, ignore_errors=False): """ Catch an exception and raise it unless asked to ignore it. :keyword ignore_errors: If true, just return the error. Otherwise, raise the error. :type ignore_errors: ``bool`` :return: The exception that was raised. :rtype: :class:`Exception` """ e = sys.exc_info()[1] if ignore_errors: return e else: raise e def _get_components_from_path(self, path): """ Return a dictionary containing name & zone/region from a request path. :param path: HTTP request path (e.g. '/project/pjt-name/zones/us-central1-a/instances/mynode') :type path: ``str`` :return: Dictionary containing name and zone/region of resource :rtype: ``dict`` """ region = None zone = None glob = False components = path.split('/') name = components[-1] if components[-4] == 'regions': region = components[-3] elif components[-4] == 'zones': zone = components[-3] elif components[-3] == 'global': glob = True return {'name': name, 'region': region, 'zone': zone, 'global': glob} def _get_object_by_kind(self, url): """ Fetch a resource and return its object representation by mapping its 'kind' parameter to the appropriate class. Returns ``None`` if url is ``None`` :param url: fully qualified URL of the resource to request from GCE :type url: ``str`` :return: Object representation of the requested resource. "rtype: :class:`object` or ``None`` """ if not url: return None # Relies on GoogleBaseConnection.morph_action_hook to rewrite # the URL to a request response = self.connection.request(url, method='GET').object return GCENodeDriver.KIND_METHOD_MAP[response['kind']](self, response) def _get_region_from_zone(self, zone): """ Return the Region object that contains the given Zone object. :param zone: Zone object :type zone: :class:`GCEZone` :return: Region object that contains the zone :rtype: :class:`GCERegion` """ for region in self.region_list: zones = [z.name for z in region.zones] if zone.name in zones: return region def _find_zone_or_region(self, name, res_type, region=False, res_name=None): """ Find the zone or region for a named resource. :param name: Name of resource to find :type name: ``str`` :param res_type: Type of resource to find. Examples include: 'disks', 'instances' or 'addresses' :type res_type: ``str`` :keyword region: If True, search regions instead of zones :type region: ``bool`` :keyword res_name: The name of the resource type for error messages. Examples: 'Volume', 'Node', 'Address' :keyword res_name: ``str`` :return: Zone/Region object for the zone/region for the resource. :rtype: :class:`GCEZone` or :class:`GCERegion` """ if region: rz = 'region' else: rz = 'zone' rz_name = None res_name = res_name or res_type res_list = self.connection.request_aggregated_items(res_type) for k, v in res_list['items'].items(): for res in v.get(res_type, []): if res['name'] == name: rz_name = k.replace('%ss/' % (rz), '') break if not rz_name: raise ResourceNotFoundError('%s \'%s\' not found in any %s.' % (res_name, name, rz), None, None) else: getrz = getattr(self, 'ex_get_%s' % (rz)) return getrz(rz_name) def _match_images(self, project, partial_name): """ Find the latest image, given a partial name. For example, providing 'debian-7' will return the image object for the most recent image with a name that starts with 'debian-7' in the supplied project. If no project is given, it will search your own project. :param project: The name of the project to search for images. Examples include: 'debian-cloud' and 'centos-cloud'. :type project: ``str``, ``list`` of ``str``, or ``None`` :param partial_name: The full name or beginning of a name for an image. :type partial_name: ``str`` :return: The latest image object that matches the partial name or None if no matching image is found. :rtype: :class:`GCENodeImage` or ``None`` """ project_images_list = self.ex_list( self.list_images, ex_project=project, ex_include_deprecated=True) partial_match = [] for page in project_images_list.page(): for image in page: if image.name == partial_name: return image if image.name.startswith(partial_name): ts = timestamp_to_datetime( image.extra['creationTimestamp']) if not partial_match or partial_match[0] < ts: partial_match = [ts, image] if partial_match: return partial_match[1] def _set_region(self, region): """ Return the region to use for listing resources. :param region: A name, region object, None, or 'all' :type region: ``str`` or :class:`GCERegion` or ``None`` :return: A region object or None if all regions should be considered :rtype: :class:`GCERegion` or ``None`` """ region = region or self.region if region == 'all' or region is None: return None if not hasattr(region, 'name'): region = self.ex_get_region(region) return region def _set_zone(self, zone): """ Return the zone to use for listing resources. :param zone: A name, zone object, None, or 'all' :type zone: ``str`` or :class:`GCEZone` or ``None`` :return: A zone object or None if all zones should be considered :rtype: :class:`GCEZone` or ``None`` """ zone = zone or self.zone if zone == 'all' or zone is None: return None if not hasattr(zone, 'name'): zone = self.ex_get_zone(zone) return zone def _create_node_req( self, name, size, image, location, network=None, tags=None, metadata=None, boot_disk=None, external_ip='ephemeral', internal_ip=None, ex_disk_type='pd-standard', ex_disk_auto_delete=True, ex_service_accounts=None, description=None, ex_can_ip_forward=None, ex_disks_gce_struct=None, ex_nic_gce_struct=None, ex_on_host_maintenance=None, ex_automatic_restart=None, ex_preemptible=None, ex_subnetwork=None, ex_labels=None, ex_accelerator_type=None, ex_accelerator_count=None, ex_disk_size=None): """ Returns a request and body to create a new node. This is a helper method to support both :class:`create_node` and :class:`ex_create_multiple_nodes`. :param name: The name of the node to create. :type name: ``str`` :param size: The machine type to use. :type size: :class:`GCENodeSize` :param image: The image to use to create the node (or, if using a persistent disk, the image the disk was created from). :type image: :class:`GCENodeImage` or ``None`` :param location: The location (zone) to create the node in. :type location: :class:`NodeLocation` or :class:`GCEZone` :param network: The network to associate with the node. :type network: :class:`GCENetwork` :keyword tags: A list of tags to associate with the node. :type tags: ``list`` of ``str`` :keyword metadata: Metadata dictionary for instance. :type metadata: ``dict`` :keyword boot_disk: Persistent boot disk to attach. :type :class:`StorageVolume` or ``None`` :keyword external_ip: The external IP address to use. If 'ephemeral' (default), a new non-static address will be used. If 'None', then no external address will be used. To use an existing static IP address, a GCEAddress object should be passed in. This param will be ignored if also using the ex_nic_gce_struct param. :type external_ip: :class:`GCEAddress` or ``str`` or None :keyword internal_ip: The private IP address to use. :type internal_ip: :class:`GCEAddress` or ``str`` or ``None`` :keyword ex_disk_type: Specify a pd-standard (default) disk or pd-ssd for an SSD disk. :type ex_disk_type: ``str`` or :class:`GCEDiskType` or ``None`` :keyword ex_disk_auto_delete: Indicate that the boot disk should be deleted when the Node is deleted. Set to True by default. :type ex_disk_auto_delete: ``bool`` :keyword ex_service_accounts: Specify a list of serviceAccounts when creating the instance. The format is a list of dictionaries containing email and list of scopes, e.g. [{'email':'default', 'scopes':['compute', ...]}, ...] Scopes can either be full URLs or short names. If not provided, use the 'default' service account email and a scope of 'devstorage.read_only'. Also accepts the aliases defined in 'gcloud compute'. :type ex_service_accounts: ``list`` :keyword description: The description of the node (instance). :type description: ``str`` or ``None`` :keyword ex_can_ip_forward: Set to ``True`` to allow this node to send/receive non-matching src/dst packets. :type ex_can_ip_forward: ``bool`` or ``None`` :keyword ex_disks_gce_struct: Support for passing in the GCE-specific formatted disks[] structure. No attempt is made to ensure proper formatting of the disks[] structure. Using this structure obviates the need of using other disk params like 'boot_disk', etc. See the GCE docs for specific details. :type ex_disks_gce_struct: ``list`` or ``None`` :keyword ex_nic_gce_struct: Support passing in the GCE-specific formatted networkInterfaces[] structure. No attempt is made to ensure proper formatting of the networkInterfaces[] data. Using this structure obviates the need of using 'external_ip' and 'ex_network'. See the GCE docs for details. :type ex_nic_gce_struct: ``list`` or ``None`` :keyword ex_on_host_maintenance: Defines whether node should be terminated or migrated when host machine goes down. Acceptable values are: 'MIGRATE' or 'TERMINATE' (If not supplied, value will be reset to GCE default value for the instance type.) :type ex_on_host_maintenance: ``str`` or ``None`` :keyword ex_automatic_restart: Defines whether the instance should be automatically restarted when it is terminated by Compute Engine. (If not supplied, value will be set to the GCE default value for the instance type.) :type ex_automatic_restart: ``bool`` or ``None`` :keyword ex_preemptible: Defines whether the instance is preemptible. (If not supplied, the instance will not be preemptible) :type ex_preemptible: ``bool`` or ``None`` :param ex_subnetwork: The network to associate with the node. :type ex_subnetwork: :class:`GCESubnetwork` :keyword ex_disk_size: Specify the size of boot disk. Integer in gigabytes. :type ex_disk_size: ``int`` or ``None`` :param ex_labels: Label dict for node. :type ex_labels: ``dict`` or ``None`` :param ex_accelerator_type: The accelerator to associate with the node. :type ex_accelerator_type: :class:`GCEAcceleratorType` or ``None`` :param ex_accelerator_count: The number of accelerators to associate with the node. :type ex_accelerator_count: ``int`` or ``None`` :keyword ex_disk_size: Specify size of the boot disk. Integer in gigabytes. :type ex_disk_size: ``int`` or ``None`` :return: A tuple containing a request string and a node_data dict. :rtype: ``tuple`` of ``str`` and ``dict`` """ # build disks if not image and not boot_disk and not ex_disks_gce_struct: raise ValueError("Missing root device or image. Must specify an " "'image', existing 'boot_disk', or use the " "'ex_disks_gce_struct'.") if boot_disk and ex_disks_gce_struct: raise ValueError("Cannot specify both 'boot_disk' and " "'ex_disks_gce_struct'. Use one or the other.") use_selflinks = True source = None if boot_disk: source = boot_disk node_data = self._create_instance_properties( name, node_size=size, image=image, source=source, disk_type=ex_disk_type, disk_auto_delete=ex_disk_auto_delete, external_ip=external_ip, network=network, subnetwork=ex_subnetwork, can_ip_forward=ex_can_ip_forward, internal_ip=internal_ip, service_accounts=ex_service_accounts, on_host_maintenance=ex_on_host_maintenance, automatic_restart=ex_automatic_restart, preemptible=ex_preemptible, tags=tags, metadata=metadata, labels=ex_labels, description=description, disks_gce_struct=ex_disks_gce_struct, nic_gce_struct=ex_nic_gce_struct, accelerator_type=ex_accelerator_type, accelerator_count=ex_accelerator_count, use_selflinks=use_selflinks, disk_size=ex_disk_size) node_data['name'] = name request = '/zones/%s/instances' % (location.name) return request, node_data def _multi_create_disk(self, status, node_attrs): """Create disk for ex_create_multiple_nodes. :param status: Dictionary for holding node/disk creation status. (This dictionary is modified by this method) :type status: ``dict`` :param node_attrs: Dictionary for holding node attribute information. (size, image, location, ex_disk_type, etc.) :type node_attrs: ``dict`` """ disk = None # Check for existing disk if node_attrs['use_existing_disk']: try: disk = self.ex_get_volume(status['name'], node_attrs['location']) except ResourceNotFoundError: pass if disk: status['disk'] = disk else: # Create disk and return response object back in the status dict. # Or, if there is an error, mark as failed. disk_req, disk_data, disk_params = self._create_vol_req( None, status['name'], location=node_attrs['location'], image=node_attrs['image'], ex_disk_type=node_attrs['ex_disk_type']) try: disk_res = self.connection.request(disk_req, method='POST', data=disk_data, params=disk_params).object except GoogleBaseError: e = self._catch_error( ignore_errors=node_attrs['ignore_errors']) error = e.value code = e.code disk_res = None status['disk'] = GCEFailedDisk(status['name'], error, code) status['disk_response'] = disk_res def _multi_check_disk(self, status, node_attrs): """Check disk status for ex_create_multiple_nodes. :param status: Dictionary for holding node/disk creation status. (This dictionary is modified by this method) :type status: ``dict`` :param node_attrs: Dictionary for holding node attribute information. (size, image, location, etc.) :type node_attrs: ``dict`` """ error = None try: response = self.connection.request(status['disk_response'][ 'selfLink']).object except GoogleBaseError: e = self._catch_error(ignore_errors=node_attrs['ignore_errors']) error = e.value code = e.code response = {'status': 'DONE'} if response['status'] == 'DONE': status['disk_response'] = None if error: status['disk'] = GCEFailedDisk(status['name'], error, code) else: status['disk'] = self.ex_get_volume(status['name'], node_attrs['location']) def _multi_create_node(self, status, node_attrs): """Create node for ex_create_multiple_nodes. :param status: Dictionary for holding node creation status. (This dictionary is modified by this method) :type status: ``dict`` :param node_attrs: Dictionary for holding node attribute information. (size, image, location, etc.) :type node_attrs: ``dict`` """ # Create node and return response object in status dictionary. # Or, if there is an error, mark as failed. request, node_data = self._create_node_req( status['name'], node_attrs['size'], node_attrs['image'], node_attrs['location'], node_attrs['network'], node_attrs['tags'], node_attrs['metadata'], external_ip=node_attrs['external_ip'], internal_ip=node_attrs['internal_ip'], ex_service_accounts=node_attrs['ex_service_accounts'], description=node_attrs['description'], ex_can_ip_forward=node_attrs['ex_can_ip_forward'], ex_disk_auto_delete=node_attrs['ex_disk_auto_delete'], ex_disks_gce_struct=node_attrs['ex_disks_gce_struct'], ex_nic_gce_struct=node_attrs['ex_nic_gce_struct'], ex_on_host_maintenance=node_attrs['ex_on_host_maintenance'], ex_automatic_restart=node_attrs['ex_automatic_restart'], ex_subnetwork=node_attrs['subnetwork'], ex_preemptible=node_attrs['ex_preemptible'], ex_labels=node_attrs['ex_labels'], ex_disk_size=node_attrs['ex_disk_size'] ) try: node_res = self.connection.request(request, method='POST', data=node_data).object except GoogleBaseError: e = self._catch_error(ignore_errors=node_attrs['ignore_errors']) error = e.value code = e.code node_res = None status['node'] = GCEFailedNode(status['name'], error, code) status['node_response'] = node_res def _multi_check_node(self, status, node_attrs): """Check node status for ex_create_multiple_nodes. :param status: Dictionary for holding node/disk creation status. (This dictionary is modified by this method) :type status: ``dict`` :param node_attrs: Dictionary for holding node attribute information. (size, image, location, etc.) :type node_attrs: ``dict`` """ error = None try: response = self.connection.request(status['node_response'][ 'selfLink']).object except GoogleBaseError: e = self._catch_error(ignore_errors=node_attrs['ignore_errors']) error = e.value code = e.code response = {'status': 'DONE'} if response['status'] == 'DONE': status['node_response'] = None if error: status['node'] = GCEFailedNode(status['name'], error, code) else: status['node'] = self.ex_get_node(status['name'], node_attrs['location']) def _create_vol_req(self, size, name, location=None, snapshot=None, image=None, ex_disk_type='pd-standard'): """ Assemble the request/data for creating a volume. Used by create_volume and ex_create_multiple_nodes :param size: Size of volume to create (in GB). Can be None if image or snapshot is supplied. :type size: ``int`` or ``str`` or ``None`` :param name: Name of volume to create :type name: ``str`` :keyword location: Location (zone) to create the volume in :type location: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` :keyword snapshot: Snapshot to create image from :type snapshot: :class:`GCESnapshot` or ``str`` or ``None`` :keyword image: Image to create disk from. :type image: :class:`GCENodeImage` or ``str`` or ``None`` :keyword ex_disk_type: Specify pd-standard (default) or pd-ssd :type ex_disk_type: ``str`` or :class:`GCEDiskType` :return: Tuple containing the request string, the data dictionary and the URL parameters :rtype: ``tuple`` """ volume_data = {} params = None volume_data['name'] = name if size: volume_data['sizeGb'] = str(size) if image: if not hasattr(image, 'name'): image = self.ex_get_image(image) params = {'sourceImage': image.extra['selfLink']} volume_data['description'] = 'Image: %s' % ( image.extra['selfLink']) if snapshot: if not hasattr(snapshot, 'name'): # Check for full URI to not break backward-compatibility if snapshot.startswith('https'): snapshot = self._get_components_from_path(snapshot)['name'] snapshot = self.ex_get_snapshot(snapshot) snapshot_link = snapshot.extra['selfLink'] volume_data['sourceSnapshot'] = snapshot_link volume_data['description'] = 'Snapshot: %s' % (snapshot_link) location = location or self.zone if not hasattr(location, 'name'): location = self.ex_get_zone(location) if hasattr(ex_disk_type, 'name'): # pylint: disable=no-member volume_data['type'] = ex_disk_type.extra['selfLink'] elif ex_disk_type.startswith('https'): volume_data['type'] = ex_disk_type else: volume_data['type'] = 'https://www.googleapis.com/compute/' volume_data['type'] += '%s/projects/%s/zones/%s/diskTypes/%s' % ( API_VERSION, self.project, location.name, ex_disk_type) request = '/zones/%s/disks' % (location.name) return request, volume_data, params def _to_disktype(self, disktype): """ Return a DiskType object from the JSON-response dictionary. :param disktype: The dictionary describing the disktype. :type disktype: ``dict`` :return: DiskType object :rtype: :class:`GCEDiskType` """ extra = {} zone = self.ex_get_zone(disktype['zone']) extra['selfLink'] = disktype.get('selfLink') extra['creationTimestamp'] = disktype.get('creationTimestamp') extra['description'] = disktype.get('description') extra['valid_disk_size'] = disktype.get('validDiskSize') extra['default_disk_size_gb'] = disktype.get('defaultDiskSizeGb') type_id = "%s:%s" % (zone.name, disktype['name']) return GCEDiskType(id=type_id, name=disktype['name'], zone=zone, driver=self, extra=extra) def _to_accelerator_type(self, accelerator_type): """ Return an AcceleratorType object from the JSON-response dictionary. :param accelerator_type: The dictionary describing the accelerator_type. :type accelerator_type: ``dict`` :return: AcceleratorType object :rtype: :class:`GCEAcceleratorType` """ extra = {} zone = self.ex_get_zone(accelerator_type['zone']) extra['selfLink'] = accelerator_type.get('selfLink') extra['creationTimestamp'] = accelerator_type.get('creationTimestamp') extra['description'] = accelerator_type.get('description') extra['maximumCardsPerInstance'] = accelerator_type.get( 'maximumCardsPerInstance') extra['default_disk_size_gb'] = accelerator_type.get( 'defaultDiskSizeGb') type_id = "%s:%s" % (zone.name, accelerator_type['name']) return GCEAcceleratorType(id=type_id, name=accelerator_type['name'], zone=zone, driver=self, extra=extra) def _to_address(self, address): """ Return an Address object from the JSON-response dictionary. :param address: The dictionary describing the address. :type address: ``dict`` :return: Address object :rtype: :class:`GCEAddress` """ extra = {} if 'region' in address: region = self.ex_get_region(address['region']) else: region = 'global' extra['selfLink'] = address.get('selfLink') extra['status'] = address.get('status') extra['description'] = address.get('description', None) if address.get('users', None) is not None: extra['users'] = address.get('users') extra['creationTimestamp'] = address.get('creationTimestamp') return GCEAddress(id=address['id'], name=address['name'], address=address['address'], region=region, driver=self, extra=extra) def _to_backendservice(self, backendservice): """ Return a Backend Service object from the JSON-response dictionary. :param backendservice: The dictionary describing the backend service. :type backendservice: ``dict`` :return: BackendService object :rtype: :class:`GCEBackendService` """ extra = {} for extra_key in ('selfLink', 'creationTimestamp', 'fingerprint', 'description'): extra[extra_key] = backendservice.get(extra_key) backends = backendservice.get('backends', []) healthchecks = [self._get_object_by_kind(h) for h in backendservice.get('healthChecks', [])] return GCEBackendService( id=backendservice['id'], name=backendservice['name'], backends=backends, healthchecks=healthchecks, port=backendservice['port'], port_name=backendservice['portName'], protocol=backendservice['protocol'], timeout=backendservice['timeoutSec'], driver=self, extra=extra) def _to_healthcheck(self, healthcheck): """ Return a HealthCheck object from the JSON-response dictionary. :param healthcheck: The dictionary describing the healthcheck. :type healthcheck: ``dict`` :return: HealthCheck object :rtype: :class:`GCEHealthCheck` """ extra = {} extra['selfLink'] = healthcheck.get('selfLink') extra['creationTimestamp'] = healthcheck.get('creationTimestamp') extra['description'] = healthcheck.get('description') extra['host'] = healthcheck.get('host') return GCEHealthCheck( id=healthcheck['id'], name=healthcheck['name'], path=healthcheck.get('requestPath'), port=healthcheck.get('port'), interval=healthcheck.get('checkIntervalSec'), timeout=healthcheck.get('timeoutSec'), unhealthy_threshold=healthcheck.get('unhealthyThreshold'), healthy_threshold=healthcheck.get('healthyThreshold'), driver=self, extra=extra) def _to_firewall(self, firewall): """ Return a Firewall object from the JSON-response dictionary. :param firewall: The dictionary describing the firewall. :type firewall: ``dict`` :return: Firewall object :rtype: :class:`GCEFirewall` """ extra = {} extra['selfLink'] = firewall.get('selfLink') extra['creationTimestamp'] = firewall.get('creationTimestamp') extra['description'] = firewall.get('description') extra['network_name'] = self._get_components_from_path(firewall[ 'network'])['name'] network = self.ex_get_network(extra['network_name']) allowed = firewall.get('allowed') denied = firewall.get('denied') priority = firewall.get('priority') direction = firewall.get('direction') source_ranges = firewall.get('sourceRanges') source_tags = firewall.get('sourceTags') source_service_accounts = firewall.get('sourceServiceAccounts') target_tags = firewall.get('targetTags') target_service_accounts = firewall.get('targetServiceAccounts') target_ranges = firewall.get('targetRanges') return GCEFirewall(id=firewall['id'], name=firewall['name'], allowed=allowed, denied=denied, network=network, target_ranges=target_ranges, source_ranges=source_ranges, priority=priority, source_tags=source_tags, target_tags=target_tags, source_service_accounts=source_service_accounts, target_service_accounts=target_service_accounts, direction=direction, driver=self, extra=extra) def _to_forwarding_rule(self, forwarding_rule): """ Return a Forwarding Rule object from the JSON-response dictionary. :param forwarding_rule: The dictionary describing the rule. :type forwarding_rule: ``dict`` :return: ForwardingRule object :rtype: :class:`GCEForwardingRule` """ extra = {} extra['selfLink'] = forwarding_rule.get('selfLink') extra['portRange'] = forwarding_rule.get('portRange') extra['creationTimestamp'] = forwarding_rule.get('creationTimestamp') extra['description'] = forwarding_rule.get('description') region = forwarding_rule.get('region') if region: region = self.ex_get_region(region) target = self._get_object_by_kind(forwarding_rule['target']) return GCEForwardingRule(id=forwarding_rule['id'], name=forwarding_rule['name'], region=region, address=forwarding_rule.get('IPAddress'), protocol=forwarding_rule.get('IPProtocol'), targetpool=target, driver=self, extra=extra) def _to_sslcertificate(self, sslcertificate): """ Return the SslCertificate object from the JSON-response. :param sslcertificate: Dictionary describing SslCertificate :type sslcertificate: ``dict`` :return: Return SslCertificate object. :rtype: :class:`GCESslCertificate` """ extra = {} if 'description' in sslcertificate: extra['description'] = sslcertificate['description'] extra['selfLink'] = sslcertificate['selfLink'] return GCESslCertificate(id=sslcertificate['id'], name=sslcertificate['name'], certificate=sslcertificate['certificate'], driver=self, extra=extra) def _to_subnetwork(self, subnetwork): """ Return a Subnetwork object from the JSON-response dictionary. :param subnetwork: The dictionary describing the subnetwork. :type subnetwork: ``dict`` :return: Subnetwork object :rtype: :class:`GCESubnetwork` """ extra = {} extra['creationTimestamp'] = subnetwork.get('creationTimestamp') extra['description'] = subnetwork.get('description') extra['gatewayAddress'] = subnetwork.get('gatewayAddress') extra['ipCidrRange'] = subnetwork.get('ipCidrRange') extra['network'] = subnetwork.get('network') extra['region'] = subnetwork.get('region') extra['selfLink'] = subnetwork.get('selfLink') extra['privateIpGoogleAccess'] = \ subnetwork.get('privateIpGoogleAccess') extra['secondaryIpRanges'] = subnetwork.get('secondaryIpRanges') network = self._get_object_by_kind(subnetwork.get('network')) region = self._get_object_by_kind(subnetwork.get('region')) return GCESubnetwork(id=subnetwork['id'], name=subnetwork['name'], cidr=subnetwork.get('ipCidrRange'), network=network, region=region, driver=self, extra=extra) def _to_network(self, network): """ Return a Network object from the JSON-response dictionary. :param network: The dictionary describing the network. :type network: ``dict`` :return: Network object :rtype: :class:`GCENetwork` """ extra = {} extra['selfLink'] = network.get('selfLink') extra['description'] = network.get('description') extra['creationTimestamp'] = network.get('creationTimestamp') # 'legacy' extra['gatewayIPv4'] = network.get('gatewayIPv4') extra['IPv4Range'] = network.get('IPv4Range') # 'auto' or 'custom' extra['autoCreateSubnetworks'] = network.get('autoCreateSubnetworks') extra['subnetworks'] = network.get('subnetworks') extra['routingConfig'] = network.get('routingConfig') # match Cloud SDK 'gcloud' if 'autoCreateSubnetworks' in network: if network['autoCreateSubnetworks']: extra['mode'] = 'auto' else: extra['mode'] = 'custom' else: extra['mode'] = 'legacy' return GCENetwork(id=network['id'], name=network['name'], cidr=network.get('IPv4Range'), driver=self, extra=extra) def _to_route(self, route): """ Return a Route object from the JSON-response dictionary. :param route: The dictionary describing the route. :type route: ``dict`` :return: Route object :rtype: :class:`GCERoute` """ extra = {} extra['selfLink'] = route.get('selfLink') extra['description'] = route.get('description') extra['creationTimestamp'] = route.get('creationTimestamp') network = route.get('network') priority = route.get('priority') if 'nextHopInstance' in route: extra['nextHopInstance'] = route['nextHopInstance'] if 'nextHopIp' in route: extra['nextHopIp'] = route['nextHopIp'] if 'nextHopNetwork' in route: extra['nextHopNetwork'] = route['nextHopNetwork'] if 'nextHopGateway' in route: extra['nextHopGateway'] = route['nextHopGateway'] if 'warnings' in route: extra['warnings'] = route['warnings'] return GCERoute(id=route['id'], name=route['name'], dest_range=route.get('destRange'), priority=priority, network=network, tags=route.get('tags'), driver=self, extra=extra) def _to_node_image(self, image): """ Return an Image object from the JSON-response dictionary. :param image: The dictionary describing the image. :type image: ``dict`` :return: Image object :rtype: :class:`GCENodeImage` """ extra = {} if 'preferredKernel' in image: extra['preferredKernel'] = image.get('preferredKernel', None) extra['description'] = image.get('description', None) extra['family'] = image.get('family', None) extra['creationTimestamp'] = image.get('creationTimestamp') extra['selfLink'] = image.get('selfLink') if 'deprecated' in image: extra['deprecated'] = image.get('deprecated', None) extra['sourceType'] = image.get('sourceType', None) extra['rawDisk'] = image.get('rawDisk', None) extra['status'] = image.get('status', None) extra['archiveSizeBytes'] = image.get('archiveSizeBytes', None) extra['diskSizeGb'] = image.get('diskSizeGb', None) if 'guestOsFeatures' in image: extra['guestOsFeatures'] = image.get('guestOsFeatures', []) if 'sourceDisk' in image: extra['sourceDisk'] = image.get('sourceDisk', None) if 'sourceDiskId' in image: extra['sourceDiskId'] = image.get('sourceDiskId', None) if 'licenses' in image: lic_objs = self._licenses_from_urls(licenses=image['licenses']) extra['licenses'] = lic_objs extra['labels'] = image.get('labels', None) extra['labelFingerprint'] = image.get('labelFingerprint', None) return GCENodeImage(id=image['id'], name=image['name'], driver=self, extra=extra) def _to_node_location(self, location): """ Return a Location object from the JSON-response dictionary. :param location: The dictionary describing the location. :type location: ``dict`` :return: Location object :rtype: :class:`NodeLocation` """ return NodeLocation(id=location['id'], name=location['name'], country=location['name'].split('-')[0], driver=self) def _to_node(self, node, use_disk_cache=False): """ Return a Node object from the JSON-response dictionary. :param node: The dictionary describing the node. :type node: ``dict`` :keyword use_disk_cache: If true, ex_get_volume call will use cache. :type use_disk_cache: ``bool`` :return: Node object :rtype: :class:`Node` """ public_ips = [] private_ips = [] extra = {} extra['status'] = node.get('status', "UNKNOWN") extra['statusMessage'] = node.get('statusMessage') extra['description'] = node.get('description') extra['zone'] = self.ex_get_zone(node['zone']) extra['image'] = node.get('image') extra['machineType'] = node.get('machineType') extra['cpuPlatform'] = node.get('cpuPlatform') extra['minCpuPlatform'] = node.get('minCpuPlatform') extra['disks'] = node.get('disks', []) extra['networkInterfaces'] = node.get('networkInterfaces') extra['id'] = node['id'] extra['selfLink'] = node.get('selfLink') extra['kind'] = node.get('kind') extra['creationTimestamp'] = node.get('creationTimestamp') extra['name'] = node['name'] extra['metadata'] = node.get('metadata', {}) extra['tags_fingerprint'] = node['tags']['fingerprint'] extra['scheduling'] = node.get('scheduling', {}) extra['deprecated'] = True if node.get('deprecated', None) else False extra['canIpForward'] = node.get('canIpForward') extra['serviceAccounts'] = node.get('serviceAccounts', []) extra['scheduling'] = node.get('scheduling', {}) extra['boot_disk'] = None extra['labels'] = node.get('labels') extra['labelFingerprint'] = node.get('labelFingerprint') for disk in extra['disks']: if disk.get('boot') and disk.get('type') == 'PERSISTENT': bd = self._get_components_from_path(disk['source']) extra['boot_disk'] = self.ex_get_volume( bd['name'], bd['zone'], use_cache=use_disk_cache) if 'items' in node['tags']: tags = node['tags']['items'] else: tags = [] extra['tags'] = tags for network_interface in node.get('networkInterfaces', []): private_ips.append(network_interface.get('networkIP')) for access_config in network_interface.get('accessConfigs', []): public_ips.append(access_config.get('natIP')) # For the node attributes, use just machine and image names, not full # paths. Full paths are available in the "extra" dict. image = None if extra['image']: image = self._get_components_from_path(extra['image'])['name'] else: if extra['boot_disk'] and \ hasattr(extra['boot_disk'], 'extra') and \ 'sourceImage' in extra['boot_disk'].extra and \ extra['boot_disk'].extra['sourceImage'] is not None: src_image = extra['boot_disk'].extra['sourceImage'] image = self._get_components_from_path(src_image)['name'] extra['image'] = image size = self._get_components_from_path(node['machineType'])['name'] state = self.NODE_STATE_MAP.get(node['status'], NodeState.UNKNOWN) return Node(id=node['id'], name=node['name'], state=state, public_ips=public_ips, private_ips=private_ips, driver=self, size=size, image=image, extra=extra) def _to_node_size(self, machine_type): """ Return a Size object from the JSON-response dictionary. :param machine_type: The dictionary describing the machine. :type machine_type: ``dict`` :return: Size object :rtype: :class:`GCENodeSize` """ extra = {} extra['selfLink'] = machine_type.get('selfLink') extra['zone'] = self.ex_get_zone(machine_type['zone']) extra['description'] = machine_type.get('description') extra['guestCpus'] = machine_type.get('guestCpus') extra['creationTimestamp'] = machine_type.get('creationTimestamp') try: orig_api_name = self.api_name self.api_name = "%s_%s" % (self.api_name, extra['zone'].name.split("-")[0]) price = self._get_size_price(size_id=machine_type['name']) self.api_name = orig_api_name except Exception: price = None return GCENodeSize(id=machine_type['id'], name=machine_type['name'], ram=machine_type.get('memoryMb'), disk=machine_type.get('imageSpaceGb'), bandwidth=0, price=price, driver=self, extra=extra) def _to_project(self, project): """ Return a Project object from the JSON-response dictionary. :param project: The dictionary describing the project. :type project: ``dict`` :return: Project object :rtype: :class:`GCEProject` """ extra = {} extra['selfLink'] = project.get('selfLink') extra['creationTimestamp'] = project.get('creationTimestamp') extra['description'] = project.get('description') metadata = project['commonInstanceMetadata'].get('items') if 'commonInstanceMetadata' in project: # add this struct to get 'fingerprint' too extra['commonInstanceMetadata'] = project['commonInstanceMetadata'] if 'usageExportLocation' in project: extra['usageExportLocation'] = project['usageExportLocation'] return GCEProject(id=project['id'], name=project['name'], metadata=metadata, quotas=project.get('quotas'), driver=self, extra=extra) def _to_region(self, region): """ Return a Region object from the JSON-response dictionary. :param region: The dictionary describing the region. :type region: ``dict`` :return: Region object :rtype: :class:`GCERegion` """ extra = {} extra['selfLink'] = region.get('selfLink') extra['creationTimestamp'] = region.get('creationTimestamp') extra['description'] = region.get('description') quotas = region.get('quotas') zones = [self.ex_get_zone(z) for z in region.get('zones', [])] # Work around a bug that will occasionally list missing zones in the # region output zones = [z for z in zones if z is not None] deprecated = region.get('deprecated') return GCERegion(id=region['id'], name=region['name'], status=region.get('status'), zones=zones, quotas=quotas, deprecated=deprecated, driver=self, extra=extra) def _to_snapshot(self, snapshot): """ Return a Snapshot object from the JSON-response dictionary. :param snapshot: The dictionary describing the snapshot :type snapshot: ``dict`` :return: Snapshot object :rtype: :class:`VolumeSnapshot` """ extra = {} extra['selfLink'] = snapshot.get('selfLink') extra['creationTimestamp'] = snapshot.get('creationTimestamp') extra['sourceDisk'] = snapshot.get('sourceDisk') if 'description' in snapshot: extra['description'] = snapshot['description'] if 'sourceDiskId' in snapshot: extra['sourceDiskId'] = snapshot['sourceDiskId'] if 'storageBytes' in snapshot: extra['storageBytes'] = snapshot['storageBytes'] if 'storageBytesStatus' in snapshot: extra['storageBytesStatus'] = snapshot['storageBytesStatus'] if 'licenses' in snapshot: lic_objs = self._licenses_from_urls(licenses=snapshot['licenses']) extra['licenses'] = lic_objs try: created = parse_date(snapshot.get('creationTimestamp')) except ValueError: created = None return GCESnapshot(id=snapshot['id'], name=snapshot['name'], size=snapshot['diskSizeGb'], status=snapshot.get('status'), driver=self, extra=extra, created=created) def _to_storage_volume(self, volume): """ Return a Volume object from the JSON-response dictionary. :param volume: The dictionary describing the volume. :type volume: ``dict`` :return: Volume object :rtype: :class:`StorageVolume` """ extra = {} extra['selfLink'] = volume.get('selfLink') extra['zone'] = self.ex_get_zone(volume['zone']) extra['status'] = volume.get('status') extra['creationTimestamp'] = volume.get('creationTimestamp') extra['description'] = volume.get('description') extra['sourceImage'] = volume.get('sourceImage') extra['sourceImageId'] = volume.get('sourceImageId') extra['sourceSnapshot'] = volume.get('sourceSnapshot') extra['sourceSnapshotId'] = volume.get('sourceSnapshotId') extra['options'] = volume.get('options') extra['labels'] = volume.get('labels', {}) extra['labelFingerprint'] = volume.get('labelFingerprint') if 'licenses' in volume: lic_objs = self._licenses_from_urls(licenses=volume['licenses']) extra['licenses'] = lic_objs extra['type'] = volume.get('type', 'pd-standard').split('/')[-1] return StorageVolume(id=volume['id'], name=volume['name'], size=volume['sizeGb'], driver=self, extra=extra) def _to_targethttpproxy(self, targethttpproxy): """ Return a Target HTTP Proxy object from the JSON-response dictionary. :param targethttpproxy: The dictionary describing the proxy. :type targethttpproxy: ``dict`` :return: Target HTTP Proxy object :rtype: :class:`GCETargetHttpProxy` """ extra = dict( [(k, targethttpproxy.get(k)) for k in ('creationTimestamp', 'description', 'selfLink')]) urlmap = self._get_object_by_kind(targethttpproxy.get('urlMap')) return GCETargetHttpProxy(id=targethttpproxy['id'], name=targethttpproxy['name'], urlmap=urlmap, driver=self, extra=extra) def _to_targethttpsproxy(self, targethttpsproxy): """ Return the TargetHttpsProxy object from the JSON-response. :param targethttpsproxy: Dictionary describing TargetHttpsProxy :type targethttpsproxy: ``dict`` :return: Return TargetHttpsProxy object. :rtype: :class:`GCETargetHttpsProxy` """ extra = {} if 'description' in targethttpsproxy: extra['description'] = targethttpsproxy['description'] extra['selfLink'] = targethttpsproxy['selfLink'] sslcertificates = [ self._get_object_by_kind(x) for x in targethttpsproxy.get('sslCertificates', []) ] obj_name = self._get_components_from_path(targethttpsproxy['urlMap'])[ 'name'] urlmap = self.ex_get_urlmap(obj_name) return GCETargetHttpsProxy(id=targethttpsproxy['id'], name=targethttpsproxy['name'], sslcertificates=sslcertificates, urlmap=urlmap, driver=self, extra=extra) def _to_targetinstance(self, targetinstance): """ Return a Target Instance object from the JSON-response dictionary. :param targetinstance: The dictionary describing the target instance. :type targetinstance: ``dict`` :return: Target Instance object :rtype: :class:`GCETargetInstance` """ node = None extra = {} extra['selfLink'] = targetinstance.get('selfLink') extra['description'] = targetinstance.get('description') extra['natPolicy'] = targetinstance.get('natPolicy') zone = self.ex_get_zone(targetinstance['zone']) if 'instance' in targetinstance: node_name = targetinstance['instance'].split('/')[-1] try: node = self.ex_get_node(node_name, zone) except ResourceNotFoundError: node = targetinstance['instance'] return GCETargetInstance(id=targetinstance['id'], name=targetinstance['name'], zone=zone, node=node, driver=self, extra=extra) def _to_targetpool(self, targetpool): """ Return a Target Pool object from the JSON-response dictionary. :param targetpool: The dictionary describing the volume. :type targetpool: ``dict`` :return: Target Pool object :rtype: :class:`GCETargetPool` """ extra = {} extra['selfLink'] = targetpool.get('selfLink') extra['description'] = targetpool.get('description') extra['sessionAffinity'] = targetpool.get('sessionAffinity') region = self.ex_get_region(targetpool['region']) healthcheck_list = [self.ex_get_healthcheck(h.split('/')[-1]) for h in targetpool.get('healthChecks', [])] node_list = [] for n in targetpool.get('instances', []): # Nodes that do not exist can be part of a target pool. If the # node does not exist, use the URL of the node instead of the node # object. comp = self._get_components_from_path(n) try: node = self.ex_get_node(comp['name'], comp['zone']) except ResourceNotFoundError: node = n node_list.append(node) if 'failoverRatio' in targetpool: extra['failoverRatio'] = targetpool['failoverRatio'] if 'backupPool' in targetpool: tp_split = targetpool['backupPool'].split('/') extra['backupPool'] = self.ex_get_targetpool(tp_split[10], tp_split[8]) return GCETargetPool(id=targetpool['id'], name=targetpool['name'], region=region, healthchecks=healthcheck_list, nodes=node_list, driver=self, extra=extra) def _to_instancegroup(self, instancegroup): """ Return the InstanceGroup object from the JSON-response. :param instancegroup: Dictionary describing InstanceGroup :type instancegroup: ``dict`` :return: InstanceGroup object. :rtype: :class:`GCEInstanceGroup` """ extra = {} extra['description'] = instancegroup.get('description', None) extra['selfLink'] = instancegroup['selfLink'] extra['namedPorts'] = instancegroup.get('namedPorts', []) extra['fingerprint'] = instancegroup.get('fingerprint', None) zone = self.ex_get_zone(instancegroup['zone']) # Note: network/subnetwork will not be available if the Instance Group # does not contain instances. network = instancegroup.get('network', None) if network: network = self.ex_get_network(network) subnetwork = instancegroup.get('subnetwork', None) if subnetwork: subnetwork = self.ex_get_subnetwork(subnetwork) return GCEInstanceGroup( id=instancegroup['id'], name=instancegroup['name'], zone=zone, network=network, subnetwork=subnetwork, named_ports=instancegroup.get('namedPorts', []), driver=self, extra=extra) def _to_instancegroupmanager(self, manager): """ Return a Instance Group Manager object from the JSON-response. :param instancegroupmanager: dictionary describing the Instance Group Manager. :type instancegroupmanager: ``dict`` :return: Instance Group Manager object. :rtype: :class:`GCEInstanceGroupManager` """ zone = self.ex_get_zone(manager['zone']) extra = {} extra['selfLink'] = manager.get('selfLink') extra['description'] = manager.get('description') extra['currentActions'] = manager.get('currentActions') extra['baseInstanceName'] = manager.get('baseInstanceName') extra['namedPorts'] = manager.get('namedPorts', []) extra['autoHealingPolicies'] = manager.get('autoHealingPolicies', []) template_name = self._get_components_from_path(manager[ 'instanceTemplate'])['name'] template = self.ex_get_instancetemplate(template_name) ig_name = self._get_components_from_path(manager['instanceGroup'])[ 'name'] instance_group = self.ex_get_instancegroup(ig_name, zone) return GCEInstanceGroupManager( id=manager['id'], name=manager['name'], zone=zone, size=manager['targetSize'], instance_group=instance_group, template=template, driver=self, extra=extra) def _to_instancetemplate(self, instancetemplate): """ Return a Instance Template object from the JSON-response. :param instancetemplate: dictionary describing the Instance Template. :type instancetemplate: ``dict`` :return: Instance Template object. :rtype: :class:`GCEInstanceTemplate` """ extra = {} extra['selfLink'] = instancetemplate.get('selfLink') extra['description'] = instancetemplate.get('description') extra['properties'] = instancetemplate.get('properties') return GCEInstanceTemplate(id=instancetemplate['id'], name=instancetemplate['name'], driver=self, extra=extra) def _to_autoscaler(self, autoscaler): """ Return an Autoscaler object from the JSON-response. :param autoscaler: dictionary describing the Autoscaler. :type autoscaler: ``dict`` :return: Autoscaler object. :rtype: :class:`GCEAutoscaler` """ extra = {} extra['selfLink'] = autoscaler.get('selfLink') extra['description'] = autoscaler.get('description') zone = self.ex_get_zone(autoscaler.get('zone')) ig_name = self._get_components_from_path(autoscaler.get('target'))[ 'name'] target = self.ex_get_instancegroupmanager(ig_name, zone) return GCEAutoscaler(id=autoscaler['id'], name=autoscaler['name'], zone=zone, target=target, policy=autoscaler['autoscalingPolicy'], driver=self, extra=extra) def _format_guest_accelerators(self, accelerator_type, accelerator_count): """ Formats a GCE-friendly guestAccelerators request. Accepts an accelerator_type and accelerator_count that is wrapped up into a list of dictionaries for GCE to consume for a node creation request. :param accelerator_type: Accelerator type to request. :type accelerator_type: :class:`GCEAcceleratorType` :param accelerator_count: Number of accelerators to request. :type accelerator_count: ``int`` :return: GCE-friendly guestAccelerators list of dictionaries. :rtype: ``list`` """ accelerator_type = self._get_selflink_or_name( obj=accelerator_type, get_selflinks=True, objname='accelerator_type') return [{'acceleratorType': accelerator_type, 'acceleratorCount': accelerator_count}] def _format_metadata(self, fingerprint, metadata=None): """ Convert various data formats into the metadata format expected by Google Compute Engine and suitable for passing along to the API. Can accept the following formats: (a) [{'key': 'k1', 'value': 'v1'}, ...] (b) [{'k1': 'v1'}, ...] (c) {'key': 'k1', 'value': 'v1'} (d) {'k1': 'v1', 'k2': v2', ...} (e) {'items': [...]} # does not check for valid list contents The return value is a 'dict' that GCE expects, e.g. {'fingerprint': 'xx...', 'items': [{'key': 'key1', 'value': 'val1'}, {'key': 'key2', 'value': 'val2'}, ..., ] } :param fingerprint: Current metadata fingerprint :type fingerprint: ``str`` :param metadata: Variety of input formats. :type metadata: ``list``, ``dict``, or ``None`` :return: GCE-friendly metadata dict :rtype: ``dict`` """ if not metadata: return {'fingerprint': fingerprint, 'items': []} md = {'fingerprint': fingerprint} # Check `list` format. Can support / convert the following: # (a) [{'key': 'k1', 'value': 'v1'}, ...] # (b) [{'k1': 'v1'}, ...] if isinstance(metadata, list): item_list = [] for i in metadata: if isinstance(i, dict): # check (a) if 'key' in i and 'value' in i and len(i) == 2: item_list.append(i) # check (b) elif len(i) == 1: item_list.append({'key': list(i.keys())[0], 'value': list(i.values())[0]}) else: raise ValueError("Unsupported metadata format.") else: raise ValueError("Unsupported metadata format.") md['items'] = item_list # Check `dict` format. Can support / convert the following: # (c) {'key': 'k1', 'value': 'v1'} # (d) {'k1': 'v1', 'k2': 'v2', ...} # (e) {'items': [...]} if isinstance(metadata, dict): # Check (c) if 'key' in metadata and 'value' in metadata and \ len(metadata) == 2: md['items'] = [metadata] # check (d) elif len(metadata) == 1: if 'items' in metadata: # check (e) if isinstance(metadata['items'], list): md['items'] = metadata['items'] else: raise ValueError("Unsupported metadata format.") else: md['items'] = [{'key': list(metadata.keys())[0], 'value': list(metadata.values())[0]}] else: # check (d) md['items'] = [] for k, v in metadata.items(): md['items'].append({'key': k, 'value': v}) if 'items' not in md: raise ValueError("Unsupported metadata format.") return md def _to_urlmap(self, urlmap): """ Return a UrlMap object from the JSON-response dictionary. :param zone: The dictionary describing the url-map. :type zone: ``dict`` :return: UrlMap object :rtype: :class:`GCEUrlMap` """ extra = dict([(k, urlmap.get(k)) for k in ('creationTimestamp', 'description', 'fingerprint', 'selfLink')]) default_service = self._get_object_by_kind( urlmap.get('defaultService')) host_rules = urlmap.get('hostRules', []) path_matchers = urlmap.get('pathMatchers', []) tests = urlmap.get('tests', []) return GCEUrlMap(id=urlmap['id'], name=urlmap['name'], default_service=default_service, host_rules=host_rules, path_matchers=path_matchers, tests=tests, driver=self, extra=extra) def _to_zone(self, zone): """ Return a Zone object from the JSON-response dictionary. :param zone: The dictionary describing the zone. :type zone: ``dict`` :return: Zone object :rtype: :class:`GCEZone` """ extra = {} extra['selfLink'] = zone.get('selfLink') extra['creationTimestamp'] = zone.get('creationTimestamp') extra['description'] = zone.get('description') extra['region'] = zone.get('region') deprecated = zone.get('deprecated') return GCEZone(id=zone['id'], name=zone['name'], status=zone['status'], maintenance_windows=zone.get('maintenanceWindows'), deprecated=deprecated, driver=self, extra=extra) def _set_project_metadata(self, metadata=None, force=False, current_keys=""): """ Return the GCE-friendly dictionary of metadata with/without an entry for 'sshKeys' based on params for 'force' and 'current_keys'. This method was added to simplify the set_common_instance_metadata method and make it easier to test. :param metadata: The GCE-formatted dict (e.g. 'items' list of dicts) :type metadata: ``dict`` or ``None`` :param force: Flag to specify user preference for keeping current_keys :type force: ``bool`` :param current_keys: The value, if any, of existing 'sshKeys' :type current_keys: ``str`` :return: GCE-friendly metadata dict :rtype: ``dict`` """ if metadata is None: # User wants to delete metdata, but if 'force' is False # and we already have sshKeys, we should retain them. # Otherwise, delete ALL THE THINGS! if not force and current_keys: new_md = [{'key': 'sshKeys', 'value': current_keys}] else: new_md = [] else: # User is providing new metadata. If 'force' is False, they # want to preserve existing sshKeys, otherwise 'force' is True # and the user wants to add/replace sshKeys. new_md = metadata['items'] if not force and current_keys: # not sure how duplicate keys would be resolved, so ensure # existing 'sshKeys' entry is removed. updated_md = [] for d in new_md: if d['key'] != 'sshKeys': updated_md.append({'key': d['key'], 'value': d['value']}) new_md = updated_md new_md.append({'key': 'sshKeys', 'value': current_keys}) return new_md def _licenses_from_urls(self, licenses): """ Convert a list of license selfLinks into a list of :class:`GCELicense` objects. :param licenses: A list of GCE license selfLink URLs. :type licenses: ``list`` of ``str`` :return: List of :class:`GCELicense` objects. :rtype: ``list`` """ return_list = [] for license in licenses: selfLink_parts = license.split('/') lic_proj = selfLink_parts[6] lic_name = selfLink_parts[-1] return_list.append( self.ex_get_license(project=lic_proj, name=lic_name)) return return_list KIND_METHOD_MAP = { 'compute#address': _to_address, 'compute#backendService': _to_backendservice, 'compute#disk': _to_storage_volume, 'compute#firewall': _to_firewall, 'compute#forwardingRule': _to_forwarding_rule, 'compute#httpHealthCheck': _to_healthcheck, 'compute#image': _to_node_image, 'compute#instance': _to_node, 'compute#machineType': _to_node_size, 'compute#network': _to_network, 'compute#project': _to_project, 'compute#region': _to_region, 'compute#snapshot': _to_snapshot, 'compute#sslCertificate': _to_sslcertificate, 'compute#targetHttpProxy': _to_targethttpproxy, 'compute#targetHttpsProxy': _to_targethttpsproxy, 'compute#targetInstance': _to_targetinstance, 'compute#targetPool': _to_targetpool, 'compute#urlMap': _to_urlmap, 'compute#zone': _to_zone, } apache-libcloud-2.8.0/libcloud/compute/drivers/gogrid.py0000664000175000017500000003562213577507766023236 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ GoGrid driver """ import time import hashlib import copy from libcloud.utils.py3 import b from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.common.gogrid import GoGridConnection, BaseGoGridDriver from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState from libcloud.compute.base import Node, NodeDriver from libcloud.compute.base import NodeSize, NodeImage, NodeLocation STATE = { "Starting": NodeState.PENDING, "On": NodeState.RUNNING, "On/Saving": NodeState.RUNNING, "Off": NodeState.PENDING, "Restarting": NodeState.REBOOTING, "Saving": NodeState.PENDING, "Restoring": NodeState.PENDING, } GOGRID_INSTANCE_TYPES = { '512MB': {'id': '512MB', 'name': '512MB', 'ram': 512, 'disk': 30, 'bandwidth': None}, '1GB': {'id': '1GB', 'name': '1GB', 'ram': 1024, 'disk': 60, 'bandwidth': None}, '2GB': {'id': '2GB', 'name': '2GB', 'ram': 2048, 'disk': 120, 'bandwidth': None}, '4GB': {'id': '4GB', 'name': '4GB', 'ram': 4096, 'disk': 240, 'bandwidth': None}, '8GB': {'id': '8GB', 'name': '8GB', 'ram': 8192, 'disk': 480, 'bandwidth': None}, '16GB': {'id': '16GB', 'name': '16GB', 'ram': 16384, 'disk': 960, 'bandwidth': None}, '24GB': {'id': '24GB', 'name': '24GB', 'ram': 24576, 'disk': 960, 'bandwidth': None}, } class GoGridNode(Node): # Generating uuid based on public ip to get around missing id on # create_node in gogrid api # # Used public ip since it is not mutable and specified at create time, # so uuid of node should not change after add is completed def get_uuid(self): return hashlib.sha1( b("%s:%s" % (self.public_ips, self.driver.type)) ).hexdigest() class GoGridNodeDriver(BaseGoGridDriver, NodeDriver): """ GoGrid node driver """ connectionCls = GoGridConnection type = Provider.GOGRID api_name = 'gogrid' name = 'GoGrid' website = 'http://www.gogrid.com/' features = {"create_node": ["generates_password"]} _instance_types = GOGRID_INSTANCE_TYPES def __init__(self, *args, **kwargs): """ @inherits: :class:`NodeDriver.__init__` """ super(GoGridNodeDriver, self).__init__(*args, **kwargs) def _get_state(self, element): try: return STATE[element['state']['name']] except Exception: pass return NodeState.UNKNOWN def _get_ip(self, element): return element.get('ip').get('ip') def _get_id(self, element): return element.get('id') def _to_node(self, element, password=None): state = self._get_state(element) ip = self._get_ip(element) id = self._get_id(element) n = GoGridNode(id=id, name=element['name'], state=state, public_ips=[ip], private_ips=[], extra={'ram': element.get('ram').get('name'), 'description': element.get('description', '')}, driver=self.connection.driver) if password: n.extra['password'] = password return n def _to_image(self, element): n = NodeImage(id=element['id'], name=element['friendlyName'], driver=self.connection.driver) return n def _to_images(self, object): return [self._to_image(el) for el in object['list']] def _to_location(self, element): location = NodeLocation(id=element['id'], name=element['name'], country="US", driver=self.connection.driver) return location def _to_locations(self, object): return [self._to_location(el) for el in object['list']] def list_images(self, location=None): params = {} if location is not None: params["datacenter"] = location.id images = self._to_images( self.connection.request('/api/grid/image/list', params).object) return images def list_nodes(self): """ @inherits: :class:`NodeDriver.list_nodes` :rtype: ``list`` of :class:`GoGridNode` """ passwords_map = {} res = self._server_list() try: for password in self._password_list()['list']: try: passwords_map[password['server']['id']] = \ password['password'] except KeyError: pass except InvalidCredsError: # some gogrid API keys don't have permission to access the # password list. pass return [self._to_node(el, passwords_map.get(el.get('id'))) for el in res['list']] def reboot_node(self, node): """ @inherits: :class:`NodeDriver.reboot_node` :type node: :class:`GoGridNode` """ id = node.id power = 'restart' res = self._server_power(id, power) if not res.success(): raise Exception(res.parse_error()) return True def destroy_node(self, node): """ @inherits: :class:`NodeDriver.reboot_node` :type node: :class:`GoGridNode` """ id = node.id res = self._server_delete(id) if not res.success(): raise Exception(res.parse_error()) return True def _server_list(self): return self.connection.request('/api/grid/server/list').object def _password_list(self): return self.connection.request('/api/support/password/list').object def _server_power(self, id, power): # power in ['start', 'stop', 'restart'] params = {'id': id, 'power': power} return self.connection.request("/api/grid/server/power", params, method='POST') def _server_delete(self, id): params = {'id': id} return self.connection.request("/api/grid/server/delete", params, method='POST') def _get_first_ip(self, location=None): ips = self.ex_list_ips(public=True, assigned=False, location=location) try: return ips[0].ip except IndexError: raise LibcloudError('No public unassigned IPs left', GoGridNodeDriver) def list_sizes(self, location=None): sizes = [] for key, values in self._instance_types.items(): attributes = copy.deepcopy(values) attributes.update({'price': self._get_size_price(size_id=key)}) sizes.append(NodeSize(driver=self.connection.driver, **attributes)) return sizes def list_locations(self): locations = self._to_locations( self.connection.request('/api/common/lookup/list', params={'lookup': 'ip.datacenter'}).object) return locations def ex_create_node_nowait(self, name, size, image, location=None, ex_description=None, ex_ip=None): """Don't block until GoGrid allocates id for a node but return right away with id == None. The existence of this method is explained by the fact that GoGrid assigns id to a node only few minutes after creation. :keyword name: String with a name for this new node (required) :type name: ``str`` :keyword size: The size of resources allocated to this node . (required) :type size: :class:`NodeSize` :keyword image: OS Image to boot on node. (required) :type image: :class:`NodeImage` :keyword ex_description: Description of a Node :type ex_description: ``str`` :keyword ex_ip: Public IP address to use for a Node. If not specified, first available IP address will be picked :type ex_ip: ``str`` :rtype: :class:`GoGridNode` """ if not ex_ip: ip = self._get_first_ip(location) params = {'name': name, 'image': image.id, 'description': ex_description or '', 'server.ram': size.id, 'ip': ip} object = self.connection.request('/api/grid/server/add', params=params, method='POST').object node = self._to_node(object['list'][0]) return node def create_node(self, name, size, image, location=None, ex_description=None, ex_ip=None): """Create a new GoGird node @inherits: :class:`NodeDriver.create_node` :keyword ex_description: Description of a Node :type ex_description: ``str`` :keyword ex_ip: Public IP address to use for a Node. If not specified, first available IP address will be picked :type ex_ip: ``str`` :rtype: :class:`GoGridNode` """ node = self.ex_create_node_nowait(name=name, size=size, image=image, ex_description=ex_description, ex_ip=ex_ip) timeout = 60 * 20 waittime = 0 interval = 2 * 60 while node.id is None and waittime < timeout: nodes = self.list_nodes() for i in nodes: if i.public_ips[0] == node.public_ips[0] and i.id is not None: return i waittime += interval time.sleep(interval) if id is None: raise Exception( "Wasn't able to wait for id allocation for the node %s" % str(node)) return node def ex_save_image(self, node, name): """Create an image for node. Please refer to GoGrid documentation to get info how prepare a node for image creation: http://wiki.gogrid.com/wiki/index.php/MyGSI :keyword node: node to use as a base for image :type node: :class:`GoGridNode` :keyword name: name for new image :type name: ``str`` :rtype: :class:`NodeImage` """ params = {'server': node.id, 'friendlyName': name} object = self.connection.request('/api/grid/image/save', params=params, method='POST').object return self._to_images(object)[0] def ex_edit_node(self, **kwargs): """Change attributes of a node. :keyword node: node to be edited (required) :type node: :class:`GoGridNode` :keyword size: new size of a node (required) :type size: :class:`NodeSize` :keyword ex_description: new description of a node :type ex_description: ``str`` :rtype: :class:`Node` """ node = kwargs['node'] size = kwargs['size'] params = {'id': node.id, 'server.ram': size.id} if 'ex_description' in kwargs: params['description'] = kwargs['ex_description'] object = self.connection.request('/api/grid/server/edit', params=params).object return self._to_node(object['list'][0]) def ex_edit_image(self, **kwargs): """Edit metadata of a server image. :keyword image: image to be edited (required) :type image: :class:`NodeImage` :keyword public: should be the image public (required) :type public: ``bool`` :keyword ex_description: description of the image (optional) :type ex_description: ``str`` :keyword name: name of the image :type name: ``str`` :rtype: :class:`NodeImage` """ image = kwargs['image'] public = kwargs['public'] params = {'id': image.id, 'isPublic': str(public).lower()} if 'ex_description' in kwargs: params['description'] = kwargs['ex_description'] if 'name' in kwargs: params['friendlyName'] = kwargs['name'] object = self.connection.request('/api/grid/image/edit', params=params).object return self._to_image(object['list'][0]) def ex_list_ips(self, **kwargs): """Return list of IP addresses assigned to the account. :keyword public: set to True to list only public IPs or False to list only private IPs. Set to None or not specify at all not to filter by type :type public: ``bool`` :keyword assigned: set to True to list only addresses assigned to servers, False to list unassigned addresses and set to None or don't set at all not no filter by state :type assigned: ``bool`` :keyword location: filter IP addresses by location :type location: :class:`NodeLocation` :rtype: ``list`` of :class:`GoGridIpAddress` """ params = {} if "public" in kwargs and kwargs["public"] is not None: params["ip.type"] = {True: "Public", False: "Private"}[kwargs["public"]] if "assigned" in kwargs and kwargs["assigned"] is not None: params["ip.state"] = {True: "Assigned", False: "Unassigned"}[kwargs["assigned"]] if "location" in kwargs and kwargs['location'] is not None: params['datacenter'] = kwargs['location'].id ips = self._to_ips( self.connection.request('/api/grid/ip/list', params=params).object) return ips apache-libcloud-2.8.0/libcloud/compute/drivers/gridscale.py0000664000175000017500000010506513576514553023706 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import time from libcloud.common.gridscale import GridscaleBaseDriver from libcloud.common.gridscale import GridscaleConnection from libcloud.compute.base import NodeImage, NodeLocation, VolumeSnapshot, \ Node, StorageVolume, KeyPair, NodeState, StorageVolumeState, NodeDriver from libcloud.compute.providers import Provider from libcloud.utils.iso8601 import parse_date class GridscaleIp(object): """ Ip Object :param id: uuid :type id: ``str`` :param family: family of ip (v4 or v6) :type family: ``str`` :param prefix: prefix of ip :type prefix: ``str`` :param ip_address: Ip address :type ip_address: ``str`` :param create_time: Time ip was created :type create_time: ``str`` """ def __init__(self, id, family, prefix, create_time, address, extra=None): self.id = id self.family = family self.prefix = prefix self.create_time = create_time self.ip_address = address self.extra = extra or {} def __repr__(self): return ('Ip: id={}, family={}, prefix={}, create_time={}, ' 'ip_address={}' .format(self.id, self.family, self.prefix, self.create_time, self.ip_address)) class GridscaleNetwork(object): """ Network Object :param id: uuid :type id: ``str`` :param name: Name of Network :type name: ``str`` :param status: Network status :type status: ``str`` :param relations: object related to network :type relations: ``object`` :param create_time: Time Network was created :type create_time: ``str`` """ def __init__(self, id, name, status, create_time, relations): self.id = id self.name = name self.status = status self.create_time = create_time self.relations = relations def __repr__(self): return ('Network: id={}, name={}, status={}, create_time={}, ' 'relations={}'.format(self.id, self.name, self.status, self.create_time, self.relations)) class GridscaleNodeDriver(GridscaleBaseDriver, NodeDriver): """ create and entry in libcloud/compute/providers for gridscale """ connectionCls = GridscaleConnection type = Provider.GRIDSCALE name = 'Gridscale' api_name = 'gridscale' website = 'https://gridscale.io' features = {'create_node': ['ssh_key']} def __init__(self, user_id, key, **kwargs): super(GridscaleNodeDriver, self).__init__(user_id, key, **kwargs) def list_nodes(self): """ List all nodes. :return: List of node objects :rtype: ``list`` of :class:`.Node` """ result = self._sync_request(data=None, endpoint='objects/servers/') nodes = [] for key, value in self._get_response_dict(result).items(): node = self._to_node(value) nodes.append(node) return sorted(nodes, key=lambda sort: sort.created_at) def list_locations(self): """ List all available data centers. :return: List of node location objects :rtype: ``list`` of :class:`.NodeLocation` """ locations = [] result = self._sync_request(endpoint='objects/locations/') for key, value in self._get_response_dict(result).items(): location = self._to_location(value) locations.append(location) return sorted(locations, key=lambda nod: nod.id) def list_volumes(self): """ List all volumes. :return: List of StorageVolume object :rtype: ``list`` of :class:`.StorageVolume` """ volumes = [] result = self._sync_request(endpoint='objects/storages/') for key, value in self._get_response_dict(result).items(): volume = self._to_volume(value) volumes.append(volume) return sorted(volumes, key=lambda sort: sort.extra['create_time']) def ex_list_networks(self): """ List all networks. :return: List of objects. :rtype: ``list`` of :class:`.GridscaleNetwork` """ networks = [] result = self._sync_request(endpoint='objects/networks/') for key, value in self._get_response_dict(result).items(): network = self._to_network(value) networks.append(network) return sorted(networks, key=lambda sort: sort.create_time) def list_volume_snapshots(self, volume): """ Lists all snapshots for storage volume. :param volume: storage the snapshot is attached to :type volume: :class:`.StorageVolume` :return: Snapshots :rtype: ``list`` of :class:`.VolumeSnapshot` """ snapshots = [] result = self._sync_request( endpoint='objects/storages/' '{}/snapshots'.format(volume.id)) for key, value in self._get_response_dict(result).items(): snapshot = self._to_volume_snapshot(value) snapshots.append(snapshot) return sorted(snapshots, key=lambda snapshot: snapshot.created) def ex_list_ips(self): """ Lists all IPs available. :return: List of IP objects. :rtype: ``list`` of :class:`.GridscaleIp` """ ips = [] result = self._sync_request(endpoint='objects/ips/') for key, value in self._get_response_dict(result).items(): ip = self._to_ip(value) ips.append(ip) return ips def list_images(self): """ List images. :return: List of node image objects :rtype: ``list`` of :class:`.NodeImage` """ templates = [] result = self._sync_request(endpoint='objects/templates') for key, value in self._get_response_dict(result).items(): template = self._to_node_image(value) templates.append(template) return sorted(templates, key=lambda sort: sort.name) def create_node(self, name, size, image, location, ex_ssh_key_ids=None, **kwargs): """ Create a simple node with a name, cores, memory at the designated location. :param name: Name of the server. :type name: ``str`` :param size: Nodesize object. :type size: :class:`.NodeSize` :param image: OS image to attach to the storage. :type image: :class:`.GridscaleTemplate` :param location: The data center to create a node in. :type location: :class:`.NodeLocation` :keyword ex_ssh_key_ids: List of SSH key IDs to add to the server. :type ex_ssh_key_ids: ``list`` of ``str`` :return: The newly created Node. :rtype: :class:`.Node` """ if size.ram % 1024 != 0: raise Exception('Value not accepted. Use a multiple of 1024 e.g.' '1024, 2048, 3072...') data = { 'name': name, 'cores': size.extra['cores'], 'memory': int(size.ram / 1024), 'location_uuid': location.id } self.connection.async_request('objects/servers/', data=data, method='POST') node = self._to_node(self._get_resource('servers', self.connection .poll_response_initial .object['object_uuid'])) volume = self._create_volume_from_template(name=image.extra['ostype'], size=size.disk, location=location, template={ 'template_uuid': image.id, 'sshkeys': ex_ssh_key_ids}) ip = self.ex_create_ip(4, location, name + '_ip') self.attach_volume(node, volume) self.ex_link_ip_to_node(node, ip) self.ex_link_network_to_node(node, self.ex_list_networks()[0]) self.ex_start_node(node) return self._to_node(self._get_resource('servers', node.id)) def ex_create_ip(self, family, location, name): """ Create either an ip_v4 ip or a ip_v6. :param family: Defines if the ip is v4 or v6 with int 4 or int 6. :type family: ``int`` :param location: Defines which datacenter the created ip responds with. :type location: :class:`.NodeLocation` :param name: Name of your Ip. :type name: ``str`` :return: Ip :rtype: :class:`.GridscaleIp` """ self.connection.async_request( 'objects/ips/', data={ 'name': name, 'family': family, 'location_uuid': location.id}, method='POST') return self._to_ip(self._get_resource('ips', self.connection .poll_response_initial .object['object_uuid'])) def ex_create_networks(self, name, location): """ Create a network at the data center location. :param name: Name of the network. :type name: ``str`` :param location: Location. :type location: :class:`.NodeLocation` :return: Network. :rtype: :class:`.GridscaleNetwork` """ self.connection.async_request( 'objects/networks', data={ 'name': name, 'location_uuid': location.id}, method='POST') return self._to_network(self._get_resource('network', self.connection .poll_response_initial .object['object_uuid'])) def create_volume(self, size, name, location=None, snapshot=None): """ Create a new volume. :param size: Integer in GB. :type size: ``int`` :param name: Name of the volume. :type name: ``str`` :param location: The server location. :type location: :class:`.NodeLocation` :param snapshot: Snapshot from which to create the new volume. (optional) :type snapshot: :class:`.VolumeSnapshot` :return: Newly created StorageVolume. :rtype: :class:`.StorageVolume` """ return self._create_volume_from_template(size, name, location) def _create_volume_from_template(self, size, name, location=None, template=None): """ create Storage :param name: name of your Storage unit :type name: ``str`` :param size: Integer in GB. :type size: ``int`` :param location: your server location :type location: :class:`.NodeLocation` :param template: template to shape the storage capacity to :type template: ``dict`` :return: newly created StorageVolume :rtype: :class:`.GridscaleVolumeStorage` """ template = template self.connection.async_request( 'objects/storages/', data={ 'name': name, 'capacity': size, 'location_uuid': location.id, 'template': template}, method='POST') return self._to_volume(self._get_resource('storages', self.connection .poll_response_initial .object['object_uuid'])) def create_volume_snapshot(self, volume, name): """ Creates a snapshot of the current state of your volume, you can rollback to. :param volume: Volume you want to create a snapshot of. :type volume: :class:`.StorageVolume` :param name: Name of the snapshot. :type name: ``str`` :return: VolumeSnapshot. :rtype: :class:`.VolumeSnapshot` """ self.connection.async_request( 'objects/storages/{}/snapshots'.format(volume.id), data={ 'name': name}, method='POST') return self._to_volume_snapshot(self._get_resource( 'storages/{}/snapshots'.format(volume.id), self.connection .poll_response_initial.object['object_uuid'])) def create_image(self, node, name): """ Creates an image from a node object. :param node: Node to run the task on. :type node: :class:`.Node` :param name: Name for new image. :type name: ``str`` :return: NodeImage. :rtype: :class:`.NodeImage` """ storage_dict = node.extra['relations']['storages'][0] snapshot_uuid = '' if storage_dict['bootdevice'] is True: self.connection.async_request( 'objects/storages/{}/snapshots/' .format(storage_dict['object_uuid']), data={'name': name + '_snapshot'}, method='POST') snapshot_uuid = self.connection.poll_response_initial.object[ 'object_uuid'] self.connection.async_request( 'objects/templates/', data={ 'name': name, 'snapshot_uuid': snapshot_uuid}, method='POST') snapshot_dict = self._get_response_dict(self._sync_request( endpoint='objects/storages/{}/snapshots/{}' .format(storage_dict['object_uuid'], snapshot_uuid))) self.destroy_volume_snapshot( self._to_volume_snapshot(snapshot_dict)) return self._to_node_image(self._get_resource( 'templates', self.connection.poll_response_initial.object[ 'object_uuid'])) def destroy_node(self, node, ex_destroy_associated_resources=False): """ Destroy node. :param node: Node object. :type node: :class:`.Node` :param ex_destroy_associated_resources: True to destroy associated resources such as storage volumes and IPs. :type ex_destroy_associated_resources: ``bool`` :return: True if the destroy was successful, otherwise False. :rtype: ``bool`` """ if ex_destroy_associated_resources: associated_volumes = self.ex_list_volumes_for_node(node=node) associated_ips = self.ex_list_ips_for_node(node=node) # 1. Delete the server itself result = self._sync_request(endpoint='objects/servers/{}' .format(node.id), method='DELETE') # 2. Destroy associated resouces (if requested) if ex_destroy_associated_resources: for volume in associated_volumes: self.destroy_volume(volume=volume) for ip in associated_ips: self.ex_destroy_ip(ip=ip) return result.status == 204 def destroy_volume(self, volume): """ Delete volume. :param volume: Volume to be destroyed. :type volume: :class:`.StorageVolume` :return: True if the destroy was successful, otherwise False. :rtype: ``bool`` """ result = self._sync_request(endpoint='objects/storages/{}' .format(volume.id), method='DELETE') return result.status == 204 def ex_destroy_ip(self, ip): """ Delete an ip. :param ip: IP object. :type ip: :class:`.GridscaleIp` :return: ``True`` if delete_image was successful, ``False`` otherwise. :rtype: ``bool`` """ result = self._sync_request(endpoint='objects/ips/{}' .format(ip.id), method='DELETE') return result.status == 204 def destroy_volume_snapshot(self, snapshot): """ Destroy a snapshot. :param snapshot: The snapshot to delete. :type snapshot: :class:'.VolumeSnapshot` :return: True if the destroy was successful, otherwise False. :rtype: ``bool`` """ result = self._sync_request(endpoint='objects/storages/' '{}/snapshots/{}/' .format(snapshot.extra['parent_uuid'], snapshot.id), method='DELETE') return result.status == 204 def ex_destroy_network(self, network): """ Delete network. :param network: Network object. :type network: :class:`.GridscaleNetwork` :return: ``True`` if destroyed successfully, otherwise ``False`` :rtype: ``bool`` """ result = self._sync_request(endpoint='objects/networks/{}' .format(network.id), method='DELETE') return result.status == 204 def delete_image(self, node_image): """ Destroy an image. :param node_image: Node image object. :type node_image: :class:`.NodeImage` :return: True if the destroy was successful, otherwise False :rtype: ``bool`` """ result = self._sync_request(endpoint='objects/templates/{}' .format(node_image.id), method='DELETE') return result.status == 204 def ex_rename_node(self, node, name): """ Modify node name. :param name: New node name. :type name: ``str`` :param node: Node :type node: :class:`.Node` :return: ``True`` or ``False`` :rtype: ``bool`` """ result = self._sync_request(data={'name': name}, endpoint='objects/servers/{}' .format(node.id), method='PATCH') return result.status == 204 def ex_rename_volume(self, volume, name): """ Modify storage volume name :param volume: Storage. :type volume: :class:.`StorageVolume` :param name: New storage name. :type name: ``str`` :return: ``True`` or ``False`` :rtype: ``bool`` """ result = self._sync_request(data={'name': name}, endpoint='objects/storages/{}' .format(volume.id), method='PATCH') return result.status == 204 def ex_rename_network(self, network, name): """ Modify networks name. :param network: Network. :type network: :class:`.GridscaleNetwork` :param name: New network name. :type name: ``str`` :return: ``True`` or ``False`` :rtype: ``bool`` """ result = self._sync_request(data={'name': name}, endpoint='objects/networks/{}' .format(network.id), method='PATCH') return result.status == 204 def reboot_node(self, node, ex_sleep_interval=3): """ Reboot a node. :param node: Node object. :type node: :class:`.Node` :return: True if the reboot was successful, otherwise False. :rtype: ``bool`` :keyword ex_sleep_interval: time to let the shutdown process finish :type ex_sleep_interval: ``int`` """ if node.extra['power'] is True: data = dict({'power': False}) self._sync_request(data=data, endpoint='objects/servers/{}/power' .format(node.id), method='PATCH') time.sleep(ex_sleep_interval) data = dict({'power': True}) self._sync_request(data=data, endpoint='objects/servers/{}/power' .format(node.id), method='PATCH') return True else: return False def import_key_pair_from_string(self, name, key_material): data = { 'name': name, 'sshkey': key_material } result = self._sync_request(endpoint='objects/sshkeys/', method='POST', data=data) key = self._to_key(result.object, name=name, sshkey=key_material) return key def list_key_pairs(self): """ List all the available key pair objects. :rtype: ``list``of :class:`.KeyPair` objects """ keys = [] result = self._sync_request(endpoint='objects/sshkeys/') for key, value in self._get_response_dict(result).items(): key = self._to_key(value) keys.append(key) return keys def get_image(self, image_id): """ Get an image based on an image_id. :param image_id: Image identifier. :type image_id: ``str`` :return: A NodeImage object. :rtype: :class:`.NodeImage` """ response_dict = self._get_response_dict(self._sync_request( endpoint='/objects/templates/{}'.format(image_id))) return self._to_node_image(response_dict) def start_node(self, node): result = self._sync_request(data={'power': True}, endpoint='objects/servers/{}/power' .format(node.id), method='PATCH') return result.status == 204 def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_link_isoimage_to_node(self, node, isoimage): """ link and isoimage to a node :param node: Node you want to link the iso image to :type node: ``object`` :param isoimage: isomiage you want to link :type isoimage: ``object`` :return: None -> success :rtype: ``None`` """ result = self._sync_request(data={'object_uuid': isoimage.id}, endpoint='objects/servers/{}/isoimages/' .format(node.id), method='POST') return result def attach_volume(self, node, volume): """ Attaches volume to node. :param node: Node to attach volume to. :type node: :class:`.Node` :param volume: Volume to attach. :type volume: :class:`.StorageVolume` :rytpe: ``bool`` """ result = self._sync_request(data={'object_uuid': volume.id}, endpoint='objects/servers/{}/storages/' .format(node.id), method='POST') return result.status == 204 def ex_link_network_to_node(self, node, network): """ Link a network to a node. :param node: Node object to link networks to. :type node: :class:`.Node` :param network: Network you want to link. :type network: :class:`.GridscaleNetwork` :return: ``True`` if linked sucessfully, otherwise ``False`` :rtype: ``bool`` """ result = self._sync_request(data={'object_uuid': network.id}, endpoint='objects/servers/{}/networks/' .format(node.id), method='POST') return result.status == 204 def ex_link_ip_to_node(self, node, ip): """ links a existing ip with a node :param node: node object :type node: ``object`` :param ip: ip object :type ip: ``object`` :return: Request ID :rtype: ``str`` """ result = self._sync_request(data={'object_uuid': ip.id}, endpoint='objects/servers/{}/ips/' .format(node.id), method='POST') return result def ex_unlink_isoimage_from_node(self, node, isoimage): """ unlink isoimages from server :param node: node you want to unlink the image from :type node: ``object`` :param isoimage: isoimage you want to unlink :type isoimage: ``object`` :return: None -> success :rtype: ``None`` """ result = self._sync_request(endpoint='objects/servers/{}/isoimages/{}' .format(node.id, isoimage.id), method='DELETE') return result def ex_unlink_ip_from_node(self, node, ip): """ unlink ips from server :param node: node you want to unlink the ip from :type node: ``object`` :param ip: the ip you want to unlink :type ip: ``object`` :return: None -> success :rtype: ``None`` """ result = self._sync_request(endpoint='objects/servers/{}/ips/{}' .format(node.id, ip.id), method='DELETE') return result def ex_unlink_network_from_node(self, node, network): """ Unlink network from node. :param node: Node you want to unlink from network. :type node: :class:`.Node` :param network: Network you want to unlink. :type network: :class:`.GridscaleNetwork :return: ``True`` if unlink was successful, otherwise ``False`` :rtype: ``bool`` """ result = self._sync_request(endpoint='objects/servers/{}/networks/{}' .format(node.id, network.id), method='DELETE') return result.status == 204 def detach_volume(self, volume): """ Detaches a volume from a node. :param volume: Volume to be detached :type volume: :class:`.StorageVolume` :rtype: ``bool`` """ node = volume.extra['relations']['servers'][0] result = self._sync_request(endpoint='objects/servers/{}/storages/{}' .format(node['object_uuid'], volume.id), method='DELETE') return result.status == 204 def ex_storage_rollback(self, volume, snapshot, rollback): """ initiate a rollback on your storage :param volume: storage uuid :type volume: ``string`` :param snapshot: snapshot uuid :type snapshot: ``string`` :param rollback: variable :type rollback: ``bool`` :return: RequestID :rtype: ``str`` """ result = self._sync_request(data={'rollback': rollback}, endpoint='objects/storages/{}/snapshots/' '{}/rollback' .format(volume.id, snapshot.id), method='PATCH') return result def ex_list_volumes_for_node(self, node): """ Return a list of associated volumes for the provided node. :rtype: ``list`` of :class:`StorageVolume` """ volumes = self.list_volumes() result = [] for volume in volumes: related_servers = volume.extra.get('relations', {}) \ .get('servers', []) for server in related_servers: if server['object_uuid'] == node.id: result.append(volume) return result def ex_list_ips_for_node(self, node): """ Return a list of associated IPs for the provided node. :rype: ``list`` of :class:`GridscaleIp` """ ips = self.ex_list_ips() result = [] for ip in ips: related_servers = ip.extra.get('relations', {}) \ .get('servers', []) for server in related_servers: # TODO: This is not consistent with volumes where key is # called "object_uuid" if server['server_uuid'] == node.id: result.append(ip) return result def _to_node(self, data): extra_keys = ['cores', 'power', 'memory', 'current_price', 'relations'] extra = self._extract_values_to_dict(data=data, keys=extra_keys) ips = [] for diction in data['relations']['public_ips']: ips.append(diction['ip']) state = '' if data['power'] is True: state = NodeState.RUNNING else: state = NodeState.STOPPED node = Node(id=data['object_uuid'], name=data['name'], state=state, public_ips=ips, created_at=parse_date(data['create_time']), private_ips=None, driver=self.connection.driver, extra=extra) return node def _to_volume(self, data): extra_keys = ['create_time', 'current_price', 'storage_type', 'relations'] extra = self._extract_values_to_dict(data=data, keys=extra_keys) storage = StorageVolume(id=data['object_uuid'], name=data['name'], size=data['capacity'], driver=self.connection.driver, extra=extra) return storage def _to_volume_snapshot(self, data): extra_keys = ['labels', 'status', 'usage_in_minutes', 'location_country', 'current_price', 'parent_uuid'] extra = self._extract_values_to_dict(data=data, keys=extra_keys) volume_snapshot = VolumeSnapshot(id=data['object_uuid'], driver=self.connection.driver, size=data['capacity'], extra=extra, created=parse_date( data['create_time']), state=StorageVolumeState.AVAILABLE, name=data['name']) return volume_snapshot def _to_location(self, data): location = NodeLocation(id=data['object_uuid'], name=data['name'], country=data['country'], driver=self.connection.driver, ) return location def _to_ip(self, data): extra_keys = ['create_time', 'current_price', 'name', 'relations', 'reverse_dns', 'status'] extra = self._extract_values_to_dict(data=data, keys=extra_keys) ip = GridscaleIp(id=data['object_uuid'], family=data['family'], prefix=data['prefix'], create_time=data['create_time'], address=data['ip'], extra=extra) return ip def _to_network(self, data): network = GridscaleNetwork(id=data['object_uuid'], name=data['name'], create_time=data['create_time'], status=data['status'], relations=data['relations']) return network def _to_node_image(self, data): extra_keys = ['capacity', 'create_time', 'labels', 'ostype', 'location_name', 'private', 'status', 'usage_in_minutes', 'version'] extra = self._extract_values_to_dict(data=data, keys=extra_keys) template = NodeImage(id=data['object_uuid'], name=data['name'], driver=self.connection.driver, extra=extra) return template def _to_key(self, data, name=None, sshkey=None): extra = { 'uuid': data['object_uuid'], 'labels': data.get('labels', []) } name = data.get('name', name) sshkey = data.get('sshkey', sshkey) key = KeyPair(name=name, fingerprint=data['object_uuid'], public_key=sshkey, private_key=None, extra=extra, driver=self.connection.driver) return key def _extract_values_to_dict(self, data, keys): """ Extract extra values to dict. :param data: dict to extract values from. :type data: ``dict`` :param keys: keys to extract :type keys: ``List`` :return: dictionary containing extra values :rtype: ``dict`` """ result = {} for key in keys: if key == 'memory': result[key] = data[key] * 1024 else: result[key] = data[key] return result def _get_response_dict(self, raw_response): """ Get the actual response dictionary. :param raw_response: Nested dictionary. :type raw_response: ``dict`` :return: Not-nested dictionary. :rtype: ``dict`` """ return list(raw_response.object.values())[0] def _get_resource(self, endpoint_suffix, object_uuid): """ Get specific uuid specific resource. :param endpoint_suffix: Endpoint resource e.g. servers/. :type endpoint_suffix: ``str`` :param object_uuid: Uuid of resource to be pulled. :type object_uuid: ``str`` :return: Response dictionary. :rtype: nested ``dict`` """ data = self._sync_request( endpoint='objects/{}/{}'.format(endpoint_suffix, object_uuid)) data = self._get_response_dict(data) return data apache-libcloud-2.8.0/libcloud/compute/drivers/gridspot.py0000664000175000017500000001006113600144066023555 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.base import NodeDriver, Node from libcloud.compute.base import NodeState from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.compute.types import Provider from libcloud.common.types import InvalidCredsError class GridspotAPIException(Exception): def __str__(self): return self.args[0] def __repr__(self): return "" % (self.args[0]) class GridspotResponse(JsonResponse): """ Response class for Gridspot """ def parse_body(self): body = super(GridspotResponse, self).parse_body() if 'exception_name' in body and body['exception_name']: raise GridspotAPIException(body['exception_name']) return body def parse_error(self): # Gridspot 404s on invalid api key or instance_id raise InvalidCredsError("Invalid api key/instance_id") class GridspotConnection(ConnectionKey): """ Connection class to connect to Gridspot's API servers """ host = 'gridspot.com' responseCls = GridspotResponse def add_default_params(self, params): params['api_key'] = self.key return params class GridspotNodeDriver(NodeDriver): """ Gridspot (http://www.gridspot.com/) node driver. """ type = Provider.GRIDSPOT name = 'Gridspot' website = 'http://www.gridspot.com/' connectionCls = GridspotConnection NODE_STATE_MAP = { 'Running': NodeState.RUNNING, 'Starting': NodeState.PENDING } def list_nodes(self): data = self.connection.request( '/compute_api/v1/list_instances').object return [self._to_node(n) for n in data['instances']] def destroy_node(self, node): data = {'instance_id': node.id} self.connection.request('/compute_api/v1/stop_instance', data).object return True def _get_node_state(self, state): result = self.NODE_STATE_MAP.get(state, NodeState.UNKNOWN) return result def _add_int_param(self, params, data, field): if data[field]: try: params[field] = int(data[field]) except Exception: pass def _to_node(self, data): port = None ip = None state = self._get_node_state(data['current_state']) if data['vm_ssh_wan_ip_endpoint'] != 'null': parts = data['vm_ssh_wan_ip_endpoint'].split(':') ip = parts[0] port = int(parts[1]) extra_params = { 'winning_bid_id': data['winning_bid_id'], 'port': port } # Spec is vague and doesn't indicate if these will always be present self._add_int_param(extra_params, data, 'vm_num_logical_cores') self._add_int_param(extra_params, data, 'vm_num_physical_cores') self._add_int_param(extra_params, data, 'vm_ram') self._add_int_param(extra_params, data, 'start_state_time') self._add_int_param(extra_params, data, 'ended_state_time') self._add_int_param(extra_params, data, 'running_state_time') return Node( id=data['instance_id'], name=data['instance_id'], state=state, public_ips=[ip], private_ips=[], driver=self.connection.driver, extra=extra_params) apache-libcloud-2.8.0/libcloud/compute/drivers/hostvirtual.py0000664000175000017500000003413313577507766024343 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ libcloud driver for the Host Virtual Inc. (VR) API Home page https://www.hostvirtual.com/ """ import time import re try: import simplejson as json except ImportError: import json from libcloud.common.hostvirtual import HostVirtualResponse from libcloud.common.hostvirtual import HostVirtualConnection from libcloud.common.hostvirtual import HostVirtualException from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState from libcloud.compute.base import Node, NodeDriver from libcloud.compute.base import NodeImage, NodeSize, NodeLocation from libcloud.compute.base import NodeAuthSSHKey, NodeAuthPassword API_ROOT = '' NODE_STATE_MAP = { 'BUILDING': NodeState.PENDING, 'PENDING': NodeState.PENDING, 'RUNNING': NodeState.RUNNING, # server is powered up 'STOPPING': NodeState.REBOOTING, 'REBOOTING': NodeState.REBOOTING, 'STARTING': NodeState.REBOOTING, 'TERMINATED': NodeState.TERMINATED, # server is powered down 'STOPPED': NodeState.STOPPED } DEFAULT_NODE_LOCATION_ID = 21 class HostVirtualComputeResponse(HostVirtualResponse): pass class HostVirtualComputeConnection(HostVirtualConnection): responseCls = HostVirtualComputeResponse class HostVirtualNodeDriver(NodeDriver): type = Provider.HOSTVIRTUAL name = 'HostVirtual' website = 'http://www.hostvirtual.com' connectionCls = HostVirtualComputeConnection features = {'create_node': ['ssh_key', 'password']} def __init__(self, key, secure=True, host=None, port=None): self.location = None super(HostVirtualNodeDriver, self).__init__(key=key, secure=secure, host=host, port=port) def list_nodes(self): try: result = self.connection.request( API_ROOT + '/cloud/servers/').object except HostVirtualException: return [] nodes = [] for value in result: node = self._to_node(value) nodes.append(node) return nodes def list_locations(self): result = self.connection.request(API_ROOT + '/cloud/locations/').object locations = [] for k in result: dc = result[k] locations.append(NodeLocation( dc["id"], dc["name"], dc["name"].split(',')[1].replace(" ", ""), # country self)) return sorted(locations, key=lambda x: int(x.id)) def list_sizes(self, location=None): params = {} if location is not None: params = {'location': location.id} result = self.connection.request( API_ROOT + '/cloud/sizes/', params=params).object sizes = [] for size in result: n = NodeSize(id=size['plan_id'], name=size['plan'], ram=size['ram'], disk=size['disk'], bandwidth=size['transfer'], price=size['price'], driver=self.connection.driver) sizes.append(n) return sizes def list_images(self): result = self.connection.request(API_ROOT + '/cloud/images/').object images = [] for image in result: i = NodeImage(id=image["id"], name=image["os"], driver=self.connection.driver, extra=image) del i.extra['id'] del i.extra['os'] images.append(i) return images def create_node(self, name, image, size, location=None, auth=None): """ Creates a node Example of node creation with ssh key deployed: >>> from libcloud.compute.base import NodeAuthSSHKey >>> key = open('/home/user/.ssh/id_rsa.pub').read() >>> auth = NodeAuthSSHKey(pubkey=key) >>> from libcloud.compute.providers import get_driver >>> driver = get_driver('hostvirtual') >>> conn = driver('API_KEY') >>> image = conn.list_images()[1] >>> size = conn.list_sizes()[0] >>> location = conn.list_locations()[1] >>> name = 'markos-dev' >>> node = conn.create_node(name, image, size, auth=auth, >>> location=location) """ dc = None auth = self._get_and_check_auth(auth) if not self._is_valid_fqdn(name): raise HostVirtualException( 500, "Name should be a valid FQDN (e.g, hostname.example.com)") # simply order a package first pkg = self.ex_order_package(size) if location: dc = location.id else: dc = DEFAULT_NODE_LOCATION_ID # create a stub node stub_node = self._to_node({ 'mbpkgid': pkg['id'], 'status': 'PENDING', 'fqdn': name, 'plan_id': size.id, 'os_id': image.id, 'location_id': dc }) # provisioning a server using the stub node self.ex_provision_node(node=stub_node, auth=auth) node = self._wait_for_node(stub_node.id) if getattr(auth, 'generated', False): node.extra['password'] = auth.password return node def reboot_node(self, node): params = {'force': 0, 'mbpkgid': node.id} result = self.connection.request( API_ROOT + '/cloud/server/reboot', data=json.dumps(params), method='POST').object return bool(result) def destroy_node(self, node): params = { 'mbpkgid': node.id, # 'reason': 'Submitted through Libcloud API' } result = self.connection.request( API_ROOT + '/cloud/cancel', data=json.dumps(params), method='POST').object return bool(result) def ex_list_packages(self): """ List the server packages. """ try: result = self.connection.request( API_ROOT + '/cloud/packages/').object except HostVirtualException: return [] pkgs = [] for value in result: pkgs.append(value) return pkgs def ex_order_package(self, size): """ Order a server package. :param size: :type node: :class:`NodeSize` :rtype: ``str`` """ params = {'plan': size.name} pkg = self.connection.request(API_ROOT + '/cloud/buy/', data=json.dumps(params), method='POST').object return pkg def ex_cancel_package(self, node): """ Cancel a server package. :param node: Node which should be used :type node: :class:`Node` :rtype: ``str`` """ params = {'mbpkgid': node.id} result = self.connection.request(API_ROOT + '/cloud/cancel/', data=json.dumps(params), method='POST').object return result def ex_unlink_package(self, node): """ Unlink a server package from location. :param node: Node which should be used :type node: :class:`Node` :rtype: ``str`` """ params = {'mbpkgid': node.id} result = self.connection.request(API_ROOT + '/cloud/unlink/', data=json.dumps(params), method='POST').object return result def ex_get_node(self, node_id): """ Get a single node. :param node_id: id of the node that we need the node object for :type node_id: ``str`` :rtype: :class:`Node` """ params = {'mbpkgid': node_id} result = self.connection.request( API_ROOT + '/cloud/server', params=params).object node = self._to_node(result) return node def start_node(self, node): """ Start a node. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ params = {'mbpkgid': node.id} result = self.connection.request( API_ROOT + '/cloud/server/start', data=json.dumps(params), method='POST').object return bool(result) def stop_node(self, node): """ Stop a node. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ params = {'force': 0, 'mbpkgid': node.id} result = self.connection.request( API_ROOT + '/cloud/server/shutdown', data=json.dumps(params), method='POST').object return bool(result) def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_provision_node(self, **kwargs): """ Provision a server on a VR package and get it booted :keyword node: node which should be used :type node: :class:`Node` :keyword image: The distribution to deploy on your server (mandatory) :type image: :class:`NodeImage` :keyword auth: an SSH key or root password (mandatory) :type auth: :class:`NodeAuthSSHKey` or :class:`NodeAuthPassword` :keyword location: which datacenter to create the server in :type location: :class:`NodeLocation` :return: Node representing the newly built server :rtype: :class:`Node` """ node = kwargs['node'] if 'image' in kwargs: image = kwargs['image'] else: image = node.extra['image'] params = { 'mbpkgid': node.id, 'image': image, 'fqdn': node.name, 'location': node.extra['location'], } auth = kwargs['auth'] ssh_key = None password = None if isinstance(auth, NodeAuthSSHKey): ssh_key = auth.pubkey params['ssh_key'] = ssh_key elif isinstance(auth, NodeAuthPassword): password = auth.password params['password'] = password if not ssh_key and not password: raise HostVirtualException( 500, "SSH key or Root password is required") try: result = self.connection.request(API_ROOT + '/cloud/server/build', data=json.dumps(params), method='POST').object return bool(result) except HostVirtualException: self.ex_cancel_package(node) def ex_delete_node(self, node): """ Delete a node. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ params = {'mbpkgid': node.id} result = self.connection.request( API_ROOT + '/cloud/server/delete', data=json.dumps(params), method='POST').object return bool(result) def _to_node(self, data): state = NODE_STATE_MAP[data['status']] public_ips = [] private_ips = [] extra = {} if 'plan_id' in data: extra['size'] = data['plan_id'] if 'os_id' in data: extra['image'] = data['os_id'] if 'fqdn' in data: extra['fqdn'] = data['fqdn'] if 'location_id' in data: extra['location'] = data['location_id'] if 'ip' in data: public_ips.append(data['ip']) node = Node(id=data['mbpkgid'], name=data['fqdn'], state=state, public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver, extra=extra) return node def _wait_for_node(self, node_id, timeout=30, interval=5.0): """ :param node_id: ID of the node to wait for. :type node_id: ``int`` :param timeout: Timeout (in seconds). :type timeout: ``int`` :param interval: How long to wait (in seconds) between each attempt. :type interval: ``float`` :return: Node representing the newly built server :rtype: :class:`Node` """ # poll until we get a node for i in range(0, timeout, int(interval)): try: node = self.ex_get_node(node_id) return node except HostVirtualException: time.sleep(interval) raise HostVirtualException(412, 'Timeout on getting node details') def _is_valid_fqdn(self, fqdn): if len(fqdn) > 255: return False if fqdn[-1] == ".": fqdn = fqdn[:-1] valid = re.compile(r"(?!-)[A-Z\d-]{1,63}(? 1: return all(valid.match(x) for x in fqdn.split(".")) else: return False apache-libcloud-2.8.0/libcloud/compute/drivers/ikoula.py0000664000175000017500000000222413535474530023221 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.providers import Provider from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver __all__ = [ 'IkoulaNodeDriver' ] class IkoulaNodeDriver(CloudStackNodeDriver): type = Provider.IKOULA name = 'Ikoula' website = 'http://express.ikoula.co.uk/cloudstack' # API endpoint info host = 'cloudstack.ikoula.com' path = '/client/api' apache-libcloud-2.8.0/libcloud/compute/drivers/indosat.py0000664000175000017500000000371513535474530023404 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Indosat Driver """ from libcloud.compute.providers import Provider from libcloud.common.dimensiondata import (DimensionDataConnection, API_ENDPOINTS) from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver DEFAULT_REGION = 'indosat-id' class IndosatNodeDriver(DimensionDataNodeDriver): """ Indosat node driver, based on Dimension Data driver """ selected_region = None connectionCls = DimensionDataConnection name = 'Indosat' website = 'http://www.indosat.com/' type = Provider.INDOSAT features = {'create_node': ['password']} api_version = 1.0 def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS: raise ValueError('Invalid region: %s' % (region)) self.selected_region = API_ENDPOINTS[region] super(IndosatNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) apache-libcloud-2.8.0/libcloud/compute/drivers/internetsolutions.py0000664000175000017500000000400213535474530025541 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Internet Solutions Driver """ from libcloud.compute.providers import Provider from libcloud.common.dimensiondata import (DimensionDataConnection, API_ENDPOINTS) from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver DEFAULT_REGION = 'is-af' class InternetSolutionsNodeDriver(DimensionDataNodeDriver): """ InternetSolutions node driver, based on Dimension Data driver """ selected_region = None connectionCls = DimensionDataConnection name = 'InternetSolutions' website = 'http://www.is.co.za/' type = Provider.INTERNETSOLUTIONS features = {'create_node': ['password']} api_version = 1.0 def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS: raise ValueError('Invalid region: %s' % (region)) self.selected_region = API_ENDPOINTS[region] super(InternetSolutionsNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) apache-libcloud-2.8.0/libcloud/compute/drivers/joyent.py0000664000175000017500000002002513577507766023262 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Joyent Cloud (http://www.joyentcloud.com) driver. """ import base64 try: import simplejson as json except Exception: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.types import LibcloudError from libcloud.compute.providers import Provider from libcloud.common.base import JsonResponse, ConnectionUserAndKey from libcloud.compute.types import NodeState, InvalidCredsError from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeSize from libcloud.utils.networking import is_private_subnet API_HOST_SUFFIX = '.api.joyentcloud.com' API_VERSION = '~6.5' NODE_STATE_MAP = { 'provisioning': NodeState.PENDING, 'running': NodeState.RUNNING, 'stopping': NodeState.TERMINATED, 'stopped': NodeState.TERMINATED, 'deleted': NodeState.TERMINATED } VALID_REGIONS = [ 'us-east-1', 'us-east-2', 'us-east-3', 'us-west-1', 'us-sw-1', 'eu-ams-1' ] DEFAULT_REGION = 'us-east-1' class JoyentResponse(JsonResponse): """ Joyent response class. """ valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_error(self): if self.status == httplib.UNAUTHORIZED: data = self.parse_body() raise InvalidCredsError(data['code'] + ': ' + data['message']) return self.body def success(self): return self.status in self.valid_response_codes class JoyentConnection(ConnectionUserAndKey): """ Joyent connection class. """ responseCls = JoyentResponse allow_insecure = False def add_default_headers(self, headers): headers['Accept'] = 'application/json' headers['Content-Type'] = 'application/json; charset=UTF-8' headers['X-Api-Version'] = API_VERSION user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) return headers class JoyentNodeDriver(NodeDriver): """ Joyent node driver class. """ type = Provider.JOYENT name = 'Joyent' website = 'http://www.joyentcloud.com' connectionCls = JoyentConnection features = {'create_node': ['generates_password']} def __init__(self, key, secret=None, secure=True, host=None, port=None, region=DEFAULT_REGION, **kwargs): # Location is here for backward compatibility reasons if 'location' in kwargs: region = kwargs['location'] if region not in VALID_REGIONS: msg = 'Invalid region: "%s". Valid region: %s' raise LibcloudError(msg % (region, ', '.join(VALID_REGIONS)), driver=self) super(JoyentNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) self.connection.host = region + API_HOST_SUFFIX def list_images(self): result = self.connection.request('/my/datasets').object images = [] for value in result: extra = {'type': value['type'], 'urn': value['urn'], 'os': value['os'], 'default': value['default']} image = NodeImage(id=value['id'], name=value['name'], driver=self.connection.driver, extra=extra) images.append(image) return images def list_sizes(self): result = self.connection.request('/my/packages').object sizes = [] for value in result: size = NodeSize(id=value['name'], name=value['name'], ram=value['memory'], disk=value['disk'], bandwidth=None, price=0.0, driver=self.connection.driver) sizes.append(size) return sizes def list_nodes(self): result = self.connection.request('/my/machines').object nodes = [] for value in result: node = self._to_node(value) nodes.append(node) return nodes def reboot_node(self, node): data = json.dumps({'action': 'reboot'}) result = self.connection.request('/my/machines/%s' % (node.id), data=data, method='POST') return result.status == httplib.ACCEPTED def destroy_node(self, node): result = self.connection.request('/my/machines/%s' % (node.id), method='DELETE') return result.status == httplib.NO_CONTENT def create_node(self, name, size, image): data = json.dumps({'name': name, 'package': size.id, 'dataset': image.id}) result = self.connection.request('/my/machines', data=data, method='POST') return self._to_node(result.object) def start_node(self, node): """ Start node :param node: The node to be stopped :type node: :class:`Node` :rtype: ``bool`` """ data = json.dumps({'action': 'start'}) result = self.connection.request('/my/machines/%s' % (node.id), data=data, method='POST') return result.status == httplib.ACCEPTED def stop_node(self, node): """ Stop node :param node: The node to be stopped :type node: :class:`Node` :rtype: ``bool`` """ data = json.dumps({'action': 'stop'}) result = self.connection.request('/my/machines/%s' % (node.id), data=data, method='POST') return result.status == httplib.ACCEPTED def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_get_node(self, node_id): """ Return a Node object based on a node ID. :param node_id: ID of the node :type node_id: ``str`` :return: A Node object for the node :rtype: :class:`Node` """ result = self.connection.request('/my/machines/%s' % (node_id)) return self._to_node(result.object) def _to_node(self, data): state = NODE_STATE_MAP[data['state']] public_ips = [] private_ips = [] extra = {} for ip in data['ips']: if is_private_subnet(ip): private_ips.append(ip) else: public_ips.append(ip) if 'credentials' in data['metadata']: extra['password'] = data['metadata']['credentials']['root'] node = Node(id=data['id'], name=data['name'], state=state, public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver, extra=extra) return node apache-libcloud-2.8.0/libcloud/compute/drivers/kili.py0000664000175000017500000000617713535474530022700 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ HP Public cloud driver which is essentially just a small wrapper around OpenStack driver. """ from libcloud.compute.types import Provider, LibcloudError from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection from libcloud.compute.drivers.openstack import OpenStack_1_1_NodeDriver __all__ = [ 'KiliCloudNodeDriver' ] ENDPOINT_ARGS = { 'service_type': 'compute', 'name': 'nova', 'region': 'RegionOne' } AUTH_URL = 'https://api.kili.io/keystone/v2.0/tokens' class KiliCloudConnection(OpenStack_1_1_Connection): _auth_version = '2.0_password' def __init__(self, *args, **kwargs): self.region = kwargs.pop('region', None) self.get_endpoint_args = kwargs.pop('get_endpoint_args', None) super(KiliCloudConnection, self).__init__(*args, **kwargs) self._auth_version = KiliCloudConnection._auth_version def get_endpoint(self): if not self.get_endpoint_args: raise LibcloudError( 'KiliCloudConnection must have get_endpoint_args set') if '2.0_password' in self._auth_version: ep = self.service_catalog.get_endpoint(**self.get_endpoint_args) else: raise LibcloudError( 'Auth version "%s" not supported' % (self._auth_version)) public_url = ep.url if not public_url: raise LibcloudError('Could not find specified endpoint') return public_url class KiliCloudNodeDriver(OpenStack_1_1_NodeDriver): name = 'Kili Public Cloud' website = 'http://kili.io/' connectionCls = KiliCloudConnection type = Provider.HPCLOUD def __init__(self, key, secret, tenant_name, secure=True, host=None, port=None, **kwargs): """ Note: tenant_name argument is required for Kili cloud. """ self.tenant_name = tenant_name super(KiliCloudNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def _ex_connection_class_kwargs(self): kwargs = self.openstack_connection_kwargs() kwargs['get_endpoint_args'] = ENDPOINT_ARGS kwargs['ex_force_auth_url'] = AUTH_URL kwargs['ex_tenant_name'] = self.tenant_name return kwargs apache-libcloud-2.8.0/libcloud/compute/drivers/ktucloud.py0000664000175000017500000000701313577507766023606 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.providers import Provider from libcloud.compute.base import Node, NodeImage, NodeSize from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver class KTUCloudNodeDriver(CloudStackNodeDriver): """Driver for KTUCloud Compute platform.""" EMPTY_DISKOFFERINGID = '0' type = Provider.KTUCLOUD name = 'KTUCloud' website = 'https://ucloudbiz.olleh.com/' def list_images(self, location=None): args = { 'templatefilter': 'executable' } if location is not None: args['zoneid'] = location.id imgs = self._sync_request(command='listAvailableProductTypes', method='GET') images = [] for img in imgs['producttypes']: images.append( NodeImage( img['serviceofferingid'], img['serviceofferingdesc'], self, {'hypervisor': '', 'format': '', 'os': img['templatedesc'], 'templateid': img['templateid'], 'zoneid': img['zoneid']} ) ) return images def list_sizes(self, location=None): szs = self._sync_request('listAvailableProductTypes') sizes = [] for sz in szs['producttypes']: diskofferingid = sz.get('diskofferingid', self.EMPTY_DISKOFFERINGID) sizes.append(NodeSize( diskofferingid, sz['diskofferingdesc'], 0, 0, 0, 0, self) ) return sizes def create_node(self, name, size, image, location=None, ex_usageplantype='hourly'): params = {'displayname': name, 'serviceofferingid': image.id, 'templateid': str(image.extra['templateid']), 'zoneid': str(image.extra['zoneid'])} if ex_usageplantype is None: params['usageplantype'] = 'hourly' else: params['usageplantype'] = ex_usageplantype if size.id != self.EMPTY_DISKOFFERINGID: params['diskofferingid'] = size.id result = self._async_request( command='deployVirtualMachine', params=params, method='GET') node = result['virtualmachine'] return Node( id=node['id'], name=node['displayname'], state=self.NODE_STATE_MAP[node['state']], public_ips=[], private_ips=[], driver=self, extra={ 'zoneid': image.extra['zoneid'], 'ip_addresses': [], 'forwarding_rules': [], } ) apache-libcloud-2.8.0/libcloud/compute/drivers/libvirt_driver.py0000664000175000017500000003451713576514553025002 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import re import os import time import platform import subprocess import mimetypes from os.path import join as pjoin from collections import defaultdict from libcloud.utils.py3 import ET from libcloud.compute.base import NodeDriver, Node from libcloud.compute.base import NodeState from libcloud.compute.types import Provider from libcloud.utils.networking import is_public_subnet from libcloud.utils.py3 import ensure_string try: import libvirt have_libvirt = True except ImportError: have_libvirt = False class LibvirtNodeDriver(NodeDriver): """ Libvirt (http://libvirt.org/) node driver. To enable debug mode, set LIBVIR_DEBUG environment variable. """ type = Provider.LIBVIRT name = 'Libvirt' website = 'http://libvirt.org/' NODE_STATE_MAP = { 0: NodeState.TERMINATED, # no state 1: NodeState.RUNNING, # domain is running 2: NodeState.PENDING, # domain is blocked on resource 3: NodeState.TERMINATED, # domain is paused by user 4: NodeState.TERMINATED, # domain is being shut down 5: NodeState.TERMINATED, # domain is shut off 6: NodeState.UNKNOWN, # domain is crashed 7: NodeState.UNKNOWN, # domain is suspended by guest power management } def __init__(self, uri, key=None, secret=None): """ :param uri: Hypervisor URI (e.g. vbox:///session, qemu:///system, etc.). :type uri: ``str`` :param key: the username for a remote libvirtd server :type key: ``str`` :param secret: the password for a remote libvirtd server :type key: ``str`` """ if not have_libvirt: raise RuntimeError('Libvirt driver requires \'libvirt\' Python ' + 'package') self._uri = uri self._key = key self._secret = secret if uri is not None and '+tcp' in self._uri: if key is None and secret is None: raise RuntimeError('The remote Libvirt instance requires ' + 'authentication, please set \'key\' and ' + '\'secret\' parameters') auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE], self._cred_callback, None] self.connection = libvirt.openAuth(uri, auth, 0) else: self.connection = libvirt.open(uri) if uri is None: self._uri = self.connection.getInfo() def _cred_callback(self, cred, user_data): """ Callback for the authentication scheme, which will provide username and password for the login. Reference: ( http://bit.ly/1U5yyQg ) :param cred: The credentials requested and the return :type cred: ``list`` :param user_data: Custom data provided to the authentication routine :type user_data: ``list`` :rtype: ``int`` """ for credential in cred: if credential[0] == libvirt.VIR_CRED_AUTHNAME: credential[4] = self._key elif credential[0] == libvirt.VIR_CRED_PASSPHRASE: credential[4] = self._secret return 0 def list_nodes(self): domains = self.connection.listAllDomains() nodes = self._to_nodes(domains=domains) return nodes def reboot_node(self, node): domain = self._get_domain_for_node(node=node) return domain.reboot(flags=0) == 0 def destroy_node(self, node): domain = self._get_domain_for_node(node=node) return domain.destroy() == 0 def start_node(self, node): domain = self._get_domain_for_node(node=node) return domain.create() == 0 def stop_node(self, node): domain = self._get_domain_for_node(node=node) return domain.shutdown() == 0 def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 """ Start a stopped node. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ return self.start_node(node=node) def ex_shutdown_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 """ Shutdown a running node. Note: Usually this will result in sending an ACPI event to the node. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ return self.stop_node(node=node) def ex_suspend_node(self, node): """ Suspend a running node. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ domain = self._get_domain_for_node(node=node) return domain.suspend() == 0 def ex_resume_node(self, node): """ Resume a suspended node. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ domain = self._get_domain_for_node(node=node) return domain.resume() == 0 def ex_get_node_by_uuid(self, uuid): """ Retrieve Node object for a domain with a provided uuid. :param uuid: Uuid of the domain. :type uuid: ``str`` """ domain = self._get_domain_for_uuid(uuid=uuid) node = self._to_node(domain=domain) return node def ex_get_node_by_name(self, name): """ Retrieve Node object for a domain with a provided name. :param name: Name of the domain. :type name: ``str`` """ domain = self._get_domain_for_name(name=name) node = self._to_node(domain=domain) return node def ex_take_node_screenshot(self, node, directory, screen=0): """ Take a screenshot of a monitoring of a running instance. :param node: Node to take the screenshot of. :type node: :class:`libcloud.compute.base.Node` :param directory: Path where the screenshot will be saved. :type directory: ``str`` :param screen: ID of the monitor to take the screenshot of. :type screen: ``int`` :return: Full path where the screenshot has been saved. :rtype: ``str`` """ if not os.path.exists(directory) or not os.path.isdir(directory): raise ValueError('Invalid value for directory argument') domain = self._get_domain_for_node(node=node) stream = self.connection.newStream() mime_type = domain.screenshot(stream=stream, screen=0) extensions = mimetypes.guess_all_extensions(type=mime_type) if extensions: extension = extensions[0] else: extension = '.png' name = 'screenshot-%s%s' % (int(time.time()), extension) file_path = pjoin(directory, name) with open(file_path, 'wb') as fp: def write(stream, buf, opaque): fp.write(buf) stream.recvAll(write, None) try: stream.finish() except Exception: # Finish is not supported by all backends pass return file_path def ex_get_hypervisor_hostname(self): """ Return a system hostname on which the hypervisor is running. """ hostname = self.connection.getHostname() return hostname def ex_get_hypervisor_sysinfo(self): """ Retrieve hypervisor system information. :rtype: ``dict`` """ xml = self.connection.getSysinfo() etree = ET.XML(xml) attributes = ['bios', 'system', 'processor', 'memory_device'] sysinfo = {} for attribute in attributes: element = etree.find(attribute) entries = self._get_entries(element=element) sysinfo[attribute] = entries return sysinfo def _to_nodes(self, domains): nodes = [self._to_node(domain=domain) for domain in domains] return nodes def _to_node(self, domain): state, max_mem, memory, vcpu_count, used_cpu_time = domain.info() state = self.NODE_STATE_MAP.get(state, NodeState.UNKNOWN) public_ips, private_ips = [], [] ip_addresses = self._get_ip_addresses_for_domain(domain) for ip_address in ip_addresses: if is_public_subnet(ip_address): public_ips.append(ip_address) else: private_ips.append(ip_address) extra = {'uuid': domain.UUIDString(), 'os_type': domain.OSType(), 'types': self.connection.getType(), 'used_memory': memory / 1024, 'vcpu_count': vcpu_count, 'used_cpu_time': used_cpu_time} node = Node(id=domain.ID(), name=domain.name(), state=state, public_ips=public_ips, private_ips=private_ips, driver=self, extra=extra) node._uuid = domain.UUIDString() # we want to use a custom UUID return node def _get_ip_addresses_for_domain(self, domain): """ Retrieve IP addresses for the provided domain. Note: This functionality is currently only supported on Linux and only works if this code is run on the same machine as the VMs run on. :return: IP addresses for the provided domain. :rtype: ``list`` """ result = [] if platform.system() != 'Linux': # Only Linux is supported atm return result if '///' not in self._uri: # Only local libvirtd is supported atm return result mac_addresses = self._get_mac_addresses_for_domain(domain=domain) arp_table = {} try: cmd = ['arp', '-an'] child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, _ = child.communicate() arp_table = self._parse_ip_table_arp(arp_output=stdout) except OSError as e: if e.errno == 2: cmd = ['ip', 'neigh'] child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, _ = child.communicate() arp_table = self._parse_ip_table_neigh(ip_output=stdout) for mac_address in mac_addresses: if mac_address in arp_table: ip_addresses = arp_table[mac_address] result.extend(ip_addresses) return result def _get_mac_addresses_for_domain(self, domain): """ Parses network interface MAC addresses from the provided domain. """ xml = domain.XMLDesc() etree = ET.XML(xml) elems = etree.findall("devices/interface[@type='network']/mac") result = [] for elem in elems: mac_address = elem.get('address') result.append(mac_address) return result def _get_domain_for_node(self, node): """ Return libvirt domain object for the provided node. """ domain = self.connection.lookupByUUIDString(node.uuid) return domain def _get_domain_for_uuid(self, uuid): """ Return libvirt domain object for the provided uuid. """ domain = self.connection.lookupByUUIDString(uuid) return domain def _get_domain_for_name(self, name): """ Return libvirt domain object for the provided name. """ domain = self.connection.lookupByName(name) return domain def _get_entries(self, element): """ Parse entries dictionary. :rtype: ``dict`` """ elements = element.findall('entry') result = {} for element in elements: name = element.get('name') value = element.text result[name] = value return result def _parse_ip_table_arp(self, arp_output): """ Sets up the regexp for parsing out IP addresses from the 'arp -an' command and pass it along to the parser function. :return: Dictionary from the parsing funtion :rtype: ``dict`` """ arp_regex = re.compile(r'.*?\((.*?)\) at (.*?)\s+') return self._parse_mac_addr_table(arp_output, arp_regex) def _parse_ip_table_neigh(self, ip_output): """ Sets up the regexp for parsing out IP addresses from the 'ip neighbor' command and pass it along to the parser function. :return: Dictionary from the parsing function :rtype: ``dict`` """ ip_regex = re.compile(r'(.*?)\s+.*lladdr\s+(.*?)\s+') return self._parse_mac_addr_table(ip_output, ip_regex) def _parse_mac_addr_table(self, cmd_output, mac_regex): """ Parse the command output and return a dictionary which maps mac address to an IP address. :return: Dictionary which maps mac address to IP address. :rtype: ``dict`` """ lines = ensure_string(cmd_output).split('\n') arp_table = defaultdict(list) for line in lines: match = mac_regex.match(line) if not match: continue groups = match.groups() ip_address = groups[0] mac_address = groups[1] arp_table[mac_address].append(ip_address) return arp_table apache-libcloud-2.8.0/libcloud/compute/drivers/linode.py0000664000175000017500000006377113600144066023214 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """libcloud driver for the Linode(R) API This driver implements all libcloud functionality for the Linode API. Since the API is a bit more fine-grained, create_node abstracts a significant amount of work (and may take a while to run). Linode home page http://www.linode.com/ Linode API documentation http://www.linode.com/api/ Alternate bindings for reference http://github.com/tjfontaine/linode-python Linode(R) is a registered trademark of Linode, LLC. """ import os try: import simplejson as json except ImportError: import json import itertools import binascii from copy import copy from libcloud.utils.py3 import PY3 from libcloud.common.linode import (API_ROOT, LinodeException, LinodeConnection, LINODE_PLAN_IDS, LINODE_DISK_FILESYSTEMS) from libcloud.compute.types import Provider, NodeState from libcloud.compute.base import NodeDriver, NodeSize, Node, NodeLocation from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey from libcloud.compute.base import NodeImage, StorageVolume class LinodeNodeDriver(NodeDriver): """libcloud driver for the Linode API Rough mapping of which is which: - list_nodes linode.list - reboot_node linode.reboot - destroy_node linode.delete - create_node linode.create, linode.update, linode.disk.createfromdistribution, linode.disk.create, linode.config.create, linode.ip.addprivate, linode.boot - list_sizes avail.linodeplans - list_images avail.distributions - list_locations avail.datacenters - list_volumes linode.disk.list - destroy_volume linode.disk.delete For more information on the Linode API, be sure to read the reference: http://www.linode.com/api/ """ type = Provider.LINODE name = "Linode" website = 'http://www.linode.com/' connectionCls = LinodeConnection _linode_plan_ids = LINODE_PLAN_IDS _linode_disk_filesystems = LINODE_DISK_FILESYSTEMS features = {'create_node': ['ssh_key', 'password']} def __init__(self, key): """Instantiate the driver with the given API key :param key: the API key to use (required) :type key: ``str`` :rtype: ``None`` """ self.datacenter = None NodeDriver.__init__(self, key) # Converts Linode's state from DB to a NodeState constant. LINODE_STATES = { (-2): NodeState.UNKNOWN, # Boot Failed (-1): NodeState.PENDING, # Being Created 0: NodeState.PENDING, # Brand New 1: NodeState.RUNNING, # Running 2: NodeState.STOPPED, # Powered Off 3: NodeState.REBOOTING, # Shutting Down 4: NodeState.UNKNOWN # Reserved } def list_nodes(self): """ List all Linodes that the API key can access This call will return all Linodes that the API key in use has access to. If a node is in this list, rebooting will work; however, creation and destruction are a separate grant. :return: List of node objects that the API key can access :rtype: ``list`` of :class:`Node` """ params = {"api_action": "linode.list"} data = self.connection.request(API_ROOT, params=params).objects[0] return self._to_nodes(data) def start_node(self, node): """ Boot the given Linode """ params = {"api_action": "linode.boot", "LinodeID": node.id} self.connection.request(API_ROOT, params=params) return True def stop_node(self, node): """ Shutdown the given Linode """ params = {"api_action": "linode.shutdown", "LinodeID": node.id} self.connection.request(API_ROOT, params=params) return True def reboot_node(self, node): """ Reboot the given Linode Will issue a shutdown job followed by a boot job, using the last booted configuration. In most cases, this will be the only configuration. :param node: the Linode to reboot :type node: :class:`Node` :rtype: ``bool`` """ params = {"api_action": "linode.reboot", "LinodeID": node.id} self.connection.request(API_ROOT, params=params) return True def destroy_node(self, node): """Destroy the given Linode Will remove the Linode from the account and issue a prorated credit. A grant for removing Linodes from the account is required, otherwise this method will fail. In most cases, all disk images must be removed from a Linode before the Linode can be removed; however, this call explicitly skips those safeguards. There is no going back from this method. :param node: the Linode to destroy :type node: :class:`Node` :rtype: ``bool`` """ params = {"api_action": "linode.delete", "LinodeID": node.id, "skipChecks": True} self.connection.request(API_ROOT, params=params) return True def create_node(self, name, image, size, auth, location=None, ex_swap=None, ex_rsize=None, ex_kernel=None, ex_payment=None, ex_comment=None, ex_private=False, lconfig=None, lroot=None, lswap=None): """Create a new Linode, deploy a Linux distribution, and boot This call abstracts much of the functionality of provisioning a Linode and getting it booted. A global grant to add Linodes to the account is required, as this call will result in a billing charge. Note that there is a safety valve of 5 Linodes per hour, in order to prevent a runaway script from ruining your day. :keyword name: the name to assign the Linode (mandatory) :type name: ``str`` :keyword image: which distribution to deploy on the Linode (mandatory) :type image: :class:`NodeImage` :keyword size: the plan size to create (mandatory) :type size: :class:`NodeSize` :keyword auth: an SSH key or root password (mandatory) :type auth: :class:`NodeAuthSSHKey` or :class:`NodeAuthPassword` :keyword location: which datacenter to create the Linode in :type location: :class:`NodeLocation` :keyword ex_swap: size of the swap partition in MB (128) :type ex_swap: ``int`` :keyword ex_rsize: size of the root partition in MB (plan size - swap). :type ex_rsize: ``int`` :keyword ex_kernel: a kernel ID from avail.kernels (Latest 2.6 Stable). :type ex_kernel: ``str`` :keyword ex_payment: one of 1, 12, or 24; subscription length (1) :type ex_payment: ``int`` :keyword ex_comment: a small comment for the configuration (libcloud) :type ex_comment: ``str`` :keyword ex_private: whether or not to request a private IP (False) :type ex_private: ``bool`` :keyword lconfig: what to call the configuration (generated) :type lconfig: ``str`` :keyword lroot: what to call the root image (generated) :type lroot: ``str`` :keyword lswap: what to call the swap space (generated) :type lswap: ``str`` :return: Node representing the newly-created Linode :rtype: :class:`Node` """ auth = self._get_and_check_auth(auth) # Pick a location (resolves LIBCLOUD-41 in JIRA) if location: chosen = location.id elif self.datacenter: chosen = self.datacenter else: raise LinodeException(0xFB, "Need to select a datacenter first") # Step 0: Parameter validation before we purchase # We're especially careful here so we don't fail after purchase, rather # than getting halfway through the process and having the API fail. # Plan ID plans = self.list_sizes() if size.id not in [p.id for p in plans]: raise LinodeException(0xFB, "Invalid plan ID -- avail.plans") # Payment schedule payment = "1" if not ex_payment else str(ex_payment) if payment not in ["1", "12", "24"]: raise LinodeException(0xFB, "Invalid subscription (1, 12, 24)") ssh = None root = None # SSH key and/or root password if isinstance(auth, NodeAuthSSHKey): ssh = auth.pubkey # pylint: disable=no-member elif isinstance(auth, NodeAuthPassword): root = auth.password if not ssh and not root: raise LinodeException(0xFB, "Need SSH key or root password") if root is not None and len(root) < 6: raise LinodeException(0xFB, "Root password is too short") # Swap size try: swap = 128 if not ex_swap else int(ex_swap) except Exception: raise LinodeException(0xFB, "Need an integer swap size") # Root partition size imagesize = (size.disk - swap) if not ex_rsize else\ int(ex_rsize) if (imagesize + swap) > size.disk: raise LinodeException(0xFB, "Total disk images are too big") # Distribution ID distros = self.list_images() if image.id not in [d.id for d in distros]: raise LinodeException(0xFB, "Invalid distro -- avail.distributions") # Kernel if ex_kernel: kernel = ex_kernel else: if image.extra['64bit']: # For a list of available kernel ids, see # https://www.linode.com/kernels/ kernel = 138 else: kernel = 137 params = {"api_action": "avail.kernels"} kernels = self.connection.request(API_ROOT, params=params).objects[0] if kernel not in [z["KERNELID"] for z in kernels]: raise LinodeException(0xFB, "Invalid kernel -- avail.kernels") # Comments comments = "Created by Apache libcloud " if\ not ex_comment else ex_comment # Step 1: linode.create params = { "api_action": "linode.create", "DatacenterID": chosen, "PlanID": size.id, "PaymentTerm": payment } data = self.connection.request(API_ROOT, params=params).objects[0] linode = {"id": data["LinodeID"]} # Step 1b. linode.update to rename the Linode params = { "api_action": "linode.update", "LinodeID": linode["id"], "Label": name } self.connection.request(API_ROOT, params=params) # Step 1c. linode.ip.addprivate if it was requested if ex_private: params = { "api_action": "linode.ip.addprivate", "LinodeID": linode["id"] } self.connection.request(API_ROOT, params=params) # Step 1d. Labels # use the linode id as the name can be up to 63 chars and the labels # are limited to 48 chars label = { "lconfig": "[%s] Configuration Profile" % linode["id"], "lroot": "[%s] %s Disk Image" % (linode["id"], image.name), "lswap": "[%s] Swap Space" % linode["id"] } if lconfig: label['lconfig'] = lconfig if lroot: label['lroot'] = lroot if lswap: label['lswap'] = lswap # Step 2: linode.disk.createfromdistribution if not root: root = binascii.b2a_base64(os.urandom(8)).decode('ascii').strip() params = { "api_action": "linode.disk.createfromdistribution", "LinodeID": linode["id"], "DistributionID": image.id, "Label": label["lroot"], "Size": imagesize, "rootPass": root, } if ssh: params["rootSSHKey"] = ssh data = self.connection.request(API_ROOT, params=params).objects[0] linode["rootimage"] = data["DiskID"] # Step 3: linode.disk.create for swap params = { "api_action": "linode.disk.create", "LinodeID": linode["id"], "Label": label["lswap"], "Type": "swap", "Size": swap } data = self.connection.request(API_ROOT, params=params).objects[0] linode["swapimage"] = data["DiskID"] # Step 4: linode.config.create for main profile disks = "%s,%s,,,,,,," % (linode["rootimage"], linode["swapimage"]) params = { "api_action": "linode.config.create", "LinodeID": linode["id"], "KernelID": kernel, "Label": label["lconfig"], "Comments": comments, "DiskList": disks } if ex_private: params['helper_network'] = True params['helper_distro'] = True data = self.connection.request(API_ROOT, params=params).objects[0] linode["config"] = data["ConfigID"] # Step 5: linode.boot params = { "api_action": "linode.boot", "LinodeID": linode["id"], "ConfigID": linode["config"] } self.connection.request(API_ROOT, params=params) # Make a node out of it and hand it back params = {"api_action": "linode.list", "LinodeID": linode["id"]} data = self.connection.request(API_ROOT, params=params).objects[0] nodes = self._to_nodes(data) if len(nodes) == 1: node = nodes[0] if getattr(auth, "generated", False): node.extra['password'] = auth.password return node return None def ex_resize_node(self, node, size): """Resizes a Linode from one plan to another Immediately shuts the Linode down, charges/credits the account, and issue a migration to another host server. Requires a size (numeric), which is the desired PlanID available from avail.LinodePlans() After resize is complete the node needs to be booted """ params = {"api_action": "linode.resize", "LinodeID": node.id, "PlanID": size} self.connection.request(API_ROOT, params=params) return True def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_rename_node(self, node, name): """Renames a node""" params = { "api_action": "linode.update", "LinodeID": node.id, "Label": name } self.connection.request(API_ROOT, params=params) return True def list_sizes(self, location=None): """ List available Linode plans Gets the sizes that can be used for creating a Linode. Since available Linode plans vary per-location, this method can also be passed a location to filter the availability. :keyword location: the facility to retrieve plans in :type location: :class:`NodeLocation` :rtype: ``list`` of :class:`NodeSize` """ params = {"api_action": "avail.linodeplans"} data = self.connection.request(API_ROOT, params=params).objects[0] sizes = [] for obj in data: n = NodeSize(id=obj["PLANID"], name=obj["LABEL"], ram=obj["RAM"], disk=(obj["DISK"] * 1024), bandwidth=obj["XFER"], price=obj["PRICE"], driver=self.connection.driver) sizes.append(n) return sizes def list_images(self): """ List available Linux distributions Retrieve all Linux distributions that can be deployed to a Linode. :rtype: ``list`` of :class:`NodeImage` """ params = {"api_action": "avail.distributions"} data = self.connection.request(API_ROOT, params=params).objects[0] distros = [] for obj in data: i = NodeImage(id=obj["DISTRIBUTIONID"], name=obj["LABEL"], driver=self.connection.driver, extra={'pvops': obj['REQUIRESPVOPSKERNEL'], '64bit': obj['IS64BIT']}) distros.append(i) return distros def list_locations(self): """ List available facilities for deployment Retrieve all facilities that a Linode can be deployed in. :rtype: ``list`` of :class:`NodeLocation` """ params = {"api_action": "avail.datacenters"} data = self.connection.request(API_ROOT, params=params).objects[0] nl = [] for dc in data: country = None if "USA" in dc["LOCATION"]: country = "US" elif "UK" in dc["LOCATION"]: country = "GB" elif "JP" in dc["LOCATION"]: country = "JP" else: country = "??" nl.append(NodeLocation(dc["DATACENTERID"], dc["LOCATION"], country, self)) return nl def linode_set_datacenter(self, dc): """ Set the default datacenter for Linode creation Since Linodes must be created in a facility, this function sets the default that :class:`create_node` will use. If a location keyword is not passed to :class:`create_node`, this method must have already been used. :keyword dc: the datacenter to create Linodes in unless specified :type dc: :class:`NodeLocation` :rtype: ``bool`` """ did = dc.id params = {"api_action": "avail.datacenters"} data = self.connection.request(API_ROOT, params=params).objects[0] for datacenter in data: if did == dc["DATACENTERID"]: self.datacenter = did return dcs = ", ".join([d["DATACENTERID"] for d in data]) self.datacenter = None raise LinodeException(0xFD, "Invalid datacenter (use one of %s)" % dcs) def destroy_volume(self, volume): """ Destroys disk volume for the Linode. Linode id is to be provided as extra["LinodeId"] whithin :class:`StorageVolume`. It can be retrieved by :meth:`libcloud.compute.drivers.linode.LinodeNodeDriver\ .ex_list_volumes`. :param volume: Volume to be destroyed :type volume: :class:`StorageVolume` :rtype: ``bool`` """ if not isinstance(volume, StorageVolume): raise LinodeException(0xFD, "Invalid volume instance") if volume.extra["LINODEID"] is None: raise LinodeException(0xFD, "Missing LinodeID") params = { "api_action": "linode.disk.delete", "LinodeID": volume.extra["LINODEID"], "DiskID": volume.id, } self.connection.request(API_ROOT, params=params) return True def ex_create_volume(self, size, name, node, fs_type): """ Create disk for the Linode. :keyword size: Size of volume in megabytes (required) :type size: ``int`` :keyword name: Name of the volume to be created :type name: ``str`` :keyword node: Node to attach volume to. :type node: :class:`Node` :keyword fs_type: The formatted type of this disk. Valid types are: ext3, ext4, swap, raw :type fs_type: ``str`` :return: StorageVolume representing the newly-created volume :rtype: :class:`StorageVolume` """ # check node if not isinstance(node, Node): raise LinodeException(0xFD, "Invalid node instance") # check space available total_space = node.extra['TOTALHD'] existing_volumes = self.ex_list_volumes(node) used_space = 0 for volume in existing_volumes: used_space = used_space + volume.size available_space = total_space - used_space if available_space < size: raise LinodeException(0xFD, "Volume size too big. Available space\ %d" % available_space) # check filesystem type if fs_type not in self._linode_disk_filesystems: raise LinodeException(0xFD, "Not valid filesystem type") params = { "api_action": "linode.disk.create", "LinodeID": node.id, "Label": name, "Type": fs_type, "Size": size } data = self.connection.request(API_ROOT, params=params).objects[0] volume = data["DiskID"] # Make a volume out of it and hand it back params = { "api_action": "linode.disk.list", "LinodeID": node.id, "DiskID": volume } data = self.connection.request(API_ROOT, params=params).objects[0] return self._to_volumes(data)[0] def ex_list_volumes(self, node, disk_id=None): """ List existing disk volumes for for given Linode. :keyword node: Node to list disk volumes for. (required) :type node: :class:`Node` :keyword disk_id: Id for specific disk volume. (optional) :type disk_id: ``int`` :rtype: ``list`` of :class:`StorageVolume` """ if not isinstance(node, Node): raise LinodeException(0xFD, "Invalid node instance") params = { "api_action": "linode.disk.list", "LinodeID": node.id } # Add param if disk_id was specified if disk_id is not None: params["DiskID"] = disk_id data = self.connection.request(API_ROOT, params=params).objects[0] return self._to_volumes(data) def _to_volumes(self, objs): """ Covert returned JSON volumes into StorageVolume instances :keyword objs: ``list`` of JSON dictionaries representing the StorageVolumes :type objs: ``list`` :return: ``list`` of :class:`StorageVolume`s """ volumes = {} for o in objs: vid = o["DISKID"] volumes[vid] = vol = StorageVolume(id=vid, name=o["LABEL"], size=int(o["SIZE"]), driver=self.connection.driver) vol.extra = copy(o) return list(volumes.values()) def _to_nodes(self, objs): """Convert returned JSON Linodes into Node instances :keyword objs: ``list`` of JSON dictionaries representing the Linodes :type objs: ``list`` :return: ``list`` of :class:`Node`s""" # Get the IP addresses for the Linodes nodes = {} batch = [] for o in objs: lid = o["LINODEID"] nodes[lid] = n = Node(id=lid, name=o["LABEL"], public_ips=[], private_ips=[], state=self.LINODE_STATES[o["STATUS"]], driver=self.connection.driver) n.extra = copy(o) n.extra["PLANID"] = self._linode_plan_ids.get(o.get("TOTALRAM")) batch.append({"api_action": "linode.ip.list", "LinodeID": lid}) # Avoid batch limitation ip_answers = [] args = [iter(batch)] * 25 if PY3: izip_longest = itertools.zip_longest # pylint: disable=no-member else: izip_longest = getattr(itertools, 'izip_longest', _izip_longest) for twenty_five in izip_longest(*args): twenty_five = [q for q in twenty_five if q] params = {"api_action": "batch", "api_requestArray": json.dumps(twenty_five)} req = self.connection.request(API_ROOT, params=params) if not req.success() or len(req.objects) == 0: return None ip_answers.extend(req.objects) # Add the returned IPs to the nodes and return them for ip_list in ip_answers: for ip in ip_list: lid = ip["LINODEID"] which = nodes[lid].public_ips if ip["ISPUBLIC"] == 1 else\ nodes[lid].private_ips which.append(ip["IPADDRESS"]) return list(nodes.values()) def _izip_longest(*args, **kwds): """Taken from Python docs http://docs.python.org/library/itertools.html#itertools.izip """ fillvalue = kwds.get('fillvalue') def sentinel(counter=([fillvalue] * (len(args) - 1)).pop): yield counter() # yields the fillvalue, or raises IndexError fillers = itertools.repeat(fillvalue) iters = [itertools.chain(it, sentinel(), fillers) for it in args] try: for tup in itertools.izip(*iters): yield tup except IndexError: pass apache-libcloud-2.8.0/libcloud/compute/drivers/maxihost.py0000664000175000017500000002034313576514553023600 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json import re from libcloud.compute.base import Node, NodeDriver, NodeLocation from libcloud.compute.base import NodeSize, NodeImage from libcloud.compute.base import KeyPair from libcloud.common.maxihost import MaxihostConnection from libcloud.compute.types import Provider, NodeState from libcloud.common.exceptions import BaseHTTPError from libcloud.utils.py3 import httplib __all__ = [ "MaxihostNodeDriver" ] class MaxihostNodeDriver(NodeDriver): """ Base Maxihost node driver. """ connectionCls = MaxihostConnection type = Provider.MAXIHOST name = 'Maxihost' website = 'https://www.maxihost.com/' def create_node(self, name, size, image, location, ex_ssh_key_ids=None): """ Create a node. :return: The newly created node. :rtype: :class:`Node` """ attr = {'hostname': name, 'plan': size.id, 'operating_system': image.id, 'facility': location.id.lower(), 'billing_cycle': 'monthly'} if ex_ssh_key_ids: attr['ssh_keys'] = ex_ssh_key_ids try: res = self.connection.request('/devices', params=attr, method='POST') except BaseHTTPError as exc: error_message = exc.message.get('error_messages', '') raise ValueError('Failed to create node: %s' % (error_message)) return self._to_node(res.object['devices'][0]) def start_node(self, node): """ Start a node. """ params = {"type": "power_on"} res = self.connection.request('/devices/%s/actions' % node.id, params=params, method='PUT') return res.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def stop_node(self, node): """ Stop a node. """ params = {"type": "power_off"} res = self.connection.request('/devices/%s/actions' % node.id, params=params, method='PUT') return res.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def destroy_node(self, node): """ Destroy a node. """ res = self.connection.request('/devices/%s' % node.id, method='DELETE') return res.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def reboot_node(self, node): """ Reboot a node. """ params = {"type": "power_cycle"} res = self.connection.request('/devices/%s/actions' % node.id, params=params, method='PUT') return res.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def list_nodes(self): """ List nodes :rtype: ``list`` of :class:`MaxihostNode` """ response = self.connection.request('/devices') nodes = [self._to_node(host) for host in response.object['devices']] return nodes def _to_node(self, data): extra = {} private_ips = [] public_ips = [] for ip in data['ips']: if 'Private' in ip['ip_description']: private_ips.append(ip['ip_address']) else: public_ips.append(ip['ip_address']) if data['power_status']: state = NodeState.RUNNING else: state = NodeState.STOPPED for key in data: extra[key] = data[key] node = Node(id=data['id'], name=data['description'], state=state, private_ips=private_ips, public_ips=public_ips, driver=self, extra=extra) return node def list_locations(self, ex_available=True): """ List locations If ex_available is True, show only locations which are available """ locations = [] data = self.connection.request('/regions') for location in data.object['regions']: if ex_available: if location.get('available'): locations.append(self._to_location(location)) else: locations.append(self._to_location(location)) return locations def _to_location(self, data): name = data.get('location').get('city', '') country = data.get('location').get('country', '') return NodeLocation(id=data['slug'], name=name, country=country, driver=self) def list_sizes(self): """ List sizes """ sizes = [] data = self.connection.request('/plans') for size in data.object['servers']: sizes.append(self._to_size(size)) return sizes def _to_size(self, data): extra = {'specs': data['specs'], 'regions': data['regions'], 'pricing': data['pricing']} ram = data['specs']['memory']['total'] ram = re.sub("[^0-9]", "", ram) return NodeSize(id=data['slug'], name=data['name'], ram=int(ram), disk=None, bandwidth=None, price=data['pricing']['usd_month'], driver=self, extra=extra) def list_images(self): """ List images """ images = [] data = self.connection.request('/plans/operating-systems') for image in data.object['operating-systems']: images.append(self._to_image(image)) return images def _to_image(self, data): extra = {'operating_system': data['operating_system'], 'distro': data['distro'], 'version': data['version'], 'pricing': data['pricing']} return NodeImage(id=data['slug'], name=data['name'], driver=self, extra=extra) def list_key_pairs(self): """ List all the available SSH keys. :return: Available SSH keys. :rtype: ``list`` of :class:`KeyPair` """ data = self.connection.request('/account/keys') return list(map(self._to_key_pair, data.object['ssh_keys'])) def create_key_pair(self, name, public_key): """ Create a new SSH key. :param name: Key name (required) :type name: ``str`` :param public_key: base64 encoded public key string (required) :type public_key: ``str`` """ attr = {'name': name, 'public_key': public_key} res = self.connection.request('/account/keys', method='POST', data=json.dumps(attr)) data = res.object['ssh_key'] return self._to_key_pair(data=data) def _to_key_pair(self, data): extra = {'id': data['id']} return KeyPair(name=data['name'], fingerprint=data['fingerprint'], public_key=data['public_key'], private_key=None, driver=self, extra=extra) def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) apache-libcloud-2.8.0/libcloud/compute/drivers/medone.py0000664000175000017500000000370013535474530023204 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Med-1 Driver """ from libcloud.compute.providers import Provider from libcloud.common.dimensiondata import (DimensionDataConnection, API_ENDPOINTS) from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver DEFAULT_REGION = 'med1-il' class MedOneNodeDriver(DimensionDataNodeDriver): """ Med-1 node driver, based on Dimension Data driver """ selected_region = None connectionCls = DimensionDataConnection name = 'MedOne' website = 'http://www.med-1.com/' type = Provider.MEDONE features = {'create_node': ['password']} api_version = 1.0 def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS: raise ValueError('Invalid region: %s' % (region)) self.selected_region = API_ENDPOINTS[region] super(MedOneNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) apache-libcloud-2.8.0/libcloud/compute/drivers/nephoscale.py0000664000175000017500000004243213576514553024070 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ NephoScale Cloud driver (http://www.nephoscale.com) API documentation: http://docs.nephoscale.com Created by Markos Gogoulos (https://mist.io) """ import base64 import time import os import binascii from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.utils.py3 import urlencode from libcloud.compute.providers import Provider from libcloud.common.base import JsonResponse, ConnectionUserAndKey from libcloud.compute.types import (NodeState, InvalidCredsError, LibcloudError) from libcloud.compute.base import (Node, NodeDriver, NodeImage, NodeSize, NodeLocation) from libcloud.utils.networking import is_private_subnet API_HOST = 'api.nephoscale.com' NODE_STATE_MAP = { 'on': NodeState.RUNNING, 'off': NodeState.UNKNOWN, 'unknown': NodeState.UNKNOWN, } VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] # used in create_node and specifies how many times to get the list of nodes and # check if the newly created node is there. This is because when a request is # sent to create a node, NephoScale replies with the job id, and not the node # itself thus we don't have the ip addresses, that are required in deploy_node CONNECT_ATTEMPTS = 10 class NodeKey(object): def __init__(self, id, name, public_key=None, key_group=None, password=None): self.id = id self.name = name self.key_group = key_group self.password = password self.public_key = public_key def __repr__(self): return (('') % (self.id, self.name)) class NephoscaleResponse(JsonResponse): """ Nephoscale API Response """ def parse_error(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError('Authorization Failed') if self.status == httplib.NOT_FOUND: raise Exception("The resource you are looking for is not found.") return self.body def success(self): return self.status in VALID_RESPONSE_CODES class NephoscaleConnection(ConnectionUserAndKey): """ Nephoscale connection class. Authenticates to the API through Basic Authentication with username/password """ host = API_HOST responseCls = NephoscaleResponse allow_insecure = False def add_default_headers(self, headers): """ Add parameters that are necessary for every request """ user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) return headers class NephoscaleNodeDriver(NodeDriver): """ Nephoscale node driver class. >>> from libcloud.compute.providers import get_driver >>> driver = get_driver('nephoscale') >>> conn = driver('nepho_user','nepho_password') >>> conn.list_nodes() """ type = Provider.NEPHOSCALE api_name = 'nephoscale' name = 'NephoScale' website = 'http://www.nephoscale.com' connectionCls = NephoscaleConnection features = {'create_node': ['ssh_key']} def list_locations(self): """ List available zones for deployment :rtype: ``list`` of :class:`NodeLocation` """ result = self.connection.request('/datacenter/zone/').object locations = [] for value in result.get('data', []): location = NodeLocation(id=value.get('id'), name=value.get('name'), country='US', driver=self) locations.append(location) return locations def list_images(self): """ List available images for deployment :rtype: ``list`` of :class:`NodeImage` """ result = self.connection.request('/image/server/').object images = [] for value in result.get('data', []): extra = {'architecture': value.get('architecture'), 'disks': value.get('disks'), 'billable_type': value.get('billable_type'), 'pcpus': value.get('pcpus'), 'cores': value.get('cores'), 'uri': value.get('uri'), 'storage': value.get('storage'), } image = NodeImage(id=value.get('id'), name=value.get('friendly_name'), driver=self, extra=extra) images.append(image) return images def list_sizes(self): """ List available sizes containing prices :rtype: ``list`` of :class:`NodeSize` """ result = self.connection.request('/server/type/cloud/').object sizes = [] for value in result.get('data', []): value_id = value.get('id') size = NodeSize(id=value_id, name=value.get('friendly_name'), ram=value.get('ram'), disk=value.get('storage'), bandwidth=None, price=self._get_size_price(size_id=str(value_id)), driver=self) sizes.append(size) return sorted(sizes, key=lambda k: k.price) def list_nodes(self): """ List available nodes :rtype: ``list`` of :class:`Node` """ result = self.connection.request('/server/cloud/').object nodes = [self._to_node(value) for value in result.get('data', [])] return nodes def rename_node(self, node, name, hostname=None): """rename a cloud server, optionally specify hostname too""" data = {'name': name} if hostname: data['hostname'] = hostname params = urlencode(data) result = self.connection.request('/server/cloud/%s/' % node.id, data=params, method='PUT').object return result.get('response') in VALID_RESPONSE_CODES def reboot_node(self, node): """reboot a running node""" result = self.connection.request('/server/cloud/%s/initiator/restart/' % node.id, method='POST').object return result.get('response') in VALID_RESPONSE_CODES def start_node(self, node): """start a stopped node""" result = self.connection.request('/server/cloud/%s/initiator/start/' % node.id, method='POST').object return result.get('response') in VALID_RESPONSE_CODES def stop_node(self, node): """stop a running node""" result = self.connection.request('/server/cloud/%s/initiator/stop/' % node.id, method='POST').object return result.get('response') in VALID_RESPONSE_CODES def destroy_node(self, node): """destroy a node""" result = self.connection.request('/server/cloud/%s/' % node.id, method='DELETE').object return result.get('response') in VALID_RESPONSE_CODES def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_list_keypairs(self, ssh=False, password=False, key_group=None): """ List available console and server keys There are two types of keys for NephoScale, ssh and password keys. If run without arguments, lists all keys. Otherwise list only ssh keys, or only password keys. Password keys with key_group 4 are console keys. When a server is created, it has two keys, one password or ssh key, and one password console key. :keyword ssh: if specified, show ssh keys only (optional) :type ssh: ``bool`` :keyword password: if specified, show password keys only (optional) :type password: ``bool`` :keyword key_group: if specified, show keys with this key_group only eg key_group=4 for console password keys (optional) :type key_group: ``int`` :rtype: ``list`` of :class:`NodeKey` """ if (ssh and password): raise LibcloudError('You can only supply ssh or password. To \ get all keys call with no arguments') if ssh: result = self.connection.request('/key/sshrsa/').object elif password: result = self.connection.request('/key/password/').object else: result = self.connection.request('/key/').object keys = [self._to_key(value) for value in result.get('data', [])] if key_group: keys = [key for key in keys if key.key_group == key_group] return keys def ex_create_keypair(self, name, public_key=None, password=None, key_group=None): """Creates a key, ssh or password, for server or console The group for the key (key_group) is 1 for Server and 4 for Console Returns the id of the created key """ if public_key: if not key_group: key_group = 1 data = { 'name': name, 'public_key': public_key, 'key_group': key_group } params = urlencode(data) result = self.connection.request('/key/sshrsa/', data=params, method='POST').object else: if not key_group: key_group = 4 if not password: password = self.random_password() data = { 'name': name, 'password': password, 'key_group': key_group } params = urlencode(data) result = self.connection.request('/key/password/', data=params, method='POST').object return result.get('data', {}).get('id', '') def ex_delete_keypair(self, key_id, ssh=False): """Delete an ssh key or password given it's id """ if ssh: result = self.connection.request('/key/sshrsa/%s/' % key_id, method='DELETE').object else: result = self.connection.request('/key/password/%s/' % key_id, method='DELETE').object return result.get('response') in VALID_RESPONSE_CODES def create_node(self, name, size, image, server_key=None, console_key=None, zone=None, **kwargs): """Creates the node, and sets the ssh key, console key NephoScale will respond with a 200-200 response after sending a valid request. If nowait=True is specified in the args, we then ask a few times until the server is created and assigned a public IP address, so that deploy_node can be run >>> from libcloud.compute.providers import get_driver >>> driver = get_driver('nephoscale') >>> conn = driver('nepho_user','nepho_password') >>> conn.list_nodes() >>> name = 'staging-server' >>> size = conn.list_sizes()[0] >>> image = conn.list_images()[9] >>> server_keys = conn.ex_list_keypairs(key_group=1)[0] >>> server_key = conn.ex_list_keypairs(key_group=1)[0].id 70867 >>> console_keys = conn.ex_list_keypairs(key_group=4)[0] >>> console_key = conn.ex_list_keypairs(key_group=4)[0].id 70907 >>> node = conn.create_node(name=name, size=size, image=image, \ console_key=console_key, server_key=server_key) We can also create an ssh key, plus a console key and deploy node with them >>> server_key = conn.ex_create_keypair(name, public_key='123') 71211 >>> console_key = conn.ex_create_keypair(name, key_group=4) 71213 We can increase the number of connect attempts to wait until the node is created, so that deploy_node has ip address to deploy the script We can also specify the location >>> location = conn.list_locations()[0] >>> node = conn.create_node(name=name, >>> ... size=size, >>> ... image=image, >>> ... console_key=console_key, >>> ... server_key=server_key, >>> ... connect_attempts=10, >>> ... nowait=True, >>> ... zone=location.id) """ hostname = kwargs.get('hostname', name) service_type = size.id image = image.id connect_attempts = int(kwargs.get('connect_attempts', CONNECT_ATTEMPTS)) data = {'name': name, 'hostname': hostname, 'service_type': service_type, 'image': image, 'server_key': server_key, 'console_key': console_key, 'zone': zone } params = urlencode(data) try: node = self.connection.request('/server/cloud/', data=params, method='POST') except Exception as e: raise Exception("Failed to create node %s" % e) node = Node(id='', name=name, state=NodeState.UNKNOWN, public_ips=[], private_ips=[], driver=self) nowait = kwargs.get('ex_wait', False) if not nowait: return node else: # try to get the created node public ips, for use in deploy_node # At this point we don't have the id of the newly created Node, # so search name in nodes created_node = False while connect_attempts > 0: nodes = self.list_nodes() created_node = [c_node for c_node in nodes if c_node.name == name] if created_node: return created_node[0] else: time.sleep(60) connect_attempts = connect_attempts - 1 return node def _to_node(self, data): """Convert node in Node instances """ state = NODE_STATE_MAP.get(data.get('power_status'), '4') public_ips = [] private_ips = [] ip_addresses = data.get('ipaddresses', '') # E.g. "ipaddresses": "198.120.14.6, 10.132.60.1" if ip_addresses: for ip in ip_addresses.split(','): ip = ip.replace(' ', '') if is_private_subnet(ip): private_ips.append(ip) else: public_ips.append(ip) extra = { 'zone_data': data.get('zone'), 'zone': data.get('zone', {}).get('name'), 'image': data.get('image', {}).get('friendly_name'), 'create_time': data.get('create_time'), 'network_ports': data.get('network_ports'), 'is_console_enabled': data.get('is_console_enabled'), 'service_type': data.get('service_type', {}).get('friendly_name'), 'hostname': data.get('hostname') } node = Node(id=data.get('id'), name=data.get('name'), state=state, public_ips=public_ips, private_ips=private_ips, driver=self, extra=extra) return node def _to_key(self, data): return NodeKey(id=data.get('id'), name=data.get('name'), password=data.get('password'), key_group=data.get('key_group'), public_key=data.get('public_key')) def random_password(self, size=8): value = os.urandom(size) password = binascii.hexlify(value).decode('ascii') return password[:size] apache-libcloud-2.8.0/libcloud/compute/drivers/ntta.py0000664000175000017500000000373313535474530022711 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ NTT America Driver """ from libcloud.compute.providers import Provider from libcloud.common.dimensiondata import (DimensionDataConnection, API_ENDPOINTS) from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver DEFAULT_REGION = 'ntta-na' class NTTAmericaNodeDriver(DimensionDataNodeDriver): """ NTT America node driver, based on Dimension Data driver """ selected_region = None connectionCls = DimensionDataConnection name = 'NTTAmerica' website = 'http://www.nttamerica.com/' type = Provider.NTTA features = {'create_node': ['password']} api_version = 1.0 def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS: raise ValueError('Invalid region: %s' % (region)) self.selected_region = API_ENDPOINTS[region] super(NTTAmericaNodeDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) apache-libcloud-2.8.0/libcloud/compute/drivers/nttcis.py0000664000175000017500000066332513576514553023265 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ NTT CIS Driver """ import sys import re from libcloud.utils.py3 import ET from libcloud.common.nttcis import LooseVersion from libcloud.common.exceptions import BaseHTTPError from libcloud.compute.base import NodeDriver, Node, NodeAuthPassword from libcloud.compute.base import NodeSize, NodeImage, NodeLocation from libcloud.common.nttcis import process_xml, get_params from libcloud.common.nttcis import dd_object_to_id from libcloud.common.nttcis import NttCisAPIException from libcloud.common.nttcis import (NttCisConnection, NttCisStatus) from libcloud.common.nttcis import NttCisNetwork from libcloud.common.nttcis import NttCisNetworkDomain from libcloud.common.nttcis import NttCisVlan from libcloud.common.nttcis import NttCisServerCpuSpecification from libcloud.common.nttcis import NttCisServerDisk from libcloud.common.nttcis import NttCisScsiController from libcloud.common.nttcis import NttCisServerVMWareTools from libcloud.common.nttcis import NttCisPublicIpBlock from libcloud.common.nttcis import NttCisFirewallRule from libcloud.common.nttcis import NttCisFirewallAddress from libcloud.common.nttcis import NttCisNatRule from libcloud.common.nttcis import NttCisAntiAffinityRule from libcloud.common.nttcis import NttCisIpAddressList from libcloud.common.nttcis import NttCisChildIpAddressList from libcloud.common.nttcis import NttCisIpAddress from libcloud.common.nttcis import NttCisReservedIpAddress from libcloud.common.nttcis import NttCisPortList from libcloud.common.nttcis import NttCisPort from libcloud.common.nttcis import NttCisChildPortList from libcloud.common.nttcis import NttCisNic from libcloud.common.nttcis import NetworkDomainServicePlan from libcloud.common.nttcis import NttCisTagKey from libcloud.common.nttcis import NttCisTag from libcloud.common.nttcis import API_ENDPOINTS, DEFAULT_REGION from libcloud.common.nttcis import TYPES_URN from libcloud.common.nttcis import NETWORK_NS, GENERAL_NS from libcloud.utils.py3 import urlencode, ensure_string from libcloud.utils.xml import fixxpath, findtext, findall from libcloud.utils.py3 import basestring from libcloud.compute.types import NodeState, Provider # Node state map is a dictionary with the keys as tuples # These tuples represent: # (, , ) NODE_STATE_MAP = { ('NORMAL', 'false', None): NodeState.STOPPED, ('PENDING_CHANGE', 'false', None): NodeState.PENDING, ('PENDING_CHANGE', 'false', 'CHANGE_NETWORK_ADAPTER'): NodeState.PENDING, ('PENDING_CHANGE', 'true', 'CHANGE_NETWORK_ADAPTER'): NodeState.PENDING, ('PENDING_CHANGE', 'false', 'EXCHANGE_NIC_VLANS'): NodeState.PENDING, ('PENDING_CHANGE', 'true', 'EXCHANGE_NIC_VLANS'): NodeState.PENDING, ('NORMAL', 'true', None): NodeState.RUNNING, ('PENDING_CHANGE', 'true', 'START_SERVER'): NodeState.STARTING, ('PENDING_ADD', 'true', 'DEPLOY_SERVER'): NodeState.STARTING, ('PENDING_ADD', 'true', 'DEPLOY_SERVER_WITH_DISK_SPEED'): NodeState.STARTING, ('PENDING_CHANGE', 'true', 'SHUTDOWN_SERVER'): NodeState.STOPPING, ('PENDING_CHANGE', 'true', 'POWER_OFF_SERVER'): NodeState.STOPPING, ('PENDING_CHANGE', 'true', 'REBOOT_SERVER'): NodeState.REBOOTING, ('PENDING_CHANGE', 'true', 'RESET_SERVER'): NodeState.REBOOTING, ('PENDING_CHANGE', 'true', 'RECONFIGURE_SERVER'): NodeState.RECONFIGURING, } OBJECT_TO_TAGGING_ASSET_TYPE_MAP = { 'Node': 'SERVER', 'NodeImage': 'CUSTOMER_IMAGE', 'NttCisNetworkDomain': 'NETWORK_DOMAIN', 'NttCisVlan': 'VLAN', 'NttCisPublicIpBlock': 'PUBLIC_IP_BLOCK' } class NttCisNodeDriver(NodeDriver): """ NttCis node driver. Default api_version is used unless specified. """ selected_region = None connectionCls = NttCisConnection name = 'NTTC-CIS' website = 'https://www.us.ntt.com/en/services/cloud/enterprise-cloud.html' type = Provider.NTTCIS features = {'create_node': ['password']} api_version = 1.0 def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS and host is None: raise ValueError( 'Invalid region: %s, no host specified' % (region)) if region is not None: self.selected_region = API_ENDPOINTS[region] if api_version is not None: self.api_version = api_version super(NttCisNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) def _ex_connection_class_kwargs(self): """ Add the region to the kwargs before the connection is instantiated """ kwargs = super(NttCisNodeDriver, self)._ex_connection_class_kwargs() kwargs['region'] = self.selected_region kwargs['api_version'] = self.api_version return kwargs def _create_node_mcp1(self, name, image, auth, ex_description, ex_network=None, ex_memory_gb=None, ex_cpu_specification=None, ex_is_started=True, ex_primary_dns=None, ex_secondary_dns=None, **kwargs): """ Create a new NTTCIS node :keyword name: String with a name for this new node (required) :type name: ``str`` :keyword image: OS Image to boot on node. (required) :type image: :class:`NodeImage` or ``str`` :keyword auth: Initial authentication information for the node. (If this is a customer LINUX image auth will be ignored) :type auth: :class:`NodeAuthPassword` or ``str`` or ``None`` :keyword ex_description: description for this node (required) :type ex_description: ``str`` :keyword ex_network: Network to create the node within (required unless using ex_network_domain or ex_primary_ipv4) :type ex_network: :class:`NttCisNetwork` or ``str`` :keyword ex_memory_gb: The amount of memory in GB for the server :type ex_memory_gb: ``int`` :keyword ex_cpu_specification: The spec of CPU to deploy ( optional) :type ex_cpu_specification: :class:`DimensionDataServerCpuSpecification` :keyword ex_is_started: Start server after creation? default true (required) :type ex_is_started: ``bool`` :keyword ex_primary_dns: The node's primary DNS :type ex_primary_dns: ``str`` :keyword ex_secondary_dns: The node's secondary DNS :type ex_secondary_dns: ``str`` :return: The newly created :class:`Node`. :rtype: :class:`Node` """ password = None image_needs_auth = self._image_needs_auth(image) if image_needs_auth: if isinstance(auth, basestring): auth_obj = NodeAuthPassword(password=auth) password = auth else: auth_obj = self._get_and_check_auth(auth) password = auth_obj.password server_elm = ET.Element('deployServer', {'xmlns': TYPES_URN}) ET.SubElement(server_elm, "name").text = name ET.SubElement(server_elm, "description").text = ex_description image_id = self._image_to_image_id(image) ET.SubElement(server_elm, "imageId").text = image_id ET.SubElement(server_elm, "start").text = str( ex_is_started).lower() if password is not None: ET.SubElement(server_elm, "administratorPassword").text = password if ex_cpu_specification is not None: cpu = ET.SubElement(server_elm, "cpu") cpu.set('speed', ex_cpu_specification.performance) cpu.set('count', str(ex_cpu_specification.cpu_count)) cpu.set('coresPerSocket', str(ex_cpu_specification.cores_per_socket)) if ex_memory_gb is not None: ET.SubElement(server_elm, "memoryGb").text = str(ex_memory_gb) if ex_network is not None: network_elm = ET.SubElement(server_elm, "network") network_id = self._network_to_network_id(ex_network) ET.SubElement(network_elm, "networkId").text = network_id if ex_primary_dns: dns_elm = ET.SubElement(server_elm, "primaryDns") dns_elm.text = ex_primary_dns if ex_secondary_dns: dns_elm = ET.SubElement(server_elm, "secondaryDns") dns_elm.text = ex_secondary_dns response = self.connection.request_with_orgId_api_2( 'server/deployServer', method='POST', data=ET.tostring(server_elm)).object node_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'serverId': node_id = info.get('value') node = self.ex_get_node_by_id(node_id) if image_needs_auth: if getattr(auth_obj, "generated", False): node.extra['password'] = auth_obj.password return node def create_node(self, name, image, auth, ex_network_domain=None, ex_primary_nic_private_ipv4=None, ex_primary_nic_vlan=None, ex_primary_nic_network_adapter=None, ex_additional_nics=None, ex_description=None, ex_disks=None, ex_cpu_specification=None, ex_memory_gb=None, ex_is_started=True, ex_primary_dns=None, ex_secondary_dns=None, ex_ipv4_gateway=None, ex_microsoft_time_zone=None, **kwargs ): """ Create a new NTTCIS node in MCP2. However, it is still backward compatible for MCP1 for a limited time. Please consider using MCP2 datacenter as MCP1 will phase out soon. Legacy Create Node for MCP1 datacenter >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.base import NodeAuthPassword >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = False >>> NTTCIS = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Password >>> root_pw = NodeAuthPassword('password123') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU1') >>> >>> # Get network by location >>> my_network = driver.list_networks(location=location)[0] >>> pprint(my_network) >>> >>> # Get Image >>> images = driver.list_images(location=location) >>> image = images[0] >>> >>> node = driver.create_node(name='test_blah_2', image=image, >>> auth=root_pw, >>> ex_description='test3 node', >>> ex_network=my_network, >>> ex_is_started=False) >>> pprint(node) Create Node in MCP2 Data CenterF >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.base import NodeAuthPassword >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Password >>> root_pw = NodeAuthPassword('password123') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> vlan = driver.ex_list_vlans(location=location, >>> network_domain=my_network_domain)[0] >>> pprint(vlan) >>> >>> # Get Image >>> images = driver.list_images(location=location) >>> image = images[0] >>> >>> # Create node using vlan instead of private IPv4 >>> node = driver.create_node(name='test_server_01', image=image, >>> auth=root_pw, >>> ex_description='test2 node', >>> ex_network_domain=my_network_domain, >>> ex_primary_nic_vlan=vlan, >>> ex_is_started=False) >>> >>> # Option: Create node using private IPv4 instead of vlan >>> # node = driver.create_node(name='test_server_02', image=image, >>> # auth=root_pw, >>> # ex_description='test2 node', >>> # ex_network_domain=my_network_domain, >>> # ex_primary_nic_private_ipv4='10.1.1.7', >>> # ex_is_started=False) >>> >>> # Option: Create node using by specifying Network Adapter >>> # node = driver.create_node(name='test_server_03', image=image, >>> # auth=root_pw, >>> # ex_description='test2 node', >>> # ex_network_domain=my_network_domain, >>> # ex_primary_nic_vlan=vlan, >>> # ex_primary_nic_network_adapter='E1000', >>> # ex_is_started=False) >>> :keyword name: (required) String with a name for this new node :type name: ``str`` :keyword image: (required) OS Image to boot on node. :type image: :class:`NodeImage` or ``str`` :keyword auth: Initial authentication information for the node. (If this is a customer LINUX image auth will be ignored) :type auth: :class:`NodeAuthPassword` or ``str`` or ``None`` :keyword ex_description: (optional) description for this node :type ex_description: ``str`` :keyword ex_network_domain: (required) Network Domain or Network Domain ID to create the node :type ex_network_domain: :class:`DimensionDataNetworkDomain` or ``str`` :keyword ex_primary_nic_private_ipv4: Provide private IPv4. Ignore if ex_primary_nic_vlan is provided. Use one or the other. Not both. :type ex_primary_nic_private_ipv4: :``str`` :keyword ex_primary_nic_vlan: Provide VLAN for the node if ex_primary_nic_private_ipv4 NOT provided. One or the other. Not both. :type ex_primary_nic_vlan: :class: DimensionDataVlan or ``str`` :keyword ex_primary_nic_network_adapter: (Optional) Default value for the Operating System will be used if leave empty. Example: "E1000". :type ex_primary_nic_network_adapter: :``str`` :keyword ex_additional_nics: (optional) List :class:'NttCisNic' or None :type ex_additional_nics: ``list`` of :class:'NttCisNic' or ``str`` :keyword ex_memory_gb: (optional) The amount of memory in GB for the server Can be used to override the memory value inherited from the source Server Image. :type ex_memory_gb: ``int`` :keyword ex_cpu_specification: (optional) The spec of CPU to deploy :type ex_cpu_specification: :class:`DimensionDataServerCpuSpecification` :keyword ex_is_started: (required) Start server after creation. Default is set to true. :type ex_is_started: ``bool`` :keyword ex_primary_dns: (Optional) The node's primary DNS :type ex_primary_dns: ``str`` :keyword ex_secondary_dns: (Optional) The node's secondary DNS :type ex_secondary_dns: ``str`` :keyword ex_ipv4_gateway: (Optional) IPv4 address in dot-decimal notation, which will be used as the Primary NIC gateway instead of the default gateway assigned by the system. If ipv4Gateway is provided it does not have to be on the VLAN of the Primary NIC but MUST be reachable or the Guest OS will not be configured correctly. :type ex_ipv4_gateway: ``str`` :keyword ex_disks: (optional) NTTCIS disks. Optional disk elements can be used to define the disk speed that each disk on the Server; inherited from the source Server Image will be deployed to. It is not necessary to include a diskelement for every disk; only those that you wish to set a disk speed value for. Note that scsiId 7 cannot be used.Up to 13 disks can be present in addition to the required OS disk on SCSI ID 0. Refer to https://docs.mcp-services.net/x/UwIu for disk :type ex_disks: List or tuple of :class:'DimensionDataServerDisk` :keyword ex_microsoft_time_zone: (optional) For use with Microsoft Windows source Server Images only. For the exact value to use please refer to the table of time zone indexes in the following Microsoft Technet documentation. If none is supplied, the default time zone for the data center geographic region will be used. :type ex_microsoft_time_zone: `str`` :return: The newly created :class:`Node`. :rtype: :class:`Node` """ # Neither legacy MCP1 network nor MCP2 network domain provided if ex_network_domain is None and 'ex_network' not in kwargs: raise ValueError('You must provide either ex_network_domain ' 'for MCP2 or ex_network for legacy MCP1') # Ambiguous parameter provided. Can't determine if it is MCP 1 or 2. if ex_network_domain is not None and 'ex_network' in kwargs: raise ValueError('You can only supply either ' 'ex_network_domain ' 'for MCP2 or ex_network for legacy MCP1') # Set ex_is_started to False by default if none bool data type provided if not isinstance(ex_is_started, bool): ex_is_started = True # Handle MCP1 legacy if 'ex_network' in kwargs: new_node = self._create_node_mcp1( name=name, image=image, auth=auth, ex_network=kwargs.get("ex_network"), ex_description=ex_description, ex_memory_gb=ex_memory_gb, ex_cpu_specification=ex_cpu_specification, ex_is_started=ex_is_started, ex_primary_ipv4=ex_primary_nic_private_ipv4, ex_disks=ex_disks, ex_additional_nics_vlan=kwargs.get("ex_additional_nics_vlan"), ex_additional_nics_ipv4=kwargs.get("ex_additional_nics_ipv4"), ex_primary_dns=ex_primary_dns, ex_secondary_dns=ex_secondary_dns ) else: # Handle MCP2 legacy. CaaS api 2.2 or earlier if 'ex_vlan' in kwargs: ex_primary_nic_vlan = kwargs.get('ex_vlan') if 'ex_primary_ipv4' in kwargs: ex_primary_nic_private_ipv4 = kwargs.get( 'ex_primary_ipv4') additional_nics = [] if 'ex_additional_nics_vlan' in kwargs: vlans = kwargs.get('ex_additional_nics_vlan') if isinstance(vlans, (list, tuple)): for v in vlans: add_nic = NttCisNic(vlan=v) additional_nics.append(add_nic) else: raise TypeError("ex_additional_nics_vlan must " "be None or a tuple/list") if 'ex_additional_nics_ipv4' in kwargs: ips = kwargs.get('ex_additional_nics_ipv4') if isinstance(ips, (list, tuple)): for ip in ips: add_nic = NttCisNic(private_ip_v4=ip) additional_nics.append(add_nic) else: if ips is not None: raise TypeError("ex_additional_nics_ipv4 must " "be None or a tuple/list") if ('ex_additional_nics_vlan' in kwargs or 'ex_additional_nics_ipv4' in kwargs): ex_additional_nics = additional_nics # Handle MCP2 latest. CaaS API 2.3 onwards if ex_network_domain is None: raise ValueError("ex_network_domain must be specified") password = None image_needs_auth = self._image_needs_auth(image) if image_needs_auth: if isinstance(auth, basestring): auth_obj = NodeAuthPassword(password=auth) password = auth else: auth_obj = self._get_and_check_auth(auth) password = auth_obj.password server_elm = ET.Element('deployServer', {'xmlns': TYPES_URN}) ET.SubElement(server_elm, "name").text = name ET.SubElement(server_elm, "description").text = ex_description image_id = self._image_to_image_id(image) ET.SubElement(server_elm, "imageId").text = image_id ET.SubElement(server_elm, "start").text = str( ex_is_started).lower() if password is not None: ET.SubElement(server_elm, "administratorPassword").text = password if ex_cpu_specification is not None: cpu = ET.SubElement(server_elm, "cpu") cpu.set('speed', ex_cpu_specification.performance) cpu.set('count', str(ex_cpu_specification.cpu_count)) cpu.set('coresPerSocket', str(ex_cpu_specification.cores_per_socket)) if ex_memory_gb is not None: ET.SubElement(server_elm, "memoryGb").text = str(ex_memory_gb) if (ex_primary_nic_private_ipv4 is None and ex_primary_nic_vlan is None): raise ValueError("Missing argument. Either " "ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "must be specified.") if (ex_primary_nic_private_ipv4 is not None and ex_primary_nic_vlan is not None): raise ValueError("Either ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "be specified. Not both.") network_elm = ET.SubElement(server_elm, "networkInfo") net_domain_id = self._network_domain_to_network_domain_id( ex_network_domain) network_elm.set('networkDomainId', net_domain_id) pri_nic = ET.SubElement(network_elm, 'primaryNic') if ex_primary_nic_private_ipv4 is not None: ET.SubElement(pri_nic, 'privateIpv4').text = ex_primary_nic_private_ipv4 if ex_primary_nic_vlan is not None: vlan_id = self._vlan_to_vlan_id(ex_primary_nic_vlan) ET.SubElement(pri_nic, 'vlanId').text = vlan_id if ex_primary_nic_network_adapter is not None: ET.SubElement(pri_nic, "networkAdapter").text = \ ex_primary_nic_network_adapter if isinstance(ex_additional_nics, (list, tuple)): for nic in ex_additional_nics: additional_nic = ET.SubElement(network_elm, 'additionalNic') if (nic.private_ip_v4 is None and nic.vlan is None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic.") if (nic.private_ip_v4 is not None and nic.vlan is not None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic. Not both.") if nic.private_ip_v4 is not None: ET.SubElement(additional_nic, 'privateIpv4').text = nic.private_ip_v4 if nic.vlan is not None: vlan_id = self._vlan_to_vlan_id(nic.vlan) ET.SubElement(additional_nic, 'vlanId').text = vlan_id if nic.network_adapter_name is not None: ET.SubElement(additional_nic, "networkAdapter").text = \ nic.network_adapter_name elif ex_additional_nics is not None: raise TypeError( "ex_additional_NICs must be None or tuple/list") if ex_primary_dns: dns_elm = ET.SubElement(server_elm, "primaryDns") dns_elm.text = ex_primary_dns if ex_secondary_dns: dns_elm = ET.SubElement(server_elm, "secondaryDns") dns_elm.text = ex_secondary_dns if ex_ipv4_gateway: ET.SubElement(server_elm, "ipv4Gateway").text = ex_ipv4_gateway if isinstance(ex_disks, (list, tuple)): for disk in ex_disks: disk_elm = ET.SubElement(server_elm, 'disk') disk_elm.set('scsiId', disk.scsi_id) disk_elm.set('speed', disk.speed) elif ex_disks is not None: raise TypeError("ex_disks must be None or tuple/list") if ex_microsoft_time_zone: ET.SubElement(server_elm, "microsoftTimeZone").text = \ ex_microsoft_time_zone response = self.connection.request_with_orgId_api_2( 'server/deployServer', method='POST', data=ET.tostring(server_elm)).object node_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'serverId': node_id = info.get('value') new_node = self.ex_get_node_by_id(node_id) if image_needs_auth: if getattr(auth_obj, "generated", False): new_node.extra['password'] = auth_obj.password return new_node def destroy_node(self, node): """ Deletes a node, node must be stopped before deletion :keyword node: The node to delete :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('deleteServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/deleteServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def reboot_node(self, node): """ Reboots a node by requesting the OS restart via the hypervisor :keyword node: The node to reboot :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('rebootServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/rebootServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def list_nodes(self, ex_location=None, ex_name=None, ex_ipv6=None, ex_ipv4=None, ex_vlan=None, ex_image=None, ex_deployed=None, ex_started=None, ex_state=None, ex_network_domain=None, ex_snaphots=None): """ List nodes deployed for your organization. :keyword ex_location: Filters the node list to nodes that are located in this location :type ex_location: :class:`NodeLocation` or ``str`` :keyword ex_name: Filters the node list to nodes that have this name :type ex_name ``str`` :keyword ex_ipv6: Filters the node list to nodes that have this ipv6 address :type ex_ipv6: ``str`` :keyword ex_ipv4: Filters the node list to nodes that have this ipv4 address :type ex_ipv4: ``str`` :keyword ex_vlan: Filters the node list to nodes that are in this VLAN :type ex_vlan: :class:`DimensionDataVlan` or ``str`` :keyword ex_image: Filters the node list to nodes that have this image :type ex_image: :class:`NodeImage` or ``str`` :keyword ex_deployed: Filters the node list to nodes that are deployed or not :type ex_deployed: ``bool`` :keyword ex_started: Filters the node list to nodes that are started or not :type ex_started: ``bool`` :keyword ex_state: Filters the node list by nodes that are in this state :type ex_state: ``str`` :keyword ex_network_domain: Filters the node list to nodes in this network domain :type ex_network_domain: :class:`NttCisNetworkDomain` or ``str`` :return: a list of `Node` objects :rtype: ``list`` of :class:`Node` """ node_list = [] # This is a generator so we changed from the original # and if nodes is not empty, ie, the stop iteration confdition # Then set node_list to nodes and retrn. for nodes in self.ex_list_nodes_paginated( location=ex_location, name=ex_name, ipv6=ex_ipv6, ipv4=ex_ipv4, vlan=ex_vlan, image=ex_image, deployed=ex_deployed, started=ex_started, state=ex_state, network_domain=ex_network_domain): if nodes: node_list = nodes return node_list def list_images(self, location=None): """ List images available Note: Currently only returns the default 'base OS images' provided by NTTCIS. Customer images (snapshots) use ex_list_customer_images :keyword ex_location: Filters the node list to nodes that are located in this location :type ex_location: :class:`NodeLocation` or ``str`` :return: List of images available :rtype: ``list`` of :class:`NodeImage` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) return self._to_images( self.connection.request_with_orgId_api_2( 'image/osImage', params=params) .object) def list_sizes(self, location=None): """ return a list of available sizes Currently, the size of the node is dictated by the chosen OS base image, they cannot be set explicitly. @inherits: :class:`NodeDriver.list_sizes` """ return [ NodeSize(id=1, name="default", ram=0, disk=0, bandwidth=0, price=0, driver=self.connection.driver), ] def list_datacenter_properties(self, location): """ return a list of available sizes Currently, the size of the node is dictated by the chosen OS base image, they cannot be set explicitly. @inherits: :class:`NodeDriver.list_sizes` """ return [ NodeSize(id=1, name="default", ram=0, disk=0, bandwidth=0, price=0, driver=self.connection.driver), ] def list_locations(self, ex_id=None): """ List locations (datacenters) available for instantiating servers and networks. :keyword ex_id: Filters the location list to this id :type ex_id: ``str`` :return: List of locations :rtype: ``list`` of :class:`NttCisDatacenter` """ params = {} if ex_id is not None: params['id'] = ex_id return self._to_locations( self.connection .request_with_orgId_api_2( 'infrastructure/datacenter', params=params ).object ) def list_snapshot_windows(self, location, plan): """ List snapshot windows in a given location :param location: a location object or location id such as "NA9" :param plan: 'ESSENTIALS' or 'ADVANCED' :return: dictionary with keys id, day_of_week, start_hour, availability :rtype: dict """ params = {} params['datacenterId'] = self._location_to_location_id(location) params['servicePlan'] = plan return self._to_windows(self.connection.request_with_orgId_api_2( 'infrastructure/snapshotWindow', params=params).object) def list_networks(self, location=None): """ List networks deployed across all data center locations for your organization. The response includes the location of each network. :keyword location: The location :type location: :class:`NodeLocation` or ``str`` :return: a list of NttCisNetwork objects :rtype: ``list`` of :class:`NttCisNetwork` """ url_ext = '' if location is not None: url_ext = '/' + self._location_to_location_id(location) return self._to_networks( self.connection .request_with_orgId_api_2('networkWithLocation%s' % url_ext) .object) def import_image(self, ovf_package_name, name, cluster_id=None, datacenter_id=None, description=None, is_guest_os_customization=None, tagkey_name_value_dictionaries=None): """ Import image :param ovf_package_name: Image OVF package name :type ovf_package_name: ``str`` :param name: Image name :type name: ``str`` :param cluster_id: Provide either cluster_id or datacenter_id :type cluster_id: ``str`` :param datacenter_id: Provide either cluster_id or datacenter_id :type datacenter_id: ``str`` :param description: Optional. Description of image :type description: ``str`` :param is_guest_os_customization: Optional. true for NGOC image :type is_guest_os_customization: ``bool`` :param tagkey_name_value_dictionaries: Optional tagkey name value dict :type tagkey_name_value_dictionaries: dictionaries :return: Return true if successful :rtype: ``bool`` """ # Unsupported for version lower than 2.4 if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): raise Exception("import image is feature is NOT supported in " "api version earlier than 2.4") elif cluster_id is None and datacenter_id is None: raise ValueError("Either cluster_id or datacenter_id must be " "provided") elif cluster_id is not None and datacenter_id is not None: raise ValueError("Cannot accept both cluster_id and " "datacenter_id. Please provide either one") else: import_image_elem = ET.Element( 'urn:importImage', { 'xmlns:urn': TYPES_URN, }) ET.SubElement( import_image_elem, 'urn:ovfPackage' ).text = ovf_package_name ET.SubElement( import_image_elem, 'urn:name' ).text = name if description is not None: ET.SubElement( import_image_elem, 'urn:description' ).text = description if cluster_id is not None: ET.SubElement( import_image_elem, 'urn:clusterId' ).text = cluster_id else: ET.SubElement( import_image_elem, 'urn:datacenterId' ).text = datacenter_id if is_guest_os_customization is not None: ET.SubElement( import_image_elem, 'urn:guestOsCustomization' ).text = is_guest_os_customization if tagkey_name_value_dictionaries is not None and \ len(tagkey_name_value_dictionaries) > 0: for k, v in tagkey_name_value_dictionaries.items(): tag_elem = ET.SubElement( import_image_elem, 'urn:tag') ET.SubElement(tag_elem, 'urn:tagKeyName').text = k if v is not None: ET.SubElement(tag_elem, 'urn:value').text = v response = self.connection.request_with_orgId_api_2( 'image/importImage', method='POST', data=ET.tostring(import_image_elem)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def start_node(self, node): """ Powers on an existing deployed server :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('startServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/startServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def stop_node(self, node): """ This function will attempt to "gracefully" stop a server by initiating a shutdown sequence within the guest operating system. A successful response on this function means the system has successfully passed the request into the operating system. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('shutdownServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/shutdownServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_nodes_paginated(self, name=None, location=None, ipv6=None, ipv4=None, vlan=None, image=None, deployed=None, started=None, state=None, network=None, network_domain=None): """ Return a generator which yields node lists in pages :keyword location: Filters the node list to nodes that are located in this location :type location: :class:`NodeLocation` or ``str`` :keyword name: Filters the node list to nodes that have this name :type name ``str`` :keyword ipv6: Filters the node list to nodes that have this ipv6 address :type ipv6: ``str`` :keyword ipv4: Filters the node list to nodes that have this ipv4 address :type ipv4: ``str`` :keyword vlan: Filters the node list to nodes that are in this VLAN :type vlan: :class:`NttCisVlan` or ``str`` :keyword image: Filters the node list to nodes that have this image :type image: :class:`NodeImage` or ``str`` :keyword deployed: Filters the node list to nodes that are deployed or not :type deployed: ``bool`` :keyword started: Filters the node list to nodes that are started or not :type started: ``bool`` :keyword state: Filters the node list to nodes that are in this state :type state: ``str`` :keyword network: Filters the node list to nodes in this network :type network: :class:`NttCisNetwork` or ``str`` :keyword network_domain: Filters the node list to nodes in this network domain :type network_domain: :class:`NttCisNetworkDomain` or ``str`` :return: a list of `Node` objects :rtype: ``generator`` of `list` of :class:`Node` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) if ipv6 is not None: params['ipv6'] = ipv6 if ipv4 is not None: params['privateIpv4'] = ipv4 if state is not None: params['state'] = state if started is not None: params['started'] = started if deployed is not None: params['deployed'] = deployed if name is not None: params['name'] = name if network_domain is not None: params['networkDomainId'] = \ self._network_domain_to_network_domain_id(network_domain) if network is not None: params['networkId'] = self._network_to_network_id(network) if vlan is not None: params['vlanId'] = self._vlan_to_vlan_id(vlan) if image is not None: params['sourceImageId'] = self._image_to_image_id(image) nodes_obj = self._list_nodes_single_page(params) yield self._to_nodes(nodes_obj) while nodes_obj.get('pageCount') >= nodes_obj.get('pageSize'): params['pageNumber'] = int(nodes_obj.get('pageNumber')) + 1 nodes_obj = self._list_nodes_single_page(params) yield self._to_nodes(nodes_obj) def ex_edit_metadata(self, node, name=None, description=None, drs_eligible=None): request_elem = ET.Element('editServerMetadata', {'xmlns': TYPES_URN, 'id': node.id}) if name is not None: ET.SubElement(request_elem, 'name').text = name if description is not None: ET.SubElement(request_elem, 'description').text = description if drs_eligible is not None: ET.SubElement(request_elem, 'drsEligible').text = drs_eligible body = self.connection.request_with_orgId_api_2( 'server/editServerMetadata', method="POST", data=ET.tostring(request_elem)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_shutdown_graceful(self, node): return self.stop_node(node=node) def ex_power_off(self, node): """ This function will abruptly power-off a server. Unlike ex_shutdown_graceful, success ensures the node will stop but some OS and application configurations may be adversely affected by the equivalent of pulling the power plug out of the machine. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('powerOffServer', {'xmlns': TYPES_URN, 'id': node.id}) try: body = self.connection.request_with_orgId_api_2( 'server/powerOffServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) except (NttCisAPIException, NameError, BaseHTTPError): r = self.ex_get_node_by_id(node.id) response_code = r.state.upper() return response_code in ['IN_PROGRESS', 'OK', 'STOPPED', 'STOPPING'] def ex_reset(self, node): """ This function will abruptly reset a server. Unlike reboot_node, success ensures the node will restart but some OS and application configurations may be adversely affected by the equivalent of pulling the power plug out of the machine. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('resetServer', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/resetServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_update_vm_tools(self, node): """ This function triggers an update of the VMware Tools software running on the guest OS of a Server. :param node: Node which should be used :type node: :class:`Node` :rtype: ``bool`` """ request_elm = ET.Element('updateVmwareTools', {'xmlns': TYPES_URN, 'id': node.id}) body = self.connection.request_with_orgId_api_2( 'server/updateVmwareTools', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_update_node(self, node, name=None, description=None, cpu_count=None, ram_mb=None): """ Update the node, the name, CPU or RAM :param node: Node which should be used :type node: :class:`Node` :param name: The new name (optional) :type name: ``str`` :param description: The new description (optional) :type description: ``str`` :param cpu_count: The new CPU count (optional) :type cpu_count: ``int`` :param ram_mb: The new Memory in MB (optional) :type ram_mb: ``int`` :rtype: ``bool`` """ data = {} if name is not None: data['name'] = name if description is not None: data['description'] = description if cpu_count is not None: data['cpuCount'] = str(cpu_count) if ram_mb is not None: data['memory'] = str(ram_mb) body = self.connection.request_with_orgId_api_1( 'server/%s' % (node.id), method='POST', data=urlencode(data, True)).object response_code = findtext(body, 'result', GENERAL_NS) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_enable_snapshots(self, node, window, plan='ADVANCED', initiate='true'): """ Enable snapshot service on a server :param node: Node ID of the node on which to enable snapshots. :type node: ``str`` :param window: The window id of the window in which the snapshot is enabled. :type name: ``str`` :param plan: Pland type 'ESSENTIALS' or 'ADVANCED :type plan: ``str`` :param initiate: Run a snapshot upon configuration of the snapshot. :type ``str`` :rtype: ``bool`` """ update_node = ET.Element('enableSnapshotService', {'xmlns': TYPES_URN}) window_id = window plan = plan update_node.set('serverId', node) ET.SubElement(update_node, 'servicePlan').text = plan ET.SubElement(update_node, 'windowId').text = window_id ET.SubElement(update_node, 'initiateManualSnapshot').text = initiate result = self.connection.request_with_orgId_api_2( 'snapshot/enableSnapshotService', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def list_snapshots(self, node, page_size=None): """ List snapshots of a server. The list of snapshots can get large. Therefore, page_size is optional to limit this if desired. :param node: Node nameof the node on which to enable snapshots. :type node: ``str`` :param page_size: (Optional) Limit the number of records returned :return snapshots :rtype: ``list`` of `dictionaries` """ params = {} params['serverId'] = self.list_nodes(ex_name=node)[0].id if page_size is not None: params["pageSize"] = page_size return self._to_snapshots(self.connection.request_with_orgId_api_2( 'snapshot/snapshot', params=params).object) def get_snapshot(self, snapshot_id): """ Get snapshot of a server by snapshot id. :param snapshot_id: ID of snapshot to retrieve. :type snapshot_id: ``str`` :return a snapshot :rtype: ``dict`` """ return self._to_snapshot(self.connection.request_with_orgId_api_2( 'snapshot/snapshot/%s' % snapshot_id).object) def ex_disable_snapshots(self, node): """ Disable snapshots on a server. This also deletes current snapshots. :param node: Node ID of the node on which to enable snapshots. :type node: ``str`` :return True or False :rtype: ``bool`` """ update_node = ET.Element('disableSnapshotService', {'xmlns': TYPES_URN}) update_node.set('serverId', node) result = self.connection.request_with_orgId_api_2( 'snapshot/disableSnapshotService', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_initiate_manual_snapshot(self, name=None, server_id=None): """ Initiate a manual snapshot of server on the fly :param name: optional name of server :type name: ``str`` :param server_id: optinal parameter to use instead of name :type `server_id`str`` :return: True of False :rtype: ``bool`` """ if server_id is None: node = self.list_nodes(ex_name=name) if len(node) > 1: raise RuntimeError("Found more than one server Id, " "please use one the following along" " with name parameter: {}". format([n.id for n in node])) else: node = [] node.append(self.ex_get_node_by_id(server_id)) update_node = ET.Element('initiateManualSnapshot', {'xmlns': TYPES_URN}) update_node.set('serverId', node[0].id) result = self.connection.request_with_orgId_api_2( 'snapshot/initiateManualSnapshot', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_snapshot_preview_server(self, snapshot_id, server_name, server_started, nics_connected, server_description=None, target_cluster_id=None, preserve_mac_addresses=None, tag_key_name=None, tag_key_id=None, tag_value=None): """ Create a snapshot preview of a server to clone to a new server :param snapshot_id: ID of the specific snahpshot to use in creating preview server. :type snapshot_id: ``str`` :param server_name: Name of the server created from the snapshot :type ``str`` :param nics_connected: 'true' or 'false'. Should the nics be automatically connected :type ``str`` :param server_description: (Optional) A brief description of the server. :type ``str`` :param target_cluster_id: (Optional) The ID of a specific cluster as opposed to the default. :type ``str`` :param preserve_mac_address: (Optional) If set to 'true' will preserve mac address from the original server. :type ``str`` :param tag_key_name: (Optional) If tagging is desired and by name is desired, set this to the tag name. :type ``str`` :param tag_key_id: (Optional) If tagging is desired and by id is desired, set this to the tag id. :type ``str`` :param tag_value: (Optional) If using a tag_key_id or tag_key_name, set the value fo tag_value. :rtype: ``str`` """ create_preview = ET.Element('createSnapshotPreviewServer', {'xmlns': TYPES_URN, 'snapshotId': snapshot_id}) ET.SubElement(create_preview, 'serverName').text = server_name if server_description is not None: ET.SubElement(create_preview, 'serverDescription').text = \ server_description if target_cluster_id is not None: ET.SubElement(create_preview, 'targetClusterId').text = \ target_cluster_id ET.SubElement(create_preview, 'serverStarted').text = \ server_started ET.SubElement(create_preview, 'nicsConnected').text = \ nics_connected if preserve_mac_addresses is not None: ET.SubElement(create_preview, 'preserveMacAddresses').text = \ preserve_mac_addresses if tag_key_name is not None: tag_elem = ET.SubElement(create_preview, 'tag') ET.SubElement(tag_elem, 'tagKeyName').text = tag_key_name ET.SubElement(tag_elem, 'value').text = tag_value elif tag_key_id is not None: tag_elem = ET.SubElement(create_preview, 'tagById') ET.SubElement(create_preview, 'tagKeyId').text = tag_key_name ET.SubElement(tag_elem, 'value').text = tag_value result = self.connection.request_with_orgId_api_2( 'snapshot/createSnapshotPreviewServer', method='POST', data=ET.tostring(create_preview)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_migrate_preview_server(self, preview_id): migrate_preview = ET.Element('migrateSnapshotPreviewServer', {'xmlns': TYPES_URN, 'serverId': preview_id}) result = self.connection.request_with_orgId_api_2( 'snapshot/migrateSnapshotPreviewServer', method='POST', data=ET.tostring(migrate_preview)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_anti_affinity_rule(self, node_list): """ Edited to work with api 2.x. No longer supports 1.0 Create an anti affinity rule given a list of nodes Anti affinity rules ensure that servers will not reside on the same VMware ESX host :param node_list: The list of nodes to create a rule for :type node_list: ``list`` of :class:`Node` or ``list`` of ``str`` :rtype: ``bool`` """ if not isinstance(node_list, (list, tuple)): raise TypeError("Node list must be a list or a tuple.") anti_affinity_xml_request = ET.Element('createAntiAffinityRule', {'xmlns': TYPES_URN}) for node in node_list: ET.SubElement(anti_affinity_xml_request, 'serverId').text = \ self._node_to_node_id(node) result = self.connection.request_with_orgId_api_2( 'server/createAntiAffinityRule', method='POST', data=ET.tostring(anti_affinity_xml_request)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_delete_anti_affinity_rule(self, anti_affinity_rule): """ Remove anti affinity rule :param anti_affinity_rule: The anti affinity rule to delete :type anti_affinity_rule: :class:`NttCisAntiAffinityRule` or ``str`` :rtype: ``bool`` """ rule_id = anti_affinity_rule update_node = ET.Element('deleteAntiAffinityRule', {"xmlns": TYPES_URN}) update_node.set('id', rule_id) result = self.connection.request_with_orgId_api_2( 'server/deleteAntiAffinityRule', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_list_anti_affinity_rules(self, network=None, network_domain=None, node=None, filter_id=None, filter_state=None): """ List anti affinity rules for a network, network domain, or node :param network: The network to list anti affinity rules for One of network, network_domain, or node is required :type network: :class:`NttCisNetwork` or ``str`` :param network_domain: The network domain to list anti affinity rules One of network, network_domain, or node is required :type network_domain: :class:`NttCisNetworkDomain` or ``str`` :param node: The node to list anti affinity rules for One of network, netwok_domain, or node is required :type node: :class:`Node` or ``str`` :param filter_id: This will allow you to filter the rules by this node id :type filter_id: ``str`` :type filter_state: This will allow you to filter rules by node state (i.e. NORMAL) :type filter_state: ``str`` :rtype: ``list`` of :class:NttCisAntiAffinityRule` """ not_none_arguments = [key for key in (network, network_domain, node) if key is not None] if len(not_none_arguments) != 1: raise ValueError("One and ONLY one of network, " "network_domain, or node must be set") params = {} if network_domain is not None: params['networkDomainId'] = \ self._network_domain_to_network_domain_id(network_domain) if network is not None: params['networkId'] = \ self._network_to_network_id(network) if node is not None: params['serverId'] = \ self._node_to_node_id(node) if filter_id is not None: params['id'] = filter_id if filter_state is not None: params['state'] = filter_state paged_result = self.connection.paginated_request_with_orgId_api_2( 'server/antiAffinityRule', method='GET', params=params ) rules = [] for result in paged_result: rules.extend(self._to_anti_affinity_rules(result)) return rules def ex_attach_node_to_vlan(self, node, vlan=None, private_ipv4=None): """ Attach a node to a VLAN by adding an additional NIC to the node on the target VLAN. The IP will be automatically assigned based on the VLAN IP network space. Alternatively, provide a private IPv4 address instead of VLAN information, and this will be assigned to the node on corresponding NIC. :param node: Node which should be used :type node: :class:`Node` :param vlan: VLAN to attach the node to (required unless private_ipv4) :type vlan: :class:`NttCisVlan` :keyword private_ipv4: Private nic IPv4 Address (required unless vlan) :type private_ipv4: ``str`` :rtype: ``bool`` """ request = ET.Element('addNic', {'xmlns': TYPES_URN}) ET.SubElement(request, 'serverId').text = node.id nic = ET.SubElement(request, 'nic') if vlan is not None: ET.SubElement(nic, 'vlanId').text = vlan.id elif private_ipv4 is not None: ET.SubElement(nic, 'privateIpv4').text = private_ipv4 else: raise ValueError("One of vlan or primary_ipv4 " "must be specified") response = self.connection.request_with_orgId_api_2( 'server/addNic', method='POST', data=ET.tostring(request)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_destroy_nic(self, nic_id): """ Remove a NIC on a node, removing the node from a VLAN :param nic_id: The identifier of the NIC to remove :type nic_id: ``str`` :rtype: ``bool`` """ request = ET.Element('removeNic', {'xmlns': TYPES_URN, 'id': nic_id}) response = self.connection.request_with_orgId_api_2( 'server/removeNic', method='POST', data=ET.tostring(request)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_networks(self, location=None): """ List networks deployed across all data center locations for your organization. The response includes the location of each network. :param location: The target location :type location: :class:`NodeLocation` or ``str`` :return: a list of NttCisNetwork objects :rtype: ``list`` of :class:`NttCisNetwork` """ return self.list_networks(location=location) def ex_create_network(self, location, name, description=None): """ Create a new network in an MCP 1.0 location :param location: The target location (MCP1) :type location: :class:`NodeLocation` or ``str`` :param name: The name of the network :type name: ``str`` :param description: Additional description of the network :type description: ``str`` :return: A new instance of `NttCisNetwork` :rtype: Instance of :class:`NttCisNetwork` """ network_location = self._location_to_location_id(location) create_node = ET.Element('NewNetworkWithLocation', {'xmlns': NETWORK_NS}) ET.SubElement(create_node, "name").text = name if description is not None: ET.SubElement(create_node, "description").text = description ET.SubElement(create_node, "location").text = network_location self.connection.request_with_orgId_api_1( 'networkWithLocation', method='POST', data=ET.tostring(create_node)) # MCP1 API does not return the ID, but name is unique for location network = list( filter(lambda x: x.name == name, self.ex_list_networks(location)))[0] return network def ex_delete_network(self, network): """ Delete a network from an MCP 1 data center :param network: The network to delete :type network: :class:`NttCisNetwork` :rtype: ``bool`` """ response = self.connection.request_with_orgId_api_1( 'network/%s?delete' % network.id, method='GET').object response_code = findtext(response, 'result', GENERAL_NS) return response_code == "SUCCESS" def ex_rename_network(self, network, new_name): """ Rename a network in MCP 1 data center :param network: The network to rename :type network: :class:`NttCisNetwork` :param new_name: The new name of the network :type new_name: ``str`` :rtype: ``bool`` """ response = self.connection.request_with_orgId_api_1( 'network/%s' % network.id, method='POST', data='name=%s' % new_name).object response_code = findtext(response, 'result', GENERAL_NS) return response_code == "SUCCESS" def ex_get_network_domain(self, network_domain_id): """ Get an individual Network Domain, by identifier :param network_domain_id: The identifier of the network domain :type network_domain_id: ``str`` :rtype: :class:`NttCisNetworkDomain` """ locations = self.list_locations() net = self.connection.request_with_orgId_api_2( 'network/networkDomain/%s' % network_domain_id).object return self._to_network_domain(net, locations) def ex_list_network_domains(self, location=None, name=None, service_plan=None, state=None): """ List networks domains deployed across all data center locations domain. for your organization. The response includes the location of each network :param location: Only network domains in the location (optional) :type location: :class:`NodeLocation` or ``str`` :param name: Only network domains of this name (optional) :type name: ``str`` :param service_plan: Only network domains of this type (optional) :type service_plan: ``str`` :param state: Only network domains in this state (optional) :type state: ``str`` :return: a list of `NttCisNetwork` objects :rtype: ``list`` of :class:`NttCisNetwork` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) if name is not None: params['name'] = name if service_plan is not None: params['type'] = service_plan if state is not None: params['state'] = state response = self.connection \ .request_with_orgId_api_2('network/networkDomain', params=params).object return self._to_network_domains(response) def ex_create_network_domain(self, location, name, service_plan, description=None): """ Deploy a new network domain to a data center :param location: The data center to list :type location: :class:`NodeLocation` or ``str`` :param name: The name of the network domain to create :type name: ``str`` :param service_plan: The service plan, either "ESSENTIALS" or "ADVANCED" :type service_plan: ``str`` :param description: An additional description of the network domain :type description: ``str`` :return: an instance of `NttCisNetworkDomain` :rtype: :class:`NttCisNetworkDomain` """ create_node = ET.Element('deployNetworkDomain', {'xmlns': TYPES_URN}) ET.SubElement( create_node, "datacenterId" ).text = self._location_to_location_id(location) ET.SubElement(create_node, "name").text = name if description is not None: ET.SubElement(create_node, "description").text = description ET.SubElement(create_node, "type").text = service_plan response = self.connection.request_with_orgId_api_2( 'network/deployNetworkDomain', method='POST', data=ET.tostring(create_node)).object network_domain_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'networkDomainId': network_domain_id = info.get('value') return NttCisNetworkDomain( id=network_domain_id, name=name, description=description, location=location, status=NodeState.RUNNING, plan=service_plan ) def ex_update_network_domain(self, network_domain): """ Update the properties of a network domain :param network_domain: The network domain with updated properties :type network_domain: :class:`NttCisNetworkDomain` :return: an instance of `NttCisNetworkDomain` :rtype: :class:`NttCisNetworkDomain` """ edit_node = ET.Element('editNetworkDomain', {'xmlns': TYPES_URN}) edit_node.set('id', network_domain.id) ET.SubElement(edit_node, "name").text = network_domain.name if network_domain.description is not None: ET.SubElement(edit_node, "description").text \ = network_domain.description ET.SubElement(edit_node, "type").text = network_domain.plan self.connection.request_with_orgId_api_2( 'network/editNetworkDomain', method='POST', data=ET.tostring(edit_node)).object return network_domain def ex_delete_network_domain(self, network_domain): """ Delete a network domain :param network_domain: The network domain to delete :type network_domain: :class:`NttCisNetworkDomain` :rtype: ``bool`` """ delete_node = ET.Element('deleteNetworkDomain', {'xmlns': TYPES_URN}) delete_node.set('id', network_domain.id) result = self.connection.request_with_orgId_api_2( 'network/deleteNetworkDomain', method='POST', data=ET.tostring(delete_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_vlan(self, network_domain, name, private_ipv4_base_address, description=None, private_ipv4_prefix_size=24): """ Deploy a new VLAN to a network domain :param network_domain: The network domain to add the VLAN to :type network_domain: :class:`NttCisNetworkDomain` :param name: The name of the VLAN to create :type name: ``str`` :param private_ipv4_base_address: The base IPv4 address e.g. 192.168.1.0 :type private_ipv4_base_address: ``str`` :param description: An additional description of the VLAN :type description: ``str`` :param private_ipv4_prefix_size: The size of the IPv4 address space, e.g 24 :type private_ipv4_prefix_size: ``int`` :return: an instance of `NttCisVlan` :rtype: :class:`NttCisVlan` """ create_node = ET.Element('deployVlan', {'xmlns': TYPES_URN}) ET.SubElement(create_node, "networkDomainId").text = network_domain.id ET.SubElement(create_node, "name").text = name if description is not None: ET.SubElement(create_node, "description").text = description ET.SubElement(create_node, "privateIpv4BaseAddress").text = \ private_ipv4_base_address ET.SubElement(create_node, "privateIpv4PrefixSize").text = \ str(private_ipv4_prefix_size) response = self.connection.request_with_orgId_api_2( 'network/deployVlan', method='POST', data=ET.tostring(create_node)).object vlan_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'vlanId': vlan_id = info.get('value') return self.ex_get_vlan(vlan_id) def ex_get_vlan(self, vlan_id): """ Get a single VLAN, by it's identifier :param vlan_id: The identifier of the VLAN :type vlan_id: ``str`` :return: an instance of `NttCisVlan` :rtype: :class:`NttCisVlan` """ locations = self.list_locations() vlan = self.connection.request_with_orgId_api_2( 'network/vlan/%s' % vlan_id).object return self._to_vlan(vlan, locations) def ex_update_vlan(self, vlan): """ Updates the properties of the given VLAN Only name and description are updated :param vlan: The VLAN to update :type vlan: :class:`NttCisetworkDomain` :return: an instance of `NttCisVlan` :rtype: :class:`NttCisVlan` """ edit_node = ET.Element('editVlan', {'xmlns': TYPES_URN}) edit_node.set('id', vlan.id) ET.SubElement(edit_node, "name").text = vlan.name if vlan.description is not None: ET.SubElement(edit_node, "description").text \ = vlan.description self.connection.request_with_orgId_api_2( 'network/editVlan', method='POST', data=ET.tostring(edit_node)).object return vlan def ex_expand_vlan(self, vlan): """ Expands the VLAN to the prefix size in private_ipv4_range_size The expansion will not be permitted if the proposed IP space overlaps with an already deployed VLANs IP space. :param vlan: The VLAN to update :type vlan: :class:`NttCisNetworkDomain` :return: an instance of `NttCisVlan` :rtype: :class:`NttCisVlan` """ edit_node = ET.Element('expandVlan', {'xmlns': TYPES_URN}) edit_node.set('id', vlan.id) ET.SubElement(edit_node, "privateIpv4PrefixSize").text =\ vlan.private_ipv4_range_size self.connection.request_with_orgId_api_2( 'network/expandVlan', method='POST', data=ET.tostring(edit_node)).object return vlan def ex_delete_vlan(self, vlan): """ Deletes an existing VLAN :param vlan: The VLAN to delete :type vlan: :class:`DNttCisNetworkDomain` :rtype: ``bool`` """ delete_node = ET.Element('deleteVlan', {'xmlns': TYPES_URN}) delete_node.set('id', vlan.id) result = self.connection.request_with_orgId_api_2( 'network/deleteVlan', method='POST', data=ET.tostring(delete_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_vlans(self, location=None, network_domain=None, name=None, ipv4_address=None, ipv6_address=None, state=None): """ List VLANs available, can filter by location and/or network domain :param location: Only VLANs in this location (optional) :type location: :class:`NodeLocation` or ``str`` :param network_domain: Only VLANs in this domain (optional) :type network_domain: :class:`NttCisNetworkDomain` :param name: Only VLANs with this name (optional) :type name: ``str`` :param ipv4_address: Only VLANs with this ipv4 address (optional) :type ipv4_address: ``str`` :param ipv6_address: Only VLANs with this ipv6 address (optional) :type ipv6_address: ``str`` :param state: Only VLANs with this state (optional) :type state: ``str`` :return: a list of NttCisVlan objects :rtype: ``list`` of :class:`NttCisVlan` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) if network_domain is not None: params['networkDomainId'] = \ self._network_domain_to_network_domain_id(network_domain) if name is not None: params['name'] = name if ipv4_address is not None: params['privateIpv4Address'] = ipv4_address if ipv6_address is not None: params['ipv6Address'] = ipv6_address if state is not None: params['state'] = state response = self.connection.request_with_orgId_api_2( 'network/vlan', params=params).object return self._to_vlans(response) def ex_add_public_ip_block_to_network_domain(self, network_domain): add_node = ET.Element('addPublicIpBlock', {'xmlns': TYPES_URN}) ET.SubElement(add_node, "networkDomainId").text =\ network_domain.id response = self.connection.request_with_orgId_api_2( 'network/addPublicIpBlock', method='POST', data=ET.tostring(add_node)).object block_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'ipBlockId': block_id = info.get('value') return self.ex_get_public_ip_block(block_id) def ex_list_public_ip_blocks(self, network_domain): params = {} params['networkDomainId'] = network_domain.id response = self.connection \ .request_with_orgId_api_2('network/publicIpBlock', params=params).object return self._to_ip_blocks(response) def ex_get_public_ip_block(self, block_id): locations = self.list_locations() block = self.connection.request_with_orgId_api_2( 'network/publicIpBlock/%s' % block_id).object return self._to_ip_block(block, locations) def ex_delete_public_ip_block(self, block): delete_node = ET.Element('removePublicIpBlock', {'xmlns': TYPES_URN}) delete_node.set('id', block.id) result = self.connection.request_with_orgId_api_2( 'network/removePublicIpBlock', method='POST', data=ET.tostring(delete_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] # 09/10/18 Adding private IPv4 and IPv6 addressing capability def ex_reserve_ip(self, vlan, ip, description): vlan_id = self._vlan_to_vlan_id(vlan) if re.match(r'(\d+\.){3}', ip): private_ip = ET.Element('reservePrivateIpv4Address', {'xmlns': TYPES_URN}) resource = 'network/reservePrivateIpv4Address' elif re.search(r':', ip): private_ip = ET.Element('reserveIpv6Address', {'xmlns': TYPES_URN}) resource = 'network/reserveIpv6Address' ET.SubElement(private_ip, 'vlanId').text = vlan_id ET.SubElement(private_ip, 'ipAddress').text = ip if description is not None: ET.SubElement(private_ip, 'description').text = description result = self.connection.request_with_orgId_api_2( resource, method='POST', data=ET.tostring(private_ip)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_unreserve_ip_addresses(self, vlan, ip): vlan_id = self._vlan_to_vlan_id(vlan) if re.match(r'(\d+\.){3}', ip): private_ip = ET.Element('unreservePrivateIpv4Address', {'xmlns': TYPES_URN}) resource = 'network/reservePrivateIpv4Address' elif re.search(r':', ip): private_ip = ET.Element('unreserveIpv6Address', {'xmlns': TYPES_URN}) resource = 'network/unreserveIpv6Address' ET.SubElement(private_ip, 'vlanId').text = vlan_id ET.SubElement(private_ip, 'ipAddress').text = ip result = self.connection.\ request_with_orgId_api_2( resource, method='POST', data=ET.tostring(private_ip)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_reserved_ipv4(self, vlan=None, datacenter_id=None): if vlan is not None: vlan_id = self._vlan_to_vlan_id(vlan) params = {"vlanId": vlan_id} response = self.connection \ .request_with_orgId_api_2('network/reservedPrivateIpv4Address', params=params).object elif datacenter_id is not None: params = {'datacenterId': datacenter_id} response = self.connection \ .request_with_orgId_api_2('network/reservedPrivateIpv4Address', params=params).object else: response = self.connection \ .request_with_orgId_api_2( 'network/reservedPrivateIpv4Address').object addresses = self._to_ipv4_addresses(response) return addresses def ex_list_reserved_ipv6(self, vlan=None, datacenter_id=None): if vlan is not None: vlan_id = self._vlan_to_vlan_id(vlan) params = {"vlanId": vlan_id} response = self.connection \ .request_with_orgId_api_2('network/reservedIpv6Address', params=params).object elif datacenter_id is not None: params = {'datacenterId': datacenter_id} response = self.connection \ .request_with_orgId_api_2('network/reservedIpv6Address', params=params).object else: response = self.connection \ .request_with_orgId_api_2( 'network/reservedIpv6Address').object addresses = self._to_ipv6_addresses(response) return addresses def ex_get_node_by_id(self, id): node = self.connection.request_with_orgId_api_2( 'server/server/%s' % id).object return self._to_node(node) def ex_list_firewall_rules(self, network_domain, page_size=50, page_number=1): params = {'pageSize': page_size, 'pageNumber': page_number} params['networkDomainId'] = self._network_domain_to_network_domain_id( network_domain) response = self.connection \ .request_with_orgId_api_2('network/firewallRule', params=params).object return self._to_firewall_rules(response, network_domain) def ex_create_firewall_rule(self, network_domain, name, action, ip_version, protocol, source_addr, dest_addr, position, enabled=1, position_relative_to_rule=None): """ Creates a firewall rule :param network_domain: The network domain in which to create the firewall rule :type network_domain: :class:`NttCisNetworkDomain` or ``str`` :param name: The rule's name :type name: ``str`` :param action: 'ACCEPT_DECISIVELY' or 'DROP' :type action: ``str`` :param ip_version: 'IPV4' or 'IPV6' :type ip_version: ``str`` :param protocol: One of 'IP', 'ICMP', 'TCP', or 'UDP' :type protocol: ``str`` :param source_addr: The source address, which must be an NttCisFirewallAddress instance :type source_addr: ``NttCisFirewallAddress`` :param dest_addr: The destination address, which must be an NttCisFirewallAddress instance :type dest_addr: `NttCisFirewallAddress`` :param position: The position in which to create the rule There are two types of positions with position_relative_to_rule arg and without it With: 'BEFORE' or 'AFTER' Without: 'FIRST' or 'LAST' :type position: ``str`` :param enabled: Firewall rule is enabled upon creation. Set to 1 for true or 0 for false. :type enabled: ``int`` :param position_relative_to_rule: The rule or rule name in which to decide positioning by :type position_relative_to_rule: ::class:`NttCisFirewallRule` or ``str`` :rtype: ``bool`` """ positions_without_rule = ('FIRST', 'LAST') positions_with_rule = ('BEFORE', 'AFTER') create_node = ET.Element('createFirewallRule', {'xmlns': TYPES_URN}) ET.SubElement(create_node, "networkDomainId").text = \ self._network_domain_to_network_domain_id(network_domain) ET.SubElement(create_node, "name").text = name ET.SubElement(create_node, "action").text = action ET.SubElement(create_node, "ipVersion").text = ip_version ET.SubElement(create_node, "protocol").text = protocol # Setup source port rule source = ET.SubElement(create_node, "source") if source_addr.address_list_id is not None: source_ip = ET.SubElement(source, 'ipAddressListId') source_ip.text = source_addr.address_list_id else: source_ip = ET.SubElement(source, 'ip') if source_addr.any_ip: source_ip.set('address', 'ANY') else: source_ip.set('address', source_addr.ip_address) if source_addr.ip_prefix_size is not None: source_ip.set('prefixSize', str(source_addr.ip_prefix_size)) if source_addr.port_list_id is not None: source_port = ET.SubElement(source, 'portListId') source_port.text = source_addr.port_list_id else: if source_addr.port_begin is not None: source_port = ET.SubElement(source, 'port') source_port.set('begin', source_addr.port_begin) if source_addr.port_end is not None: source_port.set('end', source_addr.port_end) # Setup destination port rule dest = ET.SubElement(create_node, "destination") if dest_addr.address_list_id is not None: dest_ip = ET.SubElement(dest, 'ipAddressListId') dest_ip.text = dest_addr.address_list_id else: dest_ip = ET.SubElement(dest, 'ip') if dest_addr.any_ip: dest_ip.set('address', 'ANY') else: dest_ip.set('address', dest_addr.ip_address) if dest_addr.ip_prefix_size is not None: dest_ip.set('prefixSize', dest_addr.ip_prefix_size) if dest_addr.port_list_id is not None: dest_port = ET.SubElement(dest, 'portListId') dest_port.text = dest_addr.port_list_id else: if dest_addr.port_begin is not None: dest_port = ET.SubElement(dest, 'port') dest_port.set('begin', dest_addr.port_begin) if dest_addr.port_end is not None: dest_port.set('end', dest_addr.port_end) # Set up positioning of rule ET.SubElement(create_node, "enabled").text = str(enabled) placement = ET.SubElement(create_node, "placement") if position_relative_to_rule is not None: if position not in positions_with_rule: raise ValueError("When position_relative_to_rule is specified" " position must be %s" % ', '.join(positions_with_rule)) if isinstance(position_relative_to_rule, NttCisFirewallRule): rule_name = position_relative_to_rule.name else: rule_name = position_relative_to_rule placement.set('relativeToRule', rule_name) else: if position not in positions_without_rule: raise ValueError("When position_relative_to_rule is not" " specified position must be %s" % ', '.join(positions_without_rule)) placement.set('position', position) response = self.connection.request_with_orgId_api_2( 'network/createFirewallRule', method='POST', data=ET.tostring(create_node)).object rule_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'firewallRuleId': rule_id = info.get('value') rule = self.ex_get_firewall_rule(network_domain, rule_id) return rule def ex_edit_firewall_rule(self, rule, position=None, relative_rule_for_position=None): """ Edit a firewall rule >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> >>> # List firewall rules >>> firewall_rules = driver.ex_list_firewall_rules(my_network_domain) >>> >>> # Get Firewall Rule by name >>> pprint("List specific firewall rule by name") >>> fire_rule_under_test = (list(filter(lambda x: x.name == 'My_New_Firewall_Rule', firewall_rules))[0]) >>> pprint(fire_rule_under_test.source) >>> pprint(fire_rule_under_test.destination) >>> >>> # Edit Firewall >>> fire_rule_under_test.destination.address_list_id = '5e7c323f-c885-4e4b-9a27-94c44217dbd3' >>> fire_rule_under_test.destination.port_list_id = 'b6557c5a-45fa-4138-89bd-8fe68392691b' >>> result = driver.ex_edit_firewall_rule(fire_rule_under_test, 'LAST') >>> pprint(result) :param rule: (required) The rule in which to create :type rule: :class:`DNttCisFirewallRule` :param position: (required) There are two types of positions with position_relative_to_rule arg and without it With: 'BEFORE' or 'AFTER' Without: 'FIRST' or 'LAST' :type position: ``str`` :param relative_rule_for_position: (optional) The rule or rule name in which to decide the relative rule for positioning. :type relative_rule_for_position: :class:`NttCisFirewallRule` or ``str`` :rtype: ``bool`` """ positions_without_rule = ('FIRST', 'LAST') positions_with_rule = ('BEFORE', 'AFTER') edit_node = ET.Element('editFirewallRule', {'xmlns': TYPES_URN, 'id': rule.id}) ET.SubElement(edit_node, "action").text = rule.action ET.SubElement(edit_node, "protocol").text = rule.protocol # Source address source = ET.SubElement(edit_node, "source") if rule.source.address_list_id is not None: source_ip = ET.SubElement(source, 'ipAddressListId') source_ip.text = rule.source.address_list_id else: source_ip = ET.SubElement(source, 'ip') if rule.source.any_ip: source_ip.set('address', 'ANY') else: source_ip.set('address', rule.source.ip_address) if rule.source.ip_prefix_size is not None: source_ip.set('prefixSize', str(rule.source.ip_prefix_size)) # Setup source port rule if rule.source.port_list_id is not None: source_port = ET.SubElement(source, 'portListId') source_port.text = rule.source.port_list_id else: if rule.source.port_begin is not None: source_port = ET.SubElement(source, 'port') source_port.set('begin', rule.source.port_begin) if rule.source.port_end is not None: source_port.set('end', rule.source.port_end) # Setup destination port rule dest = ET.SubElement(edit_node, "destination") if rule.destination.address_list_id is not None: dest_ip = ET.SubElement(dest, 'ipAddressListId') dest_ip.text = rule.destination.address_list_id else: dest_ip = ET.SubElement(dest, 'ip') if rule.destination.any_ip: dest_ip.set('address', 'ANY') else: dest_ip.set('address', rule.destination.ip_address) if rule.destination.ip_prefix_size is not None: dest_ip.set('prefixSize', rule.destination.ip_prefix_size) if rule.destination.port_list_id is not None: dest_port = ET.SubElement(dest, 'portListId') dest_port.text = rule.destination.port_list_id else: if rule.destination.port_begin is not None: dest_port = ET.SubElement(dest, 'port') dest_port.set('begin', rule.destination.port_begin) if rule.destination.port_end is not None: dest_port.set('end', rule.destination.port_end) # Set up positioning of rule ET.SubElement(edit_node, "enabled").text = str(rule.enabled).lower() # changing placement to an option if position is not None: placement = ET.SubElement(edit_node, "placement") if relative_rule_for_position is not None: if position not in positions_with_rule: raise ValueError( "When position_relative_to_rule is specified" " position must be %s" % ', '.join(positions_with_rule)) if isinstance(relative_rule_for_position, NttCisFirewallRule): rule_name = relative_rule_for_position.name else: rule_name = relative_rule_for_position placement.set('relativeToRule', rule_name) else: if position not in positions_without_rule: raise ValueError("When position_relative_to_rule is not" " specified position must be %s" % ', '.join(positions_without_rule)) placement.set('position', position) response = self.connection.request_with_orgId_api_2( 'network/editFirewallRule', method='POST', data=ET.tostring(edit_node)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_firewall_rule(self, network_domain, rule_id): locations = self.list_locations() rule = self.connection.request_with_orgId_api_2( 'network/firewallRule/%s' % rule_id).object return self._to_firewall_rule(rule, locations, network_domain) def ex_set_firewall_rule_state(self, rule, state): """ Change the state (enabled or disabled) of a rule :param rule: The rule to delete :type rule: :class:`NttCisFirewallRule` :param state: The desired state enabled (True) or disabled (False) :type state: ``bool`` :rtype: ``bool`` """ update_node = ET.Element('editFirewallRule', {'xmlns': TYPES_URN}) update_node.set('id', rule.id) ET.SubElement(update_node, 'enabled').text = str(state).lower() result = self.connection.request_with_orgId_api_2( 'network/editFirewallRule', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_firewall_rule(self, rule): """ Delete a firewall rule :param rule: The rule to delete :type rule: :class:`NttCisFirewallRule` :rtype: ``bool`` """ update_node = ET.Element('deleteFirewallRule', {'xmlns': TYPES_URN}) update_node.set('id', rule.id) result = self.connection.request_with_orgId_api_2( 'network/deleteFirewallRule', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_nat_rule(self, network_domain, internal_ip, external_ip): """ Create a NAT rule :param network_domain: The network domain the rule belongs to :type network_domain: :class:`NttCisNetworkDomain` :param internal_ip: The IPv4 address internally :type internal_ip: ``str`` :param external_ip: The IPv4 address externally :type external_ip: ``str`` :rtype: :class:`NttCisNatRule` """ create_node = ET.Element('createNatRule', {'xmlns': TYPES_URN}) ET.SubElement(create_node, 'networkDomainId').text = network_domain.id ET.SubElement(create_node, 'internalIp').text = internal_ip ET.SubElement(create_node, 'externalIp').text = external_ip result = self.connection.request_with_orgId_api_2( 'network/createNatRule', method='POST', data=ET.tostring(create_node)).object rule_id = None for info in findall(result, 'info', TYPES_URN): if info.get('name') == 'natRuleId': rule_id = info.get('value') return NttCisNatRule( id=rule_id, network_domain=network_domain, internal_ip=internal_ip, external_ip=external_ip, status=NodeState.RUNNING ) def ex_list_nat_rules(self, network_domain): """ Get NAT rules for the network domain :param network_domain: The network domain the rules belongs to :type network_domain: :class:`NttCisNetworkDomain` :rtype: ``list`` of :class:`NttCisNatRule` """ params = {} params['networkDomainId'] = network_domain.id response = self.connection \ .request_with_orgId_api_2('network/natRule', params=params).object return self._to_nat_rules(response, network_domain) def ex_get_nat_rule(self, network_domain, rule_id): """ Get a NAT rule by ID :param network_domain: The network domain the rule belongs to :type network_domain: :class:`NttCisNetworkDomain` :param rule_id: The ID of the NAT rule to fetch :type rule_id: ``str`` :rtype: :class:`NttCisNatRule` """ rule = self.connection.request_with_orgId_api_2( 'network/natRule/%s' % rule_id).object return self._to_nat_rule(rule, network_domain) def ex_delete_nat_rule(self, rule): """ Delete an existing NAT rule :param rule: The rule to delete :type rule: :class:`NttCisNatRule` :rtype: ``bool`` """ update_node = ET.Element('deleteNatRule', {'xmlns': TYPES_URN}) update_node.set('id', rule.id) result = self.connection.request_with_orgId_api_2( 'network/deleteNatRule', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_location_by_id(self, id): """ Get location by ID. :param id: ID of the node location which should be used :type id: ``str`` :rtype: :class:`NodeLocation` """ location = None if id is not None: location = self.list_locations(ex_id=id)[0] return location def ex_wait_for_state(self, state, func, poll_interval=2, timeout=60, *args, **kwargs): """ Wait for the function which returns a instance with field status to match Keep polling func until one of the desired states is matched :param state: Either the desired state (`str`) or a `list` of states :type state: ``str`` or ``list`` :param func: The function to call, e.g. ex_get_vlan :type func: ``function`` :param poll_interval: The number of seconds to wait between checks :type poll_interval: `int` :param timeout: The total number of seconds to wait to reach a state :type timeout: `int` :param args: The arguments for func :type args: Positional arguments :param kwargs: The arguments for func :type kwargs: Keyword arguments """ return self.connection.wait_for_state(state, func, poll_interval, timeout, *args, **kwargs) def ex_enable_monitoring(self, node, service_plan="ESSENTIALS"): """ Enables cloud monitoring on a node :param node: The node to monitor :type node: :class:`Node` :param service_plan: The service plan, one of ESSENTIALS or ADVANCED :type service_plan: ``str`` :rtype: ``bool`` """ update_node = ET.Element('enableServerMonitoring', {'xmlns': TYPES_URN}) update_node.set('id', node.id) ET.SubElement(update_node, 'servicePlan').text = service_plan result = self.connection.request_with_orgId_api_2( 'server/enableServerMonitoring', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_update_monitoring_plan(self, node, service_plan="ESSENTIALS"): """ Updates the service plan on a node with monitoring :param node: The node to monitor :type node: :class:`Node` :param service_plan: The service plan, one of ESSENTIALS or ADVANCED :type service_plan: ``str`` :rtype: ``bool`` """ update_node = ET.Element('changeServerMonitoringPlan', {'xmlns': TYPES_URN}) update_node.set('id', node.id) ET.SubElement(update_node, 'servicePlan').text = service_plan result = self.connection.request_with_orgId_api_2( 'server/changeServerMonitoringPlan', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_disable_monitoring(self, node): """ Disables cloud monitoring for a node :param node: The node to stop monitoring :type node: :class:`Node` :rtype: ``bool`` """ update_node = ET.Element('disableServerMonitoring', {'xmlns': TYPES_URN}) update_node.set('id', node.id) result = self.connection.request_with_orgId_api_2( 'server/disableServerMonitoring', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_add_scsi_controller_to_node(self, server_id, adapter_type, bus_number=None): """ Added 8/27/18: Adds a SCSI Controller by node id :param server_id: server id :param adapter_type: the type of SCSI Adapter, i.e., LSI_LOGIC_PARALLEL :param bus_number: optional number of server's bus :return: whether addition is in progress or 'OK' otherwise false """ update_node = ET.Element('addScsiController', {'xmlns': TYPES_URN}) ET.SubElement(update_node, 'serverId').text = server_id ET.SubElement(update_node, 'adapterType').text = adapter_type if bus_number is not None: ET.SubElement(update_node, 'busNumber').text = bus_number result = self.connection.request_with_orgId_api_2( 'server/addScsiController', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_remove_scsi_controller(self, controller_id): """ Added 8/27/18: Adds a SCSI Controller by node id :param controller_id: Scsi controller's id :return: whether addition is in progress or 'OK' otherwise false """ update_node = ET.Element('removeScsiController', {'xmlns': TYPES_URN}) update_node.set('id', controller_id) result = self.connection.request_with_orgId_api_2( 'server/removeScsiController', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_add_storage_to_node(self, amount, node=None, speed='STANDARD', controller_id=None, scsi_id=None): """ Updated 8/23/18 Add storage to the node One of node or controller_id must be selected :param node: The server to add storage to (required if controller_id is not used :type node: :class:`Node` :param amount: The amount of storage to add, in GB :type amount: ``int`` :param speed: The disk speed type :type speed: ``str`` :param conrollter_id: The disk may be added using the cotnroller id (required if node object is not used) :type controller_id: ``str`` :param scsi_id: The target SCSI ID (optional) :type scsi_id: ``int`` :rtype: ``bool`` """ if (node is None and controller_id is None) or \ (node is not None and controller_id is not None): raise RuntimeError("Either a node or a controller " "id must be specified") update_node = ET.Element('addDisk', {'xmlns': TYPES_URN}) if node is not None: ET.SubElement(update_node, 'serverId').text = node.id elif controller_id is not None: scsi_node = ET.Element('scsiController') ET.SubElement(scsi_node, 'controllerId').text = controller_id update_node.insert(1, scsi_node) ET.SubElement(update_node, 'sizeGb').text = str(amount) ET.SubElement(update_node, 'speed').text = speed.upper() if scsi_id is not None: ET.SubElement(update_node, 'scsiId').text = str(scsi_id) result = self.connection.request_with_orgId_api_2( 'server/addDisk', method='POST', data=ET.tostring(update_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_remove_storage_from_node(self, node, scsi_id): """ Remove storage from a node :param node: The server to add storage to :type node: :class:`Node` :param scsi_id: The ID of the disk to remove :type scsi_id: ``str`` :rtype: ``bool`` """ disk = [disk for disk in node.extra['disks'] if disk.scsi_id == scsi_id][0] return self.ex_remove_storage(disk.id) def ex_remove_storage(self, disk_id): """ Remove storage from a node :param node: The server to add storage to :type node: :class:`Node` :param disk_id: The ID of the disk to remove :type disk_id: ``str`` :rtype: ``bool`` """ remove_disk = ET.Element('removeDisk', {'xmlns': TYPES_URN}) remove_disk.set('id', disk_id) result = self.connection.request_with_orgId_api_2( 'server/removeDisk', method='POST', data=ET.tostring(remove_disk)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_change_storage_speed(self, disk_id, speed, iops=None): """ Change the speed (disk tier) of a disk :param node: The server to change the disk speed of :type node: :class:`Node` :param disk_id: The ID of the disk to change :type disk_id: ``str`` :param speed: The disk speed type e.g. STANDARD :type speed: ``str`` :rtype: ``bool`` """ create_node = ET.Element('changeDiskSpeed', {'xmlns': TYPES_URN}) create_node.set('id', disk_id) ET.SubElement(create_node, 'speed').text = speed if iops is not None: ET.SubElement(create_node, 'iops').text = str(iops) result = self.connection.request_with_orgId_api_2( 'server/changeDiskSpeed', method='POST', data=ET.tostring(create_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_change_storage_size(self, disk_id, size): """ Change the size of a disk :param node: The server to change the disk of :type node: :class:`Node` :param disk_id: The ID of the disk to resize :type disk_id: ``str`` :param size: The disk size in GB :type size: ``int`` :rtype: ``bool`` """ create_node = ET.Element('expandDisk', {'xmlns': TYPES_URN, 'id': disk_id}) ET.SubElement(create_node, 'newSizeGb').text = str(size) ''' This code is for version 1 of MCP, need version 2 result = self.connection.request_with_orgId_api_1( 'server/%s/disk/%s/changeSize' % (node.id, disk_id), method='POST', data=ET.tostring(create_node)).object ''' result = self.connection.request_with_orgId_api_2( 'server/expandDisk', method='POST', data=ET.tostring(create_node)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_reconfigure_node(self, node, memory_gb=None, cpu_count=None, cores_per_socket=None, cpu_performance=None): """ Reconfigure the virtual hardware specification of a node :param node: The server to change :type node: :class:`Node` :param memory_gb: The amount of memory in GB (optional) :type memory_gb: ``int`` :param cpu_count: The number of CPU (optional) :type cpu_count: ``int`` :param cores_per_socket: Number of CPU cores per socket (optional) :type cores_per_socket: ``int`` :param cpu_performance: CPU Performance type (optional) :type cpu_performance: ``str`` :rtype: ``bool`` """ update = ET.Element('reconfigureServer', {'xmlns': TYPES_URN}) update.set('id', node.id) if memory_gb is not None: ET.SubElement(update, 'memoryGb').text = str(memory_gb) if cpu_count is not None: ET.SubElement(update, 'cpuCount').text = str(cpu_count) if cpu_performance is not None: ET.SubElement(update, 'cpuSpeed').text = cpu_performance if cores_per_socket is not None: ET.SubElement(update, 'coresPerSocket').text = \ str(cores_per_socket) result = self.connection.request_with_orgId_api_2( 'server/reconfigureServer', method='POST', data=ET.tostring(update)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_clone_node_to_image(self, node, image_name, image_description=None, cluster_id=None, is_guest_Os_Customization=None, tag_key_id=None, tag_value=None): """ Clone a server into a customer image. :param node: The server to clone :type node: :class:`Node` :param image_name: The name of the clone image :type image_name: ``str`` :param description: The description of the image :type description: ``str`` :rtype: ``bool`` """ if image_description is None: image_description = '' node_id = self._node_to_node_id(node) """ Removing anything below 2.4 # Version 2.3 and lower if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): response = self.connection.request_with_orgId_api_1( 'server/%s?clone=%s&desc=%s' % (node_id, image_name, image_description)).object # Version 2.4 and higher else: """ clone_server_elem = ET.Element('cloneServer', {'id': node_id, 'xmlns': TYPES_URN}) ET.SubElement(clone_server_elem, 'imageName').text = image_name if image_description is not None: ET.SubElement(clone_server_elem, 'description').text = \ image_description if cluster_id is not None: ET.SubElement(clone_server_elem, 'clusterId').text = \ cluster_id if is_guest_Os_Customization is not None: ET.SubElement(clone_server_elem, 'guestOsCustomization')\ .text = is_guest_Os_Customization if tag_key_id is not None: tag_elem = ET.SubElement(clone_server_elem, 'tagById') ET.SubElement(tag_elem, 'tagKeyId').text = tag_key_id if tag_value is not None: ET.SubElement(tag_elem, 'value').text = tag_value response = self.connection.request_with_orgId_api_2( 'server/cloneServer', method='POST', data=ET.tostring(clone_server_elem)).object """ removing references to anything lower than 2.4 # Version 2.3 and lower if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): response_code = findtext(response, 'result', GENERAL_NS) else: """ response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'SUCCESS'] def ex_clean_failed_deployment(self, node): """ Removes a node that has failed to deploy :param node: The failed node to clean :type node: :class:`Node` or ``str`` """ node_id = self._node_to_node_id(node) request_elm = ET.Element('cleanServer', {'xmlns': TYPES_URN, 'id': node_id}) body = self.connection.request_with_orgId_api_2( 'server/cleanServer', method='POST', data=ET.tostring(request_elm)).object response_code = findtext(body, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_customer_images(self, location=None): """ Return a list of customer imported images :param location: The target location :type location: :class:`NodeLocation` or ``str`` :rtype: ``list`` of :class:`NodeImage` """ params = {} if location is not None: params['datacenterId'] = self._location_to_location_id(location) return self._to_images( self.connection.request_with_orgId_api_2( 'image/customerImage', params=params) .object, 'customerImage') def ex_get_base_image_by_id(self, id): """ Gets a Base image in the NTTC-CIS Cloud given the id :param id: The id of the image :type id: ``str`` :rtype: :class:`NodeImage` """ image = self.connection.request_with_orgId_api_2( 'image/osImage/%s' % id).object return self._to_image(image) def ex_get_customer_image_by_id(self, id): """ Gets a Customer image in the NTTC-CIS Cloud given the id :param id: The id of the image :type id: ``str`` :rtype: :class:`NodeImage` """ image = self.connection.request_with_orgId_api_2( 'image/customerImage/%s' % id).object return self._to_image(image) def ex_get_image_by_id(self, id): """ Gets a Base/Customer image in the NTTC-CIS Cloud given the id Note: This first checks the base image If it is not a base image we check if it is a customer image If it is not in either of these a NttCisAPIException is thrown :param id: The id of the image :type id: ``str`` :rtype: :class:`NodeImage` """ try: return self.ex_get_base_image_by_id(id) except NttCisAPIException as e: if e.code != 'RESOURCE_NOT_FOUND': raise e return self.ex_get_customer_image_by_id(id) def ex_create_tag_key(self, name, description=None, value_required=True, display_on_report=True): """ Creates a tag key in the NTTC-CIS Cloud :param name: The name of the tag key (required) :type name: ``str`` :param description: The description of the tag key :type description: ``str`` :param value_required: If a value is required for the tag Tags themselves can be just a tag, or be a key/value pair :type value_required: ``bool`` :param display_on_report: Should this key show up on the usage reports :type display_on_report: ``bool`` :rtype: ``bool`` """ create_tag_key = ET.Element('createTagKey', {'xmlns': TYPES_URN}) ET.SubElement(create_tag_key, 'name').text = name if description is not None: ET.SubElement(create_tag_key, 'description').text = description ET.SubElement(create_tag_key, 'valueRequired').text = \ str(value_required).lower() ET.SubElement(create_tag_key, 'displayOnReport').text = \ str(display_on_report).lower() response = self.connection.request_with_orgId_api_2( 'tag/createTagKey', method='POST', data=ET.tostring(create_tag_key)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_tag_keys(self, id=None, name=None, value_required=None, display_on_report=None): """ List tag keys in the NTTC-CIS Cloud :param id: Filter the list to the id of the tag key :type id: ``str`` :param name: Filter the list to the name of the tag key :type name: ``str`` :param value_required: Filter the list to if a value is required for a tag key :type value_required: ``bool`` :param display_on_report: Filter the list to if the tag key should show up on usage reports :type display_on_report: ``bool`` :rtype: ``list`` of :class:`NttCisTagKey` """ params = {} if id is not None: params['id'] = id if name is not None: params['name'] = name if value_required is not None: params['valueRequired'] = str(value_required).lower() if display_on_report is not None: params['displayOnReport'] = str(display_on_report).lower() paged_result = self.connection.paginated_request_with_orgId_api_2( 'tag/tagKey', method='GET', params=params ) tag_keys = [] for result in paged_result: tag_keys.extend(self._to_tag_keys(result)) return tag_keys def ex_get_tag_key_by_id(self, id): """ Get a specific tag key by ID :param id: ID of the tag key you want (required) :type id: ``str`` :rtype: :class:`NttCisTagKey` """ tag_key = self.connection.request_with_orgId_api_2( 'tag/tagKey/%s' % id).object return self._to_tag_key(tag_key) def ex_get_tag_key_by_name(self, name): """ NOTICE: Tag key is one of those instances where Libloud handles the search of a list for the client code. This behavior exists inconsistently across libcloud. Get a specific tag key by Name :param name: Name of the tag key you want (required) :type name: ``str`` :rtype: :class:`NttCisTagKey` """ tag_keys = self.ex_list_tag_keys(name=name) if len(tag_keys) != 1: raise ValueError("No tags found with name %s" % name) return tag_keys[0] def ex_modify_tag_key(self, tag_key, name=None, description=None, value_required=None, display_on_report=None): """ Modify a specific tag key :param tag_key: The tag key you want to modify (required) :type tag_key: :class:`NttCisTagKey` or ``str`` :param name: Set to modifiy the name of the tag key :type name: ``str`` :param description: Set to modify the description of the tag key :type description: ``str`` :param value_required: Set to modify if a value is required for the tag key :type value_required: ``bool`` :param display_on_report: Set to modify if this tag key should display on the usage reports :type display_on_report: ``bool`` :rtype: ``bool`` """ tag_key_id = self._tag_key_to_tag_key_id(tag_key) modify_tag_key = ET.Element('editTagKey', {'xmlns': TYPES_URN, 'id': tag_key_id}) if name is not None: ET.SubElement(modify_tag_key, 'name').text = name if description is not None: ET.SubElement(modify_tag_key, 'description').text = description if value_required is not None: ET.SubElement(modify_tag_key, 'valueRequired').text = \ str(value_required).lower() if display_on_report is not None: ET.SubElement(modify_tag_key, 'displayOnReport').text = \ str(display_on_report).lower() response = self.connection.request_with_orgId_api_2( 'tag/editTagKey', method='POST', data=ET.tostring(modify_tag_key)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_remove_tag_key(self, tag_key): """ Modify a specific tag key :param tag_key: The tag key you want to remove (required) :type tag_key: :class:`NttCisTagKey` or ``str`` :rtype: ``bool`` """ tag_key_id = self._tag_key_to_tag_key_id(tag_key) remove_tag_key = ET.Element('deleteTagKey', {'xmlns': TYPES_URN, 'id': tag_key_id}) response = self.connection.request_with_orgId_api_2( 'tag/deleteTagKey', method='POST', data=ET.tostring(remove_tag_key)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_apply_tag_to_asset(self, asset, tag_key, value=None): """ Apply a tag to a NTTC-CIS Asset :param asset: The asset to apply a tag to. (required) :type asset: :class:`Node` or :class:`NodeImage` or :class:`NttCisNewtorkDomain` or :class:`NttCisVlan` or :class:`NttCisPublicIpBlock` :param tag_key: The tag_key to apply to the asset. (required) :type tag_key: :class:`NttCisTagKey` or ``str`` :param value: The value to be assigned to the tag key This is only required if the :class:`NttCisTagKey` requires it :type value: ``str`` :rtype: ``bool`` """ asset_type = self._get_tagging_asset_type(asset) tag_key_name = self._tag_key_to_tag_key_name(tag_key) apply_tags = ET.Element('applyTags', {'xmlns': TYPES_URN}) ET.SubElement(apply_tags, 'assetType').text = asset_type ET.SubElement(apply_tags, 'assetId').text = asset.id tag_ele = ET.SubElement(apply_tags, 'tag') ET.SubElement(tag_ele, 'tagKeyName').text = tag_key_name if value is not None: ET.SubElement(tag_ele, 'value').text = value response = self.connection.request_with_orgId_api_2( 'tag/applyTags', method='POST', data=ET.tostring(apply_tags)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_remove_tag_from_asset(self, asset, tag_key): """ Remove a tag from an asset :param asset: The asset to remove a tag from. (required) :type asset: :class:`Node` or :class:`NodeImage` or :class:`NttCisNewtorkDomain` or :class:`NttCisVlan` or :class:`NttCisPublicIpBlock` :param tag_key: The tag key you want to remove (required) :type tag_key: :class:`NttCisTagKey` or ``str`` :rtype: ``bool`` """ asset_type = self._get_tagging_asset_type(asset) tag_key_name = self._tag_key_to_tag_key_name(tag_key) apply_tags = ET.Element('removeTags', {'xmlns': TYPES_URN}) ET.SubElement(apply_tags, 'assetType').text = asset_type ET.SubElement(apply_tags, 'assetId').text = asset.id ET.SubElement(apply_tags, 'tagKeyName').text = tag_key_name response = self.connection.request_with_orgId_api_2( 'tag/removeTags', method='POST', data=ET.tostring(apply_tags)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_tags(self, asset_id=None, asset_type=None, location=None, tag_key_name=None, tag_key_id=None, value=None, value_required=None, display_on_report=None): """ List tags in the NTTC-CIS Cloud :param asset_id: Filter the list by asset id :type asset_id: ``str`` :param asset_type: Filter the list by asset type :type asset_type: ``str`` :param location: Filter the list by the assets location :type location: :class:``NodeLocation`` or ``str`` :param tag_key_name: Filter the list by a tag key name :type tag_key_name: ``str`` :param tag_key_id: Filter the list by a tag key id :type tag_key_id: ``str`` :param value: Filter the list by a tag value :type value: ``str`` :param value_required: Filter the list to if a value is required for a tag :type value_required: ``bool`` :param display_on_report: Filter the list to if the tag should show up on usage reports :type display_on_report: ``bool`` :rtype: ``list`` of :class:`NttCisTag` """ params = {} if asset_id is not None: params['assetId'] = asset_id if asset_type is not None: params['assetType'] = asset_type if location is not None: params['datacenterId'] = self._location_to_location_id(location) if tag_key_name is not None: params['tagKeyName'] = tag_key_name if tag_key_id is not None: params['tagKeyId'] = tag_key_id if value is not None: params['value'] = value if value_required is not None: params['valueRequired'] = str(value_required).lower() if display_on_report is not None: params['displayOnReport'] = str(display_on_report).lower() paged_result = self.connection.paginated_request_with_orgId_api_2( 'tag/tag', method='GET', params=params ) tags = [] for result in paged_result: tags.extend(self._to_tags(result)) return tags def ex_summary_usage_report(self, start_date, end_date): """ Get summary usage information :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'report/usage?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_detailed_usage_report(self, start_date, end_date): """ Get detailed usage information :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'report/usageDetailed?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_software_usage_report(self, start_date, end_date): """ Get detailed software usage reports :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'report/usageSoftwareUnits?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_audit_log_report(self, start_date, end_date): """ Get audit log report :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :rtype: ``list`` of ``list`` """ result = self.connection.raw_request_with_orgId_api_1( 'auditlog?startDate=%s&endDate=%s' % ( start_date, end_date)) return self._format_csv(result.response) def ex_backup_usage_report(self, start_date, end_date, location): """ Get audit log report :param start_date: Start date for the report :type start_date: ``str`` in format YYYY-MM-DD :param end_date: End date for the report :type end_date: ``str`` in format YYYY-MM-DD :keyword location: Filters the node list to nodes that are located in this location :type location: :class:`NodeLocation` or ``str`` :rtype: ``list`` of ``list`` """ datacenter_id = self._location_to_location_id(location) result = self.connection.raw_request_with_orgId_api_1( 'backup/detailedUsageReport?datacenterId=%s&fromDate=%s&toDate=%s' % (datacenter_id, start_date, end_date)) return self._format_csv(result.response) def ex_list_ip_address_list(self, ex_network_domain): """ List IP Address List by network domain ID specified >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # List IP Address List of network domain >>> ipaddresslist_list = driver.ex_list_ip_address_list( >>> ex_network_domain=my_network_domain) >>> pprint(ipaddresslist_list) :param ex_network_domain: The network domain or network domain ID :type ex_network_domain: :class:`NttCisNetworkDomain` or 'str' :return: a list of NttCisIpAddressList objects :rtype: ``list`` of :class:`NttCisIpAddressList` """ params = {'networkDomainId': self._network_domain_to_network_domain_id( ex_network_domain)} response = self.connection.request_with_orgId_api_2( 'network/ipAddressList', params=params).object return self._to_ip_address_lists(response) def ex_get_ip_address_list(self, ex_network_domain, ex_ip_address_list_name): """ Get IP Address List by name in network domain specified >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # Get IP Address List by Name >>> ipaddresslist_list_by_name = driver.ex_get_ip_address_list( >>> ex_network_domain=my_network_domain, >>> ex_ip_address_list_name='My_IP_AddressList_1') >>> pprint(ipaddresslist_list_by_name) :param ex_network_domain: (required) The network domain or network domain ID in which ipaddresslist resides. :type ex_network_domain: :class:`NttCisNetworkDomain` or 'str' :param ex_ip_address_list_name: (required) Get 'IP Address List' by name :type ex_ip_address_list_name: :``str`` :return: a list of NttCisIpAddressList objects :rtype: ``list`` of :class:`NttCisIpAddressList` """ ip_address_lists = self.ex_list_ip_address_list(ex_network_domain) return list(filter(lambda x: x.name == ex_ip_address_list_name, ip_address_lists)) def ex_create_ip_address_list(self, ex_network_domain, name, description, ip_version, ip_address_collection, child_ip_address_list=None): """ Create IP Address List. IP Address list. >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.nttcis import NttCisIpAddress >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # IP Address collection >>> ipAddress_1 = NttCisIpAddress(begin='190.2.2.100') >>> ipAddress_2 = NttCisIpAddress(begin='190.2.2.106', end='190.2.2.108') >>> ipAddress_3 = NttCisIpAddress(begin='190.2.2.0', prefix_size='24') >>> ip_address_collection = [ipAddress_1, ipAddress_2, ipAddress_3] >>> >>> # Create IPAddressList >>> result = driver.ex_create_ip_address_list( >>> ex_network_domain=my_network_domain, >>> name='My_IP_AddressList_2', >>> ip_version='IPV4', >>> description='Test only', >>> ip_address_collection=ip_address_collection, >>> child_ip_address_list='08468e26-eeb3-4c3d-8ff2-5351fa6d8a04' >>> ) >>> >>> pprint(result) :param ex_network_domain: The network domain or network domain ID :type ex_network_domain: :class:`NttCisNetworkDomain` or 'str' :param name: IP Address List Name (required) :type name: :``str`` :param description: IP Address List Description (optional) :type description: :``str`` :param ip_version: IP Version of ip address (required) :type ip_version: :``str`` :param ip_address_collection: List of IP Address. At least one ipAddress element or one childIpAddressListId element must be provided. :type ip_address_collection: :``str`` :param child_ip_address_list: Child IP Address List or id to be included in this IP Address List. At least one ipAddress or one childIpAddressListId must be provided. :type child_ip_address_list: :class:'NttCisChildIpAddressList` or `str`` :return: a list of NttCisIpAddressList objects :rtype: ``list`` of :class:`NttCisIpAddressList` """ if (ip_address_collection is None and child_ip_address_list is None): raise ValueError("At least one ipAddress element or one " "childIpAddressListId element must be " "provided.") create_ip_address_list = ET.Element('createIpAddressList', {'xmlns': TYPES_URN}) ET.SubElement( create_ip_address_list, 'networkDomainId' ).text = self._network_domain_to_network_domain_id(ex_network_domain) ET.SubElement( create_ip_address_list, 'name' ).text = name ET.SubElement( create_ip_address_list, 'description' ).text = description ET.SubElement( create_ip_address_list, 'ipVersion' ).text = ip_version for ip in ip_address_collection: ip_address = ET.SubElement( create_ip_address_list, 'ipAddress', ) ip_address.set('begin', ip.begin) if ip.end: ip_address.set('end', ip.end) if ip.prefix_size: ip_address.set('prefixSize', ip.prefix_size) if child_ip_address_list is not None: ET.SubElement( create_ip_address_list, 'childIpAddressListId' ).text = \ self._child_ip_address_list_to_child_ip_address_list_id( child_ip_address_list) response = self.connection.request_with_orgId_api_2( 'network/createIpAddressList', method='POST', data=ET.tostring(create_ip_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_edit_ip_address_list(self, ex_ip_address_list, description=None, ip_address_collection=None, child_ip_address_lists=None): """ Edit IP Address List. IP Address list. Bear in mind you cannot add ip addresses to >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.NTTCIS import NttCisIpAddress >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # IP Address collection >>> ipAddress_1 = NttCisIpAddress(begin='190.2.2.100') >>> ipAddress_2 = NttCisIpAddress(begin='190.2.2.106', >>> end='190.2.2.108') >>> ipAddress_3 = NttCisIpAddress( >>> begin='190.2.2.0', prefix_size='24') >>> ip_address_collection = [ipAddress_1, ipAddress_2, ipAddress_3] >>> >>> # Edit IP Address List >>> ip_address_list_id = '5e7c323f-c885-4e4b-9a27-94c44217dbd3' >>> result = driver.ex_edit_ip_address_list( >>> ex_ip_address_list=ip_address_list_id, >>> description="Edit Test", >>> ip_address_collection=ip_address_collection, >>> child_ip_address_lists=None >>> ) >>> pprint(result) :param ex_ip_address_list: (required) IpAddressList object or IpAddressList ID :type ex_ip_address_list: :class:'NttCisIpAddressList' or ``str`` :param description: IP Address List Description :type description: :``str`` :param ip_address_collection: List of IP Address :type ip_address_collection: ''list'' of :class:'NttCisIpAddressList' :param child_ip_address_lists: Child IP Address List or id to be included in this IP Address List :type child_ip_address_lists: ``list`` of :class:'NttCisChildIpAddressList' or ``str`` :return: a list of NttCisIpAddressList objects :rtype: ``list`` of :class:`NttCisIpAddressList` """ edit_ip_address_list = ET.Element( 'editIpAddressList', {'xmlns': TYPES_URN, "id": self._ip_address_list_to_ip_address_list_id( ex_ip_address_list), 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance" }) if description is not None: if description != 'nil': ET.SubElement( edit_ip_address_list, 'description' ).text = description else: ET.SubElement(edit_ip_address_list, 'description', {'xsi:nil': 'true'}) if ip_address_collection is not None: for ip in ip_address_collection: ip_address = ET.SubElement( edit_ip_address_list, 'ipAddress', ) ip_address.set('begin', ip.begin) if ip.end: ip_address.set('end', ip.end) if ip.prefix_size: ip_address.set('prefixSize', ip.prefix_size) if child_ip_address_lists is not None: ET.SubElement( edit_ip_address_list, 'childIpAddressListId' ).text = self._child_ip_address_list_to_child_ip_address_list_id( child_ip_address_lists) else: ET.SubElement( edit_ip_address_list, 'childIpAddressListId', {'xsi:nil': 'true'} ) response = self.connection.request_with_orgId_api_2( 'network/editIpAddressList', method='POST', data=ET.tostring(edit_ip_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_ip_address_list(self, ex_ip_address_list): """ Delete IP Address List by ID >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> ip_address_list_id = '5e7c323f-c885-4e4b-9a27-94c44217dbd3' >>> result = driver.ex_delete_ip_address_list(ip_address_list_id) >>> pprint(result) :param ex_ip_address_list: IP Address List object or IP Address List ID (required) :type ex_ip_address_list: :class:'NttCisIpAddressList' or ``str`` :rtype: ``bool`` """ delete_ip_address_list = \ ET.Element('deleteIpAddressList', {'xmlns': TYPES_URN, 'id': self ._ip_address_list_to_ip_address_list_id( ex_ip_address_list)}) response = self.connection.request_with_orgId_api_2( 'network/deleteIpAddressList', method='POST', data=ET.tostring(delete_ip_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_list_portlist(self, ex_network_domain): """ List Portlist by network domain ID specified >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == >>> networkDomainName][0] >>> >>> # List portlist >>> portLists = driver.ex_list_portlist( >>> ex_network_domain=my_network_domain) >>> pprint(portLists) >>> :param ex_network_domain: The network domain or network domain ID :type ex_network_domain: :class:`NttCisNetworkDomain` or 'str' :return: a list of NttCisPortList objects :rtype: ``list`` of :class:`NttCisPortList` """ params = {'networkDomainId': self._network_domain_to_network_domain_id(ex_network_domain)} response = self.connection.request_with_orgId_api_2( 'network/portList', params=params).object return self._to_port_lists(response) def ex_get_portlist(self, ex_portlist_id): """ Get Port List >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get specific portlist by ID >>> portlist_id = '27dd8c66-80ff-496b-9f54-2a3da2fe679e' >>> portlist = driver.ex_get_portlist(portlist_id) >>> pprint(portlist) :param ex_portlist_id: The ex_port_list or ex_port_list ID :type ex_portlist_id: :class:`NttCisNetworkDomain` or 'str' :return: NttCisPortList object :rtype: :class:`NttCisPort` """ url_path = ('network/portList/%s' % ex_portlist_id) response = self.connection.request_with_orgId_api_2( url_path).object return self._to_port_list(response) def ex_create_portlist(self, ex_network_domain, name, description, port_collection, child_portlist_list=None): """ Create Port List. >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.nttcis import NttCisPort >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Get location >>> location = driver.ex_get_location_by_id(id='AU9') >>> >>> # Get network domain by location >>> networkDomainName = "Baas QA" >>> network_domains = driver.ex_list_network_domains(location=location) >>> my_network_domain = [d for d in network_domains if d.name == networkDomainName][0] >>> >>> # Port Collection >>> port_1 = DimensionDataPort(begin='1000') >>> port_2 = DimensionDataPort(begin='1001', end='1003') >>> port_collection = [port_1, port_2] >>> >>> # Create Port List >>> new_portlist = driver.ex_create_portlist( >>> ex_network_domain=my_network_domain, >>> name='MyPortListX', >>> description="Test only", >>> port_collection=port_collection, >>> child_portlist_list={'a9cd4984-6ff5-4f93-89ff-8618ab642bb9'} >>> ) >>> pprint(new_portlist) :param ex_network_domain: (required) The network domain in which to create PortList. Provide networkdomain object or its id. :type ex_network_domain: :``str`` :param name: Port List Name :type name: :``str`` :param description: IP Address List Description :type description: :``str`` :param port_collection: List of Port Address :type port_collection: :``str`` :param child_portlist_list: List of Child Portlist to be included in this Port List :type child_portlist_list: :``str`` or ''list of :class:'NttCisChildPortList' :return: result of operation :rtype: ``bool`` """ new_port_list = ET.Element('createPortList', {'xmlns': TYPES_URN}) ET.SubElement( new_port_list, 'networkDomainId' ).text = self._network_domain_to_network_domain_id(ex_network_domain) ET.SubElement( new_port_list, 'name' ).text = name ET.SubElement( new_port_list, 'description' ).text = description for port in port_collection: p = ET.SubElement( new_port_list, 'port' ) p.set('begin', port.begin) if port.end: p.set('end', port.end) if child_portlist_list is not None: for child in child_portlist_list: ET.SubElement( new_port_list, 'childPortListId' ).text = self._child_port_list_to_child_port_list_id(child) response = self.connection.request_with_orgId_api_2( 'network/createPortList', method='POST', data=ET.tostring(new_port_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_edit_portlist(self, ex_portlist, description=None, port_collection=None, child_portlist_list=None): """ Edit Port List. >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> from libcloud.common.NTTCIS import DimensionDataPort >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Port Collection >>> port_1 = DimensionDataPort(begin='4200') >>> port_2 = DimensionDataPort(begin='4201', end='4210') >>> port_collection = [port_1, port_2] >>> >>> # Edit Port List >>> editPortlist = driver.ex_get_portlist( '27dd8c66-80ff-496b-9f54-2a3da2fe679e') >>> >>> result = driver.ex_edit_portlist( >>> ex_portlist=editPortlist.id, >>> description="Make Changes in portlist", >>> port_collection=port_collection, >>> child_portlist_list={'a9cd4984-6ff5-4f93-89ff-8618ab642bb9'} >>> ) >>> pprint(result) :param ex_portlist: Port List to be edited (required) :type ex_portlist: :``str`` or :class:'DNttCisPortList' :param description: Port List Description :type description: :``str`` :param port_collection: List of Ports :type port_collection: :``str`` :param child_portlist_list: Child PortList to be included in this IP Address List :type child_portlist_list: :``list`` of :class'NttCisChildPortList' or ''str'' :return: a list of NttCisPortList objects :rtype: ``list`` of :class:`NttCisPortList` """ existing_port_address_list = ET.Element( 'editPortList', { "id": self._port_list_to_port_list_id(ex_portlist), 'xmlns': TYPES_URN, 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance" }) if description is not None: if description != 'nil': ET.SubElement( existing_port_address_list, 'description' ).text = description else: ET.SubElement(existing_port_address_list, "description", {"xsi:nil": "true"}) if port_collection is not None: for port in port_collection: p = ET.SubElement( existing_port_address_list, 'port' ) p.set('begin', port.begin) if port.end: p.set('end', port.end) if child_portlist_list is not None: for child in child_portlist_list: ET.SubElement( existing_port_address_list, 'childPortListId' ).text = self._child_port_list_to_child_port_list_id(child) else: ET.SubElement( existing_port_address_list, 'childPortListId', {'xsi:nil': 'true'} ) response = self.connection.request_with_orgId_api_2( 'network/editPortList', method='POST', data=ET.tostring(existing_port_address_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_portlist(self, ex_portlist): """ Delete Port List >>> from pprint import pprint >>> from libcloud.compute.types import Provider >>> from libcloud.compute.providers import get_driver >>> import libcloud.security >>> >>> # Get NTTC-CIS driver >>> libcloud.security.VERIFY_SSL_CERT = True >>> cls = get_driver(Provider.NTTCIS) >>> driver = cls('myusername','mypassword', region='dd-au') >>> >>> # Delete Port List >>> portlist_id = '157531ce-77d4-493c-866b-d3d3fc4a912a' >>> response = driver.ex_delete_portlist(portlist_id) >>> pprint(response) :param ex_portlist: Port List to be deleted :type ex_portlist: :``str`` or :class:'NttCisPortList' :rtype: ``bool`` """ delete_port_list = ET.Element( 'deletePortList', {'xmlns': TYPES_URN, 'id': self._port_list_to_port_list_id(ex_portlist)}) response = self.connection.request_with_orgId_api_2( 'network/deletePortList', method='POST', data=ET.tostring(delete_port_list)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_exchange_nic_vlans(self, nic_id_1, nic_id_2): """ Exchange NIC Vlans :param nic_id_1: Nic ID 1 :type nic_id_1: :``str`` :param nic_id_2: Nic ID 2 :type nic_id_2: :``str`` :rtype: ``bool`` """ exchange_elem = ET.Element( 'urn:exchangeNicVlans', { 'xmlns:urn': TYPES_URN, }) ET.SubElement(exchange_elem, 'urn:nicId1').text = nic_id_1 ET.SubElement(exchange_elem, 'urn:nicId2').text = nic_id_2 response = self.connection.request_with_orgId_api_2( 'server/exchangeNicVlans', method='POST', data=ET.tostring(exchange_elem)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_change_nic_network_adapter(self, nic_id, network_adapter_name): """ Change network adapter of a NIC on a cloud server :param nic_id: Nic ID :type nic_id: :``str`` :param network_adapter_name: Network adapter name :type network_adapter_name: :``str`` :rtype: ``bool`` """ change_elem = ET.Element( 'changeNetworkAdapter', { 'nicId': nic_id, 'xmlns': TYPES_URN }) ET.SubElement(change_elem, 'networkAdapter').text = \ network_adapter_name response = self.connection.request_with_orgId_api_2( 'server/changeNetworkAdapter', method='POST', data=ET.tostring(change_elem)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_node_uncustomized(self, name, image, ex_network_domain, ex_is_started=True, ex_description=None, ex_cluster_id=None, ex_cpu_specification=None, ex_memory_gb=None, ex_primary_nic_private_ipv4=None, ex_primary_nic_vlan=None, ex_primary_nic_network_adapter=None, ex_additional_nics=None, ex_disks=None, ex_tagid_value_pairs=None, ex_tagname_value_pairs=None ): """ This MCP 2.0 only function deploys a new Cloud Server from a CloudControl compatible Server Image, which does not utilize VMware Guest OS Customization process. Create Node in MCP2 Data Center :keyword name: (required) String with a name for this new node :type name: ``str`` :keyword image: (UUID of the Server Image being used as the target for the new Server deployment. The source Server Image (OS Image or Customer Image) must have osCustomization set to true. See Get/List OS Image(s) and Get/List Customer Image(s). :type image: :class:`NodeImage` or ``str`` :keyword ex_network_domain: (required) Network Domain or Network Domain ID to create the node :type ex_network_domain: :class:`NttCisNetworkDomain` or ``str`` :keyword ex_description: (optional) description for this node :type ex_description: ``str`` :keyword ex_cluster_id: (optional) For multiple cluster environments, it is possible to set a destination cluster for the new Customer Image. Note that performance of this function is optimal when either the Server cluster and destination are the same or when shared data storage is in place for the multiple clusters. :type ex_cluster_id: ``str`` :keyword ex_primary_nic_private_ipv4: Provide private IPv4. Ignore if ex_primary_nic_vlan is provided. Use one or the other. Not both. :type ex_primary_nic_private_ipv4: :``str`` :keyword ex_primary_nic_vlan: Provide VLAN for the node if ex_primary_nic_private_ipv4 NOT provided. One or the other. Not both. :type ex_primary_nic_vlan: :class: NttCisVlan or ``str`` :keyword ex_primary_nic_network_adapter: (Optional) Default value for the Operating System will be used if leave empty. Example: "E1000". :type ex_primary_nic_network_adapter: :``str`` :keyword ex_additional_nics: (optional) List :class:'NttCisNic' or None :type ex_additional_nics: ``list`` of :class:'NttCisNic' or ``str`` :keyword ex_memory_gb: (optional) The amount of memory in GB for the server Can be used to override the memory value inherited from the source Server Image. :type ex_memory_gb: ``int`` :keyword ex_cpu_specification: (optional) The spec of CPU to deploy :type ex_cpu_specification: :class:`NttCisServerCpuSpecification` :keyword ex_is_started: (required) Start server after creation. Default is set to true. :type ex_is_started: ``bool`` :keyword ex_disks: (optional) NttCis disks. Optional disk elements can be used to define the disk speed that each disk on the Server; inherited from the source Server Image will be deployed to. It is not necessary to include a diskelement for every disk; only those that you wish to set a disk speed value for. Note that scsiId 7 cannot be used.Up to 13 disks can be present in addition to the required OS disk on SCSI ID 0. Refer to https://docs.mcp-services.net/x/UwIu for disk :type ex_disks: List or tuple of :class:'NttCisServerDisk` :keyword ex_tagid_value_pairs: (Optional) up to 10 tag elements may be provided. A combination of tagById and tag name cannot be supplied in the same request. Note: ex_tagid_value_pairs and ex_tagname_value_pairs is mutually exclusive. Use one or other. :type ex_tagname_value_pairs: ``dict``. Value can be None. :keyword ex_tagname_value_pairs: (Optional) up to 10 tag elements may be provided. A combination of tagById and tag name cannot be supplied in the same request. Note: ex_tagid_value_pairs and ex_tagname_value_pairs is mutually exclusive. Use one or other. :type ex_tagname_value_pairs: ``dict```. :return: The newly created :class:`Node`. :rtype: :class:`Node` """ # Unsupported for version lower than 2.4 if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): raise Exception("This feature is NOT supported in " "earlier api version of 2.4") # Default start to true if input is invalid if not isinstance(ex_is_started, bool): ex_is_started = True print("Warning: ex_is_started input value is invalid. Default" "to True") server_uncustomized_elm = ET.Element('deployUncustomizedServer', {'xmlns': TYPES_URN}) ET.SubElement(server_uncustomized_elm, "name").text = name ET.SubElement(server_uncustomized_elm, "description").text = \ ex_description image_id = self._image_to_image_id(image) ET.SubElement(server_uncustomized_elm, "imageId").text = image_id if ex_cluster_id: dns_elm = ET.SubElement(server_uncustomized_elm, "primaryDns") dns_elm.text = ex_cluster_id if ex_is_started is not None: ET.SubElement(server_uncustomized_elm, "start").text = str( ex_is_started).lower() if ex_cpu_specification is not None: cpu = ET.SubElement(server_uncustomized_elm, "cpu") cpu.set('speed', ex_cpu_specification.performance) cpu.set('count', str(ex_cpu_specification.cpu_count)) cpu.set('coresPerSocket', str(ex_cpu_specification.cores_per_socket)) if ex_memory_gb is not None: ET.SubElement(server_uncustomized_elm, "memoryGb").text = \ str(ex_memory_gb) if (ex_primary_nic_private_ipv4 is None and ex_primary_nic_vlan is None): raise ValueError("Missing argument. Either " "ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "must be specified.") if (ex_primary_nic_private_ipv4 is not None and ex_primary_nic_vlan is not None): raise ValueError("Either ex_primary_nic_private_ipv4 or " "ex_primary_nic_vlan " "be specified. Not both.") network_elm = ET.SubElement(server_uncustomized_elm, "networkInfo") net_domain_id = self._network_domain_to_network_domain_id( ex_network_domain) network_elm.set('networkDomainId', net_domain_id) pri_nic = ET.SubElement(network_elm, 'primaryNic') if ex_primary_nic_private_ipv4 is not None: ET.SubElement(pri_nic, 'privateIpv4').text = ex_primary_nic_private_ipv4 if ex_primary_nic_vlan is not None: vlan_id = self._vlan_to_vlan_id(ex_primary_nic_vlan) ET.SubElement(pri_nic, 'vlanId').text = vlan_id if ex_primary_nic_network_adapter is not None: ET.SubElement(pri_nic, "networkAdapter").text = \ ex_primary_nic_network_adapter if isinstance(ex_additional_nics, (list, tuple)): for nic in ex_additional_nics: additional_nic = ET.SubElement(network_elm, 'additionalNic') if (nic.private_ip_v4 is None and nic.vlan is None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic.") if (nic.private_ip_v4 is not None and nic.vlan is not None): raise ValueError("Either a vlan or private_ip_v4 " "must be specified for each " "additional nic. Not both.") if nic.private_ip_v4 is not None: ET.SubElement(additional_nic, 'privateIpv4').text = nic.private_ip_v4 if nic.vlan is not None: vlan_id = self._vlan_to_vlan_id(nic.vlan) ET.SubElement(additional_nic, 'vlanId').text = vlan_id if nic.network_adapter_name is not None: ET.SubElement(additional_nic, "networkAdapter").text = \ nic.network_adapter_name elif ex_additional_nics is not None: raise TypeError( "ex_additional_NICs must be None or tuple/list") if isinstance(ex_disks, (list, tuple)): for disk in ex_disks: disk_elm = ET.SubElement(server_uncustomized_elm, 'disk') disk_elm.set('scsiId', disk.scsi_id) disk_elm.set('speed', disk.speed) elif ex_disks is not None: raise TypeError("ex_disks must be None or tuple/list") # tagid and tagname value pair should not co-exists if ex_tagid_value_pairs is not None and ex_tagname_value_pairs is \ not None: raise ValueError("ex_tagid_value_pairs and ex_tagname_value_pairs" "is mutually exclusive. Use one or the other.") # Tag by ID if ex_tagid_value_pairs is not None: if not isinstance(ex_tagid_value_pairs, dict): raise ValueError( "ex_tagid_value_pairs must be a dictionary." ) if sys.version_info[0] < 3: tagid_items = ex_tagid_value_pairs.iteritems() else: tagid_items = ex_tagid_value_pairs.items() for k, v in tagid_items: tag_elem = ET.SubElement(server_uncustomized_elm, 'tagById') ET.SubElement(tag_elem, 'tagKeyId').text = k if v is not None: ET.SubElement(tag_elem, 'value').text = v if ex_tagname_value_pairs is not None: if not isinstance(ex_tagname_value_pairs, dict): raise ValueError( "ex_tagname_value_pairs must be a dictionary" ) if sys.version_info[0] < 3: tags_items = ex_tagname_value_pairs.iteritems() else: tags_items = ex_tagname_value_pairs.items() for k, v in tags_items: tag_name_elem = ET.SubElement(server_uncustomized_elm, 'tag') ET.SubElement(tag_name_elem, 'tagKeyName').text = k if v is not None: ET.SubElement(tag_name_elem, 'value').text = v response = self.connection.request_with_orgId_api_2( 'server/deployUncustomizedServer', method='POST', data=ET.tostring(server_uncustomized_elm)).object node_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'serverId': node_id = info.get('value') new_node = self.ex_get_node_by_id(node_id) return new_node # DRS methods def ex_create_consistency_group(self, name, journal_size_gb, source_server_id, target_server_id, description=None): """ Create a consistency group :param name: Name of consistency group :type name: ``str`` :param journal_size_gb: Journal size in GB :type journal_size_gb: ``str`` :param source_server_id: Id of the server to copy :type source_server_id: ``str`` :param target_server_id: Id of the server to receive the copy :type: target_server_id: ``str`` :param description: (Optional) Description of consistency group :type: description: ``str`` :rtype: :class:`NttCisConsistencyGroup` """ consistency_group_elm = ET.Element('createConsistencyGroup', {'xmlns': TYPES_URN}) ET.SubElement(consistency_group_elm, "name").text = name if description is not None: ET.SubElement( consistency_group_elm, "description").text = description ET.SubElement( consistency_group_elm, "journalSizeGb").text = journal_size_gb server_pair = ET.SubElement(consistency_group_elm, "serverPair") ET.SubElement( server_pair, "sourceServerId").text = source_server_id ET.SubElement( server_pair, "targetServerId").text = target_server_id response = self.connection.request_with_orgId_api_2( "consistencyGroup/createConsistencyGroup", method="POST", data=ET.tostring(consistency_group_elm)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] @get_params def ex_list_consistency_groups(self, params={}): """ Functions takes a named parameter that must be one of the following :param params: A dictionary composed of one of the following keys and a value * target_data_center_id= * source_network_domain_id= * target_network_domain_id= * source_server_id= * target_server_id= * name= * state= * operation_status= * drs_infrastructure_status= :rtype: `list` of :class: `NttCisConsistencyGroup` """ response = self.connection.request_with_orgId_api_2( 'consistencyGroup/consistencyGroup', params=params).object cgs = self._to_consistency_groups(response) return cgs def ex_get_consistency_group(self, consistency_group_id): """ Retrieves a Consistency by it's id and is more efficient thatn listing all consistency groups and filtering that result. :param consistency_group_id: An id of a consistency group :type consistency_group_id: ``str`` :rtype: :class:`NttCisConsistencygroup` """ response = self.connection.request_with_orgId_api_2( "consistencyGroup/consistencyGroup/%s" % consistency_group_id ).object cg = self._to_process(response) return cg def ex_list_consistency_group_snapshots(self, consistency_group_id, create_time_min=None, create_time_max=None): """ Optional parameters identify the date of creation of Consistency Group snapshots in *XML Schema (XSD) date time format. Best used as a combination of createTime.MIN and createTime.MAX. If neither is provided then all snapshots up to the possible maximum of 1014 will be returned. If MIN is provided by itself, all snapshots between the time specified by MIN and the point in time of execution will be returned. If MAX is provided by itself, then all snapshots up to that point in time (up to the maximum number of 1014) will be returned. MIN and MAX are inclusive for this API function :param consistency_group_id: The id of consistency group :type consistency_group_id: ``str`` :param create_time_min: (Optional) in form YYYY-MM-DDT00:00.00.00Z or substitute time offset for Z, i.e, -05:00 :type create_time_min: ``str`` :param create_time_max: (Optional) in form YYYY-MM-DDT00:00:00.000Z or substitute time offset for Z, i.e, -05:00 :type create_time_max: ``str`` :rtype: `list` of :class:`NttCisSnapshots` """ if create_time_min is None and create_time_max is None: params = {"consistencyGroupId": consistency_group_id} elif create_time_min and create_time_max: params = {"consistencyGroupId": consistency_group_id, "createTime.MIN": create_time_min, "createTime.MAX": create_time_max } elif create_time_min or create_time_max: if create_time_max is not None: params = {"consistencyGroupId": consistency_group_id, "createTime.MAX": create_time_max } elif create_time_min is not None: params = {"consistencyGroupId": consistency_group_id, "createTime.MIN": create_time_min } paged_result = self.connection.request_with_orgId_api_2( 'consistencyGroup/snapshot', method='GET', params=params ).object snapshots = self._to_process(paged_result) return snapshots def ex_expand_journal(self, consistency_group_id, size_gb): """ Expand the consistency group's journhal size in 100Gb increments. :param consistency_group_id: The consistency group's UUID :type consistency_group_id: ``str`` :param size_gb: Gb in 100 Gb increments :type size_gb: ``str`` :return: True if response_code contains either 'IN_PROGRESS' or 'OK' otherwise False :rtype: ``bool`` """ expand_elm = ET.Element("expandJournal", {"id": consistency_group_id, "xmlns": TYPES_URN}) ET.SubElement(expand_elm, "sizeGb").text = size_gb response = self.connection.request_with_orgId_api_2( "consistencyGroup/expandJournal", method="POST", data=ET.tostring(expand_elm)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_start_drs_failover_preview(self, consistency_group_id, snapshot_id): """ Brings a Consistency Group into PREVIEWING_SNAPSHOT mode. :param consistency_group_id: Id of the Consistency Group to put into PRIEVEW_MODE :type consistency_group_id: ``str`` :param snapshot_id: Id of the Snapshot to preview :type snapshot_id: ``str`` :return: True if response_code contains either 'IN_PROGRESS' or 'OK' otherwise False :rtype: ``bool`` """ preview_elm = ET.Element("startPreviewSnapshot", {"consistencyGroupId": consistency_group_id, "xmlns": TYPES_URN }) ET.SubElement(preview_elm, "snapshotId").text = snapshot_id response = self.connection.request_with_orgId_api_2( "consistencyGroup/startPreviewSnapshot", method="POST", data=ET.tostring(preview_elm)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_stop_drs_failover_preview(self, consistency_group_id): """ Takes a Consistency Group out of PREVIEW_MODE and back to DRS_MODE :param consistency_group_id: Consistency Group's Id :type ``str`` :return: True if response_code contains either 'IN_PROGRESS' or 'OK' otherwise False :rtype: ``bool`` """ preview_elm = ET.Element("stopPreviewSnapshot", {"consistencyGroupId": consistency_group_id, "xmlns": TYPES_URN}) response = self.connection.request_with_orgId_api_2( "consistencyGroup/stopPreviewSnapshot", method="POST", data=ET.tostring(preview_elm)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_initiate_drs_failover(self, consistency_group_id): """ This method is irreversible. It will failover the Consistency Group while removing it as well. :param consistency_group_id: Consistency Group's Id to failover :type consistency_group_id: ``str`` :return: True if response_code contains either IN_PROGRESS' or 'OK' otherwise False :rtype: ``bool`` """ failover_elm = ET.Element("initiateFailover", {"consistencyGroupId": consistency_group_id, "xmlns": TYPES_URN}) response = self.connection.request_with_orgId_api_2( "consistencyGroup/initiateFailover", method="POST", data=ET.tostring(failover_elm)).object response_code = findtext(response, "responseCode", TYPES_URN) return response_code in ["IN_PROGRESS", "OK"] def ex_delete_consistency_group(self, consistency_group_id): """ Delete's a Consistency Group :param consistency_group_id: Id of Consistency Group to delete :type ``str`` :return: True if response_code contains either IN_PROGRESS' or 'OK' otherwise False :rtype: ``bool`` """ delete_elm = ET.Element("deleteConsistencyGroup", {"id": consistency_group_id, "xmlns": TYPES_URN}) response = self.connection.request_with_orgId_api_2( "consistencyGroup/deleteConsistencyGroup", method="POST", data=ET.tostring(delete_elm)).object response_code = findtext(response, "responseCode", TYPES_URN) return response_code in ["IN_PROGRESS", "OK"] def _to_consistency_groups(self, object): cgs = findall(object, 'consistencyGroup', TYPES_URN) return [self._to_process(el) for el in cgs] def _to_drs_snapshots(self, object): snapshots = [] for element in object.findall(fixxpath("snapshot", TYPES_URN)): snapshots.append(self._to_process(element)) return snapshots def _to_process(self, element): return process_xml(ET.tostring(element)) def _format_csv(self, http_response): text = http_response.read() lines = str.splitlines(ensure_string(text)) return [line.split(',') for line in lines] @staticmethod def _get_tagging_asset_type(asset): objecttype = type(asset) if objecttype.__name__ in OBJECT_TO_TAGGING_ASSET_TYPE_MAP: return OBJECT_TO_TAGGING_ASSET_TYPE_MAP[objecttype.__name__] raise TypeError("Asset type %s cannot be tagged" % objecttype.__name__) def _list_nodes_single_page(self, params={}): nodes = self.connection.request_with_orgId_api_2( 'server/server', params=params).object return nodes def _to_tags(self, object): tags = [] for element in object.findall(fixxpath('tag', TYPES_URN)): tags.append(self._to_tag(element)) return tags def _to_tag(self, element): tag_key = self._to_tag_key(element, from_tag_api=True) return NttCisTag( asset_type=findtext(element, 'assetType', TYPES_URN), asset_id=findtext(element, 'assetId', TYPES_URN), asset_name=findtext(element, 'assetName', TYPES_URN), datacenter=findtext(element, 'datacenterId', TYPES_URN), key=tag_key, value=findtext(element, 'value', TYPES_URN) ) def _to_tag_keys(self, object): keys = [] for element in object.findall(fixxpath('tagKey', TYPES_URN)): keys.append(self._to_tag_key(element)) return keys def _to_tag_key(self, element, from_tag_api=False): if from_tag_api: id = findtext(element, 'tagKeyId', TYPES_URN) name = findtext(element, 'tagKeyName', TYPES_URN) else: id = element.get('id') name = findtext(element, 'name', TYPES_URN) return NttCisTagKey( id=id, name=name, description=findtext(element, 'description', TYPES_URN), value_required=self._str2bool( findtext(element, 'valueRequired', TYPES_URN) ), display_on_report=self._str2bool( findtext(element, 'displayOnReport', TYPES_URN) ) ) def _to_images(self, object, el_name='osImage'): images = [] locations = self.list_locations() # The CloudControl API will return all images # in the current geographic region (even ones in # datacenters the user's organisation does not have access to) # # We therefore need to filter out those images (since we can't # get a NodeLocation for them) location_ids = set(location.id for location in locations) for element in object.findall(fixxpath(el_name, TYPES_URN)): location_id = element.get('datacenterId') if location_id in location_ids: images.append(self._to_image(element, locations)) return images def _to_image(self, element, locations=None): location_id = element.get('datacenterId') if locations is None: locations = self.list_locations(location_id) location = [loc for loc in locations if loc.id == location_id][0] cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN))) if LooseVersion(self.connection.active_api_version) > LooseVersion( '2.3'): os_el = element.find(fixxpath('guest/operatingSystem', TYPES_URN)) else: os_el = element.find(fixxpath('operatingSystem', TYPES_URN)) if element.tag.endswith('customerImage'): is_customer_image = True else: is_customer_image = False extra = { 'description': findtext(element, 'description', TYPES_URN), 'OS_type': os_el.get('family'), 'OS_displayName': os_el.get('displayName'), 'cpu': cpu_spec, 'memoryGb': findtext(element, 'memoryGb', TYPES_URN), 'osImageKey': findtext(element, 'osImageKey', TYPES_URN), 'created': findtext(element, 'createTime', TYPES_URN), 'location': location, 'isCustomerImage': is_customer_image } return NodeImage(id=element.get('id'), name=str(findtext(element, 'name', TYPES_URN)), extra=extra, driver=self.connection.driver) def _to_nat_rules(self, object, network_domain): rules = [] for element in findall(object, 'natRule', TYPES_URN): rules.append( self._to_nat_rule(element, network_domain)) return rules def _to_nat_rule(self, element, network_domain): return NttCisNatRule( id=element.get('id'), network_domain=network_domain, internal_ip=findtext(element, 'internalIp', TYPES_URN), external_ip=findtext(element, 'externalIp', TYPES_URN), status=findtext(element, 'state', TYPES_URN)) def _to_anti_affinity_rules(self, object): rules = [] for element in findall(object, 'antiAffinityRule', TYPES_URN): rules.append( self._to_anti_affinity_rule(element)) return rules def _to_anti_affinity_rule(self, element): node_list = [] for node in findall(element, 'serverSummary', TYPES_URN): node_list.append(node.get('id')) return NttCisAntiAffinityRule( id=element.get('id'), node_list=node_list ) def _to_firewall_rules(self, object, network_domain): rules = [] locations = self.list_locations() for element in findall(object, 'firewallRule', TYPES_URN): rules.append( self._to_firewall_rule(element, locations, network_domain)) return rules def _to_firewall_rule(self, element, locations, network_domain): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] # For future dynamic rule creation # return process_xml(ET.tostring(element)) return NttCisFirewallRule( id=element.get('id'), network_domain=network_domain, name=findtext(element, 'name', TYPES_URN), action=findtext(element, 'action', TYPES_URN), ip_version=findtext(element, 'ipVersion', TYPES_URN), protocol=findtext(element, 'protocol', TYPES_URN), enabled=findtext(element, 'enabled', TYPES_URN), source=self._to_firewall_address( element.find(fixxpath('source', TYPES_URN))), destination=self._to_firewall_address( element.find(fixxpath('destination', TYPES_URN))), location=location, status=findtext(element, 'state', TYPES_URN)) def _to_firewall_address(self, element): ip = element.find(fixxpath('ip', TYPES_URN)) port = element.find(fixxpath('port', TYPES_URN)) port_list = element.find(fixxpath('portList', TYPES_URN)) address_list = element.find(fixxpath('ipAddressList', TYPES_URN)) if address_list is None: return NttCisFirewallAddress( any_ip=ip.get('address') == 'ANY', ip_address=ip.get('address'), ip_prefix_size=ip.get('prefixSize'), port_begin=port.get('begin') if port is not None else None, port_end=port.get('end') if port is not None else None, port_list_id=port_list.get('id', None) if port_list is not None else None, address_list_id=address_list.get('id') if address_list is not None else None) else: return NttCisFirewallAddress( any_ip=False, ip_address=None, ip_prefix_size=None, port_begin=None, port_end=None, port_list_id=port_list.get('id', None) if port_list is not None else None, address_list_id=address_list.get('id') if address_list is not None else None) def _to_ip_blocks(self, object): blocks = [] locations = self.list_locations() for element in findall(object, 'publicIpBlock', TYPES_URN): blocks.append(self._to_ip_block(element, locations)) return blocks def _to_ip_block(self, element, locations): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] return NttCisPublicIpBlock( id=element.get('id'), network_domain=self.ex_get_network_domain( findtext(element, 'networkDomainId', TYPES_URN) ), base_ip=findtext(element, 'baseIp', TYPES_URN), size=findtext(element, 'size', TYPES_URN), location=location, status=findtext(element, 'state', TYPES_URN)) def _to_networks(self, object): networks = [] locations = self.list_locations() for element in findall(object, 'network', NETWORK_NS): networks.append(self._to_network(element, locations)) return networks def _to_network(self, element, locations): multicast = False if findtext(element, 'multicast', NETWORK_NS) == 'true': multicast = True status = self._to_status(element.find(fixxpath('status', NETWORK_NS))) location_id = findtext(element, 'location', NETWORK_NS) location = list(filter(lambda x: x.id == location_id, locations))[0] return NttCisNetwork( id=findtext(element, 'id', NETWORK_NS), name=findtext(element, 'name', NETWORK_NS), description=findtext(element, 'description', NETWORK_NS), location=location, private_net=findtext(element, 'privateNet', NETWORK_NS), multicast=multicast, status=status) def _to_network_domains(self, object): network_domains = [] locations = self.list_locations() for element in findall(object, 'networkDomain', TYPES_URN): network_domains.append(self._to_network_domain( element, locations)) return network_domains def _to_network_domain(self, element, locations): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] plan = findtext(element, 'type', TYPES_URN) if plan == 'ESSENTIALS': plan_type = NetworkDomainServicePlan.ESSENTIALS else: plan_type = NetworkDomainServicePlan.ADVANCED return NttCisNetworkDomain( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), plan=plan_type, location=location, status=findtext(element, 'state', TYPES_URN)) def _to_vlans(self, object): vlans = [] locations = self.list_locations() for element in findall(object, 'vlan', TYPES_URN): vlans.append(self._to_vlan(element, locations=locations)) return vlans def _to_vlan(self, element, locations): location_id = element.get('datacenterId') location = list(filter(lambda x: x.id == location_id, locations))[0] ip_range = element.find(fixxpath('privateIpv4Range', TYPES_URN)) ip6_range = element.find(fixxpath('ipv6Range', TYPES_URN)) network_domain_el = element.find( fixxpath('networkDomain', TYPES_URN)) network_domain = self.ex_get_network_domain( network_domain_el.get('id')) return NttCisVlan( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), network_domain=network_domain, private_ipv4_range_address=ip_range.get('address'), private_ipv4_range_size=int(ip_range.get('prefixSize')), ipv6_range_address=ip6_range.get('address'), ipv6_range_size=int(ip6_range.get('prefixSize')), ipv4_gateway=findtext( element, 'ipv4GatewayAddress', TYPES_URN), ipv6_gateway=findtext( element, 'ipv6GatewayAddress', TYPES_URN), location=location, status=findtext(element, 'state', TYPES_URN)) def _to_locations(self, object): locations = [] for element in object.findall(fixxpath('datacenter', TYPES_URN)): locations.append(self._to_location(element)) return locations def _to_location(self, element): loc = NodeLocation(id=element.get('id'), name=findtext(element, 'displayName', TYPES_URN), country=findtext(element, 'country', TYPES_URN), driver=self) return loc def _to_cpu_spec(self, element): return NttCisServerCpuSpecification( cpu_count=int(element.get('count')), cores_per_socket=int(element.get('coresPerSocket')), performance=element.get('speed')) def _to_vmware_tools(self, element): status = None if hasattr(element, 'runningStatus'): status = element.get('runningStatus') version_status = None if hasattr(element, 'version_status'): version_status = element.get('version_status') api_version = None if hasattr(element, 'apiVersion'): api_version = element.get('apiVersion') return NttCisServerVMWareTools( status=status, version_status=version_status, api_version=api_version) def _to_scsi_controllers(self, elements): return NttCisScsiController(id=elements.get('id'), adapter_type=elements.get('adapterType'), bus_number=elements.get('busNumber'), state=elements.get('state')) def _to_disks(self, object): disk_elements = object.findall(fixxpath('disk', TYPES_URN)) return [self._to_disk(el) for el in disk_elements] def _to_disk(self, element): return NttCisServerDisk( id=element.get('id'), scsi_id=int(element.get('scsiId')), size_gb=int(element.get('sizeGb')), speed=element.get('speed'), state=element.get('state') ) def _to_snapshots(self, object): """ Takes an xml object and gathers indivicual elements :param object: XML data :return: list of dictionaries with keys id start_time end_time expiry_time type of snapshot state """ snapshot_elements = object.findall(fixxpath('snapshot', TYPES_URN)) return [self._to_snapshot(el) for el in snapshot_elements] def _to_snapshot(self, element): return {'id': element.get('id'), 'start_time': findtext(element, 'startTime', TYPES_URN), 'end_time': findtext(element, 'endTime', TYPES_URN), 'expiry_time': findtext(element, 'expiryTime', TYPES_URN), 'type': findtext(element, 'type', TYPES_URN), 'state': findtext(element, 'state', TYPES_URN), } def _to_ipv4_addresses(self, object): ipv4_address_elements = object.findall(fixxpath('ipv4', TYPES_URN)) return [self._to_ipv4_6_address(el) for el in ipv4_address_elements] def _to_ipv6_addresses(self, object): ipv6_address_elements = object.findall( fixxpath('reservedIpv6Address', TYPES_URN)) return [self._to_ipv4_6_address(el) for el in ipv6_address_elements] def _to_ipv4_6_address(self, element): return NttCisReservedIpAddress( element.get('datacenterId'), element.get('exclusive'), findtext(element, 'vlanId', TYPES_URN), findtext(element, 'ipAddress', TYPES_URN), description=findtext(element, 'description', TYPES_URN),) def _to_windows(self, object): snapshot_window_elements = object.findall( fixxpath('snapshotWindow', TYPES_URN)) return [self._to_window(el) for el in snapshot_window_elements] def _to_window(self, element): return {'id': element.get('id'), 'day_of_week': element.get('dayOfWeek'), 'start_hour': element.get('startHour'), 'availability_status': element.get('availabilityStatus')} def _to_nodes(self, object): node_elements = object.findall(fixxpath('server', TYPES_URN)) return [self._to_node(el) for el in node_elements] def _to_node(self, element): # Get all information at once and process in common/nttcis # Below, future to dynamically generate classes # return process_xml(ET.tostring(element)) started = findtext(element, 'started', TYPES_URN) status = self._to_status(element.find(fixxpath('progress', TYPES_URN))) dd_state = findtext(element, 'state', TYPES_URN) node_state = self._get_node_state(dd_state, started, status.action) has_network_info \ = element.find(fixxpath('networkInfo', TYPES_URN)) is not None cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN))) has_snapshot = element.find(fixxpath('snapshotService', TYPES_URN)) is not None has_scsi = element.find(fixxpath('scsiController', TYPES_URN)) is not None has_sata = element.find(fixxpath('sataController', TYPES_URN)) is not None has_ide = element.find(fixxpath('ideController')) is not None scsi_controllers = [] disks = [] if has_scsi: scsi_controllers.append( self._to_scsi_controllers(element.find(fixxpath( 'scsiController', TYPES_URN)))) for scsi in element.findall(fixxpath('scsiController', TYPES_URN)): disks.extend(self._to_disks(scsi)) if has_sata: for sata in element.findall(fixxpath('sataController', TYPES_URN)): disks.extend(self._to_disks(sata)) if has_ide: for ide in element.findall(fixxpath('ideController', TYPES_URN)): disks.extend(self._to_snapshot(ide)) # Vmware Tools # Version 2.3 or earlier if LooseVersion(self.connection.active_api_version) < LooseVersion( '2.4'): vmware_tools = self._to_vmware_tools( element.find(fixxpath('vmwareTools', TYPES_URN))) operation_system = element.find(fixxpath( 'operatingSystem', TYPES_URN)) # Version 2.4 or later else: # vmtools_elm = fixxpath('guest/vmTools', TYPES_URN) vmtools_elm = element.find(fixxpath('guest/vmTools', TYPES_URN)) if vmtools_elm is not None: vmware_tools = self._to_vmware_tools(vmtools_elm) else: vmware_tools = NttCisServerVMWareTools( status=None, version_status=None, api_version=None) operation_system = element.find(fixxpath( 'guest/operatingSystem', TYPES_URN)) extra = { 'description': findtext(element, 'description', TYPES_URN), 'sourceImageId': findtext(element, 'sourceImageId', TYPES_URN), 'networkId': findtext(element, 'networkId', TYPES_URN), 'networkDomainId': element.find(fixxpath('networkInfo', TYPES_URN)) .get('networkDomainId') if has_network_info else None, 'datacenterId': element.get('datacenterId'), 'deployedTime': findtext(element, 'createTime', TYPES_URN), 'window': (element.find(fixxpath('snapshotService/window', TYPES_URN)).get('dayOfWeek'), element.find(fixxpath('snapshotService/window', TYPES_URN)).get('startHour')) if has_snapshot else None, 'cpu': cpu_spec, 'memoryMb': int(findtext(element, 'memoryGb', TYPES_URN)) * 1024, 'OS_id': operation_system.get('id'), 'OS_type': operation_system.get('family'), 'OS_displayName': operation_system.get('displayName'), 'status': status, 'scsi_controller': scsi_controllers, 'disks': disks, 'vmWareTools': vmware_tools } public_ip = findtext(element, 'publicIpAddress', TYPES_URN) private_ip = element.find( fixxpath('networkInfo/primaryNic', TYPES_URN)) \ .get('privateIpv4') \ if has_network_info else \ element.find(fixxpath('nic', TYPES_URN)).get('privateIpv4') extra['ipv6'] = element.find( fixxpath('networkInfo/primaryNic', TYPES_URN)) \ .get('ipv6') \ if has_network_info else \ element.find(fixxpath('nic', TYPES_URN)).get('ipv6') n = Node(id=element.get('id'), name=findtext(element, 'name', TYPES_URN), state=node_state, public_ips=[public_ip] if public_ip is not None else [], private_ips=[private_ip] if private_ip is not None else [], size=self.list_sizes()[0], image=NodeImage(extra['sourceImageId'], extra['OS_displayName'], self.connection.driver), driver=self.connection.driver, extra=extra) return n def _to_status(self, element): if element is None: return NttCisStatus() s = NttCisStatus(action=findtext(element, 'action', TYPES_URN), request_time=findtext(element, 'requestTime', TYPES_URN), user_name=findtext(element, 'userName', TYPES_URN), number_of_steps=findtext(element, 'numberOfSteps', TYPES_URN), step_name=findtext(element, 'step/name', TYPES_URN), step_number=findtext(element, 'step_number', TYPES_URN), step_percent_complete=findtext(element, 'step/percentComplete', TYPES_URN), failure_reason=findtext(element, 'failureReason', TYPES_URN)) return s def _to_ip_address_lists(self, object): ip_address_lists = [] for element in findall(object, 'ipAddressList', TYPES_URN): ip_address_lists.append(self._to_ip_address_list(element)) return ip_address_lists def _to_ip_address_list(self, element): ipAddresses = [] for ip in findall(element, 'ipAddress', TYPES_URN): ipAddresses.append(self._to_ip_address(ip)) child_ip_address_lists = [] for child_ip_list in findall(element, 'childIpAddressList', TYPES_URN): child_ip_address_lists.append(self ._to_child_ip_list(child_ip_list)) return NttCisIpAddressList( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), ip_version=findtext(element, 'ipVersion', TYPES_URN), ip_address_collection=ipAddresses, state=findtext(element, 'state', TYPES_URN), create_time=findtext(element, 'createTime', TYPES_URN), child_ip_address_lists=child_ip_address_lists ) def _to_child_ip_list(self, element): return NttCisChildIpAddressList( id=element.get('id'), name=element.get('name') ) def _to_ip_address(self, element): return NttCisIpAddress( begin=element.get('begin'), end=element.get('end'), prefix_size=element.get('prefixSize') ) def _to_port_lists(self, object): port_lists = [] for element in findall(object, 'portList', TYPES_URN): port_lists.append(self._to_port_list(element)) return port_lists def _to_port_list(self, element): ports = [] for port in findall(element, 'port', TYPES_URN): ports.append(self._to_port(element=port)) child_portlist_list = [] for child in findall(element, 'childPortList', TYPES_URN): child_portlist_list.append( self._to_child_port_list(element=child)) return NttCisPortList( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), description=findtext(element, 'description', TYPES_URN), port_collection=ports, child_portlist_list=child_portlist_list, state=findtext(element, 'state', TYPES_URN), create_time=findtext(element, 'createTime', TYPES_URN) ) def _image_needs_auth(self, image): if not isinstance(image, NodeImage): image = self.ex_get_image_by_id(image) if image.extra['isCustomerImage'] and image.extra['OS_type'] == 'UNIX': return False return True @staticmethod def _to_port(element): return NttCisPort( begin=element.get('begin'), end=element.get('end') ) @staticmethod def _to_child_port_list(element): return NttCisChildPortList( id=element.get('id'), name=element.get('name') ) @staticmethod def _get_node_state(state, started, action): try: return NODE_STATE_MAP[(state, started, action)] except KeyError: if started == 'true': return NodeState.RUNNING else: return NodeState.TERMINATED @staticmethod def _node_to_node_id(node): return dd_object_to_id(node, Node) @staticmethod def _location_to_location_id(location): return dd_object_to_id(location, NodeLocation) @staticmethod def _vlan_to_vlan_id(vlan): return dd_object_to_id(vlan, NttCisVlan) @staticmethod def _image_to_image_id(image): return dd_object_to_id(image, NodeImage) @staticmethod def _network_to_network_id(network): return dd_object_to_id(network, NttCisNetwork) @staticmethod def _anti_affinity_rule_to_anti_affinity_rule_id(rule): return dd_object_to_id(rule, NttCisAntiAffinityRule) @staticmethod def _network_domain_to_network_domain_id(network_domain): return dd_object_to_id(network_domain, NttCisNetworkDomain) @staticmethod def _tag_key_to_tag_key_id(tag_key): return dd_object_to_id(tag_key, NttCisTagKey) @staticmethod def _tag_key_to_tag_key_name(tag_key): return dd_object_to_id(tag_key, NttCisTagKey, id_value='name') @staticmethod def _ip_address_list_to_ip_address_list_id(ip_addr_list): return dd_object_to_id(ip_addr_list, NttCisIpAddressList, id_value='id') @staticmethod def _child_ip_address_list_to_child_ip_address_list_id(child_ip_addr_list): return dd_object_to_id(child_ip_addr_list, NttCisChildIpAddressList, id_value='id') @staticmethod def _port_list_to_port_list_id(port_list): return dd_object_to_id(port_list, NttCisPortList, id_value='id') @staticmethod def _child_port_list_to_child_port_list_id(child_port_list): return dd_object_to_id(child_port_list, NttCisChildPortList, id_value='id') @staticmethod def _str2bool(string): return string.lower() in ("true") apache-libcloud-2.8.0/libcloud/compute/drivers/onapp.py0000664000175000017500000004016713570310635023054 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json from libcloud.utils.py3 import httplib from libcloud.utils.networking import is_private_subnet from libcloud.common.onapp import OnAppConnection from libcloud.compute.base import Node, NodeDriver, NodeImage, KeyPair from libcloud.compute.providers import Provider __all__ = [ "OnAppNodeDriver" ] """ Define the extra dictionary for specific resources """ RESOURCE_EXTRA_ATTRIBUTES_MAP = { "node": { "add_to_marketplace": { "key_name": "add_to_marketplace", "transform_func": bool }, "admin_note": { "key_name": "admin_note", "transform_func": str }, "allow_resize_without_reboot": { "key_name": "allow_resize_without_reboot", "transform_func": bool }, "allowed_hot_migrate": { "key_name": "allowed_hot_migrate", "transform_func": bool }, "allowed_swap": { "key_name": "allowed_swap", "transform_func": bool }, "booted": { "key_name": "booted", "transform_func": bool }, "built": { "key_name": "built", "transform_func": bool }, "cpu_priority": { "key_name": "cpu_priority", "transform_func": int }, "cpu_shares": { "key_name": "cpu_shares", "transform_func": int }, "cpu_sockets": { "key_name": "cpu_sockets", "transform_func": int }, "cpu_threads": { "key_name": "cpu_threads", "transform_func": int }, "cpu_units": { "key_name": "cpu_units", "transform_func": int }, "cpus": { "key_name": "cpus", "transform_func": int }, "created_at": { "key_name": "created_at", "transform_func": str }, "customer_network_id": { "key_name": "customer_network_id", "transform_func": str }, "deleted_at": { "key_name": "deleted_at", "transform_func": str }, "edge_server_type": { "key_name": "edge_server_type", "transform_func": str }, "enable_autoscale": { "key_name": "enable_autoscale", "transform_func": bool }, "enable_monitis": { "key_name": "enable_monitis", "transform_func": bool }, "firewall_notrack": { "key_name": "firewall_notrack", "transform_func": bool }, "hostname": { "key_name": "hostname", "transform_func": str }, "hypervisor_id": { "key_name": "hypervisor_id", "transform_func": int }, "id": { "key_name": "id", "transform_func": int }, "initial_root_password": { "key_name": "initial_root_password", "transform_func": str }, "initial_root_password_encrypted": { "key_name": "initial_root_password_encrypted", "transform_func": bool }, "local_remote_access_ip_address": { "key_name": "local_remote_access_ip_address", "transform_func": str }, "local_remote_access_port": { "key_name": "local_remote_access_port", "transform_func": int }, "locked": { "key_name": "locked", "transform_func": bool }, "memory": { "key_name": "memory", "transform_func": int }, "min_disk_size": { "key_name": "min_disk_size", "transform_func": int }, "monthly_bandwidth_used": { "key_name": "monthly_bandwidth_used", "transform_func": int }, "note": { "key_name": "note", "transform_func": str }, "operating_system": { "key_name": "operating_system", "transform_func": str }, "operating_system_distro": { "key_name": "operating_system_distro", "transform_func": str }, "preferred_hvs": { "key_name": "preferred_hvs", "transform_func": list }, "price_per_hour": { "key_name": "price_per_hour", "transform_func": float }, "price_per_hour_powered_off": { "key_name": "price_per_hour_powered_off", "transform_func": float }, "recovery_mode": { "key_name": "recovery_mode", "transform_func": bool }, "remote_access_password": { "key_name": "remote_access_password", "transform_func": str }, "service_password": { "key_name": "service_password", "transform_func": str }, "state": { "key_name": "state", "transform_func": str }, "storage_server_type": { "key_name": "storage_server_type", "transform_func": str }, "strict_virtual_machine_id": { "key_name": "strict_virtual_machine_id", "transform_func": str }, "support_incremental_backups": { "key_name": "support_incremental_backups", "transform_func": bool }, "suspended": { "key_name": "suspended", "transform_func": bool }, "template_id": { "key_name": "template_id", "transform_func": int }, "template_label": { "key_name": "template_label", "transform_func": str }, "total_disk_size": { "key_name": "total_disk_size", "transform_func": int }, "updated_at": { "key_name": "updated_at", "transform_func": str }, "user_id": { "key_name": "user_id", "transform_func": int }, "vip": { "key_name": "vip", "transform_func": bool }, "xen_id": { "key_name": "xen_id", "transform_func": int } } } class OnAppNodeDriver(NodeDriver): """ Base OnApp node driver. """ connectionCls = OnAppConnection type = Provider.ONAPP name = 'OnApp' website = 'http://onapp.com/' def create_node(self, name, ex_memory, ex_cpus, ex_cpu_shares, ex_hostname, ex_template_id, ex_primary_disk_size, ex_swap_disk_size, ex_required_virtual_machine_build=1, ex_required_ip_address_assignment=1, **kwargs): """ Add a VS :param kwargs: All keyword arguments to create a VS :type kwargs: ``dict`` :rtype: :class:`OnAppNode` """ server_params = dict( label=name, memory=ex_memory, cpus=ex_cpus, cpu_shares=ex_cpu_shares, hostname=ex_hostname, template_id=ex_template_id, primary_disk_size=ex_primary_disk_size, swap_disk_size=ex_swap_disk_size, required_virtual_machine_build=ex_required_virtual_machine_build, required_ip_address_assignment=ex_required_ip_address_assignment, rate_limit=kwargs.get("rate_limit") ) server_params.update(OnAppNodeDriver._create_args_to_params(**kwargs)) data = json.dumps({"virtual_machine": server_params}) response = self.connection.request( "/virtual_machines.json", data=data, headers={ "Content-type": "application/json"}, method="POST") return self._to_node(response.object["virtual_machine"]) def destroy_node(self, node, ex_convert_last_backup=0, ex_destroy_all_backups=0): """ Delete a VS :param node: OnApp node :type node: :class: `OnAppNode` :param convert_last_backup: set 1 to convert the last VS's backup to template, otherwise set 0 :type convert_last_backup: ``int`` :param destroy_all_backups: set 1 to destroy all existing backups of this VS, otherwise set 0 :type destroy_all_backups: ``int`` """ server_params = { "convert_last_backup": ex_convert_last_backup, "destroy_all_backups": ex_destroy_all_backups } action = "/virtual_machines/{identifier}.json".format( identifier=node.id) self.connection.request(action, params=server_params, method="DELETE") return True def list_nodes(self): """ List all VS :rtype: ``list`` of :class:`OnAppNode` """ response = self.connection.request("/virtual_machines.json") nodes = [] for vm in response.object: nodes.append(self._to_node(vm["virtual_machine"])) return nodes def list_images(self): """ List all images :rtype: ``list`` of :class:`NodeImage` """ response = self.connection.request("/templates.json") templates = [] for template in response.object: templates.append(self._to_image(template["image_template"])) return templates def list_key_pairs(self): """ List all the available key pair objects. :rtype: ``list`` of :class:`.KeyPair` objects """ user_id = self.connection.request('/profile.json').object['user']['id'] response = self.connection.request('/users/%s/ssh_keys.json' % user_id) ssh_keys = [] for ssh_key in response.object: ssh_keys.append(self._to_key_pair(ssh_key['ssh_key'])) return ssh_keys def get_key_pair(self, name): """ Retrieve a single key pair. :param name: ID of the key pair to retrieve. :type name: ``str`` :rtype: :class:`.KeyPair` object """ user_id = self.connection.request('/profile.json').object['user']['id'] response = self.connection.request( '/users/%s/ssh_keys/%s.json' % (user_id, name)) return self._to_key_pair(response.object['ssh_key']) def import_key_pair_from_string(self, name, key_material): """ Import a new public key from string. :param name: Key pair name (unused). :type name: ``str`` :param key_material: Public key material. :type key_material: ``str`` :rtype: :class:`.KeyPair` object """ data = json.dumps({'key': key_material}) user_id = self.connection.request('/profile.json').object['user']['id'] response = self.connection.request( '/users/%s/ssh_keys.json' % user_id, data=data, headers={ "Content-type": "application/json"}, method="POST") return self._to_key_pair(response.object['ssh_key']) def delete_key_pair(self, key): """ Delete an existing key pair. :param key_pair: Key pair object. :type key_pair: :class:`.KeyPair` :return: True on success :rtype: ``bool`` """ key_id = key.name response = self.connection.request( '/settings/ssh_keys/%s.json' % key_id, method='DELETE') return response.status == httplib.NO_CONTENT # # Helper methods # def _to_key_pair(self, data): extra = {'created_at': data['created_at'], 'updated_at': data['updated_at']} return KeyPair(name=data['id'], fingerprint=None, public_key=data['key'], private_key=None, driver=self, extra=extra) def _to_image(self, template): extra = {'distribution': template['operating_system_distro'], 'operating_system': template['operating_system'], 'operating_system_arch': template['operating_system_arch'], 'allow_resize_without_reboot': template['allow_resize_without_reboot'], 'allowed_hot_migrate': template['allowed_hot_migrate'], 'allowed_swap': template['allowed_swap'], 'min_disk_size': template['min_disk_size'], 'min_memory_size': template['min_memory_size'], 'created_at': template['created_at']} return NodeImage(id=template['id'], name=template['label'], driver=self, extra=extra) def _to_node(self, data): identifier = data["identifier"] name = data["label"] private_ips = [] public_ips = [] for ip in data["ip_addresses"]: address = ip["ip_address"]['address'] if is_private_subnet(address): private_ips.append(address) else: public_ips.append(address) extra = OnAppNodeDriver._get_extra_dict( data, RESOURCE_EXTRA_ATTRIBUTES_MAP["node"] ) return Node(identifier, name, extra['state'], public_ips, private_ips, self, extra=extra) @staticmethod def _get_extra_dict(response, mapping): """ Extract attributes from the element based on rules provided in the mapping dictionary. :param response: The JSON response to parse the values from. :type response: ``dict`` :param mapping: Dictionary with the extra layout :type mapping: ``dict`` :rtype: ``dict`` """ extra = {} for attribute, values in mapping.items(): transform_func = values["transform_func"] value = response.get(values["key_name"]) extra[attribute] = transform_func(value) if value else None return extra @staticmethod def _create_args_to_params(**kwargs): """ Extract server params from keyword args to create a VS :param kwargs: keyword args :return: ``dict`` """ params = [ "ex_cpu_sockets", "ex_cpu_threads", "ex_enable_autoscale", "ex_data_store_group_primary_id", "ex_data_store_group_swap_id", "ex_hypervisor_group_id", "ex_hypervisor_id", "ex_initial_root_password", "ex_note", "ex_primary_disk_min_iops", "ex_primary_network_id", "ex_primary_network_group_id", "ex_recipe_ids", "ex_required_automatic_backup", "ex_required_virtual_machine_startup", "ex_required_virtual_machine_startup", "ex_selected_ip_address_id", "ex_swap_disk_min_iops", "ex_type_of_format", "ex_custom_recipe_variables", "ex_licensing_key", "ex_licensing_server_id", "ex_licensing_type", ] server_params = {} for p in params: value = kwargs.get(p) if value: server_params[p[3:]] = value return server_params apache-libcloud-2.8.0/libcloud/compute/drivers/oneandone.py0000664000175000017500000016063613570310635023711 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ 1&1 Cloud Server Compute driver """ import json from libcloud.compute.providers import Provider from libcloud.common.base import JsonResponse, ConnectionKey from libcloud.compute.base import NodeSize, NodeImage, NodeLocation, \ Node, NodeAuthPassword, NodeAuthSSHKey from libcloud.common.types import InvalidCredsError from libcloud.compute.types import NodeState from libcloud.utils.py3 import httplib from libcloud.compute.base import NodeDriver from time import sleep API_HOST = 'cloudpanel-api.1and1.com' API_VERSION = '/v1/' __all__ = [ 'API_HOST', 'API_VERSION', 'OneAndOneResponse', 'OneAndOneConnection', 'OneAndOneNodeDriver' ] class OneAndOneResponse(JsonResponse): """ OneAndOne response parsing. """ valid_response_codes = [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def parse_error(self): if self.status == httplib.UNAUTHORIZED: body = self.parse_body() raise InvalidCredsError(body['message']) else: body = self.parse_body() if 'message' in body: error = '%s (code: %s)' % (body['message'], self.status) else: error = body return error def success(self): return self.status in self.valid_response_codes class OneAndOneConnection(ConnectionKey): """ Connection class for the 1&1 driver """ host = API_HOST api_prefix = API_VERSION responseCls = OneAndOneResponse def encode_data(self, data): return json.dumps(data) def add_default_headers(self, headers): """ Add headers that are necessary for every request This method adds ``token`` and ``Content-Type`` to the request. """ headers['X-Token'] = self.key headers['Content-Type'] = 'application/json' return headers def request(self, action, params=None, data=None, headers=None, method='GET', raw=False): """ Some requests will use the href attribute directly. If this is not the case, then we should formulate the url based on the action specified. If we are using a full url, we need to remove the host and protocol components. """ action = self.api_prefix + action.lstrip('/') return super(OneAndOneConnection, self). \ request(action=action, params=params, data=data, headers=headers, method=method, raw=raw) class OneAndOneNodeDriver(NodeDriver): """ Base OneAndOne node driver. """ connectionCls = OneAndOneConnection name = '1and1' website = 'http://www.1and1.com' type = Provider.ONEANDONE NODE_STATE_MAP = { 'POWERING_ON': NodeState.STARTING, 'POWERING_OFF': NodeState.PENDING, 'POWERED_OFF': NodeState.STOPPING, 'POWERED_ON': NodeState.RUNNING, 'REBOOTING': NodeState.REBOOTING, 'CONFIGURING': NodeState.RECONFIGURING, 'REMOVING': NodeState.UNKNOWN, 'DEPLOYING': NodeState.STARTING, } """ Core Functions """ def list_sizes(self): """ Lists all sizes :return: A list of all configurable node sizes. :rtype: ``list`` of :class:`NodeSize` """ sizes = [] fixed_instances = self._list_fixed_instances() for value in fixed_instances: node_size = self._to_node_size(value) sizes.append(node_size) return sizes def list_locations(self): """ Lists all locations :return: ``list`` of :class:`NodeLocation` :rtype: ``list`` """ datacenters = self.ex_list_datacenters() locations = [] for values in datacenters: node_size = self._to_location(values) locations.append(node_size) return locations def list_images(self, image_type=None): """ :return: ``list`` of :class: `NodeImage` :rtype: ``list`` """ response = self.connection.request( action='server_appliances', method='GET' ) return self._to_images(response.object, image_type) def get_image(self, image_id): response = self.connection.request( action='server_appliances/%s' % image_id, method='GET' ) return self._to_image(response.object) """ Node functions """ def create_node(self, name, image, ex_fixed_instance_size_id, location=None, auth=None, ex_ip=None, ex_monitoring_policy_id=None, ex_firewall_policy_id=None, ex_loadbalancer_id=None, ex_description=None, ex_power_on=None): """ Creates a node. :param name: The name of the new node :type name: `str` :param ex_fixed_instance_size_id: Fixed instance size ID from list_sizes :type ex_fixed_instance_size_id: ``str`` :param location: 1&1 Data center Location :type location: `NodeLocation` :param ex_ip: IP address :type ex_ip: `str` :param ex_ssh_key: SSH Key :type ex_ssh_key: `str` :param password: Password :type password: `str` :param ex_monitoring_policy_id: :type ex_firewall_policy_id: `str` :param ex_firewall_policy_id: :type ex_firewall_policy_id: `str` :param ex_loadbalancer_id: :type ex_loadbalancer_id: `str` :param ex_description: :type ex_description: `str` :param ex_power_on: :type ex_power_on: `bool` :return: Instance of class ``Node`` :rtype: :class:`Node` """ body = { 'name': name, 'appliance_id': image.id, 'hardware': { 'fixed_instance_size_id': ex_fixed_instance_size_id }, } if location is not None: body['datacenter_id'] = location.id if ex_power_on is not None: body['power_on'] = ex_power_on if ex_description is not None: body['description'] = ex_description if ex_firewall_policy_id is not None: body['firewall_policy_id'] = ex_firewall_policy_id if ex_monitoring_policy_id is not None: body['monitoring_policy_id'] = ex_monitoring_policy_id if ex_loadbalancer_id is not None: body['loadbalancer_id'] = ex_loadbalancer_id if auth is not None: if isinstance(auth, NodeAuthPassword): body['password'] = auth.password elif isinstance(auth, NodeAuthSSHKey): body['rsa_key'] = auth.pubkey if ex_ip is not None: body['ip_id'] = ex_ip response = self.connection.request( action='servers', data=body, method='POST', ) return self._to_node(response.object) def list_nodes(self): """ List all nodes. :return: ``list`` of :class:`Node` :rtype: ``list`` """ response = self.connection.request( action='servers', method='GET' ) return self._to_nodes(response.object) def destroy_node(self, node, ex_keep_ips=False): """ Destroys a node. :param node: The node you wish to destroy. :type volume: :class:`Node` :param ex_keep_ips: True to keep all IP addresses assigned to the node :type ex_keep_ips: : ``bool`` :return: Instance of class ``Node`` :rtype: :class: `Node` """ self.ex_shutdown_server(node.id) self._wait_for_state(node.id, 'POWERED_OFF') response = self.connection.request( action='servers/%s' % node.id, params={'keep_ips': ex_keep_ips}, method='DELETE' ) return self._to_node(response.object) def reboot_node(self, node): """ Reboots the node. :param node: The node you wish to destroy. :type volume: :class:`Node` :return: Instance of class ``Node`` :rtype: :class: `Node` """ shutdown_body = { "action": "REBOOT", "method": "HARDWARE" } response = self.connection.request( action='servers/%s/status/action' % node.id, data=shutdown_body, method='PUT', ) return self._to_node(response.object) """ Extension functions """ def ex_rename_server(self, server_id, name=None, description=None): """ Renames the server :param server_id: ID of the server you want to rename :param name: New name of the server :type: ``str`` :param description: New description of the server :type: ``str`` :return: Instance of class ``Node`` :rtype: :class: `Node` """ body = {} if name is not None: body["name"] = name if description is not None: body["description"] = description response = self.connection.request( action='servers/%s' % server_id, data=body, method='PUT' ) return self._to_node(response.object) def ex_get_server_hardware(self, server_id): """ Gets all server hardware :param server_id: Id of the server :type: ``str`` :return: Server's hardware :rtype: ``dict`` """ response = self.connection.request( action='servers/%s/hardware' % server_id, method='GET' ) return response.object """ Hardware operations """ def ex_modify_server_hardware(self, server_id, fixed_instance_size_id=None, vcore=None, cores_per_processor=None, ram=None): """ Modifies server's hardware :param server_id: :type: ``str`` :param fixed_instance_size_id: Id of the fixed instance size :type: ``str`` :param vcore: Virtual cores count :type: ``int`` :param cores_per_processor: Count of cores per procesor :type: ``int`` :param ram: Amount of ram for the server :type: ``int`` :return: Instance of class ``Node`` :type: :class: `Node` """ body = {} if fixed_instance_size_id is not None: body['fixed_instance_size_id'] = fixed_instance_size_id if vcore is not None: body['vcore'] = vcore if cores_per_processor is not None: body['cores_per_processor'] = cores_per_processor if ram is not None: body['ram'] = ram response = self.connection.request( action='servers/%s/hardware' % server_id, data=body, method='PUT' ) return self._to_node(response.object) """ HDD operations """ def ex_modify_server_hdd(self, server_id, hdd_id=None, size=None): """ Modifies server hard disk drives :param server_id: Id of the server :type: ``str`` :param hdd_id: Id of the hard disk :type: ``str`` :param size: Size of the hard disk :type: ``str`` :return: Instance of class ``Node`` :rtype: :class: `Node` """ body = {} if size is not None: body['size'] = size response = self.connection.request( action='servers/%s/hardware/hdds/%s' % (server_id, hdd_id), data=body, method='PUT' ) return self._to_node(response.object) def ex_add_hdd(self, server_id, size, is_main): """ Add a hard disk to the server :param server_id: Id of the server :type: ``str`` :param size: Size of the new disk :type: ``str`` :param is_main: Indicates if the disk is going to be the boot disk :type: ``boolean`` :return: Instance of class ``Node`` :type: :class: `Node` """ body = { 'size': size, 'is_main': is_main } response = self.connection.request( action='servers/%s/hardware/hdds' % server_id, data=body, method='POST' ) return self._to_node(response.object) def ex_remove_hdd(self, server_id, hdd_id): """ Removes existing hard disk :param server_id: Id of the server :type: ``str`` :param hdd_id: Id of the hard disk :type: ``str`` :return: Instance of class ``Node`` :rtype: :class: `Node` """ response = self.connection.request( action='servers/%s/hardware/hdds/%s' % (server_id, hdd_id), method='DELETE' ) return self._to_node(response.object) """ Data center operations """ def ex_list_datacenters(self): """ Lists all data centers :return: List of data centers :rtype: ``dict`` """ response = self.connection.request( action='datacenters', method='GET' ) return response.object def ex_get_server(self, server_id): """ Gets a server :param server_id: Id of the server to be retrieved :type: ``str`` :return: Instance of class ``Node`` :rtype: :class: `Node` """ response = self.connection.request( action='servers/%s' % (server_id), method='GET' ) return self._to_node(response.object) def ex_shutdown_server(self, server_id, method='SOFTWARE'): """ Shuts down the server :param server_id: Id of the server to be shut down :type: ``str`` :param method: Method of shutting down "SOFTWARE" or "HARDWARE" :return: Instance of class ``Node`` :rtype: :class: `Node` """ shutdown_body = { 'action': 'POWER_OFF', 'method': method } response = self.connection.request( action='servers/%s/status/action' % (server_id), data=shutdown_body, method='PUT', ) return self._to_node(response.object) """ Image operations """ def ex_get_server_image(self, server_id): """ Gets server image :param server_id: Id of the server :type: ``str`` :return: Server image :rtype: ``dict`` """ response = self.connection.request( action='servers/%s/image' % server_id, method='GET' ) return response.object def ex_reinstall_server_image(self, server_id, image_id, password=None): """ Installs a new image on the server :param server_id: Id of the server :type: ``str`` :param image_id: Id of the image (Server Appliance) :type: ``str`` :param password: New password for the server :return: Instance of class ``Node`` :rtype: :class: `Node` """ body = { 'id': image_id, } if password is not None: body['password'] = password response = self.connection.request( action='servers/%s/image' % server_id, data=body, method='PUT' ) return self._to_node(response.object) """ Server IP operations """ def ex_list_server_ips(self, server_id): """ Gets all server IP objects :param server_id: Id of the server :type: ``str`` :return: List of server IP objects :rtype: ``list`` of ``dict`` """ response = self.connection.request( action='servers/%s/ips' % server_id, method='GET' ) return response.object def ex_get_server_ip(self, server_id, ip_id): """ Get a single server IP object :param server_id: Id of the server :type: ``str`` :param ip_id: ID of the IP address :type: ``str`` :return: IP address object :rtype: ``dict`` """ response = self.connection.request( action='servers/%s/ips/%s' % (server_id, ip_id), method='GET' ) return response.object def ex_assign_server_ip(self, server_id, ip_type): """ Assigns a new IP address to the server :param server_id: Id of the server :type: ``str`` :param ip_type: Type of the IP address [IPV4,IPV6] :type: ``str`` :return: ``Node`` instance :rtype: ``Node`` """ body = { 'type': ip_type } response = self.connection.request( action='servers/%s/ips' % server_id, data=body, method='POST' ) return self._to_node(response.object) def ex_remove_server_ip(self, server_id, ip_id, keep_ip=None): """ Removes an IP address from the server :param server_id: Id of the server :type: ``str`` :param ip_id: ID of the IP address :type: ``str`` :param keep_ip: Indicates whether IP address will be removed from the Cloud Panel :type: ``boolean`` :return: ``Node`` instance :rtype: ``Node`` """ body = {} if keep_ip is not None: body['keep_ip'] = keep_ip response = self.connection.request( action='servers/%s/ips/%s' % (server_id, ip_id), data=body, method='DELETE' ) return self._to_node(response.object) def ex_get_server_firewall_policies(self, server_id, ip_id): """ Gets a firewall policy of attached to the server's IP :param server_id: Id of the server :type: ``str`` :param ip_id: ID of the IP address :type: ``str`` :return: IP address object :rtype: ``dict`` """ response = self.connection.request( action='/servers/%s/ips/%s/firewall_policy' % (server_id, ip_id), method='GET' ) return response.object def ex_add_server_firewall_policy(self, server_id, ip_id, firewall_id): """ Adds a firewall policy to the server's IP address :param server_id: Id of the server :type: ``str`` :param ip_id: ID of the IP address :type: ``str`` :param firewall_id: ID of the firewall policy :type: ``str`` :return: ``Node`` instance :rtype: ``Node`` """ body = { 'id': firewall_id } response = self.connection.request( action='/servers/%s/ips/%s/firewall_policy' % (server_id, ip_id), data=body, method='POST' ) return self._to_node(response.object) """ Firewall Policy operations """ def ex_create_firewall_policy(self, name, rules, description=None): """ Creates a firewall Policy. :param name: :param description: :param rules: :rtype: `dict` :return: `dict` firewall policy """ body = { 'name': name } if description is not None: body['description'] = description if len(rules) == 0: raise ValueError( 'At least one firewall rule is required.' ) else: body['rules'] = rules response = self.connection.request( action='firewall_policies', data=body, method='POST', ) return response.object def ex_list_firewall_policies(self): """" List firewall policies :return: 'dict' """ response = self.connection.request( action='firewall_policies', method='GET' ) return response.object def ex_get_firewall_policy(self, fw_id): """ Gets firewall policy :param fw_id: ID of the firewall policy :return: 'dict' """ response = self.connection.request( action='firewall_policy/%s' % fw_id, method='GET' ) return response.object def ex_delete_firewall_policy(self, fw_id): """ Deletes firewall policy :param fw_id: ID of the Firewall :return: 'dict' """ response = self.connection.request( action='firewall_policy/%s' % fw_id, method='DELETE' ) return response.object """ Shared storage operations """ def ex_list_shared_storages(self): """ List of shared storages :return: 'dict' """ response = self.connection.request( action='shared_storages', method='GET' ) return response.object def ex_get_shared_storage(self, storage_id): """ Gets a shared storage :return: 'dict' """ response = self.connection.request( action='shared_storages/%s' % (storage_id), method='GET' ) return response.object def ex_create_shared_storage(self, name, size, datacenter_id=None, description=None): """ Creates a shared storage :param name: Name of the storage :param size: Size of the storage :param datacenter_id: datacenter where storage should be created :param description: description ot the storage :return: 'dict' """ body = { 'name': name, 'size': size, 'datacenter_id': datacenter_id } if description is not None: body['description'] = description response = self.connection.request( action='shared_storages', data=body, method='POST' ) return response.object def ex_delete_shared_storage(self, storage_id): """ Removes a shared storage :param storage_id: Id of the shared storage :type: ``str`` :return: Instnace of shared storage :rtype: ``list`` of ``dict`` """ response = self.connection.request( action='shared_storages/%s' % storage_id, method='DELETE' ) return response.object def ex_attach_server_to_shared_storage(self, storage_id, server_id, rights): """ Attaches a single server to a shared storage :param storage_id: Id of the shared storage :param server_id: Id of the server to be attached to the shared storage :param rights: :return: :rtype: 'dict' """ body = { 'severs': [ { 'id': server_id, 'rights': rights } ] } response = self.connection.request( action='shared_storages/%s/servers' % storage_id, data=body, method='POST' ) return response.object def ex_get_shared_storage_server(self, storage_id, server_id): """ Gets a shared storage's server :param storage_id: :param server_id: :return: """ response = self.connection.request( action='shared_storages/%s/servers/%s' % (storage_id, server_id), ) return response.object def ex_detach_server_from_shared_storage(self, storage_id, server_id): """ Detaches a server from shared storage :param storage_id: Id of the shared storage :type: ``str`` :param server_id: Id of the server :type: ``str`` :return: Instance of shared storage :rtype: ``dict`` """ response = self.connection.request( action='shared_storages/%s/servers/%s' % (storage_id, server_id), method='DELETE' ) return response.object """ Load Balancers operations """ def ex_create_load_balancer(self, name, method, rules, persistence=None, persistence_time=None, health_check_test=None, health_check_interval=None, health_check_path=None, health_check_parser=None, datacenter_id=None, description=None): """ :param name: Name of the load balancer :param method: Load balancer method :param rules: Load balancer rules :type rules: ``list`` of ``dict`` :param persistence: Indictes if persistance is set :type persistence: ``boolean`` :param persistence_time: Persistance time :type persistence_time: ``int`` :param health_check_test: Type of test :type health_check_test:``str`` :param health_check_interval: Interval of the check :param health_check_path: Path :type health_check_path: ``str`` :param health_check_parser: Parser :type health_check_parser:``str`` :param datacenter_id: Data center id :type datacenter_id:``str`` :param description: Description of load balancer :type description:``str`` :return: ``dict`` """ body = { 'name': name, 'method': method, } body['rules'] = [] body['rules'] = rules if persistence is not None: body['persistence'] = persistence if persistence_time is not None: body['persistence_time'] = persistence_time if health_check_test is not None: body['health_check_test'] = health_check_test if health_check_interval is not None: body['health_check_interval'] = health_check_interval if health_check_path is not None: body['health_check_path'] = health_check_path if health_check_parser is not None: body['health_check_parser'] = health_check_parser if datacenter_id is not None: body['datacenter_id'] = datacenter_id if description is not None: body['description'] = description response = self.connection.request( action='load_balancers', data=body, method='POST' ) return response.object def ex_update_load_balancer(self, lb_id, name=None, description=None, health_check_test=None, health_check_interval=None, persistence=None, persistence_time=None, method=None): body = {} if name is not None: body['name'] = name if description is not None: body['description'] = description if health_check_test is not None: body['health_check_test'] = health_check_test if health_check_interval is not None: body['health_check_interval'] = health_check_interval if persistence is not None: body['persistence'] = persistence if persistence_time is not None: body['persistence_time'] = persistence_time if method is not None: body['method'] = method response = self.connection.request( action='load_balancers/%s' % lb_id, data=body, method='PUT' ) return response.object def ex_add_servers_to_load_balancer(self, lb_id, server_ips=[]): """ Adds server's IP address to load balancer :param lb_id: Load balancer ID :type: ``str`` :param server_ips: Array of server IP IDs :type: ``list`` of ``str`` :return: Instance of load balancer :rtype: ``dict`` """ body = { 'server_ips': server_ips, } response = self.connection.request( action='load_balancers/%s/server_ips' % lb_id, data=body, method='POST' ) return response.object def ex_remove_server_from_load_balancer(self, lb_id, server_ip): """ Removes server's IP from load balancer :param lb_id: Load balancer ID :type: ``str`` :param server_ip: ID of the server IP :type: ``str`` :return: Instance of load balancer :rtype: ``dict`` """ response = self.connection.request( action='/load_balancers/%s/server_ips/%s' % (lb_id, server_ip), method='DELETE' ) return response.object def ex_add_load_balancer_rule(self, lb_id, protocol, port_balancer, port_server, source=None): """ Adds a rule to load balancer :param lb_id: Load balancer ID :rtype: ``str`` :param protocol: Load balancer protocol :rtype: ``str`` :param port_balancer: Port to be balananced :rtype: ``int`` :param port_server: Server port :rtype: ``int`` :param source: Source IP address :rtype: ``str`` :return: Instance of load balancer :rtype: ``dict`` """ body = { 'rules': [ { 'protocol': protocol, 'port_balancer': port_balancer, 'port_server': port_server } ] } if source is not None: body['rules'][0]['source'] = source response = self.connection.request( action='/load_balancers/%s/rules' % lb_id, data=body, method='POST' ) return response.object def ex_remove_load_balancer_rule(self, lb_id, rule_id): """ Removes load balancer rule :param lb_id: Load balancer ID :rtype: ``str`` :param rule_id: Rule ID :rtype: ``str`` :return: Instance of load balancer :rtype: ``dict`` """ response = self.connection.request( action='/load_balancers/%s/rules/%s' % (lb_id, rule_id), method='DELETE' ) return response.object def ex_list_load_balancers(self): """ Lists all load balancers :return: List of load balancers :rtype: ``list`` of ``dict`` """ response = self.connection.request( action='load_balancers', method='GET' ) return response.object def ex_get_load_balancer(self, lb_id): """ Gets a single load balancer :param lb_id: ID of the load balancer :type lb_id: ``str`` :return: Instance of load balancer :rtype: ``dict`` """ response = self.connection.request( action='load_balancers/%s' % lb_id, method='GET' ) return response.object def ex_list_load_balancer_server_ips(self, lb_id): """ List balanced server IP addresses :param lb_id: ID of the load balancer :type lb_id: ``str`` :return: Array of IP address IDs :rtype: ``dict`` """ response = self.connection.request( action='load_balancers/%s/server_ips' % lb_id, method='GET' ) return response.object def ex_get_load_balancer_server_ip(self, lb_id, server_ip): """ Gets load balanced server id :param lb_id: ID of the load balancer :type lb_id: ``str`` :param server_ip: ID of the server IP :type server_ip: ``str`` :return: Server IP :rtype: ``dict`` """ response = self.connection.request( action='load_balancers/%s/server_ips/%s' % (lb_id, server_ip), method='GET' ) return response.object def ex_list_load_balancer_rules(self, lb_id): """ Lists loadbalancer rules :param lb_id: ID of the load balancer :type lb_id: ``str`` :return: Lists of rules :rtype: ``list`` of ``dict`` """ response = self.connection.request( action='load_balancers/%s/rules' % lb_id, method='GET' ) return response.object def ex_get_load_balancer_rule(self, lb_id, rule_id): """ Get a load balancer rule :param lb_id: ID of the load balancer :type lb_id: ``str`` :param rule_id: Rule ID :type rule_id: ``str`` :return: A load balancer rule :rtype: ``dict`` """ response = self.connection.request( action='load_balancers/%s/rules/%s' % (lb_id, rule_id), method='GET' ) return response.object def ex_delete_load_balancer(self, lb_id): """ Deletes a load balancer rule :param lb_id: ID of the load balancer :type lb_id: ``str`` :param rule_id: Rule ID :type rule_id: ``str`` :return: Instance of load balancer :rtype: ``dict`` """ response = self.connection.request( action='load_balancers/%s' % lb_id, method='DELETE' ) return response.object """ Public IP operations """ def ex_list_public_ips(self): """ Lists all public IP addresses :return: Array of public addresses :rtype: ``list`` of ``dict`` """ response = self.connection.request( action='public_ips', method='GET' ) return response.object def ex_create_public_ip(self, type, reverse_dns=None, datacenter_id=None): """ Creates a public IP :param type: Type of IP (IPV4 or IPV6) :type type: ``str`` :param reverse_dns: Reverse DNS :type reverse_dns: ``str`` :param datacenter_id: Datacenter ID where IP address will be crated :type datacenter_id: ``str`` :return: Instance of Public IP :rtype: ``dict`` """ body = { 'type': type } if reverse_dns is not None: body['reverse_dns'] = reverse_dns if datacenter_id is not None: body['datacenter_id'] = datacenter_id response = self.connection.request( action='public_ips', data=body, method='POST' ) return response.object def ex_get_public_ip(self, ip_id): """ Gets a Public IP :param ip_id: ID of the IP :type ip_id: ``str`` :return: Instance of Public IP :rtype: ``dict`` """ response = self.connection.request( action='public_ips/%s' % ip_id, method='GET' ) return response.object def ex_delete_public_ip(self, ip_id): """ Deletes a public IP :param ip_id: ID of public IP :type ip_id: ``str`` :return: Instance of IP Address :rtype: ``dict`` """ response = self.connection.request( action='public_ips/%s' % ip_id, method='DELETE' ) return response def ex_update_public_ip(self, ip_id, reverse_dns): """ Updates a Public IP :param ip_id: ID of public IP :type ip_id: ``str`` :param reverse_dns: Reverse DNS :type reverse_dns: ``str`` :return: Instance of Public IP :rtype: ``dict`` """ body = { 'reverse_dns': reverse_dns } response = self.connection.request( action='public_ips/%s' % ip_id, data=body, method='DELETE' ) return response.object """ Private Network Operations """ def ex_list_private_networks(self): """ Lists all private networks :return: List of private networks :rtype: ``dict`` """ response = self.connection.request( action='private_networks', method='GET' ) return response.object def ex_create_private_network(self, name, description=None, datacenter_id=None, network_address=None, subnet_mask=None): """ Creates a private network :param name: Name of the private network :type name: ``str`` :param description: Description of the private network :type description: ``str`` :param datacenter_id: ID of the data center for the private network :type datacenter_id: ``str`` :param network_address: Network address of the private network :type network_address: ``str`` :param subnet_mask: Subnet mask of the private network :type subnet_mask: ``str`` :return: Newly created private network :rtype: ``dict`` """ body = { 'name': name } if description is not None: body['description'] = description if datacenter_id is not None: body['datacenter_id'] = datacenter_id if network_address is not None: body['network_address'] = network_address if subnet_mask is not None: body['subnet_maks'] = subnet_mask response = self.connection.request( action='private_networks', data=body, method='POST' ) return response.object def ex_delete_private_network(self, network_id): """ Deletes a private network :param network_id: Id of the private network :type network_id: ``str`` :return: Instance of the private network being deleted :rtype: ``dict`` """ response = self.connection.request( action='private_networks' % network_id, method='DELETE' ) return response.object def ex_update_private_network(self, network_id, name=None, description=None, datacenter_id=None, network_address=None, subnet_mask=None): """ Updates a private network :param name: Name of the private network :type name: ``str`` :param description: Description of the private network :type description: ``str`` :param datacenter_id: ID of the data center for the private network :type datacenter_id: ``str`` :param network_address: Network address of the private network :type network_address: ``str`` :param subnet_mask: Subnet mask of the private network :type subnet_mask: ``str`` :return: Instance of private network :rtype: ``dict`` """ body = {} if name is not None: body['name'] = name if description is not None: body['description'] = description if datacenter_id is not None: body['datacenter_id'] = datacenter_id if network_address is not None: body['network_address'] = network_address if subnet_mask is not None: body['subnet_maks'] = subnet_mask response = self.connection.request( action='private_networks/%s', data=body, method='PUT' ) return response.object def ex_list_private_network_servers(self, network_id): """ Lists all private network servers :param network_id: Private network ID :type network_id: ``str`` :return: List of private network servers :rtype: ``dict`` """ response = self.connection.request( action='/private_networks/%s/servers' % network_id, method='GET' ) return response.object def ex_add_private_network_server(self, network_id, server_ids): """ Add servers to private network :param network_id: Private Network ID :type network_id: ``str`` :param server_ids: List of server IDs :type server_ids: ``list`` of ``str`` :return: List of attached servers :rtype: ``dict`` """ body = { 'servers': server_ids } response = self.connection.request( action='/private_networks/%s/servers' % network_id, data=body, method='POST' ) return response.object def ex_remove_server_from_private_network(self, network_id, server_id): """ Removes a server from the private network :param network_id: Private Network ID :type network_id: ``str`` :param server_id: Id of the server :type server_id: ``str`` :return: Instance of the private network :rtype: ``dict`` """ response = self.connection.request( action='/private_networks/%s/servers/%s' % (network_id, server_id), method='POST' ) return response.object """ Monitoring policy operations """ def ex_list_monitoring_policies(self): """ Lists all monitoring policies :return: List of monitoring policies :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies', method='GET' ) return response.object def ex_create_monitoring_policy(self, name, thresholds, ports, processes, description=None, email=None, agent=None, ): """ Creates a monitoring policy :param name: Name for the monitoring policy :type name: ``str`` :param thresholds: Thresholds for the monitoring policy :type thresholds: ``dict`` :param ports: Monitoring policies for ports :type ports: ``list`` of ``dict`` :param processes: Processes to be monitored :type processes: ``list`` of ``dict`` :param description: Description for the monitoring policy :type description: ``str`` :param email: Email for notifications :type email: ``str`` :param agent: Indicates if agent application will be installed :type agent: ``boolean`` :return: Newly created instance of monitofing policy :rtype: ``dict`` """ body = { 'name': name, 'thresholds': thresholds, 'ports': ports, 'processes': processes } if description is not None: body['description'] = description if email is not None: body['email'] = email if agent is not None: body['agent'] = agent response = self.connection.request( action='monitoring_policies', data=body, method='POST' ) return response.object def ex_delete_monitoring_policy(self, policy_id): """ Deletes a monitoring policy :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :return: Instance of the monitoring policy being deleted :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies' % policy_id, method='DELETE' ) return response.object def ex_update_monitoring_policy(self, policy_id, email, thresholds, name=None, description=None): """ Updates monitoring policy :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param email: Email to send notifications to :type email: ``str`` :param thresholds: Thresholds for the monitoring policy :type thresholds: ``dict`` :param name: Name of the monitoring policy :type name: ``str`` :param description: Description of the monitoring policy :type description: ``str`` :return: Instance of the monitoring policy being deleted :rtype: ``dict`` """ body = {} if name is not None: body['name'] = name if description is not None: body['description'] = description if thresholds is not None: body['thresholds'] = thresholds if email is not None: body['email'] = email response = self.connection.request( action='monitoring_policies/%s' % policy_id, data=body, method='PUT' ) return response.object def ex_get_monitoring_policy(self, policy_id): """ Fetches a monitoring policy :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s' % policy_id, method='GET' ) return response.object def ex_get_monitoring_policy_ports(self, policy_id): """ Fetches monitoring policy ports :param policy_id: Id of the monitoring policy :type policy_id: :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/ports' % policy_id, method='GET' ) return response.object def ex_get_monitoring_policy_port(self, policy_id, port_id): """ Fetches monitoring policy port :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param port_id: Id of the port :type port_id: ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/ports/%s' % (policy_id, port_id), method='GET' ) return response.object def ex_remove_monitoring_policy_port(self, policy_id, port_id): """ Removes monitoring policy port :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param port_id: Id of the port :type port_id: ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/ports/%s' % (policy_id, port_id), method='DELETE' ) return response.object def ex_add_monitoring_policy_ports(self, policy_id, ports): """ Add monitoring policy ports :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param ports: List of ports :type ports: ``dict`` [ { 'protocol':'TCP', 'port':'80', 'alert_if':'RESPONDING', 'email_notification':true } ] :return: Instance of a monitoring policy :rtype: ``dict`` """ body = {'ports': ports} response = self.connection.request( action='monitoring_policies/%s/ports' % policy_id, data=body, method='POST' ) return response.object def ex_get_monitoring_policy_processes(self, policy_id): """ Fetches monitoring policy processes :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/processes' % policy_id, method='GET' ) return response.object def ex_get_monitoring_policy_process(self, policy_id, process_id): """ Fetches monitoring policy process :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param process_id: Id of the process :type process_id: ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/processes/%s' % (policy_id, process_id), method='GET' ) return response.object def ex_remove_monitoring_policy_process(self, policy_id, process_id): """ Removes monitoring policy process :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param process_id: Id of the process :type process_id: ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/processes/%s' % (policy_id, process_id), method='DELETE' ) return response.object def ex_add_monitoring_policy_processes(self, policy_id, processes): """ Add monitoring policy processes :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param processes: List of processes :type processes: ``list`` of ``dict`` [ { 'process': 'taskmmgr', 'alert_if': 'RUNNING', 'email_notification': true } ] :return: Instance of a monitoring policy :rtype: ``dict`` """ body = {'processes': processes} response = self.connection.request( action='monitoring_policies/%s/processes' % policy_id, data=body, method='POST' ) return response.object def ex_list_monitoring_policy_servers(self, policy_id): """ List all servers that are being monitoried by the policy :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :return: List of servers being monitored :rtype: ``list`` of ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/servers' % policy_id, method='GET' ) return response.object def ex_add_servers_to_monitoring_policy(self, policy_id, servers): """ Adds servers to monitoring policy :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param servers: List of server ID :type servers: ``list`` of ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ body = { 'servers': servers } response = self.connection.request( action='monitoring_policies/%s/servers' % policy_id, data=body, method='POST' ) return response.object def ex_remove_server_from_monitoring_policy(self, policy_id, server_id): """ Removes a server from monitoring policy :param policy_id: Id of the monitoring policy :type policy_id: ``str`` :param server_id: Id of the server :type server_id: ``str`` :return: Instance of a monitoring policy :rtype: ``dict`` """ response = self.connection.request( action='monitoring_policies/%s/servers/%s' % (policy_id, server_id), method='DELETE' ) return response.object """ Private Functions """ def _to_images(self, object, image_type=None): if image_type is not None: images = [image for image in object if image['type'] == image_type] else: images = [image for image in object] return [self._to_image(image) for image in images] def _to_image(self, data): extra = { 'os_family': data['os_family'], 'os': data['os'], 'os_version': data['os_version'], 'os_architecture': data['os_architecture'], 'os_image_type': data['os_image_type'], 'min_hdd_size': data['min_hdd_size'], 'available_datacenters': data['available_datacenters'], 'licenses': data['licenses'], 'version': data['version'], 'categories': data['categories'] } return NodeImage(id=data['id'], name=data['name'], driver=self, extra=extra) def _to_node_size(self, data): return NodeSize( id=data['id'], name=data['name'], ram=data['hardware']['ram'], disk=data['hardware']['hdds'][0]['size'], bandwidth=None, price=None, driver=self.connection.driver, extra={ 'vcores': data['hardware']['vcore'], 'cores_per_processor': data['hardware']['cores_per_processor']} ) def _to_location(self, location): return NodeLocation( id=location['id'], name=location['country_code'], country=location['location'], driver=self.connection.driver ) def _to_nodes(self, servers): return [self._to_node( server) for server in servers] def _to_node(self, server): extra = {} extra['datacenter'] = server['datacenter'] if 'description' in server: extra['description'] = server['description'] if 'status' in server: extra['status'] = server['status'] if 'image' in server: extra['image'] = server['image'] if 'hardware' in server: extra['hardware'] = server['hardware'] if 'dvd' in server: extra['dvd'] = server['dvd'] if 'snapshot' in server: extra['snapshot'] = server['snapshot'] if 'ips' in server: extra['ips'] = server['ips'] if 'alerts' in server: extra['alerts'] = server['alerts'] if 'monitoring_policy' in server: extra['monitoring_policy'] = server['monitoring_policy'] if 'private_networks' in server: extra['private_networks'] = server['private_networks'] ips = [] if server['ips'] is not None: for ip in server['ips']: ips.append(ip['ip']) state = self.NODE_STATE_MAP.get( server['status']['state']) return Node( id=server['id'], state=state, name=server['name'], driver=self.connection.driver, public_ips=ips, private_ips=None, extra=extra ) def _wait_for_state(self, server_id, state, retries=50): for i in (0, retries): server = self.ex_get_server(server_id) if server.extra['status']['state'] == state: return sleep(5) if i == retries: raise Exception('Retries count reached') def _list_fixed_instances(self): response = self.connection.request( action='/servers/fixed_instance_sizes', method='GET' ) return response.object apache-libcloud-2.8.0/libcloud/compute/drivers/opennebula.py0000664000175000017500000012451713577507766024115 0ustar kamikami00000000000000# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad # Complutense de Madrid (dsa-research.org) # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ OpenNebula.org driver. """ __docformat__ = 'epytext' from base64 import b64encode import hashlib from libcloud.utils.py3 import ET from libcloud.utils.py3 import httplib from libcloud.utils.py3 import next from libcloud.utils.py3 import b from libcloud.compute.base import NodeState, NodeDriver, Node, NodeLocation from libcloud.common.base import ConnectionUserAndKey, XmlResponse from libcloud.compute.base import NodeImage, NodeSize, StorageVolume from libcloud.common.types import InvalidCredsError from libcloud.compute.providers import Provider __all__ = [ 'ACTION', 'OpenNebulaResponse', 'OpenNebulaConnection', 'OpenNebulaNodeSize', 'OpenNebulaNetwork', 'OpenNebulaNodeDriver', 'OpenNebula_1_4_NodeDriver', 'OpenNebula_2_0_NodeDriver', 'OpenNebula_3_0_NodeDriver', 'OpenNebula_3_2_NodeDriver', 'OpenNebula_3_8_NodeDriver'] API_HOST = '' API_PORT = (4567, 443) API_SECURE = True API_PLAIN_AUTH = False DEFAULT_API_VERSION = '3.2' class ACTION(object): """ All actions, except RESUME, only apply when the VM is in the "Running" state. """ STOP = 'STOPPED' """ The VM is stopped, and its memory state stored to a checkpoint file. VM state, and disk image, are transferred back to the front-end. Resuming the VM requires the VM instance to be re-scheduled. """ SUSPEND = 'SUSPENDED' """ The VM is stopped, and its memory state stored to a checkpoint file. The VM state, and disk image, are left on the host to be resumed later. Resuming the VM does not require the VM to be re-scheduled. Rather, after suspending, the VM resources are reserved for later resuming. """ RESUME = 'RESUME' """ The VM is resumed using the saved memory state from the checkpoint file, and the VM's disk image. The VM is either started immediately, or re-scheduled depending on how it was suspended. """ CANCEL = 'CANCEL' """ The VM is forcibly shutdown, its memory state is deleted. If a persistent disk image was used, that disk image is transferred back to the front-end. Any non-persistent disk images are deleted. """ SHUTDOWN = 'SHUTDOWN' """ The VM is gracefully shutdown by sending the ACPI signal. If the VM does not shutdown, then it is considered to still be running. If successfully, shutdown, its memory state is deleted. If a persistent disk image was used, that disk image is transferred back to the front-end. Any non-persistent disk images are deleted. """ REBOOT = 'REBOOT' """ Introduced in OpenNebula v3.2. The VM is gracefully restarted by sending the ACPI signal. """ DONE = 'DONE' """ The VM is forcibly shutdown, its memory state is deleted. If a persistent disk image was used, that disk image is transferred back to the front-end. Any non-persistent disk images are deleted. """ class OpenNebulaResponse(XmlResponse): """ XmlResponse class for the OpenNebula.org driver. """ def success(self): """ Check if response has the appropriate HTTP response code to be a success. :rtype: ``bool`` :return: True is success, else False. """ i = int(self.status) return 200 <= i <= 299 def parse_error(self): """ Check if response contains any errors. @raise: :class:`InvalidCredsError` :rtype: :class:`ElementTree` :return: Contents of HTTP response body. """ if int(self.status) == httplib.UNAUTHORIZED: raise InvalidCredsError(self.body) return self.body class OpenNebulaConnection(ConnectionUserAndKey): """ Connection class for the OpenNebula.org driver. with plain_auth support """ host = API_HOST port = API_PORT secure = API_SECURE plain_auth = API_PLAIN_AUTH responseCls = OpenNebulaResponse def __init__(self, *args, **kwargs): if 'plain_auth' in kwargs: self.plain_auth = kwargs.pop('plain_auth') super(OpenNebulaConnection, self).__init__(*args, **kwargs) def add_default_headers(self, headers): """ Add headers required by the OpenNebula.org OCCI interface. Includes adding Basic HTTP Authorization headers for authenticating against the OpenNebula.org OCCI interface. :type headers: ``dict`` :param headers: Dictionary containing HTTP headers. :rtype: ``dict`` :return: Dictionary containing updated headers. """ if self.plain_auth: passwd = self.key else: passwd = hashlib.sha1(b(self.key)).hexdigest() headers['Authorization'] =\ ('Basic %s' % b64encode(b('%s:%s' % (self.user_id, passwd))).decode('utf-8')) return headers class OpenNebulaNodeSize(NodeSize): """ NodeSize class for the OpenNebula.org driver. """ def __init__(self, id, name, ram, disk, bandwidth, price, driver, cpu=None, vcpu=None): super(OpenNebulaNodeSize, self).__init__(id=id, name=name, ram=ram, disk=disk, bandwidth=bandwidth, price=price, driver=driver) self.cpu = cpu self.vcpu = vcpu def __repr__(self): return (('') % (self.id, self.name, self.ram, self.disk, self.bandwidth, self.price, self.driver.name, self.cpu, self.vcpu)) class OpenNebulaNetwork(object): """ Provide a common interface for handling networks of all types. Network objects are analogous to physical switches connecting two or more physical nodes together. The Network object provides the interface in libcloud through which we can manipulate networks in different cloud providers in the same way. Network objects don't actually do much directly themselves, instead the network driver handles the connection to the network. You don't normally create a network object yourself; instead you use a driver and then have that create the network for you. >>> from libcloud.compute.drivers.dummy import DummyNodeDriver >>> driver = DummyNodeDriver() >>> network = driver.create_network() >>> network = driver.list_networks()[0] >>> network.name 'dummy-1' """ def __init__(self, id, name, address, size, driver, extra=None): self.id = str(id) self.name = name self.address = address self.size = size self.driver = driver self.uuid = self.get_uuid() self.extra = extra or {} def get_uuid(self): """ Unique hash for this network. The hash is a function of an SHA1 hash of the network's ID and its driver which means that it should be unique between all networks. In some subclasses (e.g. GoGrid) there is no ID available so the public IP address is used. This means that, unlike a properly done system UUID, the same UUID may mean a different system install at a different time >>> from libcloud.network.drivers.dummy import DummyNetworkDriver >>> driver = DummyNetworkDriver() >>> network = driver.create_network() >>> network.get_uuid() 'd3748461511d8b9b0e0bfa0d4d3383a619a2bb9f' Note, for example, that this example will always produce the same UUID! :rtype: ``str`` :return: Unique identifier for this instance. """ return hashlib.sha1(b("%s:%s" % (self.id, self.driver.type))).hexdigest() def __repr__(self): return (('') % (self.uuid, self.name, self.address, self.size, self.driver.name)) class OpenNebulaNodeDriver(NodeDriver): """ OpenNebula.org node driver. """ connectionCls = OpenNebulaConnection name = 'OpenNebula' website = 'http://opennebula.org/' type = Provider.OPENNEBULA NODE_STATE_MAP = { 'INIT': NodeState.PENDING, 'PENDING': NodeState.PENDING, 'HOLD': NodeState.PENDING, 'ACTIVE': NodeState.RUNNING, 'STOPPED': NodeState.TERMINATED, 'SUSPENDED': NodeState.PENDING, 'DONE': NodeState.TERMINATED, 'FAILED': NodeState.TERMINATED} def __new__(cls, key, secret=None, api_version=DEFAULT_API_VERSION, **kwargs): if cls is OpenNebulaNodeDriver: if api_version in ['1.4']: cls = OpenNebula_1_4_NodeDriver elif api_version in ['2.0', '2.2']: cls = OpenNebula_2_0_NodeDriver elif api_version in ['3.0']: cls = OpenNebula_3_0_NodeDriver elif api_version in ['3.2']: cls = OpenNebula_3_2_NodeDriver elif api_version in ['3.6']: cls = OpenNebula_3_6_NodeDriver elif api_version in ['3.8']: cls = OpenNebula_3_8_NodeDriver if 'plain_auth' not in kwargs: kwargs['plain_auth'] = cls.plain_auth else: cls.plain_auth = kwargs['plain_auth'] else: raise NotImplementedError( "No OpenNebulaNodeDriver found for API version %s" % (api_version)) return super(OpenNebulaNodeDriver, cls).__new__(cls) def create_node(self, name, size, image, networks=None): """ Create a new OpenNebula node. @inherits: :class:`NodeDriver.create_node` :keyword networks: List of virtual networks to which this node should connect. (optional) :type networks: :class:`OpenNebulaNetwork` or ``list`` of :class:`OpenNebulaNetwork` """ compute = ET.Element('COMPUTE') name = ET.SubElement(compute, 'NAME') name.text = name instance_type = ET.SubElement(compute, 'INSTANCE_TYPE') instance_type.text = size.name storage = ET.SubElement(compute, 'STORAGE') ET.SubElement(storage, 'DISK', {'image': '%s' % (str(image.id))}) if networks: if not isinstance(networks, list): networks = [networks] networkGroup = ET.SubElement(compute, 'NETWORK') for network in networks: if network.address: ET.SubElement(networkGroup, 'NIC', {'network': '%s' % (str(network.id)), 'ip': network.address}) else: ET.SubElement(networkGroup, 'NIC', {'network': '%s' % (str(network.id))}) xml = ET.tostring(compute) node = self.connection.request('/compute', method='POST', data=xml).object return self._to_node(node) def destroy_node(self, node): url = '/compute/%s' % (str(node.id)) resp = self.connection.request(url, method='DELETE') return resp.status == httplib.OK def list_nodes(self): return self._to_nodes(self.connection.request('/compute').object) def list_images(self, location=None): return self._to_images(self.connection.request('/storage').object) def list_sizes(self, location=None): """ Return list of sizes on a provider. @inherits: :class:`NodeDriver.list_sizes` :return: List of compute node sizes supported by the cloud provider. :rtype: ``list`` of :class:`OpenNebulaNodeSize` """ return [ NodeSize(id=1, name='small', ram=None, disk=None, bandwidth=None, price=None, driver=self), NodeSize(id=2, name='medium', ram=None, disk=None, bandwidth=None, price=None, driver=self), NodeSize(id=3, name='large', ram=None, disk=None, bandwidth=None, price=None, driver=self), ] def list_locations(self): return [NodeLocation(0, '', '', self)] def ex_list_networks(self, location=None): """ List virtual networks on a provider. :param location: Location from which to request a list of virtual networks. (optional) :type location: :class:`NodeLocation` :return: List of virtual networks available to be connected to a compute node. :rtype: ``list`` of :class:`OpenNebulaNetwork` """ return self._to_networks(self.connection.request('/network').object) def ex_node_action(self, node, action): """ Build action representation and instruct node to commit action. Build action representation from the compute node ID, and the action which should be carried out on that compute node. Then instruct the node to carry out that action. :param node: Compute node instance. :type node: :class:`Node` :param action: Action to be carried out on the compute node. :type action: ``str`` :return: False if an HTTP Bad Request is received, else, True is returned. :rtype: ``bool`` """ compute_node_id = str(node.id) compute = ET.Element('COMPUTE') compute_id = ET.SubElement(compute, 'ID') compute_id.text = compute_node_id state = ET.SubElement(compute, 'STATE') state.text = action xml = ET.tostring(compute) url = '/compute/%s' % compute_node_id resp = self.connection.request(url, method='PUT', data=xml) if resp.status == httplib.BAD_REQUEST: return False else: return True def _to_images(self, object): """ Request a list of images and convert that list to a list of NodeImage objects. Request a list of images from the OpenNebula web interface, and issue a request to convert each XML object representation of an image to a NodeImage object. :rtype: ``list`` of :class:`NodeImage` :return: List of images. """ images = [] for element in object.findall('DISK'): image_id = element.attrib['href'].partition('/storage/')[2] image = self.connection.request( ('/storage/%s' % (image_id))).object images.append(self._to_image(image)) return images def _to_image(self, image): """ Take XML object containing an image description and convert to NodeImage object. :type image: :class:`ElementTree` :param image: XML representation of an image. :rtype: :class:`NodeImage` :return: The newly extracted :class:`NodeImage`. """ return NodeImage(id=image.findtext('ID'), name=image.findtext('NAME'), driver=self.connection.driver, extra={'size': image.findtext('SIZE'), 'url': image.findtext('URL')}) def _to_networks(self, object): """ Request a list of networks and convert that list to a list of OpenNebulaNetwork objects. Request a list of networks from the OpenNebula web interface, and issue a request to convert each XML object representation of a network to an OpenNebulaNetwork object. :rtype: ``list`` of :class:`OpenNebulaNetwork` :return: List of virtual networks. """ networks = [] for element in object.findall('NETWORK'): network_id = element.attrib['href'].partition('/network/')[2] network_element = self.connection.request( ('/network/%s' % (network_id))).object networks.append(self._to_network(network_element)) return networks def _to_network(self, element): """ Take XML object containing a network description and convert to OpenNebulaNetwork object. Take XML representation containing a network description and convert to OpenNebulaNetwork object. :rtype: :class:`OpenNebulaNetwork` :return: The newly extracted :class:`OpenNebulaNetwork`. """ return OpenNebulaNetwork(id=element.findtext('ID'), name=element.findtext('NAME'), address=element.findtext('ADDRESS'), size=element.findtext('SIZE'), driver=self.connection.driver) def _to_nodes(self, object): """ Request a list of compute nodes and convert that list to a list of Node objects. Request a list of compute nodes from the OpenNebula web interface, and issue a request to convert each XML object representation of a node to a Node object. :rtype: ``list`` of :class:`Node` :return: A list of compute nodes. """ computes = [] for element in object.findall('COMPUTE'): compute_id = element.attrib['href'].partition('/compute/')[2] compute = self.connection.request( ('/compute/%s' % (compute_id))).object computes.append(self._to_node(compute)) return computes def _to_node(self, compute): """ Take XML object containing a compute node description and convert to Node object. Take XML representation containing a compute node description and convert to Node object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: :class:`Node` :return: The newly extracted :class:`Node`. """ try: state = self.NODE_STATE_MAP[compute.findtext('STATE').upper()] except KeyError: state = NodeState.UNKNOWN return Node(id=compute.findtext('ID'), name=compute.findtext('NAME'), state=state, public_ips=self._extract_networks(compute), private_ips=[], driver=self.connection.driver, image=self._extract_images(compute)) def _extract_networks(self, compute): """ Extract networks from a compute node XML representation. Extract network descriptions from a compute node XML representation, converting each network to an OpenNebulaNetwork object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: ``list`` of :class:`OpenNebulaNetwork`s. :return: List of virtual networks attached to the compute node. """ networks = list() network_list = compute.find('NETWORK') for element in network_list.findall('NIC'): networks.append( OpenNebulaNetwork(id=element.attrib.get('network', None), name=None, address=element.attrib.get('ip', None), size=1, driver=self.connection.driver)) return networks def _extract_images(self, compute): """ Extract image disks from a compute node XML representation. Extract image disk descriptions from a compute node XML representation, converting the disks to an NodeImage object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: :class:`NodeImage`. :return: First disk attached to a compute node. """ disks = list() disk_list = compute.find('STORAGE') if disk_list is not None: for element in disk_list.findall('DISK'): disks.append( NodeImage(id=element.attrib.get('image', None), name=None, driver=self.connection.driver, extra={'dev': element.attrib.get('dev', None)})) # @TODO: Return all disks when the Node type accepts multiple # attached disks per node. if len(disks) > 0: return disks[0] else: return None class OpenNebula_1_4_NodeDriver(OpenNebulaNodeDriver): """ OpenNebula.org node driver for OpenNebula.org v1.4. """ name = 'OpenNebula (v1.4)' class OpenNebula_2_0_NodeDriver(OpenNebulaNodeDriver): """ OpenNebula.org node driver for OpenNebula.org v2.0 through OpenNebula.org v2.2. """ name = 'OpenNebula (v2.0 - v2.2)' def create_node(self, name, size, image, networks=None, context=None): """ Create a new OpenNebula node. @inherits: :class:`NodeDriver.create_node` :keyword networks: List of virtual networks to which this node should connect. (optional) :type networks: :class:`OpenNebulaNetwork` or ``list`` of :class:`OpenNebulaNetwork` :keyword context: Custom (key, value) pairs to be injected into compute node XML description. (optional) :type context: ``dict`` :return: Instance of a newly created node. :rtype: :class:`Node` """ compute = ET.Element('COMPUTE') name = ET.SubElement(compute, 'NAME') name.text = name instance_type = ET.SubElement(compute, 'INSTANCE_TYPE') instance_type.text = size.name disk = ET.SubElement(compute, 'DISK') ET.SubElement(disk, 'STORAGE', {'href': '/storage/%s' % (str(image.id))}) if networks: if not isinstance(networks, list): networks = [networks] for network in networks: nic = ET.SubElement(compute, 'NIC') ET.SubElement(nic, 'NETWORK', {'href': '/network/%s' % (str(network.id))}) if network.address: ip_line = ET.SubElement(nic, 'IP') ip_line.text = network.address if context and isinstance(context, dict): contextGroup = ET.SubElement(compute, 'CONTEXT') for key, value in list(context.items()): context = ET.SubElement(contextGroup, key.upper()) context.text = value xml = ET.tostring(compute) node = self.connection.request('/compute', method='POST', data=xml).object return self._to_node(node) def destroy_node(self, node): url = '/compute/%s' % (str(node.id)) resp = self.connection.request(url, method='DELETE') return resp.status == httplib.NO_CONTENT def list_sizes(self, location=None): """ Return list of sizes on a provider. @inherits: :class:`NodeDriver.list_sizes` :return: List of compute node sizes supported by the cloud provider. :rtype: ``list`` of :class:`OpenNebulaNodeSize` """ return [ OpenNebulaNodeSize(id=1, name='small', ram=1024, cpu=1, disk=None, bandwidth=None, price=None, driver=self), OpenNebulaNodeSize(id=2, name='medium', ram=4096, cpu=4, disk=None, bandwidth=None, price=None, driver=self), OpenNebulaNodeSize(id=3, name='large', ram=8192, cpu=8, disk=None, bandwidth=None, price=None, driver=self), OpenNebulaNodeSize(id=4, name='custom', ram=0, cpu=0, disk=None, bandwidth=None, price=None, driver=self), ] def _to_images(self, object): """ Request a list of images and convert that list to a list of NodeImage objects. Request a list of images from the OpenNebula web interface, and issue a request to convert each XML object representation of an image to a NodeImage object. :rtype: ``list`` of :class:`NodeImage` :return: List of images. """ images = [] for element in object.findall('STORAGE'): image_id = element.attrib["href"].partition("/storage/")[2] image = self.connection.request( ("/storage/%s" % (image_id))).object images.append(self._to_image(image)) return images def _to_image(self, image): """ Take XML object containing an image description and convert to NodeImage object. :type image: :class:`ElementTree` :param image: XML representation of an image. :rtype: :class:`NodeImage` :return: The newly extracted :class:`NodeImage`. """ return NodeImage(id=image.findtext('ID'), name=image.findtext('NAME'), driver=self.connection.driver, extra={'description': image.findtext('DESCRIPTION'), 'type': image.findtext('TYPE'), 'size': image.findtext('SIZE'), 'fstype': image.findtext('FSTYPE', None)}) def _to_node(self, compute): """ Take XML object containing a compute node description and convert to Node object. Take XML representation containing a compute node description and convert to Node object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: :class:`Node` :return: The newly extracted :class:`Node`. """ try: state = self.NODE_STATE_MAP[compute.findtext('STATE').upper()] except KeyError: state = NodeState.UNKNOWN return Node(id=compute.findtext('ID'), name=compute.findtext('NAME'), state=state, public_ips=self._extract_networks(compute), private_ips=[], driver=self.connection.driver, image=self._extract_images(compute), size=self._extract_size(compute), extra={'context': self._extract_context(compute)}) def _extract_networks(self, compute): """ Extract networks from a compute node XML representation. Extract network descriptions from a compute node XML representation, converting each network to an OpenNebulaNetwork object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: ``list`` of :class:`OpenNebulaNetwork` :return: List of virtual networks attached to the compute node. """ networks = [] for element in compute.findall('NIC'): network = element.find('NETWORK') network_id = network.attrib['href'].partition('/network/')[2] networks.append( OpenNebulaNetwork(id=network_id, name=network.attrib.get('name', None), address=element.findtext('IP'), size=1, driver=self.connection.driver, extra={'mac': element.findtext('MAC')})) return networks def _extract_images(self, compute): """ Extract image disks from a compute node XML representation. Extract image disk descriptions from a compute node XML representation, converting the disks to an NodeImage object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: ``list`` of :class:`NodeImage` :return: Disks attached to a compute node. """ disks = list() for element in compute.findall('DISK'): disk = element.find('STORAGE') image_id = disk.attrib['href'].partition('/storage/')[2] if 'id' in element.attrib: disk_id = element.attrib['id'] else: disk_id = None disks.append( NodeImage(id=image_id, name=disk.attrib.get('name', None), driver=self.connection.driver, extra={'type': element.findtext('TYPE'), 'disk_id': disk_id, 'target': element.findtext('TARGET')})) # Return all disks when the Node type accepts multiple attached disks # per node. if len(disks) > 1: return disks elif len(disks) == 1: return disks[0] else: return None def _extract_size(self, compute): """ Extract size, or node type, from a compute node XML representation. Extract node size, or node type, description from a compute node XML representation, converting the node size to a NodeSize object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: :class:`OpenNebulaNodeSize` :return: Node type of compute node. """ instance_type = compute.find('INSTANCE_TYPE') try: return next((node_size for node_size in self.list_sizes() if node_size.name == instance_type.text)) except StopIteration: return None def _extract_context(self, compute): """ Extract size, or node type, from a compute node XML representation. Extract node size, or node type, description from a compute node XML representation, converting the node size to a NodeSize object. :type compute: :class:`ElementTree` :param compute: XML representation of a compute node. :rtype: ``dict`` :return: Dictionary containing (key, value) pairs related to compute node context. """ contexts = dict() context = compute.find('CONTEXT') if context is not None: for context_element in list(context): contexts[context_element.tag.lower()] = context_element.text return contexts class OpenNebula_3_0_NodeDriver(OpenNebula_2_0_NodeDriver): """ OpenNebula.org node driver for OpenNebula.org v3.0. """ name = 'OpenNebula (v3.0)' def ex_node_set_save_name(self, node, name): """ Build action representation and instruct node to commit action. Build action representation from the compute node ID, the disk image which will be saved, and the name under which the image will be saved upon shutting down the compute node. :param node: Compute node instance. :type node: :class:`Node` :param name: Name under which the image should be saved after shutting down the compute node. :type name: ``str`` :return: False if an HTTP Bad Request is received, else, True is returned. :rtype: ``bool`` """ compute_node_id = str(node.id) compute = ET.Element('COMPUTE') compute_id = ET.SubElement(compute, 'ID') compute_id.text = compute_node_id disk = ET.SubElement(compute, 'DISK', {'id': str(node.image.id)}) ET.SubElement(disk, 'STORAGE', {'href': '/storage/%s' % (str(node.image.id)), 'name': node.image.name}) ET.SubElement(disk, 'SAVE_AS', {'name': str(name)}) xml = ET.tostring(compute) url = '/compute/%s' % compute_node_id resp = self.connection.request(url, method='PUT', data=xml) if resp.status == httplib.BAD_REQUEST: return False else: return True def _to_network(self, element): """ Take XML object containing a network description and convert to OpenNebulaNetwork object. Take XML representation containing a network description and convert to OpenNebulaNetwork object. :return: The newly extracted :class:`OpenNebulaNetwork`. :rtype: :class:`OpenNebulaNetwork` """ return OpenNebulaNetwork(id=element.findtext('ID'), name=element.findtext('NAME'), address=element.findtext('ADDRESS'), size=element.findtext('SIZE'), driver=self.connection.driver, extra={'public': element.findtext('PUBLIC')}) class OpenNebula_3_2_NodeDriver(OpenNebula_3_0_NodeDriver): """ OpenNebula.org node driver for OpenNebula.org v3.2. """ name = 'OpenNebula (v3.2)' def reboot_node(self, node): return self.ex_node_action(node, ACTION.REBOOT) def list_sizes(self, location=None): """ Return list of sizes on a provider. @inherits: :class:`NodeDriver.list_sizes` :return: List of compute node sizes supported by the cloud provider. :rtype: ``list`` of :class:`OpenNebulaNodeSize` """ return self._to_sizes(self.connection.request('/instance_type').object) def _to_sizes(self, object): """ Request a list of instance types and convert that list to a list of OpenNebulaNodeSize objects. Request a list of instance types from the OpenNebula web interface, and issue a request to convert each XML object representation of an instance type to an OpenNebulaNodeSize object. :return: List of instance types. :rtype: ``list`` of :class:`OpenNebulaNodeSize` """ sizes = [] size_id = 1 attributes = [('name', str, None), ('ram', int, 'MEMORY'), ('cpu', float, None), ('vcpu', float, None), ('disk', str, None), ('bandwidth', float, None), ('price', float, None)] for element in object.findall('INSTANCE_TYPE'): size_kwargs = {'id': size_id, 'driver': self} values = self._get_attributes_values(attributes=attributes, element=element) size_kwargs.update(values) size = OpenNebulaNodeSize(**size_kwargs) sizes.append(size) size_id += 1 return sizes def _get_attributes_values(self, attributes, element): values = {} for attribute_name, attribute_type, alias in attributes: key = alias if alias else attribute_name.upper() value = element.findtext(key) if value is not None: value = attribute_type(value) values[attribute_name] = value return values class OpenNebula_3_6_NodeDriver(OpenNebula_3_2_NodeDriver): """ OpenNebula.org node driver for OpenNebula.org v3.6. """ name = 'OpenNebula (v3.6)' def create_volume(self, size, name, location=None, snapshot=None): storage = ET.Element('STORAGE') vol_name = ET.SubElement(storage, 'NAME') vol_name.text = name vol_type = ET.SubElement(storage, 'TYPE') vol_type.text = 'DATABLOCK' description = ET.SubElement(storage, 'DESCRIPTION') description.text = 'Attached storage' public = ET.SubElement(storage, 'PUBLIC') public.text = 'NO' persistent = ET.SubElement(storage, 'PERSISTENT') persistent.text = 'YES' fstype = ET.SubElement(storage, 'FSTYPE') fstype.text = 'ext3' vol_size = ET.SubElement(storage, 'SIZE') vol_size.text = str(size) xml = ET.tostring(storage) volume = self.connection.request('/storage', {'occixml': xml}, method='POST').object return self._to_volume(volume) def destroy_volume(self, volume): url = '/storage/%s' % (str(volume.id)) resp = self.connection.request(url, method='DELETE') return resp.status == httplib.NO_CONTENT def attach_volume(self, node, volume, device): action = ET.Element('ACTION') perform = ET.SubElement(action, 'PERFORM') perform.text = 'ATTACHDISK' params = ET.SubElement(action, 'PARAMS') ET.SubElement(params, 'STORAGE', {'href': '/storage/%s' % (str(volume.id))}) target = ET.SubElement(params, 'TARGET') target.text = device xml = ET.tostring(action) url = '/compute/%s/action' % node.id resp = self.connection.request(url, method='POST', data=xml) return resp.status == httplib.ACCEPTED def _do_detach_volume(self, node_id, disk_id): action = ET.Element('ACTION') perform = ET.SubElement(action, 'PERFORM') perform.text = 'DETACHDISK' params = ET.SubElement(action, 'PARAMS') ET.SubElement(params, 'DISK', {'id': disk_id}) xml = ET.tostring(action) url = '/compute/%s/action' % node_id resp = self.connection.request(url, method='POST', data=xml) return resp.status == httplib.ACCEPTED def detach_volume(self, volume): # We need to find the node using this volume for node in self.list_nodes(): if type(node.image) is not list: # This node has only one associated image. It is not the one we # are after. continue for disk in node.image: if disk.id == volume.id: # Node found. We can now detach the volume disk_id = disk.extra['disk_id'] return self._do_detach_volume(node.id, disk_id) return False def list_volumes(self): return self._to_volumes(self.connection.request('/storage').object) def _to_volume(self, storage): return StorageVolume(id=storage.findtext('ID'), name=storage.findtext('NAME'), size=int(storage.findtext('SIZE')), driver=self.connection.driver) def _to_volumes(self, object): volumes = [] for storage in object.findall('STORAGE'): storage_id = storage.attrib['href'].partition('/storage/')[2] volumes.append(self._to_volume( self.connection.request('/storage/%s' % storage_id).object)) return volumes class OpenNebula_3_8_NodeDriver(OpenNebula_3_6_NodeDriver): """ OpenNebula.org node driver for OpenNebula.org v3.8. """ name = 'OpenNebula (v3.8)' plain_auth = API_PLAIN_AUTH def _to_sizes(self, object): """ Request a list of instance types and convert that list to a list of OpenNebulaNodeSize objects. Request a list of instance types from the OpenNebula web interface, and issue a request to convert each XML object representation of an instance type to an OpenNebulaNodeSize object. :return: List of instance types. :rtype: ``list`` of :class:`OpenNebulaNodeSize` """ sizes = [] size_id = 1 attributes = [('name', str, None), ('ram', int, 'MEMORY'), ('cpu', float, None), ('vcpu', float, None), ('disk', str, None), ('bandwidth', float, None), ('price', float, None)] for element in object.findall('INSTANCE_TYPE'): element = self.connection.request( ('/instance_type/%s') % (element.attrib['name'])).object size_kwargs = {'id': size_id, 'driver': self} values = self._get_attributes_values(attributes=attributes, element=element) size_kwargs.update(values) size = OpenNebulaNodeSize(**size_kwargs) sizes.append(size) size_id += 1 return sizes def _ex_connection_class_kwargs(self): """ Set plain_auth as an extra :class:`OpenNebulaConnection_3_8` argument :return: ``dict`` of :class:`OpenNebulaConnection_3_8` input arguments """ return {'plain_auth': self.plain_auth} apache-libcloud-2.8.0/libcloud/compute/drivers/openstack.py0000664000175000017500000043114513577507766023752 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ OpenStack driver """ from libcloud.common.exceptions import BaseHTTPError from libcloud.utils.iso8601 import parse_date try: import simplejson as json except ImportError: import json import warnings import base64 from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.utils.py3 import next from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qs from libcloud.common.openstack import OpenStackBaseConnection from libcloud.common.openstack import OpenStackDriverMixin from libcloud.common.openstack import OpenStackException from libcloud.common.openstack import OpenStackResponse from libcloud.utils.networking import is_public_subnet from libcloud.compute.base import NodeSize, NodeImage, NodeImageMember, \ UuidMixin from libcloud.compute.base import (NodeDriver, Node, NodeLocation, StorageVolume, VolumeSnapshot) from libcloud.compute.base import KeyPair from libcloud.compute.types import NodeState, StorageVolumeState, Provider, \ VolumeSnapshotState, Type from libcloud.pricing import get_size_price from libcloud.utils.xml import findall from libcloud.utils.py3 import ET __all__ = [ 'OpenStack_1_0_Response', 'OpenStack_1_0_Connection', 'OpenStack_1_0_NodeDriver', 'OpenStack_1_0_SharedIpGroup', 'OpenStack_1_0_NodeIpAddresses', 'OpenStack_1_1_Response', 'OpenStack_1_1_Connection', 'OpenStack_1_1_NodeDriver', 'OpenStack_1_1_FloatingIpPool', 'OpenStack_2_FloatingIpPool', 'OpenStack_1_1_FloatingIpAddress', 'OpenStack_2_PortInterfaceState', 'OpenStack_2_PortInterface', 'OpenStackNodeDriver' ] ATOM_NAMESPACE = "http://www.w3.org/2005/Atom" DEFAULT_API_VERSION = '1.1' PAGINATION_LIMIT = 1000 class OpenStackComputeConnection(OpenStackBaseConnection): # default config for http://devstack.org/ service_type = 'compute' service_name = 'nova' service_region = 'RegionOne' class OpenStackImageConnection(OpenStackBaseConnection): service_type = 'image' service_name = 'glance' service_region = 'RegionOne' class OpenStackNetworkConnection(OpenStackBaseConnection): service_type = 'network' service_name = 'neutron' service_region = 'RegionOne' class OpenStackVolumeV2Connection(OpenStackBaseConnection): service_type = 'volumev2' service_name = 'cinderv2' service_region = 'RegionOne' class OpenStackNodeDriver(NodeDriver, OpenStackDriverMixin): """ Base OpenStack node driver. Should not be used directly. """ api_name = 'openstack' name = 'OpenStack' website = 'http://openstack.org/' NODE_STATE_MAP = { 'BUILD': NodeState.PENDING, 'REBUILD': NodeState.PENDING, 'ACTIVE': NodeState.RUNNING, 'SUSPENDED': NodeState.SUSPENDED, 'SHUTOFF': NodeState.STOPPED, 'DELETED': NodeState.TERMINATED, 'QUEUE_RESIZE': NodeState.PENDING, 'PREP_RESIZE': NodeState.PENDING, 'VERIFY_RESIZE': NodeState.RUNNING, 'PASSWORD': NodeState.PENDING, 'RESCUE': NodeState.PENDING, 'REBOOT': NodeState.REBOOTING, 'HARD_REBOOT': NodeState.REBOOTING, 'SHARE_IP': NodeState.PENDING, 'SHARE_IP_NO_CONFIG': NodeState.PENDING, 'DELETE_IP': NodeState.PENDING, 'ERROR': NodeState.ERROR, 'UNKNOWN': NodeState.UNKNOWN } # http://developer.openstack.org/api-ref-blockstorage-v2.html#volumes-v2 VOLUME_STATE_MAP = { 'creating': StorageVolumeState.CREATING, 'available': StorageVolumeState.AVAILABLE, 'attaching': StorageVolumeState.ATTACHING, 'in-use': StorageVolumeState.INUSE, 'deleting': StorageVolumeState.DELETING, 'error': StorageVolumeState.ERROR, 'error_deleting': StorageVolumeState.ERROR, 'backing-up': StorageVolumeState.BACKUP, 'restoring-backup': StorageVolumeState.BACKUP, 'error_restoring': StorageVolumeState.ERROR, 'error_extending': StorageVolumeState.ERROR, } # http://developer.openstack.org/api-ref-blockstorage-v2.html#ext-backups-v2 SNAPSHOT_STATE_MAP = { 'creating': VolumeSnapshotState.CREATING, 'available': VolumeSnapshotState.AVAILABLE, 'deleting': VolumeSnapshotState.DELETING, 'error': VolumeSnapshotState.ERROR, 'restoring': VolumeSnapshotState.RESTORING, 'error_restoring': VolumeSnapshotState.ERROR } def __new__(cls, key, secret=None, secure=True, host=None, port=None, api_version=DEFAULT_API_VERSION, **kwargs): if cls is OpenStackNodeDriver: if api_version == '1.0': cls = OpenStack_1_0_NodeDriver elif api_version == '1.1': cls = OpenStack_1_1_NodeDriver elif api_version in ['2.0', '2.1', '2.2']: cls = OpenStack_2_NodeDriver else: raise NotImplementedError( "No OpenStackNodeDriver found for API version %s" % (api_version)) return super(OpenStackNodeDriver, cls).__new__(cls) def __init__(self, *args, **kwargs): OpenStackDriverMixin.__init__(self, **kwargs) super(OpenStackNodeDriver, self).__init__(*args, **kwargs) @staticmethod def _paginated_request(url, obj, connection, params=None): """ Perform multiple calls in order to have a full list of elements when the API responses are paginated. :param url: API endpoint :type url: ``str`` :param obj: Result object key :type obj: ``str`` :param connection: The API connection to use to perform the request :type connection: ``obj`` :param params: Any request parameters :type params: ``dict`` :return: ``list`` of API response objects :rtype: ``list`` """ params = params or {} objects = list() loop_count = 0 while True: data = connection.request(url, params=params) values = data.object.get(obj, list()) objects.extend(values) links = data.object.get('%s_links' % obj, list()) next_links = [n for n in links if n['rel'] == 'next'] if next_links: next_link = next_links[0] query = urlparse.urlparse(next_link['href']) # The query[4] references the query parameters from the url params.update(parse_qs(query[4])) else: break # Prevent the pagination from looping indefinitely in case # the API returns a loop for some reason. loop_count += 1 if loop_count > PAGINATION_LIMIT: raise OpenStackException( 'Pagination limit reached for %s, the limit is %d. ' 'This might indicate that your API is returning a ' 'looping next target for pagination!' % ( url, PAGINATION_LIMIT ), None ) return {obj: objects} def destroy_node(self, node): uri = '/servers/%s' % (node.id) resp = self.connection.request(uri, method='DELETE') # The OpenStack and Rackspace documentation both say this API will # return a 204, but in-fact, everyone everywhere agrees it actually # returns a 202, so we are going to accept either, and someday, # someone will fix either the implementation or the documentation to # agree. return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def reboot_node(self, node): # pylint: disable=no-member return self._reboot_node(node, reboot_type='HARD') def start_node(self, node): # pylint: disable=no-member return self._post_simple_node_action(node, 'os-start') def stop_node(self, node): # pylint: disable=no-member return self._post_simple_node_action(node, 'os-stop') def list_nodes(self, ex_all_tenants=False): """ List the nodes in a tenant :param ex_all_tenants: List nodes for all the tenants. Note: Your user must have admin privileges for this functionality to work. :type ex_all_tenants: ``bool`` """ params = {} if ex_all_tenants: params = {'all_tenants': 1} # pylint: disable=no-member return self._to_nodes( self.connection.request('/servers/detail', params=params).object) def create_volume(self, size, name, location=None, snapshot=None, ex_volume_type=None): """ Create a new volume. :param size: Size of volume in gigabytes (required) :type size: ``int`` :param name: Name of the volume to be created :type name: ``str`` :param location: Which data center to create a volume in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param snapshot: Snapshot from which to create the new volume. (optional) :type snapshot: :class:`.VolumeSnapshot` :param ex_volume_type: What kind of volume to create. (optional) :type ex_volume_type: ``str`` :return: The newly created volume. :rtype: :class:`StorageVolume` """ volume = { 'display_name': name, 'display_description': name, 'size': size, 'metadata': { 'contents': name, }, } if ex_volume_type: volume['volume_type'] = ex_volume_type if location: volume['availability_zone'] = location if snapshot: volume['snapshot_id'] = snapshot.id resp = self.connection.request('/os-volumes', method='POST', data={'volume': volume}) # pylint: disable=no-member return self._to_volume(resp.object) def destroy_volume(self, volume): return self.connection.request('/os-volumes/%s' % volume.id, method='DELETE').success() def attach_volume(self, node, volume, device="auto"): # when "auto" or None is provided for device, openstack will let # the guest OS pick the next available device (fi. /dev/vdb) return self.connection.request( '/servers/%s/os-volume_attachments' % node.id, method='POST', data={ 'volumeAttachment': { 'volumeId': volume.id, 'device': device, } }).success() def detach_volume(self, volume, ex_node=None): # when ex_node is not provided, volume is detached from all nodes failed_nodes = [] for attachment in volume.extra['attachments']: if not ex_node or ex_node.id in filter(None, (attachment.get( 'serverId' ), attachment.get('server_id'))): response = self.connection.request( '/servers/%s/os-volume_attachments/%s' % (attachment.get('serverId') or attachment['server_id'], attachment['id']), method='DELETE') if not response.success(): failed_nodes.append( attachment.get('serverId') or attachment['server_id'] ) if failed_nodes: raise OpenStackException( 'detach_volume failed for nodes with id: %s' % ', '.join(failed_nodes), 500, self ) return True def list_volumes(self): # pylint: disable=no-member return self._to_volumes( self.connection.request('/os-volumes').object) def ex_get_volume(self, volumeId): # pylint: disable=no-member return self._to_volume( self.connection.request('/os-volumes/%s' % volumeId).object) def list_images(self, location=None, ex_only_active=True): """ Lists all active images @inherits: :class:`NodeDriver.list_images` :param ex_only_active: True if list only active (optional) :type ex_only_active: ``bool`` """ # pylint: disable=no-member return self._to_images( self.connection.request('/images/detail').object, ex_only_active) def get_image(self, image_id): """ Get an image based on an image_id @inherits: :class:`NodeDriver.get_image` :param image_id: Image identifier :type image_id: ``str`` :return: A NodeImage object :rtype: :class:`NodeImage` """ # pylint: disable=no-member return self._to_image(self.connection.request( '/images/%s' % (image_id,)).object['image']) def list_sizes(self, location=None): # pylint: disable=no-member return self._to_sizes( self.connection.request('/flavors/detail').object) def list_locations(self): return [NodeLocation(0, '', '', self)] def _ex_connection_class_kwargs(self): return self.openstack_connection_kwargs() def ex_get_node_details(self, node_id): """ Lists details of the specified server. :param node_id: ID of the node which should be used :type node_id: ``str`` :rtype: :class:`Node` """ # @TODO: Remove this if in 0.6 if isinstance(node_id, Node): node_id = node_id.id uri = '/servers/%s' % (node_id) try: resp = self.connection.request(uri, method='GET') except BaseHTTPError as e: if e.code == httplib.NOT_FOUND: return None raise # pylint: disable=no-member return self._to_node_from_obj(resp.object) def ex_soft_reboot_node(self, node): """ Soft reboots the specified server :param node: node :type node: :class:`Node` :rtype: ``bool`` """ # pylint: disable=no-member return self._reboot_node(node, reboot_type='SOFT') def ex_hard_reboot_node(self, node): """ Hard reboots the specified server :param node: node :type node: :class:`Node` :rtype: ``bool`` """ # pylint: disable=no-member return self._reboot_node(node, reboot_type='HARD') class OpenStackNodeSize(NodeSize): """ NodeSize class for the OpenStack.org driver. Following the example of OpenNebula.org driver and following guidelines: https://issues.apache.org/jira/browse/LIBCLOUD-119 """ def __init__(self, id, name, ram, disk, bandwidth, price, driver, vcpus=None, ephemeral_disk=None, swap=None, extra=None): super(OpenStackNodeSize, self).__init__(id=id, name=name, ram=ram, disk=disk, bandwidth=bandwidth, price=price, driver=driver) self.vcpus = vcpus self.ephemeral_disk = ephemeral_disk self.swap = swap self.extra = extra def __repr__(self): return (('') % (self.id, self.name, self.ram, self.disk, self.bandwidth, self.price, self.driver.name, self.vcpus)) class OpenStack_1_0_Response(OpenStackResponse): def __init__(self, *args, **kwargs): # done because of a circular reference from # NodeDriver -> Connection -> Response self.node_driver = OpenStack_1_0_NodeDriver super(OpenStack_1_0_Response, self).__init__(*args, **kwargs) class OpenStack_1_0_Connection(OpenStackComputeConnection): responseCls = OpenStack_1_0_Response default_content_type = 'application/xml; charset=UTF-8' accept_format = 'application/xml' XML_NAMESPACE = 'http://docs.rackspacecloud.com/servers/api/v1.0' class OpenStack_1_0_NodeDriver(OpenStackNodeDriver): """ OpenStack node driver. Extra node attributes: - password: root password, available after create. - hostId: represents the host your cloud server runs on - imageId: id of image - flavorId: id of flavor """ connectionCls = OpenStack_1_0_Connection type = Provider.OPENSTACK features = {'create_node': ['generates_password']} def __init__(self, *args, **kwargs): self._ex_force_api_version = str(kwargs.pop('ex_force_api_version', None)) self.XML_NAMESPACE = self.connectionCls.XML_NAMESPACE super(OpenStack_1_0_NodeDriver, self).__init__(*args, **kwargs) def _to_images(self, object, ex_only_active): images = [] for image in findall(object, 'image', self.XML_NAMESPACE): if ex_only_active and image.get('status') != 'ACTIVE': continue images.append(self._to_image(image)) return images def _to_image(self, element): return NodeImage(id=element.get('id'), name=element.get('name'), driver=self.connection.driver, extra={'updated': element.get('updated'), 'created': element.get('created'), 'status': element.get('status'), 'serverId': element.get('serverId'), 'progress': element.get('progress'), 'minDisk': element.get('minDisk'), 'minRam': element.get('minRam') } ) def _change_password_or_name(self, node, name=None, password=None): uri = '/servers/%s' % (node.id) if not name: name = node.name body = {'xmlns': self.XML_NAMESPACE, 'name': name} if password is not None: body['adminPass'] = password server_elm = ET.Element('server', body) resp = self.connection.request( uri, method='PUT', data=ET.tostring(server_elm)) if resp.status == httplib.NO_CONTENT and password is not None: node.extra['password'] = password return resp.status == httplib.NO_CONTENT def create_node(self, name, size, image, ex_metadata=None, ex_files=None, ex_shared_ip_group=None, ex_shared_ip_group_id=None): """ Create a new node @inherits: :class:`NodeDriver.create_node` :keyword ex_metadata: Key/Value metadata to associate with a node :type ex_metadata: ``dict`` :keyword ex_files: File Path => File contents to create on the node :type ex_files: ``dict`` :keyword ex_shared_ip_group_id: The server is launched into that shared IP group :type ex_shared_ip_group_id: ``str`` """ attributes = {'xmlns': self.XML_NAMESPACE, 'name': name, 'imageId': str(image.id), 'flavorId': str(size.id)} if ex_shared_ip_group: # Deprecate this. Be explicit and call the variable # ex_shared_ip_group_id since user needs to pass in the id, not the # name. warnings.warn('ex_shared_ip_group argument is deprecated.' ' Please use ex_shared_ip_group_id') if ex_shared_ip_group_id: attributes['sharedIpGroupId'] = ex_shared_ip_group_id server_elm = ET.Element('server', attributes) metadata_elm = self._metadata_to_xml(ex_metadata or {}) if metadata_elm: server_elm.append(metadata_elm) files_elm = self._files_to_xml(ex_files or {}) if files_elm: server_elm.append(files_elm) resp = self.connection.request("/servers", method='POST', data=ET.tostring(server_elm)) return self._to_node(resp.object) def ex_set_password(self, node, password): """ Sets the Node's root password. This will reboot the instance to complete the operation. :class:`Node.extra['password']` will be set to the new value if the operation was successful. :param node: node to set password :type node: :class:`Node` :param password: new password. :type password: ``str`` :rtype: ``bool`` """ return self._change_password_or_name(node, password=password) def ex_set_server_name(self, node, name): """ Sets the Node's name. This will reboot the instance to complete the operation. :param node: node to set name :type node: :class:`Node` :param name: new name :type name: ``str`` :rtype: ``bool`` """ return self._change_password_or_name(node, name=name) def ex_resize_node(self, node, size): """ Change an existing server flavor / scale the server up or down. :param node: node to resize. :type node: :class:`Node` :param size: new size. :type size: :class:`NodeSize` :rtype: ``bool`` """ elm = ET.Element( 'resize', {'xmlns': self.XML_NAMESPACE, 'flavorId': str(size.id)} ) resp = self.connection.request("/servers/%s/action" % (node.id), method='POST', data=ET.tostring(elm)) return resp.status == httplib.ACCEPTED def ex_resize(self, node, size): """ NOTE: This method is here for backward compatibility reasons. You should use ``ex_resize_node`` instead. """ return self.ex_resize_node(node=node, size=size) def ex_confirm_resize(self, node): """ Confirm a resize request which is currently in progress. If a resize request is not explicitly confirmed or reverted it's automatically confirmed after 24 hours. For more info refer to the API documentation: http://goo.gl/zjFI1 :param node: node for which the resize request will be confirmed. :type node: :class:`Node` :rtype: ``bool`` """ elm = ET.Element( 'confirmResize', {'xmlns': self.XML_NAMESPACE}, ) resp = self.connection.request("/servers/%s/action" % (node.id), method='POST', data=ET.tostring(elm)) return resp.status == httplib.NO_CONTENT def ex_revert_resize(self, node): """ Revert a resize request which is currently in progress. All resizes are automatically confirmed after 24 hours if they have not already been confirmed explicitly or reverted. For more info refer to the API documentation: http://goo.gl/AizBu :param node: node for which the resize request will be reverted. :type node: :class:`Node` :rtype: ``bool`` """ elm = ET.Element( 'revertResize', {'xmlns': self.XML_NAMESPACE} ) resp = self.connection.request("/servers/%s/action" % (node.id), method='POST', data=ET.tostring(elm)) return resp.status == httplib.NO_CONTENT def ex_rebuild(self, node_id, image_id): """ Rebuilds the specified server. :param node_id: ID of the node which should be used :type node_id: ``str`` :param image_id: ID of the image which should be used :type image_id: ``str`` :rtype: ``bool`` """ # @TODO: Remove those ifs in 0.6 if isinstance(node_id, Node): node_id = node_id.id if isinstance(image_id, NodeImage): image_id = image_id.id elm = ET.Element( 'rebuild', {'xmlns': self.XML_NAMESPACE, 'imageId': image_id} ) resp = self.connection.request("/servers/%s/action" % node_id, method='POST', data=ET.tostring(elm)) return resp.status == httplib.ACCEPTED def ex_create_ip_group(self, group_name, node_id=None): """ Creates a shared IP group. :param group_name: group name which should be used :type group_name: ``str`` :param node_id: ID of the node which should be used :type node_id: ``str`` :rtype: ``bool`` """ # @TODO: Remove this if in 0.6 if isinstance(node_id, Node): node_id = node_id.id group_elm = ET.Element( 'sharedIpGroup', {'xmlns': self.XML_NAMESPACE, 'name': group_name} ) if node_id: ET.SubElement( group_elm, 'server', {'id': node_id} ) resp = self.connection.request('/shared_ip_groups', method='POST', data=ET.tostring(group_elm)) return self._to_shared_ip_group(resp.object) def ex_list_ip_groups(self, details=False): """ Lists IDs and names for shared IP groups. If details lists all details for shared IP groups. :param details: True if details is required :type details: ``bool`` :rtype: ``list`` of :class:`OpenStack_1_0_SharedIpGroup` """ uri = '/shared_ip_groups/detail' if details else '/shared_ip_groups' resp = self.connection.request(uri, method='GET') groups = findall(resp.object, 'sharedIpGroup', self.XML_NAMESPACE) return [self._to_shared_ip_group(el) for el in groups] def ex_delete_ip_group(self, group_id): """ Deletes the specified shared IP group. :param group_id: group id which should be used :type group_id: ``str`` :rtype: ``bool`` """ uri = '/shared_ip_groups/%s' % group_id resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.NO_CONTENT def ex_share_ip(self, group_id, node_id, ip, configure_node=True): """ Shares an IP address to the specified server. :param group_id: group id which should be used :type group_id: ``str`` :param node_id: ID of the node which should be used :type node_id: ``str`` :param ip: ip which should be used :type ip: ``str`` :param configure_node: configure node :type configure_node: ``bool`` :rtype: ``bool`` """ # @TODO: Remove this if in 0.6 if isinstance(node_id, Node): node_id = node_id.id if configure_node: str_configure = 'true' else: str_configure = 'false' elm = ET.Element( 'shareIp', {'xmlns': self.XML_NAMESPACE, 'sharedIpGroupId': group_id, 'configureServer': str_configure}, ) uri = '/servers/%s/ips/public/%s' % (node_id, ip) resp = self.connection.request(uri, method='PUT', data=ET.tostring(elm)) return resp.status == httplib.ACCEPTED def ex_unshare_ip(self, node_id, ip): """ Removes a shared IP address from the specified server. :param node_id: ID of the node which should be used :type node_id: ``str`` :param ip: ip which should be used :type ip: ``str`` :rtype: ``bool`` """ # @TODO: Remove this if in 0.6 if isinstance(node_id, Node): node_id = node_id.id uri = '/servers/%s/ips/public/%s' % (node_id, ip) resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.ACCEPTED def ex_list_ip_addresses(self, node_id): """ List all server addresses. :param node_id: ID of the node which should be used :type node_id: ``str`` :rtype: :class:`OpenStack_1_0_NodeIpAddresses` """ # @TODO: Remove this if in 0.6 if isinstance(node_id, Node): node_id = node_id.id uri = '/servers/%s/ips' % node_id resp = self.connection.request(uri, method='GET') return self._to_ip_addresses(resp.object) def _metadata_to_xml(self, metadata): if not metadata: return None metadata_elm = ET.Element('metadata') for k, v in list(metadata.items()): meta_elm = ET.SubElement(metadata_elm, 'meta', {'key': str(k)}) meta_elm.text = str(v) return metadata_elm def _files_to_xml(self, files): if not files: return None personality_elm = ET.Element('personality') for k, v in list(files.items()): file_elm = ET.SubElement(personality_elm, 'file', {'path': str(k)}) file_elm.text = base64.b64encode(b(v)).decode('ascii') return personality_elm def _reboot_node(self, node, reboot_type='SOFT'): resp = self._node_action(node, ['reboot', ('type', reboot_type)]) return resp.status == httplib.ACCEPTED def _node_action(self, node, body): if isinstance(body, list): attr = ' '.join(['%s="%s"' % (item[0], item[1]) for item in body[1:]]) body = '<%s xmlns="%s" %s/>' % (body[0], self.XML_NAMESPACE, attr) uri = '/servers/%s/action' % (node.id) resp = self.connection.request(uri, method='POST', data=body) return resp def _to_nodes(self, object): node_elements = findall(object, 'server', self.XML_NAMESPACE) return [self._to_node(el) for el in node_elements] def _to_node_from_obj(self, obj): return self._to_node(findall(obj, 'server', self.XML_NAMESPACE)[0]) def _to_node(self, el): def get_ips(el): return [ip.get('addr') for ip in el] def get_meta_dict(el): d = {} for meta in el: d[meta.get('key')] = meta.text return d public_ip = get_ips(findall(el, 'addresses/public/ip', self.XML_NAMESPACE)) private_ip = get_ips(findall(el, 'addresses/private/ip', self.XML_NAMESPACE)) metadata = get_meta_dict(findall(el, 'metadata/meta', self.XML_NAMESPACE)) n = Node(id=el.get('id'), name=el.get('name'), state=self.NODE_STATE_MAP.get( el.get('status'), NodeState.UNKNOWN), public_ips=public_ip, private_ips=private_ip, driver=self.connection.driver, # pylint: disable=no-member extra={ 'password': el.get('adminPass'), 'hostId': el.get('hostId'), 'imageId': el.get('imageId'), 'flavorId': el.get('flavorId'), 'uri': "https://%s%s/servers/%s" % ( self.connection.host, self.connection.request_path, el.get('id')), 'service_name': self.connection.get_service_name(), 'metadata': metadata}) return n def _to_sizes(self, object): elements = findall(object, 'flavor', self.XML_NAMESPACE) return [self._to_size(el) for el in elements] def _to_size(self, el): vcpus = int(el.get('vcpus')) if el.get('vcpus', None) else None return OpenStackNodeSize(id=el.get('id'), name=el.get('name'), ram=int(el.get('ram')), disk=int(el.get('disk')), # XXX: needs hardcode vcpus=vcpus, bandwidth=None, extra=el.get('extra_specs'), # Hardcoded price=self._get_size_price(el.get('id')), driver=self.connection.driver) def ex_limits(self): """ Extra call to get account's limits, such as rates (for example amount of POST requests per day) and absolute limits like total amount of available RAM to be used by servers. :return: dict with keys 'rate' and 'absolute' :rtype: ``dict`` """ def _to_rate(el): rate = {} for item in list(el.items()): rate[item[0]] = item[1] return rate def _to_absolute(el): return {el.get('name'): el.get('value')} limits = self.connection.request("/limits").object rate = [_to_rate(el) for el in findall(limits, 'rate/limit', self.XML_NAMESPACE)] absolute = {} for item in findall(limits, 'absolute/limit', self.XML_NAMESPACE): absolute.update(_to_absolute(item)) return {"rate": rate, "absolute": absolute} def create_image(self, node, name, description=None, reboot=True): """Create an image for node. @inherits: :class:`NodeDriver.create_image` :param node: node to use as a base for image :type node: :class:`Node` :param name: name for new image :type name: ``str`` :rtype: :class:`NodeImage` """ image_elm = ET.Element( 'image', {'xmlns': self.XML_NAMESPACE, 'name': name, 'serverId': node.id} ) return self._to_image( self.connection.request("/images", method="POST", data=ET.tostring(image_elm)).object) def delete_image(self, image): """Delete an image for node. @inherits: :class:`NodeDriver.delete_image` :param image: the image to be deleted :type image: :class:`NodeImage` :rtype: ``bool`` """ uri = '/images/%s' % image.id resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.NO_CONTENT def _to_shared_ip_group(self, el): servers_el = findall(el, 'servers', self.XML_NAMESPACE) if servers_el: servers = [s.get('id') for s in findall(servers_el[0], 'server', self.XML_NAMESPACE)] else: servers = None return OpenStack_1_0_SharedIpGroup(id=el.get('id'), name=el.get('name'), servers=servers) def _to_ip_addresses(self, el): public_ips = [ip.get('addr') for ip in findall( findall(el, 'public', self.XML_NAMESPACE)[0], 'ip', self.XML_NAMESPACE)] private_ips = [ip.get('addr') for ip in findall( findall(el, 'private', self.XML_NAMESPACE)[0], 'ip', self.XML_NAMESPACE)] return OpenStack_1_0_NodeIpAddresses(public_ips, private_ips) def _get_size_price(self, size_id): try: return get_size_price(driver_type='compute', driver_name=self.api_name, size_id=size_id) except KeyError: return 0.0 class OpenStack_1_0_SharedIpGroup(object): """ Shared IP group info. """ def __init__(self, id, name, servers=None): self.id = str(id) self.name = name self.servers = servers class OpenStack_1_0_NodeIpAddresses(object): """ List of public and private IP addresses of a Node. """ def __init__(self, public_addresses, private_addresses): self.public_addresses = public_addresses self.private_addresses = private_addresses class OpenStack_1_1_Response(OpenStackResponse): def __init__(self, *args, **kwargs): # done because of a circular reference from # NodeDriver -> Connection -> Response self.node_driver = OpenStack_1_1_NodeDriver super(OpenStack_1_1_Response, self).__init__(*args, **kwargs) class OpenStackNetwork(object): """ A Virtual Network. """ def __init__(self, id, name, cidr, driver, extra=None): self.id = str(id) self.name = name self.cidr = cidr self.driver = driver self.extra = extra or {} def __repr__(self): return '' % (self.id, self.name, self.cidr,) class OpenStackSecurityGroup(object): """ A Security Group. """ def __init__(self, id, tenant_id, name, description, driver, rules=None, extra=None): """ Constructor. :keyword id: Group id. :type id: ``str`` :keyword tenant_id: Owner of the security group. :type tenant_id: ``str`` :keyword name: Human-readable name for the security group. Might not be unique. :type name: ``str`` :keyword description: Human-readable description of a security group. :type description: ``str`` :keyword rules: Rules associated with this group. :type rules: ``list`` of :class:`OpenStackSecurityGroupRule` :keyword extra: Extra attributes associated with this group. :type extra: ``dict`` """ self.id = id self.tenant_id = tenant_id self.name = name self.description = description self.driver = driver self.rules = rules or [] self.extra = extra or {} def __repr__(self): return ('' % (self.id, self.tenant_id, self.name, self.description)) class OpenStackSecurityGroupRule(object): """ A Rule of a Security Group. """ def __init__(self, id, parent_group_id, ip_protocol, from_port, to_port, driver, ip_range=None, group=None, tenant_id=None, direction=None, extra=None): """ Constructor. :keyword id: Rule id. :type id: ``str`` :keyword parent_group_id: ID of the parent security group. :type parent_group_id: ``str`` :keyword ip_protocol: IP Protocol (icmp, tcp, udp, etc). :type ip_protocol: ``str`` :keyword from_port: Port at start of range. :type from_port: ``int`` :keyword to_port: Port at end of range. :type to_port: ``int`` :keyword ip_range: CIDR for address range. :type ip_range: ``str`` :keyword group: Name of a source security group to apply to rule. :type group: ``str`` :keyword tenant_id: Owner of the security group. :type tenant_id: ``str`` :keyword direction: Security group Direction (ingress or egress). :type direction: ``str`` :keyword extra: Extra attributes associated with this rule. :type extra: ``dict`` """ self.id = id self.parent_group_id = parent_group_id self.ip_protocol = ip_protocol self.from_port = from_port self.to_port = to_port self.driver = driver self.ip_range = '' self.group = {} self.direction = 'ingress' if group is None: self.ip_range = ip_range else: self.group = {'name': group, 'tenant_id': tenant_id} # by default in old versions only ingress was used if direction is not None: if direction in ['ingress', 'egress']: self.direction = direction else: raise OpenStackException("Security group direction incorrect " "value: ingress or egress.", 500, driver) self.tenant_id = tenant_id self.extra = extra or {} def __repr__(self): return ('' % (self.id, self.parent_group_id, self.ip_protocol, self.from_port, self.to_port)) class OpenStackKeyPair(object): """ A KeyPair. """ def __init__(self, name, fingerprint, public_key, driver, private_key=None, extra=None): """ Constructor. :keyword name: Name of the KeyPair. :type name: ``str`` :keyword fingerprint: Fingerprint of the KeyPair :type fingerprint: ``str`` :keyword public_key: Public key in OpenSSH format. :type public_key: ``str`` :keyword private_key: Private key in PEM format. :type private_key: ``str`` :keyword extra: Extra attributes associated with this KeyPair. :type extra: ``dict`` """ self.name = name self.fingerprint = fingerprint self.public_key = public_key self.private_key = private_key self.driver = driver self.extra = extra or {} def __repr__(self): return ('' % (self.name, self.fingerprint, self.public_key)) class OpenStack_1_1_Connection(OpenStackComputeConnection): responseCls = OpenStack_1_1_Response accept_format = 'application/json' default_content_type = 'application/json; charset=UTF-8' def encode_data(self, data): return json.dumps(data) class OpenStack_1_1_NodeDriver(OpenStackNodeDriver): """ OpenStack node driver. """ connectionCls = OpenStack_1_1_Connection type = Provider.OPENSTACK features = {"create_node": ["generates_password"]} _networks_url_prefix = '/os-networks' def __init__(self, *args, **kwargs): self._ex_force_api_version = str(kwargs.pop('ex_force_api_version', None)) super(OpenStack_1_1_NodeDriver, self).__init__(*args, **kwargs) def create_node(self, name, size, image=None, ex_keyname=None, ex_userdata=None, ex_config_drive=None, ex_security_groups=None, ex_metadata=None, ex_files=None, networks=None, ex_disk_config=None, ex_admin_pass=None, ex_availability_zone=None, ex_blockdevicemappings=None): """Create a new node @inherits: :class:`NodeDriver.create_node` :keyword ex_keyname: The name of the key pair :type ex_keyname: ``str`` :keyword ex_userdata: String containing user data see https://help.ubuntu.com/community/CloudInit :type ex_userdata: ``str`` :keyword ex_config_drive: Enable config drive see http://docs.openstack.org/grizzly/openstack-compute/admin/content/config-drive.html :type ex_config_drive: ``bool`` :keyword ex_security_groups: List of security groups to assign to the node :type ex_security_groups: ``list`` of :class:`OpenStackSecurityGroup` :keyword ex_metadata: Key/Value metadata to associate with a node :type ex_metadata: ``dict`` :keyword ex_files: File Path => File contents to create on the node :type ex_files: ``dict`` :keyword networks: The server is launched into a set of Networks. :type networks: ``list`` of :class:`OpenStackNetwork` :keyword ex_disk_config: Name of the disk configuration. Can be either ``AUTO`` or ``MANUAL``. :type ex_disk_config: ``str`` :keyword ex_config_drive: If True enables metadata injection in a server through a configuration drive. :type ex_config_drive: ``bool`` :keyword ex_admin_pass: The root password for the node :type ex_admin_pass: ``str`` :keyword ex_availability_zone: Nova availability zone for the node :type ex_availability_zone: ``str`` """ ex_metadata = ex_metadata or {} ex_files = ex_files or {} networks = networks or [] ex_security_groups = ex_security_groups or [] server_params = self._create_args_to_params( node=None, name=name, size=size, image=image, ex_keyname=ex_keyname, ex_userdata=ex_userdata, ex_config_drive=ex_config_drive, ex_security_groups=ex_security_groups, ex_metadata=ex_metadata, ex_files=ex_files, networks=networks, ex_disk_config=ex_disk_config, ex_availability_zone=ex_availability_zone, ex_blockdevicemappings=ex_blockdevicemappings) resp = self.connection.request("/servers", method='POST', data={'server': server_params}) create_response = resp.object['server'] server_resp = self.connection.request( '/servers/%s' % create_response['id']) server_object = server_resp.object['server'] # adminPass is not always present # http://docs.openstack.org/essex/openstack-compute/admin/ # content/configuring-compute-API.html#d6e1833 server_object['adminPass'] = create_response.get('adminPass', None) return self._to_node(server_object) def _to_images(self, obj, ex_only_active): images = [] for image in obj['images']: if ex_only_active and image.get('status') != 'ACTIVE': continue images.append(self._to_image(image)) return images def _to_image(self, api_image): server = api_image.get('server', {}) updated = api_image.get('updated_at') or api_image['updated'] created = api_image.get('created_at') or api_image['created'] min_ram = api_image.get('min_ram') if min_ram is None: min_ram = api_image.get('minRam') min_disk = api_image.get('min_disk') if min_disk is None: min_disk = api_image.get('minDisk') return NodeImage( id=api_image['id'], name=api_image['name'], driver=self, extra=dict( visibility=api_image.get('visibility'), updated=updated, created=created, status=api_image['status'], progress=api_image.get('progress'), metadata=api_image.get('metadata'), os_type=api_image.get('os_type'), serverId=server.get('id'), minDisk=min_disk, minRam=min_ram, ) ) def _to_image_member(self, api_image_member): created = api_image_member['created_at'] updated = api_image_member.get('updated_at') return NodeImageMember( id=api_image_member['member_id'], image_id=api_image_member['image_id'], state=api_image_member['status'], created=created, driver=self, extra=dict( schema=api_image_member.get('schema'), updated=updated, ) ) def _to_nodes(self, obj): servers = obj['servers'] return [self._to_node(server) for server in servers] def _to_volumes(self, obj): volumes = obj['volumes'] return [self._to_volume(volume) for volume in volumes] def _to_snapshots(self, obj): snapshots = obj['snapshots'] return [self._to_snapshot(snapshot) for snapshot in snapshots] def _to_sizes(self, obj): flavors = obj['flavors'] return [self._to_size(flavor) for flavor in flavors] def _create_args_to_params(self, node, **kwargs): server_params = { 'name': kwargs.get('name'), 'metadata': kwargs.get('ex_metadata', {}) or {}, 'personality': self._files_to_personality(kwargs.get("ex_files", {}) or {}) } if kwargs.get('ex_availability_zone', None): server_params['availability_zone'] = kwargs['ex_availability_zone'] if kwargs.get('ex_keyname', None): server_params['key_name'] = kwargs['ex_keyname'] if kwargs.get('ex_userdata', None): server_params['user_data'] = base64.b64encode( b(kwargs['ex_userdata'])).decode('ascii') if kwargs.get('ex_disk_config', None): server_params['OS-DCF:diskConfig'] = kwargs['ex_disk_config'] if kwargs.get('ex_config_drive', None): server_params['config_drive'] = str(kwargs['ex_config_drive']) if kwargs.get('ex_admin_pass', None): server_params['adminPass'] = kwargs['ex_admin_pass'] if kwargs.get('networks', None): networks = kwargs['networks'] or [] networks = [{'uuid': network.id} for network in networks] server_params['networks'] = networks if kwargs.get('ex_security_groups', None): server_params['security_groups'] = [] for security_group in kwargs['ex_security_groups'] or []: name = security_group.name server_params['security_groups'].append({'name': name}) if kwargs.get('ex_blockdevicemappings', None): server_params['block_device_mapping_v2'] = \ kwargs['ex_blockdevicemappings'] if kwargs.get('name', None): server_params['name'] = kwargs.get('name') else: server_params['name'] = node.name if kwargs.get('image', None): server_params['imageRef'] = kwargs.get('image').id else: server_params['imageRef'] = node.extra.get( 'imageId', '' ) if node else '' if kwargs.get('size', None): server_params['flavorRef'] = kwargs.get('size').id else: server_params['flavorRef'] = node.extra.get('flavorId') return server_params def _files_to_personality(self, files): rv = [] for k, v in list(files.items()): rv.append({'path': k, 'contents': base64.b64encode(b(v))}) return rv def _reboot_node(self, node, reboot_type='SOFT'): resp = self._node_action(node, 'reboot', type=reboot_type) return resp.status == httplib.ACCEPTED def ex_set_password(self, node, password): """ Changes the administrator password for a specified server. :param node: Node to rebuild. :type node: :class:`Node` :param password: The administrator password. :type password: ``str`` :rtype: ``bool`` """ resp = self._node_action(node, 'changePassword', adminPass=password) node.extra['password'] = password return resp.status == httplib.ACCEPTED def ex_rebuild(self, node, image, **kwargs): """ Rebuild a Node. :param node: Node to rebuild. :type node: :class:`Node` :param image: New image to use. :type image: :class:`NodeImage` :keyword ex_metadata: Key/Value metadata to associate with a node :type ex_metadata: ``dict`` :keyword ex_files: File Path => File contents to create on the node :type ex_files: ``dict`` :keyword ex_keyname: Name of existing public key to inject into instance :type ex_keyname: ``str`` :keyword ex_userdata: String containing user data see https://help.ubuntu.com/community/CloudInit :type ex_userdata: ``str`` :keyword ex_security_groups: List of security groups to assign to the node :type ex_security_groups: ``list`` of :class:`OpenStackSecurityGroup` :keyword ex_disk_config: Name of the disk configuration. Can be either ``AUTO`` or ``MANUAL``. :type ex_disk_config: ``str`` :keyword ex_config_drive: If True enables metadata injection in a server through a configuration drive. :type ex_config_drive: ``bool`` :rtype: ``bool`` """ server_params = self._create_args_to_params(node, image=image, **kwargs) resp = self._node_action(node, 'rebuild', **server_params) return resp.status == httplib.ACCEPTED def ex_resize(self, node, size): """ Change a node size. :param node: Node to resize. :type node: :class:`Node` :type size: :class:`NodeSize` :param size: New size to use. :rtype: ``bool`` """ server_params = {'flavorRef': size.id} resp = self._node_action(node, 'resize', **server_params) return resp.status == httplib.ACCEPTED def ex_confirm_resize(self, node): """ Confirms a pending resize action. :param node: Node to resize. :type node: :class:`Node` :rtype: ``bool`` """ resp = self._node_action(node, 'confirmResize') return resp.status == httplib.NO_CONTENT def ex_revert_resize(self, node): """ Cancels and reverts a pending resize action. :param node: Node to resize. :type node: :class:`Node` :rtype: ``bool`` """ resp = self._node_action(node, 'revertResize') return resp.status == httplib.ACCEPTED def create_image(self, node, name, metadata=None): """ Creates a new image. :param node: Node :type node: :class:`Node` :param name: The name for the new image. :type name: ``str`` :param metadata: Key and value pairs for metadata. :type metadata: ``dict`` :rtype: :class:`NodeImage` """ optional_params = {} if metadata: optional_params['metadata'] = metadata resp = self._node_action(node, 'createImage', name=name, **optional_params) image_id = self._extract_image_id_from_url(resp.headers['location']) return self.get_image(image_id=image_id) def ex_set_server_name(self, node, name): """ Sets the Node's name. :param node: Node :type node: :class:`Node` :param name: The name of the server. :type name: ``str`` :rtype: :class:`Node` """ return self._update_node(node, name=name) def ex_get_metadata(self, node): """ Get a Node's metadata. :param node: Node :type node: :class:`Node` :return: Key/Value metadata associated with node. :rtype: ``dict`` """ return self.connection.request( '/servers/%s/metadata' % (node.id,), method='GET',).object['metadata'] def ex_set_metadata(self, node, metadata): """ Sets the Node's metadata. :param node: Node :type node: :class:`Node` :param metadata: Key/Value metadata to associate with a node :type metadata: ``dict`` :rtype: ``dict`` """ return self.connection.request( '/servers/%s/metadata' % (node.id,), method='PUT', data={'metadata': metadata} ).object['metadata'] def ex_update_node(self, node, **node_updates): """ Update the Node's editable attributes. The OpenStack API currently supports editing name and IPv4/IPv6 access addresses. The driver currently only supports updating the node name. :param node: Node :type node: :class:`Node` :keyword name: New name for the server :type name: ``str`` :rtype: :class:`Node` """ potential_data = self._create_args_to_params(node, **node_updates) updates = {'name': potential_data['name']} return self._update_node(node, **updates) def _to_networks(self, obj): networks = obj['networks'] return [self._to_network(network) for network in networks] def _to_network(self, obj): return OpenStackNetwork(id=obj['id'], name=obj['label'], cidr=obj.get('cidr', None), driver=self) def ex_list_networks(self): """ Get a list of Networks that are available. :rtype: ``list`` of :class:`OpenStackNetwork` """ response = self.connection.request(self._networks_url_prefix).object return self._to_networks(response) def ex_create_network(self, name, cidr): """ Create a new Network :param name: Name of network which should be used :type name: ``str`` :param cidr: cidr of network which should be used :type cidr: ``str`` :rtype: :class:`OpenStackNetwork` """ data = {'network': {'cidr': cidr, 'label': name}} response = self.connection.request(self._networks_url_prefix, method='POST', data=data).object return self._to_network(response['network']) def ex_delete_network(self, network): """ Delete a Network :param network: Network which should be used :type network: :class:`OpenStackNetwork` :rtype: ``bool`` """ resp = self.connection.request('%s/%s' % (self._networks_url_prefix, network.id), method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def ex_get_console_output(self, node, length=None): """ Get console output :param node: node :type node: :class:`Node` :param length: Optional number of lines to fetch from the console log :type length: ``int`` :return: Dictionary with the output :rtype: ``dict`` """ data = { "os-getConsoleOutput": { "length": length } } resp = self.connection.request('/servers/%s/action' % node.id, method='POST', data=data).object return resp def ex_list_snapshots(self): return self._to_snapshots( self.connection.request('/os-snapshots').object) def ex_get_snapshot(self, snapshotId): return self._to_snapshot( self.connection.request('/os-snapshots/%s' % snapshotId).object) def list_volume_snapshots(self, volume): return [snapshot for snapshot in self.ex_list_snapshots() if snapshot.extra['volume_id'] == volume.id] def create_volume_snapshot(self, volume, name=None, ex_description=None, ex_force=True): """ Create snapshot from volume :param volume: Instance of `StorageVolume` :type volume: `StorageVolume` :param name: Name of snapshot (optional) :type name: `str` | `NoneType` :param ex_description: Description of the snapshot (optional) :type ex_description: `str` | `NoneType` :param ex_force: Specifies if we create a snapshot that is not in state `available`. For example `in-use`. Defaults to True. (optional) :type ex_force: `bool` :rtype: :class:`VolumeSnapshot` """ data = {'snapshot': {'volume_id': volume.id, 'force': ex_force}} if name is not None: data['snapshot']['display_name'] = name if ex_description is not None: data['snapshot']['display_description'] = ex_description return self._to_snapshot(self.connection.request('/os-snapshots', method='POST', data=data).object) def destroy_volume_snapshot(self, snapshot): resp = self.connection.request('/os-snapshots/%s' % snapshot.id, method='DELETE') return resp.status == httplib.NO_CONTENT def ex_create_snapshot(self, volume, name, description=None, force=False): """ Create a snapshot based off of a volume. :param volume: volume :type volume: :class:`StorageVolume` :keyword name: New name for the volume snapshot :type name: ``str`` :keyword description: Description of the snapshot (optional) :type description: ``str`` :keyword force: Whether to force creation (optional) :type force: ``bool`` :rtype: :class:`VolumeSnapshot` """ warnings.warn('This method has been deprecated in favor of the ' 'create_volume_snapshot method') return self.create_volume_snapshot(volume, name, ex_description=description, ex_force=force) def ex_delete_snapshot(self, snapshot): """ Delete a VolumeSnapshot :param snapshot: snapshot :type snapshot: :class:`VolumeSnapshot` :rtype: ``bool`` """ warnings.warn('This method has been deprecated in favor of the ' 'destroy_volume_snapshot method') return self.destroy_volume_snapshot(snapshot) def _to_security_group_rules(self, obj): return [self._to_security_group_rule(security_group_rule) for security_group_rule in obj] def _to_security_group_rule(self, obj): ip_range = group = tenant_id = None if obj['group'] == {}: ip_range = obj['ip_range'].get('cidr', None) else: group = obj['group'].get('name', None) tenant_id = obj['group'].get('tenant_id', None) return OpenStackSecurityGroupRule( id=obj['id'], parent_group_id=obj['parent_group_id'], ip_protocol=obj['ip_protocol'], from_port=obj['from_port'], to_port=obj['to_port'], driver=self, ip_range=ip_range, group=group, tenant_id=tenant_id) def _to_security_groups(self, obj): security_groups = obj['security_groups'] return [self._to_security_group(security_group) for security_group in security_groups] def _to_security_group(self, obj): rules = self._to_security_group_rules(obj.get('security_group_rules', obj.get('rules', []))) return OpenStackSecurityGroup(id=obj['id'], tenant_id=obj['tenant_id'], name=obj['name'], description=obj.get('description', ''), rules=rules, driver=self) def ex_list_security_groups(self): """ Get a list of Security Groups that are available. :rtype: ``list`` of :class:`OpenStackSecurityGroup` """ return self._to_security_groups( self.connection.request('/os-security-groups').object) def ex_get_node_security_groups(self, node): """ Get Security Groups of the specified server. :rtype: ``list`` of :class:`OpenStackSecurityGroup` """ return self._to_security_groups( self.connection.request('/servers/%s/os-security-groups' % (node.id)).object) def ex_create_security_group(self, name, description): """ Create a new Security Group :param name: Name of the new Security Group :type name: ``str`` :param description: Description of the new Security Group :type description: ``str`` :rtype: :class:`OpenStackSecurityGroup` """ return self._to_security_group(self.connection.request( '/os-security-groups', method='POST', data={'security_group': {'name': name, 'description': description}} ).object['security_group']) def ex_delete_security_group(self, security_group): """ Delete a Security Group. :param security_group: Security Group should be deleted :type security_group: :class:`OpenStackSecurityGroup` :rtype: ``bool`` """ resp = self.connection.request('/os-security-groups/%s' % (security_group.id), method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def ex_create_security_group_rule(self, security_group, ip_protocol, from_port, to_port, cidr=None, source_security_group=None): """ Create a new Rule in a Security Group :param security_group: Security Group in which to add the rule :type security_group: :class:`OpenStackSecurityGroup` :param ip_protocol: Protocol to which this rule applies Examples: tcp, udp, ... :type ip_protocol: ``str`` :param from_port: First port of the port range :type from_port: ``int`` :param to_port: Last port of the port range :type to_port: ``int`` :param cidr: CIDR notation of the source IP range for this rule :type cidr: ``str`` :param source_security_group: Existing Security Group to use as the source (instead of CIDR) :type source_security_group: L{OpenStackSecurityGroup :rtype: :class:`OpenStackSecurityGroupRule` """ source_security_group_id = None if type(source_security_group) == OpenStackSecurityGroup: source_security_group_id = source_security_group.id return self._to_security_group_rule(self.connection.request( '/os-security-group-rules', method='POST', data={'security_group_rule': { 'ip_protocol': ip_protocol, 'from_port': from_port, 'to_port': to_port, 'cidr': cidr, 'group_id': source_security_group_id, 'parent_group_id': security_group.id}} ).object['security_group_rule']) def ex_delete_security_group_rule(self, rule): """ Delete a Rule from a Security Group. :param rule: Rule should be deleted :type rule: :class:`OpenStackSecurityGroupRule` :rtype: ``bool`` """ resp = self.connection.request('/os-security-group-rules/%s' % (rule.id), method='DELETE') return resp.status == httplib.NO_CONTENT def _to_key_pairs(self, obj): key_pairs = obj['keypairs'] key_pairs = [self._to_key_pair(key_pair['keypair']) for key_pair in key_pairs] return key_pairs def _to_key_pair(self, obj): key_pair = KeyPair(name=obj['name'], fingerprint=obj['fingerprint'], public_key=obj['public_key'], private_key=obj.get('private_key', None), driver=self) return key_pair def list_key_pairs(self): response = self.connection.request('/os-keypairs') key_pairs = self._to_key_pairs(response.object) return key_pairs def get_key_pair(self, name): self.connection.set_context({'key_pair_name': name}) response = self.connection.request('/os-keypairs/%s' % (name)) key_pair = self._to_key_pair(response.object['keypair']) return key_pair def create_key_pair(self, name): data = {'keypair': {'name': name}} response = self.connection.request('/os-keypairs', method='POST', data=data) key_pair = self._to_key_pair(response.object['keypair']) return key_pair def import_key_pair_from_string(self, name, key_material): data = {'keypair': {'name': name, 'public_key': key_material}} response = self.connection.request('/os-keypairs', method='POST', data=data) key_pair = self._to_key_pair(response.object['keypair']) return key_pair def delete_key_pair(self, key_pair): """ Delete a KeyPair. :param keypair: KeyPair to delete :type keypair: :class:`OpenStackKeyPair` :rtype: ``bool`` """ response = self.connection.request('/os-keypairs/%s' % (key_pair.name), method='DELETE') return response.status == httplib.ACCEPTED def ex_list_keypairs(self): """ Get a list of KeyPairs that are available. :rtype: ``list`` of :class:`OpenStackKeyPair` """ warnings.warn('This method has been deprecated in favor of ' 'list_key_pairs method') return self.list_key_pairs() def ex_create_keypair(self, name): """ Create a new KeyPair :param name: Name of the new KeyPair :type name: ``str`` :rtype: :class:`OpenStackKeyPair` """ warnings.warn('This method has been deprecated in favor of ' 'create_key_pair method') return self.create_key_pair(name=name) def ex_import_keypair(self, name, keyfile): """ Import a KeyPair from a file :param name: Name of the new KeyPair :type name: ``str`` :param keyfile: Path to the public key file (in OpenSSH format) :type keyfile: ``str`` :rtype: :class:`OpenStackKeyPair` """ warnings.warn('This method has been deprecated in favor of ' 'import_key_pair_from_file method') return self.import_key_pair_from_file(name=name, key_file_path=keyfile) def ex_import_keypair_from_string(self, name, key_material): """ Import a KeyPair from a string :param name: Name of the new KeyPair :type name: ``str`` :param key_material: Public key (in OpenSSH format) :type key_material: ``str`` :rtype: :class:`OpenStackKeyPair` """ warnings.warn('This method has been deprecated in favor of ' 'import_key_pair_from_string method') return self.import_key_pair_from_string(name=name, key_material=key_material) def ex_delete_keypair(self, keypair): """ Delete a KeyPair. :param keypair: KeyPair to delete :type keypair: :class:`OpenStackKeyPair` :rtype: ``bool`` """ warnings.warn('This method has been deprecated in favor of ' 'delete_key_pair method') return self.delete_key_pair(key_pair=keypair) def ex_get_size(self, size_id): """ Get a NodeSize :param size_id: ID of the size which should be used :type size_id: ``str`` :rtype: :class:`NodeSize` """ return self._to_size(self.connection.request( '/flavors/%s' % (size_id,)) .object['flavor']) def get_image(self, image_id): """ Get a NodeImage @inherits: :class:`NodeDriver.get_image` :param image_id: ID of the image which should be used :type image_id: ``str`` :rtype: :class:`NodeImage` """ return self._to_image(self.connection.request( '/images/%s' % (image_id,)).object['image']) def delete_image(self, image): """ Delete a NodeImage @inherits: :class:`NodeDriver.delete_image` :param image: image witch should be used :type image: :class:`NodeImage` :rtype: ``bool`` """ resp = self.connection.request('/images/%s' % (image.id,), method='DELETE') return resp.status == httplib.NO_CONTENT def _node_action(self, node, action, **params): params = params or None return self.connection.request('/servers/%s/action' % (node.id,), method='POST', data={action: params}) def _update_node(self, node, **node_updates): """ Updates the editable attributes of a server, which currently include its name and IPv4/IPv6 access addresses. """ return self._to_node( self.connection.request( '/servers/%s' % (node.id,), method='PUT', data={'server': node_updates} ).object['server'] ) def _to_node_from_obj(self, obj): return self._to_node(obj['server']) def _to_node(self, api_node): public_networks_labels = ['public', 'internet'] public_ips, private_ips = [], [] for label, values in api_node['addresses'].items(): for value in values: ip = value['addr'] is_public_ip = False try: is_public_ip = is_public_subnet(ip) except Exception: # IPv6 # Openstack Icehouse sets 'OS-EXT-IPS:type' to 'floating' # for public and 'fixed' for private explicit_ip_type = value.get('OS-EXT-IPS:type', None) if label in public_networks_labels: is_public_ip = True elif explicit_ip_type == 'floating': is_public_ip = True elif explicit_ip_type == 'fixed': is_public_ip = False if is_public_ip: public_ips.append(ip) else: private_ips.append(ip) # Sometimes 'image' attribute is not present if the node is in an error # state image = api_node.get('image', None) image_id = image.get('id', None) if image else None config_drive = api_node.get("config_drive", False) volumes_attached = api_node.get('os-extended-volumes:volumes_attached') created = parse_date(api_node["created"]) return Node( id=api_node['id'], name=api_node['name'], state=self.NODE_STATE_MAP.get(api_node['status'], NodeState.UNKNOWN), public_ips=public_ips, private_ips=private_ips, created_at=created, driver=self, extra=dict( addresses=api_node['addresses'], hostId=api_node['hostId'], access_ip=api_node.get('accessIPv4'), access_ipv6=api_node.get('accessIPv6', None), # Docs says "tenantId", but actual is "tenant_id". *sigh* # Best handle both. tenantId=api_node.get('tenant_id') or api_node['tenantId'], userId=api_node.get('user_id', None), imageId=image_id, flavorId=api_node['flavor']['id'], uri=next(link['href'] for link in api_node['links'] if link['rel'] == 'self'), # pylint: disable=no-member service_name=self.connection.get_service_name(), metadata=api_node['metadata'], password=api_node.get('adminPass', None), created=api_node['created'], updated=api_node['updated'], key_name=api_node.get('key_name', None), disk_config=api_node.get('OS-DCF:diskConfig', None), config_drive=config_drive, availability_zone=api_node.get('OS-EXT-AZ:availability_zone'), volumes_attached=volumes_attached, task_state=api_node.get("OS-EXT-STS:task_state", None), vm_state=api_node.get("OS-EXT-STS:vm_state", None), power_state=api_node.get("OS-EXT-STS:power_state", None), progress=api_node.get("progress", None), fault=api_node.get('fault') ), ) def _to_volume(self, api_node): if 'volume' in api_node: api_node = api_node['volume'] state = self.VOLUME_STATE_MAP.get(api_node['status'], StorageVolumeState.UNKNOWN) return StorageVolume( id=api_node['id'], name=api_node.get('displayName', api_node.get('name')), size=api_node['size'], state=state, driver=self, extra={ 'description': api_node.get('displayDescription', api_node.get('description')), 'attachments': [att for att in api_node['attachments'] if att], # TODO: remove in 1.18.0 'state': api_node.get('status', None), 'snapshot_id': api_node.get('snapshot_id', api_node.get('snapshotId')), 'location': api_node.get('availability_zone', api_node.get('availabilityZone')), 'volume_type': api_node.get('volume_type', api_node.get('volumeType')), 'metadata': api_node.get('metadata', None), 'created_at': api_node.get('created_at', api_node.get('createdAt')) } ) def _to_snapshot(self, data): if 'snapshot' in data: data = data['snapshot'] volume_id = data.get('volume_id', data.get('volumeId', None)) display_name = data.get('name', data.get('display_name', data.get('displayName', None))) created_at = data.get('created_at', data.get('createdAt', None)) description = data.get('description', data.get('display_description', data.get('displayDescription', None))) status = data.get('status', None) extra = {'volume_id': volume_id, 'name': display_name, 'created': created_at, 'description': description, 'status': status} state = self.SNAPSHOT_STATE_MAP.get( status, VolumeSnapshotState.UNKNOWN ) try: created_dt = parse_date(created_at) except ValueError: created_dt = None snapshot = VolumeSnapshot(id=data['id'], driver=self, size=data['size'], extra=extra, created=created_dt, state=state, name=display_name) return snapshot def _to_size(self, api_flavor, price=None, bandwidth=None): # if provider-specific subclasses can get better values for # price/bandwidth, then can pass them in when they super(). if not price: price = self._get_size_price(str(api_flavor['id'])) extra = api_flavor.get('OS-FLV-WITH-EXT-SPECS:extra_specs', {}) return OpenStackNodeSize( id=api_flavor['id'], name=api_flavor['name'], ram=api_flavor['ram'], disk=api_flavor['disk'], vcpus=api_flavor['vcpus'], ephemeral_disk=api_flavor.get('OS-FLV-EXT-DATA:ephemeral', None), swap=api_flavor['swap'], extra=extra, bandwidth=bandwidth, price=price, driver=self, ) def _get_size_price(self, size_id): try: return get_size_price( driver_type='compute', driver_name=self.api_name, size_id=size_id, ) except KeyError: return(0.0) def _extract_image_id_from_url(self, location_header): path = urlparse.urlparse(location_header).path image_id = path.split('/')[-1] return image_id def ex_rescue(self, node, password=None): # Requires Rescue Mode extension """ Rescue a node :param node: node :type node: :class:`Node` :param password: password :type password: ``str`` :rtype: :class:`Node` """ if password: resp = self._node_action(node, 'rescue', adminPass=password) else: resp = self._node_action(node, 'rescue') password = json.loads(resp.body)['adminPass'] node.extra['password'] = password return node def ex_unrescue(self, node): """ Unrescue a node :param node: node :type node: :class:`Node` :rtype: ``bool`` """ resp = self._node_action(node, 'unrescue') return resp.status == httplib.ACCEPTED def _to_floating_ip_pools(self, obj): pool_elements = obj['floating_ip_pools'] return [self._to_floating_ip_pool(pool) for pool in pool_elements] def _to_floating_ip_pool(self, obj): return OpenStack_1_1_FloatingIpPool(obj['name'], self.connection) def ex_list_floating_ip_pools(self): """ List available floating IP pools :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpPool` """ return self._to_floating_ip_pools( self.connection.request('/os-floating-ip-pools').object) def _to_floating_ips(self, obj): ip_elements = obj['floating_ips'] return [self._to_floating_ip(ip) for ip in ip_elements] def _to_floating_ip(self, obj): return OpenStack_1_1_FloatingIpAddress(id=obj['id'], ip_address=obj['ip'], pool=None, node_id=obj['instance_id'], driver=self) def ex_list_floating_ips(self): """ List floating IPs :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpAddress` """ return self._to_floating_ips( self.connection.request('/os-floating-ips').object) def ex_get_floating_ip(self, ip): """ Get specified floating IP :param ip: floating IP to get :type ip: ``str`` :rtype: :class:`OpenStack_1_1_FloatingIpAddress` """ floating_ips = self.ex_list_floating_ips() ip_obj, = [x for x in floating_ips if x.ip_address == ip] return ip_obj def ex_create_floating_ip(self, ip_pool=None): """ Create new floating IP. The ip_pool attribute is optional only if your infrastructure has only one IP pool available. :param ip_pool: name of the floating IP pool :type ip_pool: ``str`` :rtype: :class:`OpenStack_1_1_FloatingIpAddress` """ data = {'pool': ip_pool} if ip_pool is not None else {} resp = self.connection.request('/os-floating-ips', method='POST', data=data) data = resp.object['floating_ip'] id = data['id'] ip_address = data['ip'] return OpenStack_1_1_FloatingIpAddress(id=id, ip_address=ip_address, pool=None, node_id=None, driver=self) def ex_delete_floating_ip(self, ip): """ Delete specified floating IP :param ip: floating IP to remove :type ip: :class:`OpenStack_1_1_FloatingIpAddress` :rtype: ``bool`` """ resp = self.connection.request('/os-floating-ips/%s' % ip.id, method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def ex_attach_floating_ip_to_node(self, node, ip): """ Attach the floating IP to the node :param node: node :type node: :class:`Node` :param ip: floating IP to attach :type ip: ``str`` or :class:`OpenStack_1_1_FloatingIpAddress` :rtype: ``bool`` """ address = ip.ip_address if hasattr(ip, 'ip_address') else ip data = { 'addFloatingIp': {'address': address} } resp = self.connection.request('/servers/%s/action' % node.id, method='POST', data=data) return resp.status == httplib.ACCEPTED def ex_detach_floating_ip_from_node(self, node, ip): """ Detach the floating IP from the node :param node: node :type node: :class:`Node` :param ip: floating IP to remove :type ip: ``str`` or :class:`OpenStack_1_1_FloatingIpAddress` :rtype: ``bool`` """ address = ip.ip_address if hasattr(ip, 'ip_address') else ip data = { 'removeFloatingIp': {'address': address} } resp = self.connection.request('/servers/%s/action' % node.id, method='POST', data=data) return resp.status == httplib.ACCEPTED def ex_get_metadata_for_node(self, node): """ Return the metadata associated with the node. :param node: Node instance :type node: :class:`Node` :return: A dictionary or other mapping of strings to strings, associating tag names with tag values. :type tags: ``dict`` """ return node.extra['metadata'] def ex_pause_node(self, node): return self._post_simple_node_action(node, 'pause') def ex_unpause_node(self, node): return self._post_simple_node_action(node, 'unpause') def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_suspend_node(self, node): return self._post_simple_node_action(node, 'suspend') def ex_resume_node(self, node): return self._post_simple_node_action(node, 'resume') def _post_simple_node_action(self, node, action): """ Post a simple, data-less action to the OS node action endpoint :param `Node` node: :param str action: the action to call :return `bool`: a boolean that indicates success """ uri = '/servers/{node_id}/action'.format(node_id=node.id) resp = self.connection.request(uri, method='POST', data={action: None}) return resp.status == httplib.ACCEPTED class OpenStack_2_Connection(OpenStackComputeConnection): responseCls = OpenStack_1_1_Response accept_format = 'application/json' default_content_type = 'application/json; charset=UTF-8' def encode_data(self, data): return json.dumps(data) class OpenStack_2_ImageConnection(OpenStackImageConnection): responseCls = OpenStack_1_1_Response accept_format = 'application/json' default_content_type = 'application/json; charset=UTF-8' def encode_data(self, data): return json.dumps(data) class OpenStack_2_NetworkConnection(OpenStackNetworkConnection): responseCls = OpenStack_1_1_Response accept_format = 'application/json' default_content_type = 'application/json; charset=UTF-8' def encode_data(self, data): return json.dumps(data) class OpenStack_2_VolumeV2Connection(OpenStackVolumeV2Connection): responseCls = OpenStack_1_1_Response accept_format = 'application/json' default_content_type = 'application/json; charset=UTF-8' def encode_data(self, data): return json.dumps(data) class OpenStack_2_PortInterfaceState(Type): """ Standard states of OpenStack_2_PortInterfaceState """ BUILD = 'build' ACTIVE = 'active' DOWN = 'down' UNKNOWN = 'unknown' class OpenStack_2_NodeDriver(OpenStack_1_1_NodeDriver): """ OpenStack node driver. """ connectionCls = OpenStack_2_Connection # Previously all image functionality was available through the # compute API. This deprecated proxied API does not offer all # functionality that the Glance Image service API offers. # See https://developer.openstack.org/api-ref/compute/ # # > These APIs are proxy calls to the Image service. Nova has deprecated # > all the proxy APIs and users should use the native APIs instead. These # > will fail with a 404 starting from microversion 2.36. See: Relevant # > Image APIs. # # For example, managing image visibility and sharing machine # images across tenants can not be done using the proxied image API in the # compute endpoint, but it can be done with the Glance Image API. # See https://developer.openstack.org/api-ref/ # image/v2/index.html#list-image-members image_connectionCls = OpenStack_2_ImageConnection image_connection = None # Similarly not all node-related operations are exposed through the # compute API # See https://developer.openstack.org/api-ref/compute/ # For example, creating a new node in an OpenStack that is configured to # create a new port for every new instance will make it so that if that # port is detached it disappears. But if the port is manually created # beforehand using the neutron network API and node is booted with that # port pre-specified, then detaching that port later will result in that # becoming a re-attachable resource much like a floating ip. So because # even though this is the compute driver, we do connect to the networking # API here because some operations relevant for compute can only be # accessed from there. network_connectionCls = OpenStack_2_NetworkConnection network_connection = None # Similarly all image operations are noe exposed through the block-storage # API of the cinder service: # https://developer.openstack.org/api-ref/block-storage/ volumev2_connectionCls = OpenStack_2_VolumeV2Connection volumev2_connection = None type = Provider.OPENSTACK features = {"create_node": ["generates_password"]} _networks_url_prefix = '/v2.0/networks' _subnets_url_prefix = '/v2.0/subnets' PORT_INTERFACE_MAP = { 'BUILD': OpenStack_2_PortInterfaceState.BUILD, 'ACTIVE': OpenStack_2_PortInterfaceState.ACTIVE, 'DOWN': OpenStack_2_PortInterfaceState.DOWN, 'UNKNOWN': OpenStack_2_PortInterfaceState.UNKNOWN } def __init__(self, *args, **kwargs): original_connectionCls = self.connectionCls self._ex_force_api_version = str(kwargs.pop('ex_force_api_version', None)) if 'ex_force_auth_version' not in kwargs: kwargs['ex_force_auth_version'] = '3.x_password' original_ex_force_base_url = kwargs.get('ex_force_base_url') # We run the init once to get the Glance V2 API connection # and put that on the object under self.image_connection. if original_ex_force_base_url or kwargs.get('ex_force_image_url'): kwargs['ex_force_base_url'] = \ str(kwargs.pop('ex_force_image_url', original_ex_force_base_url)) self.connectionCls = self.image_connectionCls super(OpenStack_2_NodeDriver, self).__init__(*args, **kwargs) self.image_connection = self.connection # We run the init once to get the Cinder V2 API connection # and put that on the object under self.volumev2_connection. if original_ex_force_base_url or kwargs.get('ex_force_volume_url'): kwargs['ex_force_base_url'] = \ str(kwargs.pop('ex_force_volume_url', original_ex_force_base_url)) self.connectionCls = self.volumev2_connectionCls super(OpenStack_2_NodeDriver, self).__init__(*args, **kwargs) self.volumev2_connection = self.connection # We run the init once to get the Neutron V2 API connection # and put that on the object under self.network_connection. if original_ex_force_base_url or kwargs.get('ex_force_network_url'): kwargs['ex_force_base_url'] = \ str(kwargs.pop('ex_force_network_url', original_ex_force_base_url)) self.connectionCls = self.network_connectionCls super(OpenStack_2_NodeDriver, self).__init__(*args, **kwargs) self.network_connection = self.connection # We run the init once again to get the compute API connection # and that's put under self.connection as normal. self._ex_force_base_url = original_ex_force_base_url if original_ex_force_base_url: kwargs['ex_force_base_url'] = self._ex_force_base_url self.connectionCls = original_connectionCls super(OpenStack_2_NodeDriver, self).__init__(*args, **kwargs) def _to_port(self, element): created = element.get('created_at') updated = element.get('updated_at') return OpenStack_2_PortInterface( id=element['id'], state=self.PORT_INTERFACE_MAP.get( element.get('status'), OpenStack_2_PortInterfaceState.UNKNOWN ), created=created, driver=self, extra=dict( admin_state_up=element['admin_state_up'], allowed_address_pairs=element['allowed_address_pairs'], binding_vnic_type=element['binding:vnic_type'], device_id=element['device_id'], description=element['description'], device_owner=element['device_owner'], fixed_ips=element['fixed_ips'], mac_address=element['mac_address'], name=element['name'], network_id=element['network_id'], project_id=element.get('project_id', None), port_security_enabled=element.get('port_security_enabled', None), revision_number=element.get('revision_number', None), security_groups=element['security_groups'], tags=element.get('tags', None), tenant_id=element['tenant_id'], updated=updated, ) ) def list_nodes(self, ex_all_tenants=False): """ List the nodes in a tenant :param ex_all_tenants: List nodes for all the tenants. Note: Your user must have admin privileges for this functionality to work. :type ex_all_tenants: ``bool`` """ params = {} if ex_all_tenants: params = {'all_tenants': 1} return self._to_nodes(self._paginated_request( '/servers/detail', 'servers', self.connection, params=params)) def get_image(self, image_id): """ Get a NodeImage using the V2 Glance API @inherits: :class:`OpenStack_1_1_NodeDriver.get_image` :param image_id: ID of the image which should be used :type image_id: ``str`` :rtype: :class:`NodeImage` """ return self._to_image(self.image_connection.request( '/v2/images/%s' % (image_id,)).object) def list_images(self, location=None, ex_only_active=True): """ Lists all active images using the V2 Glance API @inherits: :class:`NodeDriver.list_images` :param location: Which data center to list the images in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param ex_only_active: True if list only active (optional) :type ex_only_active: ``bool`` """ if location is not None: raise NotImplementedError( "location in list_images is not implemented " "in the OpenStack_2_NodeDriver") if not ex_only_active: raise NotImplementedError( "ex_only_active in list_images is not implemented " "in the OpenStack_2_NodeDriver") response = self.image_connection.request('/v2/images') images = [] for image in response.object['images']: images.append(self._to_image(image)) return images def ex_update_image(self, image_id, data): """ Patch a NodeImage. Can be used to set visibility :param image_id: ID of the image which should be used :type image_id: ``str`` :param data: The data to PATCH, either a dict or a list for example: [ {'op': 'replace', 'path': '/visibility', 'value': 'shared'} ] :type data: ``dict|list`` :rtype: :class:`NodeImage` """ response = self.image_connection.request( '/v2/images/%s' % (image_id,), headers={'Content-type': 'application/' 'openstack-images-' 'v2.1-json-patch'}, method='PATCH', data=data ) return self._to_image(response.object) def ex_list_image_members(self, image_id): """ List all members of an image. See https://developer.openstack.org/api-ref/image/v2/index.html#sharing :param image_id: ID of the image of which the members should be listed :type image_id: ``str`` :rtype: ``list`` of :class:`NodeImageMember` """ response = self.image_connection.request( '/v2/images/%s/members' % (image_id,) ) image_members = [] for image_member in response.object['members']: image_members.append(self._to_image_member(image_member)) return image_members def ex_create_image_member(self, image_id, member_id): """ Give a project access to an image. The image should have visibility status 'shared'. Note that this is not an idempotent operation. If this action is attempted using a tenant that is already in the image members group the API will throw a Conflict (409). See the 'create-image-member' section on https://developer.openstack.org/api-ref/image/v2/index.html :param str image_id: The ID of the image to share with the specified tenant :param str member_id: The ID of the project / tenant (the image member) Note that this is the Keystone project ID and not the project name, so something like e2151b1fe02d4a8a2d1f5fc331522c0a :return None: :param image_id: ID of the image to share :type image_id: ``str`` :param project: ID of the project to give access to the image :type image_id: ``str`` :rtype: ``list`` of :class:`NodeImageMember` """ data = {'member': member_id} response = self.image_connection.request( '/v2/images/%s/members' % image_id, method='POST', data=data ) return self._to_image_member(response.object) def ex_get_image_member(self, image_id, member_id): """ Get a member of an image by id :param image_id: ID of the image of which the member should be listed :type image_id: ``str`` :param member_id: ID of the member to list :type image_id: ``str`` :rtype: ``list`` of :class:`NodeImageMember` """ response = self.image_connection.request( '/v2/images/%s/members/%s' % (image_id, member_id) ) return self._to_image_member(response.object) def ex_accept_image_member(self, image_id, member_id): """ Accept a pending image as a member. This call is idempotent unlike ex_create_image_member, you can accept the same image many times. :param image_id: ID of the image to accept :type image_id: ``str`` :param project: ID of the project to accept the image as :type image_id: ``str`` :rtype: ``bool`` """ data = {'status': 'accepted'} response = self.image_connection.request( '/v2/images/%s/members/%s' % (image_id, member_id), method='PUT', data=data ) return self._to_image_member(response.object) def _to_networks(self, obj): networks = obj['networks'] return [self._to_network(network) for network in networks] def _to_network(self, obj): extra = {} if obj.get('router:external', None): extra['router:external'] = obj.get('router:external') if obj.get('subnets', None): extra['subnets'] = obj.get('subnets') return OpenStackNetwork(id=obj['id'], name=obj['name'], cidr=None, driver=self, extra=extra) def ex_list_networks(self): """ Get a list of Networks that are available. :rtype: ``list`` of :class:`OpenStackNetwork` """ response = self.network_connection.request( self._networks_url_prefix).object return self._to_networks(response) def ex_create_network(self, name, **kwargs): """ Create a new Network :param name: Name of network which should be used :type name: ``str`` :rtype: :class:`OpenStackNetwork` """ data = {'network': {'name': name}} # Add optional values for key, value in kwargs.items(): data['network'][key] = value response = self.network_connection.request(self._networks_url_prefix, method='POST', data=data).object return self._to_network(response['network']) def ex_delete_network(self, network): """ Delete a Network :param network: Network which should be used :type network: :class:`OpenStackNetwork` :rtype: ``bool`` """ resp = self.network_connection.request( '%s/%s' % (self._networks_url_prefix, network.id), method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def _to_subnets(self, obj): subnets = obj['subnets'] return [self._to_subnet(subnet) for subnet in subnets] def _to_subnet(self, obj): extra = {} if obj.get('router:external', None): extra['router:external'] = obj.get('router:external') if obj.get('subnets', None): extra['subnets'] = obj.get('subnets') return OpenStack_2_SubNet(id=obj['id'], name=obj['name'], cidr=obj['cidr'], network_id=obj['network_id'], driver=self, extra=extra) def ex_list_subnets(self): """ Get a list of Subnet that are available. :rtype: ``list`` of :class:`OpenStack_2_SubNet` """ response = self.network_connection.request( self._subnets_url_prefix).object return self._to_subnets(response) def ex_create_subnet(self, name, network, cidr, ip_version=4, description='', dns_nameservers=None, host_routes=None): """ Create a new Subnet :param name: Name of subnet which should be used :type name: ``str`` :param network: Parent network of the subnet :type network: ``OpenStackNetwork`` :param cidr: cidr of network which should be used :type cidr: ``str`` :param ip_version: ip_version of subnet which should be used :type ip_version: ``int`` :param description: Description for the resource. :type description: ``str`` :param dns_nameservers: List of dns name servers. :type dns_nameservers: ``list`` of ``str`` :param host_routes: Additional routes for the subnet. :type host_routes: ``list`` of ``str`` :rtype: :class:`OpenStack_2_SubNet` """ data = { 'subnet': { 'cidr': cidr, 'network_id': network.id, 'ip_version': ip_version, 'name': name or '', 'description': description or '', 'dns_nameservers': dns_nameservers or [], 'host_routes': host_routes or [] } } response = self.network_connection.request( self._subnets_url_prefix, method='POST', data=data).object return self._to_subnet(response['subnet']) def ex_delete_subnet(self, subnet): """ Delete a Subnet :param subnet: Subnet which should be deleted :type subnet: :class:`OpenStack_2_SubNet` :rtype: ``bool`` """ resp = self.network_connection.request('%s/%s' % ( self._subnets_url_prefix, subnet.id), method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def ex_update_subnet(self, subnet, name=None, description=None, dns_nameservers=None, host_routes=None): """ Update data of an existing SubNet :param subnet: Subnet which should be updated :type subnet: :class:`OpenStack_2_SubNet` :param name: Name of subnet which should be used :type name: ``str`` :param description: Description for the resource. :type description: ``str`` :param dns_nameservers: List of dns name servers. :type dns_nameservers: ``list`` of ``str`` :param host_routes: Additional routes for the subnet. :type host_routes: ``list`` of ``str`` :rtype: :class:`OpenStack_2_SubNet` """ data = {'subnet': {}} if name is not None: data['subnet']['name'] = name if description is not None: data['subnet']['description'] = description if dns_nameservers is not None: data['subnet']['dns_nameservers'] = dns_nameservers if host_routes is not None: data['subnet']['host_routes'] = host_routes response = self.network_connection.request( "%s/%s" % (self._subnets_url_prefix, subnet.id), method='PUT', data=data).object return self._to_subnet(response['subnet']) def ex_list_ports(self): """ List all OpenStack_2_PortInterfaces https://developer.openstack.org/api-ref/network/v2/#list-ports :rtype: ``list`` of :class:`OpenStack_2_PortInterface` """ response = self._paginated_request( '/v2.0/ports', 'ports', self.network_connection) return [self._to_port(port) for port in response['ports']] def ex_delete_port(self, port): """ Delete an OpenStack_2_PortInterface https://developer.openstack.org/api-ref/network/v2/#delete-port :param port: port interface to remove :type port: :class:`OpenStack_2_PortInterface` :rtype: ``bool`` """ response = self.network_connection.request( '/v2.0/ports/%s' % port.id, method='DELETE' ) return response.success() def ex_detach_port_interface(self, node, port): """ Detaches an OpenStack_2_PortInterface interface from a Node. :param node: node :type node: :class:`Node` :param port: port interface to detach :type port: :class:`OpenStack_2_PortInterface` :rtype: ``bool`` """ return self.connection.request( '/servers/%s/os-interface/%s' % (node.id, port.id), method='DELETE' ).success() def ex_attach_port_interface(self, node, port): """ Attaches an OpenStack_2_PortInterface to a Node. :param node: node :type node: :class:`Node` :param port: port interface to attach :type port: :class:`OpenStack_2_PortInterface` :rtype: ``bool`` """ data = { 'interfaceAttachment': { 'port_id': port.id } } return self.connection.request( '/servers/{}/os-interface'.format(node.id), method='POST', data=data ).success() def ex_create_port(self, network, description=None, admin_state_up=True, name=None): """ Creates a new OpenStack_2_PortInterface :param network: ID of the network where the newly created port should be attached to :type network: :class:`OpenStackNetwork` :param description: Description of the port :type description: str :param admin_state_up: The administrative state of the resource, which is up or down :type admin_state_up: bool :param name: Human-readable name of the resource :type name: str :rtype: :class:`OpenStack_2_PortInterface` """ data = { 'port': { 'description': description or '', 'admin_state_up': admin_state_up, 'name': name or '', 'network_id': network.id, } } response = self.network_connection.request( '/v2.0/ports', method='POST', data=data ) return self._to_port(response.object['port']) def ex_get_port(self, port_interface_id): """ Retrieve the OpenStack_2_PortInterface with the given ID :param port_interface_id: ID of the requested port :type port_interface_id: str :return: :class:`OpenStack_2_PortInterface` """ response = self.network_connection.request( '/v2.0/ports/{}'.format(port_interface_id), method='GET' ) return self._to_port(response.object['port']) def ex_update_port(self, port, description=None, admin_state_up=None, name=None, port_security_enabled=None, qos_policy_id=None, security_groups=None): """ Update a OpenStack_2_PortInterface :param port: port interface to update :type port: :class:`OpenStack_2_PortInterface` :param description: Description of the port :type description: ``str`` :param admin_state_up: The administrative state of the resource, which is up or down :type admin_state_up: ``bool`` :param name: Human-readable name of the resource :type name: ``str`` :param port_security_enabled: The port security status :type port_security_enabled: ``bool`` :param qos_policy_id: QoS policy associated with the port :type qos_policy_id: ``str`` :param security_groups: The IDs of security groups applied :type security_groups: ``list`` of ``str`` :rtype: :class:`OpenStack_2_PortInterface` """ data = {'port': {}} if description is not None: data['port']['description'] = description if admin_state_up is not None: data['port']['admin_state_up'] = admin_state_up if name is not None: data['port']['name'] = name if port_security_enabled is not None: data['port']['port_security_enabled'] = port_security_enabled if qos_policy_id is not None: data['port']['qos_policy_id'] = qos_policy_id if security_groups is not None: data['port']['security_groups'] = security_groups response = self.network_connection.request( '/v2.0/ports/{}'.format(port.id), method='PUT', data=data ) return self._to_port(response.object['port']) def list_volumes(self): """ Get a list of Volumes that are available. :rtype: ``list`` of :class:`StorageVolume` """ return self._to_volumes(self._paginated_request( '/volumes/detail', 'volumes', self.volumev2_connection)) def ex_get_volume(self, volumeId): """ Retrieve the StorageVolume with the given ID :param volumeId: ID of the volume :type volumeId: ``string`` :return: :class:`StorageVolume` """ return self._to_volume( self.volumev2_connection.request('/volumes/%s' % volumeId).object) def create_volume(self, size, name, location=None, snapshot=None, ex_volume_type=None, ex_image_ref=None): """ Create a new volume. :param size: Size of volume in gigabytes (required) :type size: ``int`` :param name: Name of the volume to be created :type name: ``str`` :param location: Which data center to create a volume in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param snapshot: Snapshot from which to create the new volume. (optional) :type snapshot: :class:`.VolumeSnapshot` :param ex_volume_type: What kind of volume to create. (optional) :type ex_volume_type: ``str`` :param ex_image_ref: The image to create the volume from when creating a bootable volume (optional) :type ex_image_ref: ``str`` :return: The newly created volume. :rtype: :class:`StorageVolume` """ volume = { 'name': name, 'description': name, 'size': size, 'metadata': { 'contents': name, }, } if ex_volume_type: volume['volume_type'] = ex_volume_type if ex_image_ref: volume['imageRef'] = ex_image_ref if location: volume['availability_zone'] = location if snapshot: volume['snapshot_id'] = snapshot.id resp = self.volumev2_connection.request('/volumes', method='POST', data={'volume': volume}) return self._to_volume(resp.object) def destroy_volume(self, volume): """ Delete a Volume. :param volume: Volume to be deleted :type volume: :class:`StorageVolume` :rtype: ``bool`` """ return self.volumev2_connection.request('/volumes/%s' % volume.id, method='DELETE').success() def ex_list_snapshots(self): """ Get a list of Snapshot that are available. :rtype: ``list`` of :class:`VolumeSnapshot` """ return self._to_snapshots(self._paginated_request( '/snapshots/detail', 'snapshots', self.volumev2_connection)) def create_volume_snapshot(self, volume, name=None, ex_description=None, ex_force=True): """ Create snapshot from volume :param volume: Instance of `StorageVolume` :type volume: `StorageVolume` :param name: Name of snapshot (optional) :type name: `str` | `NoneType` :param ex_description: Description of the snapshot (optional) :type ex_description: `str` | `NoneType` :param ex_force: Specifies if we create a snapshot that is not in state `available`. For example `in-use`. Defaults to True. (optional) :type ex_force: `bool` :rtype: :class:`VolumeSnapshot` """ data = {'snapshot': {'volume_id': volume.id, 'force': ex_force}} if name is not None: data['snapshot']['name'] = name if ex_description is not None: data['snapshot']['description'] = ex_description return self._to_snapshot( self.volumev2_connection.request('/snapshots', method='POST', data=data).object) def destroy_volume_snapshot(self, snapshot): """ Delete a Volume Snapshot. :param snapshot: Snapshot to be deleted :type snapshot: :class:`VolumeSnapshot` :rtype: ``bool`` """ resp = self.volumev2_connection.request('/snapshots/%s' % snapshot.id, method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def ex_list_security_groups(self): """ Get a list of Security Groups that are available. :rtype: ``list`` of :class:`OpenStackSecurityGroup` """ return self._to_security_groups( self.network_connection.request('/v2.0/security-groups').object) def ex_create_security_group(self, name, description): """ Create a new Security Group :param name: Name of the new Security Group :type name: ``str`` :param description: Description of the new Security Group :type description: ``str`` :rtype: :class:`OpenStackSecurityGroup` """ return self._to_security_group(self.network_connection .request( '/v2.0/security-groups', method='POST', data={'security_group': {'name': name, 'description': description}} ).object['security_group']) def ex_delete_security_group(self, security_group): """ Delete a Security Group. :param security_group: Security Group should be deleted :type security_group: :class:`OpenStackSecurityGroup` :rtype: ``bool`` """ resp = self.network_connection.request('/v2.0/security-groups/%s' % (security_group.id), method='DELETE') return resp.status == httplib.NO_CONTENT def _to_security_group_rule(self, obj): ip_range = group = tenant_id = parent_id = None protocol = from_port = to_port = direction = None if 'parent_group_id' in obj: if obj['group'] == {}: ip_range = obj['ip_range'].get('cidr', None) else: group = obj['group'].get('name', None) tenant_id = obj['group'].get('tenant_id', None) parent_id = obj['parent_group_id'] from_port = obj['from_port'] to_port = obj['to_port'] protocol = obj['ip_protocol'] else: ip_range = obj.get('remote_ip_prefix', None) group = obj.get('remote_group_id', None) tenant_id = obj.get('tenant_id', None) parent_id = obj['security_group_id'] from_port = obj['port_range_min'] to_port = obj['port_range_max'] protocol = obj['protocol'] return OpenStackSecurityGroupRule( id=obj['id'], parent_group_id=parent_id, ip_protocol=protocol, from_port=from_port, to_port=to_port, driver=self, ip_range=ip_range, group=group, tenant_id=tenant_id, direction=direction) def ex_create_security_group_rule(self, security_group, ip_protocol, from_port, to_port, cidr=None, source_security_group=None): """ Create a new Rule in a Security Group :param security_group: Security Group in which to add the rule :type security_group: :class:`OpenStackSecurityGroup` :param ip_protocol: Protocol to which this rule applies Examples: tcp, udp, ... :type ip_protocol: ``str`` :param from_port: First port of the port range :type from_port: ``int`` :param to_port: Last port of the port range :type to_port: ``int`` :param cidr: CIDR notation of the source IP range for this rule :type cidr: ``str`` :param source_security_group: Existing Security Group to use as the source (instead of CIDR) :type source_security_group: L{OpenStackSecurityGroup :rtype: :class:`OpenStackSecurityGroupRule` """ source_security_group_id = None if type(source_security_group) == OpenStackSecurityGroup: source_security_group_id = source_security_group.id return self._to_security_group_rule(self.network_connection.request( '/v2.0/security-group-rules', method='POST', data={'security_group_rule': { 'direction': 'ingress', 'protocol': ip_protocol, 'port_range_min': from_port, 'port_range_max': to_port, 'remote_ip_prefix': cidr, 'remote_group_id': source_security_group_id, 'security_group_id': security_group.id}} ).object['security_group_rule']) def ex_delete_security_group_rule(self, rule): """ Delete a Rule from a Security Group. :param rule: Rule should be deleted :type rule: :class:`OpenStackSecurityGroupRule` :rtype: ``bool`` """ resp = self.network_connection.request( '/v2.0/security-group-rules/%s' % (rule.id), method='DELETE') return resp.status == httplib.NO_CONTENT def ex_remove_security_group_from_node(self, security_group, node): """ Remove a Security Group from a node. :param security_group: Security Group to remove from node. :type security_group: :class:`OpenStackSecurityGroup` :param node: Node to remove the Security Group. :type node: :class:`Node` :rtype: ``bool`` """ server_params = {'name': security_group.name} resp = self._node_action(node, 'removeSecurityGroup', **server_params) return resp.status == httplib.ACCEPTED def _to_floating_ip_pool(self, obj): return OpenStack_2_FloatingIpPool(obj['id'], obj['name'], self.network_connection) def _to_floating_ip_pools(self, obj): pool_elements = obj['networks'] return [self._to_floating_ip_pool(pool) for pool in pool_elements] def ex_list_floating_ip_pools(self): """ List available floating IP pools :rtype: ``list`` of :class:`OpenStack_2_FloatingIpPool` """ return self._to_floating_ip_pools( self.network_connection.request('/v2.0/networks?router:external' '=True&fields=id&fields=' 'name').object) def _to_routers(self, obj): routers = obj['routers'] return [self._to_router(router) for router in routers] def _to_router(self, obj): extra = {} extra['external_gateway_info'] = obj['external_gateway_info'] extra['routes'] = obj['routes'] return OpenStack_2_Router(id=obj['id'], name=obj['name'], status=obj['status'], driver=self, extra=extra) def ex_list_routers(self): """ Get a list of Routers that are available. :rtype: ``list`` of :class:`OpenStack_2_Router` """ response = self.network_connection.request( '/v2.0/routers').object return self._to_routers(response) def ex_create_router(self, name, description='', admin_state_up=True, external_gateway_info=None): """ Create a new Router :param name: Name of router which should be used :type name: ``str`` :param description: Description of the port :type description: ``str`` :param admin_state_up: The administrative state of the resource, which is up or down :type admin_state_up: ``bool`` :param external_gateway_info: The external gateway information :type external_gateway_info: ``dict`` :rtype: :class:`OpenStack_2_Router` """ data = { 'router': { 'name': name or '', 'description': description or '', 'admin_state_up': admin_state_up, } } if external_gateway_info: data['router']['external_gateway_info'] = external_gateway_info response = self.network_connection.request( '/v2.0/routers', method='POST', data=data).object return self._to_router(response['router']) def ex_delete_router(self, router): """ Delete a Router :param router: Router which should be deleted :type router: :class:`OpenStack_2_Router` :rtype: ``bool`` """ resp = self.network_connection.request('%s/%s' % ( '/v2.0/routers', router.id), method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def _manage_router_interface(self, router, op, subnet=None, port=None): """ Add/Remove interface to router :param router: Router to add/remove the interface :type router: :class:`OpenStack_2_Router` :param op: Operation to perform: 'add' or 'remove' :type op: ``str`` :param subnet: Subnet object to be added to the router :type subnet: :class:`OpenStack_2_SubNet` :param port: Port object to be added to the router :type port: :class:`OpenStack_2_PortInterface` :rtype: ``bool`` """ data = {} if subnet: data['subnet_id'] = subnet.id elif port: data['port_id'] = port.id else: raise OpenStackException("Error in router interface: " "port or subnet are None.", 500, self) resp = self.network_connection.request('%s/%s/%s_router_interface' % ( '/v2.0/routers', router.id, op), method='PUT', data=data) return resp.status == httplib.OK def ex_add_router_port(self, router, port): """ Add port to a router :param router: Router to add the port :type router: :class:`OpenStack_2_Router` :param port: Port object to be added to the router :type port: :class:`OpenStack_2_PortInterface` :rtype: ``bool`` """ return self._manage_router_interface(router, 'add', port=port) def ex_del_router_port(self, router, port): """ Remove port from a router :param router: Router to remove the port :type router: :class:`OpenStack_2_Router` :param port: Port object to be added to the router :type port: :class:`OpenStack_2_PortInterface` :rtype: ``bool`` """ return self._manage_router_interface(router, 'remove', port=port) def ex_add_router_subnet(self, router, subnet): """ Add subnet to a router :param router: Router to add the subnet :type router: :class:`OpenStack_2_Router` :param subnet: Subnet object to be added to the router :type subnet: :class:`OpenStack_2_SubNet` :rtype: ``bool`` """ return self._manage_router_interface(router, 'add', subnet=subnet) def ex_del_router_subnet(self, router, subnet): """ Remove subnet to a router :param router: Router to remove the subnet :type router: :class:`OpenStack_2_Router` :param subnet: Subnet object to be added to the router :type subnet: :class:`OpenStack_2_SubNet` :rtype: ``bool`` """ return self._manage_router_interface(router, 'remove', subnet=subnet) class OpenStack_1_1_FloatingIpPool(object): """ Floating IP Pool info. """ def __init__(self, name, connection): self.name = name self.connection = connection def list_floating_ips(self): """ List floating IPs in the pool :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpAddress` """ return self._to_floating_ips( self.connection.request('/os-floating-ips').object) def _to_floating_ips(self, obj): ip_elements = obj['floating_ips'] return [self._to_floating_ip(ip) for ip in ip_elements] def _to_floating_ip(self, obj): return OpenStack_1_1_FloatingIpAddress(id=obj['id'], ip_address=obj['ip'], pool=self, node_id=obj['instance_id'], driver=self.connection.driver) def get_floating_ip(self, ip): """ Get specified floating IP from the pool :param ip: floating IP to get :type ip: ``str`` :rtype: :class:`OpenStack_1_1_FloatingIpAddress` """ ip_obj, = [x for x in self.list_floating_ips() if x.ip_address == ip] return ip_obj def create_floating_ip(self): """ Create new floating IP in the pool :rtype: :class:`OpenStack_1_1_FloatingIpAddress` """ resp = self.connection.request('/os-floating-ips', method='POST', data={'pool': self.name}) data = resp.object['floating_ip'] id = data['id'] ip_address = data['ip'] return OpenStack_1_1_FloatingIpAddress(id=id, ip_address=ip_address, pool=self, node_id=None, driver=self.connection.driver) def delete_floating_ip(self, ip): """ Delete specified floating IP from the pool :param ip: floating IP to remove :type ip: :class:`OpenStack_1_1_FloatingIpAddress` :rtype: ``bool`` """ resp = self.connection.request('/os-floating-ips/%s' % ip.id, method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def __repr__(self): return ('' % self.name) class OpenStack_1_1_FloatingIpAddress(object): """ Floating IP info. """ def __init__(self, id, ip_address, pool, node_id=None, driver=None): self.id = str(id) self.ip_address = ip_address self.pool = pool self.node_id = node_id self.driver = driver def delete(self): """ Delete this floating IP :rtype: ``bool`` """ if self.pool is not None: return self.pool.delete_floating_ip(self) elif self.driver is not None: return self.driver.ex_delete_floating_ip(self) def __repr__(self): return ('' % (self.id, self.ip_address, self.pool, self.driver)) class OpenStack_2_FloatingIpPool(object): """ Floating IP Pool info. """ def __init__(self, id, name, connection): self.id = id self.name = name self.connection = connection def _to_floating_ips(self, obj): ip_elements = obj['floatingips'] return [self._to_floating_ip(ip) for ip in ip_elements] def _to_floating_ip(self, obj): instance_id = None # In neutron version prior to 13.0.0 port_details does not exists if 'port_details' not in obj and 'port_id' in obj and obj['port_id']: port = self.connection.driver.ex_get_port(obj['port_id']) if port: obj['port_details'] = {"device_id": port.extra["device_id"], "device_owner": port.extra["device_owner"], "mac_address": port.extra["mac_address"]} if 'port_details' in obj and obj['port_details']: if obj['port_details']['device_owner'] in ['compute:nova', 'compute:None']: instance_id = obj['port_details']['device_id'] ip_address = obj['floating_ip_address'] return OpenStack_1_1_FloatingIpAddress(id=obj['id'], ip_address=ip_address, pool=self, node_id=instance_id, driver=self.connection.driver) def list_floating_ips(self): """ List floating IPs in the pool :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpAddress` """ return self._to_floating_ips( self.connection.request('/v2.0/floatingips').object) def get_floating_ip(self, ip): """ Get specified floating IP from the pool :param ip: floating IP to get :type ip: ``str`` :rtype: :class:`OpenStack_1_1_FloatingIpAddress` """ floating_ips = self._to_floating_ips( self.connection.request('/v2.0/floatingips?floating_ip_address' '=%s' % ip).object) return floating_ips[0] def create_floating_ip(self): """ Create new floating IP in the pool :rtype: :class:`OpenStack_1_1_FloatingIpAddress` """ resp = self.connection.request('/v2.0/floatingips', method='POST', data={'floatingip': {'floating_network_id': self.id}} ) data = resp.object['floatingip'] id = data['id'] ip_address = data['floating_ip_address'] return OpenStack_1_1_FloatingIpAddress(id=id, ip_address=ip_address, pool=self, node_id=None, driver=self.connection.driver) def delete_floating_ip(self, ip): """ Delete specified floating IP from the pool :param ip: floating IP to remove :type ip: :class:`OpenStack_1_1_FloatingIpAddress` :rtype: ``bool`` """ resp = self.connection.request('/v2.0/floatingips/%s' % ip.id, method='DELETE') return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED) def __repr__(self): return ('' % self.name) class OpenStack_2_SubNet(object): """ A Virtual SubNet. """ def __init__(self, id, name, cidr, network_id, driver, extra=None): self.id = str(id) self.name = name self.cidr = cidr self.network_id = network_id self.driver = driver self.extra = extra or {} def __repr__(self): return '' % (self.id, self.name, self.cidr) class OpenStack_2_Router(object): """ A Virtual Router. """ def __init__(self, id, name, status, driver, extra=None): self.id = str(id) self.name = name self.status = status self.driver = driver self.extra = extra or {} def __repr__(self): return '' % (self.id, self.name) class OpenStack_2_PortInterface(UuidMixin): """ Port Interface info. Similar in functionality to a floating IP (can be attached / detached from a compute instance) but implementation-wise a bit different. > A port is a connection point for attaching a single device, such as the > NIC of a server, to a network. The port also describes the associated > network configuration, such as the MAC and IP addresses to be used on > that port. https://docs.openstack.org/python-openstackclient/pike/cli/command-objects/port.html Also see: https://developer.openstack.org/api-ref/compute/#port-interfaces-servers-os-interface """ def __init__(self, id, state, driver, created=None, extra=None): """ :param id: Port Interface ID. :type id: ``str`` :param state: State of the OpenStack_2_PortInterface. :type state: :class:`.OpenStack_2_PortInterfaceState` :param created: A datetime object that represents when the port interface was created :type created: ``datetime.datetime`` :param extra: Optional provided specific attributes associated with this image. :type extra: ``dict`` """ self.id = str(id) self.state = state self.driver = driver self.created = created self.extra = extra or {} UuidMixin.__init__(self) def delete(self): """ Delete this Port Interface :rtype: ``bool`` """ return self.driver.ex_delete_port(self) def __repr__(self): return (('') % (self.id, self.state, self.driver.name)) apache-libcloud-2.8.0/libcloud/compute/drivers/ovh.py0000664000175000017500000004463513570310635022537 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Ovh driver """ from libcloud.utils.py3 import httplib from libcloud.common.ovh import API_ROOT, OvhConnection from libcloud.compute.base import (NodeDriver, NodeSize, Node, NodeLocation, NodeImage, StorageVolume, VolumeSnapshot) from libcloud.compute.types import (Provider, StorageVolumeState, VolumeSnapshotState) from libcloud.compute.drivers.openstack import OpenStackNodeDriver from libcloud.compute.drivers.openstack import OpenStackKeyPair class OvhNodeDriver(NodeDriver): """ Libcloud driver for the Ovh API For more information on the Ovh API, read the official reference: https://api.ovh.com/console/ """ type = Provider.OVH name = "Ovh" website = 'https://www.ovh.com/' connectionCls = OvhConnection features = {'create_node': ['ssh_key']} api_name = 'ovh' NODE_STATE_MAP = OpenStackNodeDriver.NODE_STATE_MAP VOLUME_STATE_MAP = OpenStackNodeDriver.VOLUME_STATE_MAP SNAPSHOT_STATE_MAP = OpenStackNodeDriver.SNAPSHOT_STATE_MAP def __init__(self, key, secret, ex_project_id, ex_consumer_key=None): """ Instantiate the driver with the given API credentials. :param key: Your application key (required) :type key: ``str`` :param secret: Your application secret (required) :type secret: ``str`` :param ex_project_id: Your project ID :type ex_project_id: ``str`` :param ex_consumer_key: Your consumer key (required) :type ex_consumer_key: ``str`` :rtype: ``None`` """ self.datacenter = None self.project_id = ex_project_id self.consumer_key = ex_consumer_key NodeDriver.__init__(self, key, secret, ex_consumer_key=ex_consumer_key) def _get_project_action(self, suffix): base_url = '%s/cloud/project/%s/' % (API_ROOT, self.project_id) return base_url + suffix def list_nodes(self, location=None): """ List all nodes. :keyword location: Location (region) used as filter :type location: :class:`NodeLocation` :return: List of node objects :rtype: ``list`` of :class:`Node` """ action = self._get_project_action('instance') data = {} if location: data['region'] = location.id response = self.connection.request(action, data=data) return self._to_nodes(response.object) def ex_get_node(self, node_id): """ Get a individual node. :keyword node_id: Node's ID :type node_id: ``str`` :return: Created node :rtype : :class:`Node` """ action = self._get_project_action('instance/%s' % node_id) response = self.connection.request(action, method='GET') return self._to_node(response.object) def create_node(self, name, image, size, location, ex_keyname=None): """ Create a new node :keyword name: Name of created node :type name: ``str`` :keyword image: Image used for node :type image: :class:`NodeImage` :keyword size: Size (flavor) used for node :type size: :class:`NodeSize` :keyword location: Location (region) where to create node :type location: :class:`NodeLocation` :keyword ex_keyname: Name of SSH key used :type ex_keyname: ``str`` :return: Created node :rtype : :class:`Node` """ action = self._get_project_action('instance') data = { 'name': name, 'imageId': image.id, 'flavorId': size.id, 'region': location.id, } if ex_keyname: key_id = self.get_key_pair(ex_keyname, location).extra['id'] data['sshKeyId'] = key_id response = self.connection.request(action, data=data, method='POST') return self._to_node(response.object) def destroy_node(self, node): action = self._get_project_action('instance/%s' % node.id) self.connection.request(action, method='DELETE') return True def list_sizes(self, location=None): action = self._get_project_action('flavor') params = {} if location: params['region'] = location.id response = self.connection.request(action, params=params) return self._to_sizes(response.object) def ex_get_size(self, size_id): """ Get an individual size (flavor). :keyword size_id: Size's ID :type size_id: ``str`` :return: Size :rtype: :class:`NodeSize` """ action = self._get_project_action('flavor/%s' % size_id) response = self.connection.request(action) return self._to_size(response.object) def list_images(self, location=None, ex_size=None): """ List available images :keyword location: Location (region) used as filter :type location: :class:`NodeLocation` :keyword ex_size: Exclude images which are uncompatible with given size :type ex_size: :class:`NodeImage` :return: List of images :rtype : ``list`` of :class:`NodeImage` """ action = self._get_project_action('image') params = {} if location: params['region'] = location.id if ex_size: params['flavorId'] = ex_size.id response = self.connection.request(action, params=params) return self._to_images(response.object) def get_image(self, image_id): action = self._get_project_action('image/%s' % image_id) response = self.connection.request(action) return self._to_image(response.object) def list_locations(self): action = self._get_project_action('region') data = self.connection.request(action) return self._to_locations(data.object) def list_key_pairs(self, ex_location=None): """ List available SSH public keys. :keyword ex_location: Location (region) used as filter :type ex_location: :class:`NodeLocation` :return: Public keys :rtype: ``list``of :class:`KeyPair` """ action = self._get_project_action('sshkey') params = {} if ex_location: params['region'] = ex_location.id response = self.connection.request(action, params=params) return self._to_key_pairs(response.object) def get_key_pair(self, name, ex_location=None): """ Get an individual SSH public key by its name and location. :param name: Name of the key pair to retrieve. :type name: ``str`` :keyword ex_location: Key's region :type ex_location: :class:`NodeLocation` :return: Public key :rtype: :class:`KeyPair` """ # Keys are indexed with ID keys = [key for key in self.list_key_pairs(ex_location) if key.name == name] if not keys: raise Exception("No key named '%s'" % name) return keys[0] def import_key_pair_from_string(self, name, key_material, ex_location): """ Import a new public key from string. :param name: Key pair name. :type name: ``str`` :param key_material: Public key material. :type key_material: ``str`` :param ex_location: Location where to store the key :type ex_location: :class:`NodeLocation` :return: Imported key pair object. :rtype: :class:`KeyPair` """ action = self._get_project_action('sshkey') data = { 'name': name, 'publicKey': key_material, 'region': ex_location.id } response = self.connection.request(action, data=data, method='POST') return self._to_key_pair(response.object) def delete_key_pair(self, key_pair): action = self._get_project_action('sshkey/%s' % key_pair.extra['id']) params = {'keyId': key_pair.extra['id']} self.connection.request(action, params=params, method='DELETE') return True def create_volume(self, size, name, location, snapshot=None, ex_volume_type='classic', ex_description=None): """ Create a volume. :param size: Size of volume to create (in GB). :type size: ``int`` :param name: Name of volume to create :type name: ``str`` :param location: Location to create the volume in :type location: :class:`NodeLocation` or ``None`` :param snapshot: Snapshot from which to create the new volume. (optional) :type snapshot: :class:`.VolumeSnapshot` :keyword ex_volume_type: ``'classic'`` or ``'high-speed'`` :type ex_volume_type: ``str`` :keyword ex_description: Optionnal description of volume :type ex_description: str :return: Storage Volume object :rtype: :class:`StorageVolume` """ action = self._get_project_action('volume') data = { 'name': name, 'region': location.id, 'size': size, 'type': ex_volume_type, } if ex_description: data['description'] = ex_description response = self.connection.request(action, data=data, method='POST') return self._to_volume(response.object) def destroy_volume(self, volume): action = self._get_project_action('volume/%s' % volume.id) self.connection.request(action, method='DELETE') return True def list_volumes(self, ex_location=None): """ Return a list of volumes. :keyword ex_location: Location used to filter :type ex_location: :class:`NodeLocation` or ``None`` :return: A list of volume objects. :rtype: ``list`` of :class:`StorageVolume` """ action = self._get_project_action('volume') data = {} if ex_location: data['region'] = ex_location.id response = self.connection.request(action, data=data) return self._to_volumes(response.object) def ex_get_volume(self, volume_id): """ Return a Volume object based on a volume ID. :param volume_id: The ID of the volume :type volume_id: ``int`` :return: A StorageVolume object for the volume :rtype: :class:`StorageVolume` """ action = self._get_project_action('volume/%s' % volume_id) response = self.connection.request(action) return self._to_volume(response.object) def attach_volume(self, node, volume, device=None): """ Attach a volume to a node. :param node: Node where to attach volume :type node: :class:`Node` :param volume: The ID of the volume :type volume: :class:`StorageVolume` :param device: Unsed parameter :return: True or False representing operation successful :rtype: ``bool`` """ action = self._get_project_action('volume/%s/attach' % volume.id) data = {'instanceId': node.id, 'volumeId': volume.id} self.connection.request(action, data=data, method='POST') return True def detach_volume(self, volume, ex_node=None): """ Detach a volume to a node. :param volume: The ID of the volume :type volume: :class:`StorageVolume` :param ex_node: Node to detach from (optionnal if volume is attached to only one node) :type ex_node: :class:`Node` :return: True or False representing operation successful :rtype: ``bool`` :raises: Exception: If ``ex_node`` is not provided and more than one node is attached to the volume """ action = self._get_project_action('volume/%s/detach' % volume.id) if ex_node is None: if len(volume.extra['attachedTo']) != 1: err_msg = "Volume '%s' has more or less than one attached" \ "nodes, you must specify one." raise Exception(err_msg) ex_node = self.ex_get_node(volume.extra['attachedTo'][0]) data = {'instanceId': ex_node.id} self.connection.request(action, data=data, method='POST') return True def ex_list_snapshots(self, location=None): """ List all snapshots. :keyword location: Location used to filter :type location: :class:`NodeLocation` or ``None`` :rtype: ``list`` of :class:`VolumeSnapshot` """ action = self._get_project_action('volume/snapshot') params = {} if location: params['region'] = location.id response = self.connection.request(action, params=params) return self._to_snapshots(response.object) def ex_get_volume_snapshot(self, snapshot_id): """ Returns a single volume snapshot. :param snapshot_id: Node to run the task on. :type snapshot_id: ``str`` :rtype :class:`.VolumeSnapshot`: :return: Volume snapshot. """ action = self._get_project_action('volume/snapshot/%s' % snapshot_id) response = self.connection.request(action) return self._to_snapshot(response.object) def list_volume_snapshots(self, volume): action = self._get_project_action('volume/snapshot') params = {'region': volume.extra['region']} response = self.connection.request(action, params=params) snapshots = self._to_snapshots(response.object) return [snap for snap in snapshots if snap.extra['volume_id'] == volume.id] def create_volume_snapshot(self, volume, name=None, ex_description=None): """ Create snapshot from volume :param volume: Instance of `StorageVolume` :type volume: `StorageVolume` :param name: Name of snapshot (optional) :type name: `str` | `NoneType` :param ex_description: Description of the snapshot (optional) :type ex_description: `str` | `NoneType` :rtype: :class:`VolumeSnapshot` """ action = self._get_project_action('volume/%s/snapshot/' % volume.id) data = {} if name: data['name'] = name if ex_description: data['description'] = ex_description response = self.connection.request(action, data=data, method='POST') return self._to_snapshot(response.object) def destroy_volume_snapshot(self, snapshot): action = self._get_project_action('volume/snapshot/%s' % snapshot.id) response = self.connection.request(action, method='DELETE') return response.status == httplib.OK def _to_volume(self, obj): extra = obj.copy() extra.pop('id') extra.pop('name') extra.pop('size') state = self.VOLUME_STATE_MAP.get(obj.pop('status', None), StorageVolumeState.UNKNOWN) return StorageVolume(id=obj['id'], name=obj['name'], size=obj['size'], state=state, extra=extra, driver=self) def _to_volumes(self, objs): return [self._to_volume(obj) for obj in objs] def _to_location(self, obj): location = self.connectionCls.LOCATIONS[obj] return NodeLocation(driver=self, **location) def _to_locations(self, objs): return [self._to_location(obj) for obj in objs] def _to_node(self, obj): extra = obj.copy() if 'ipAddresses' in extra: public_ips = [ip['ip'] for ip in extra['ipAddresses']] del extra['id'] del extra['name'] return Node(id=obj['id'], name=obj['name'], state=self.NODE_STATE_MAP[obj['status']], public_ips=public_ips, private_ips=[], driver=self, extra=extra) def _to_nodes(self, objs): return [self._to_node(obj) for obj in objs] def _to_size(self, obj): extra = {'vcpus': obj['vcpus'], 'type': obj['type'], 'region': obj['region']} return NodeSize(id=obj['id'], name=obj['name'], ram=obj['ram'], disk=obj['disk'], bandwidth=None, price=None, driver=self, extra=extra) def _to_sizes(self, objs): return [self._to_size(obj) for obj in objs] def _to_image(self, obj): extra = {'region': obj['region'], 'visibility': obj['visibility']} return NodeImage(id=obj['id'], name=obj['name'], driver=self, extra=extra) def _to_images(self, objs): return [self._to_image(obj) for obj in objs] def _to_key_pair(self, obj): extra = {'regions': obj['regions'], 'id': obj['id']} return OpenStackKeyPair(name=obj['name'], public_key=obj['publicKey'], driver=self, fingerprint=None, extra=extra) def _to_key_pairs(self, objs): return [self._to_key_pair(obj) for obj in objs] def _to_snapshot(self, obj): extra = { 'volume_id': obj['volumeId'], 'region': obj['region'], 'description': obj['description'], 'status': obj['status'], } state = self.SNAPSHOT_STATE_MAP.get(obj['status'], VolumeSnapshotState.UNKNOWN) snapshot = VolumeSnapshot(id=obj['id'], driver=self, size=obj['size'], extra=extra, created=obj['creationDate'], state=state, name=obj['name']) return snapshot def _to_snapshots(self, objs): return [self._to_snapshot(obj) for obj in objs] def _ex_connection_class_kwargs(self): return {'ex_consumer_key': self.consumer_key} apache-libcloud-2.8.0/libcloud/compute/drivers/packet.py0000664000175000017500000010162413576514553023215 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Packet Driver """ try: # Try to use asyncio to perform requests in parallel across projects import asyncio except ImportError: # If not available will do things serially asyncio = None import datetime import json from libcloud.utils.py3 import httplib from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.compute.types import Provider, NodeState, InvalidCredsError from libcloud.compute.base import NodeDriver, Node from libcloud.compute.base import NodeImage, NodeSize, NodeLocation from libcloud.compute.base import KeyPair from libcloud.compute.base import StorageVolume, VolumeSnapshot PACKET_ENDPOINT = "api.packet.net" # True to use async io if available (aka running under Python 3) USE_ASYNC_IO_IF_AVAILABLE = True def use_asyncio(): return asyncio is not None and USE_ASYNC_IO_IF_AVAILABLE class PacketResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_error(self): if self.status == httplib.UNAUTHORIZED: body = self.parse_body() raise InvalidCredsError(body.get('error')) else: body = self.parse_body() if 'message' in body: error = '%s (code: %s)' % (body.get('message'), self.status) elif 'errors' in body: error = body.get('errors') else: error = body raise Exception(error) def success(self): return self.status in self.valid_response_codes class PacketConnection(ConnectionKey): """ Connection class for the Packet driver. """ host = PACKET_ENDPOINT responseCls = PacketResponse def add_default_headers(self, headers): """ Add headers that are necessary for every request """ headers['Content-Type'] = 'application/json' headers['X-Auth-Token'] = self.key headers['X-Consumer-Token'] = \ 'kcrhMn7hwG8Ceo2hAhGFa2qpxLBvVHxEjS9ue8iqmsNkeeB2iQgMq4dNc1893pYu' return headers class PacketNodeDriver(NodeDriver): """ Packet NodeDriver """ connectionCls = PacketConnection type = Provider.PACKET name = 'Packet' website = 'http://www.packet.com/' NODE_STATE_MAP = {'queued': NodeState.PENDING, 'provisioning': NodeState.PENDING, 'rebuilding': NodeState.PENDING, 'powering_on': NodeState.REBOOTING, 'powering_off': NodeState.REBOOTING, 'rebooting': NodeState.REBOOTING, 'inactive': NodeState.STOPPED, 'deleted': NodeState.TERMINATED, 'deprovisioning': NodeState.TERMINATED, 'failed': NodeState.ERROR, 'active': NodeState.RUNNING} def __init__(self, key, project=None): """ Initialize a NodeDriver for Packet using the API token and optionally the project (name or id). If project name is specified we validate it lazily and populate self.project_id during the first access of self.projects variable """ super(PacketNodeDriver, self).__init__(key=key) self.project_name = project self.project_id = None # Lazily populated on first access to self.project self._project = project # Variable which indicates if self._projects has been populated yet and # has been called self._project validated self._projects_populated = False self._projects = None @property def projects(self): """ Lazily retrieve projects and set self.project_id variable on initial access to self.projects variable. """ if not self._projects_populated: # NOTE: Each Packet account needs at least one project, but to be # on the safe side and avoid infinite loop in case there are no # projects on the account, we don't use a more robust way to # determine if project list has been populated yet self._projects = self.ex_list_projects() self._projects_populated = True # If project name is specified, verify it's valid and populate # self.project_id if self._project: for project_obj in self._projects: if self._project in [project_obj.name, project_obj.id]: self.project_id = project_obj.id break if not self.project_id: # Invalid project name self.project_name = None return self._projects def ex_list_projects(self): projects = [] data = self.connection.request('/projects').object projects = data.get('projects') if projects: projects = [Project(project) for project in projects] return projects def list_nodes(self, ex_project_id=None): if ex_project_id: return self.ex_list_nodes_for_project(ex_project_id=ex_project_id) # if project has been specified during driver initialization, then # return nodes for this project only if self.project_id: return self.ex_list_nodes_for_project( ex_project_id=self.project_id) # In case of Python2 perform requests serially if not use_asyncio(): nodes = [] for project in self.projects: nodes.extend( self.ex_list_nodes_for_project(ex_project_id=project.id) ) return nodes # In case of Python3 use asyncio to perform requests in parallel return self.list_resources_async('nodes') def list_resources_async(self, resource_type): # The _list_nodes function is defined dynamically using exec in # order to prevent a SyntaxError in Python2 due to "yield from". # This cruft can be removed once Python2 support is no longer # required. assert resource_type in ['nodes', 'volumes'] glob = globals() loc = locals() exec(""" import asyncio @asyncio.coroutine def _list_async(driver): projects = [project.id for project in driver.projects] loop = asyncio.get_event_loop() futures = [ loop.run_in_executor(None, driver.ex_list_%s_for_project, p) for p in projects ] retval = [] for future in futures: result = yield from future retval.extend(result) return retval""" % resource_type, glob, loc) loop = asyncio.get_event_loop() return loop.run_until_complete(loc['_list_async'](loc['self'])) def ex_list_nodes_for_project(self, ex_project_id, include='plan', page=1, per_page=1000): params = { 'include': include, 'page': page, 'per_page': per_page } data = self.connection.request( '/projects/%s/devices' % (ex_project_id), params=params).object['devices'] return list(map(self._to_node, data)) def list_locations(self): data = self.connection.request('/facilities')\ .object['facilities'] return list(map(self._to_location, data)) def list_images(self): data = self.connection.request('/operating-systems')\ .object['operating_systems'] return list(map(self._to_image, data)) def list_sizes(self, ex_project_id=None): project_id = ex_project_id or self.project_id or ( len(self.projects) and self.projects[0].id) if project_id: data = self.connection.request('/projects/%s/plans' % project_id).object['plans'] else: # This only works with personal tokens data = self.connection.request('/plans').object['plans'] return [self._to_size(size) for size in data if size.get('line') == 'baremetal'] def create_node(self, name, size, image, location, ex_project_id=None, ip_addresses=[], cloud_init=None, **kwargs): """ Create a node. :return: The newly created node. :rtype: :class:`Node` """ # if project has been specified on initialization of driver, then # create on this project if self.project_id: ex_project_id = self.project_id else: if not ex_project_id: raise Exception('ex_project_id needs to be specified') facility = location.extra['code'] params = {'hostname': name, 'plan': size.id, 'operating_system': image.id, 'facility': facility, 'include': 'plan', 'billing_cycle': 'hourly', 'ip_addresses': ip_addresses} params.update(kwargs) if cloud_init: params["userdata"] = cloud_init data = self.connection.request('/projects/%s/devices' % (ex_project_id), data=json.dumps(params), method='POST') status = data.object.get('status', 'OK') if status == 'ERROR': message = data.object.get('message', None) error_message = data.object.get('error_message', message) raise ValueError('Failed to create node: %s' % (error_message)) node = self._to_node(data=data.object) if kwargs.get('disk'): self.attach_volume(node, kwargs.get('disk')) if kwargs.get('disk_size'): volume = self.create_volume(size=kwargs.get('disk_size'), location=location) self.attach_volume(node, volume) return node def reboot_node(self, node): params = {'type': 'reboot'} res = self.connection.request('/devices/%s/actions' % (node.id), params=params, method='POST') return res.status == httplib.OK def start_node(self, node): params = {'type': 'power_on'} res = self.connection.request('/devices/%s/actions' % (node.id), params=params, method='POST') return res.status == httplib.OK def stop_node(self, node): params = {'type': 'power_off'} res = self.connection.request('/devices/%s/actions' % (node.id), params=params, method='POST') return res.status == httplib.OK def destroy_node(self, node): res = self.connection.request('/devices/%s' % (node.id), method='DELETE') return res.status == httplib.OK def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_reinstall_node(self, node): params = {'type': 'reinstall'} res = self.connection.request('/devices/%s/actions' % (node.id), params=params, method='POST') return res.status == httplib.OK def ex_rescue_node(self, node): params = {'type': 'rescue'} res = self.connection.request('/devices/%s/actions' % (node.id), params=params, method='POST') return res.status == httplib.OK def ex_update_node(self, node, **kwargs): path = '/devices/%s' % node.id res = self.connection.request(path, params=kwargs, method='PUT') return res.status == httplib.OK def ex_get_node_bandwidth(self, node, from_time, until_time): path = '/devices/%s/bandwidth' % node.id params = {'from': from_time, 'until': until_time} return self.connection.request(path, params=params).object def ex_list_ip_assignments_for_node(self, node, include=''): path = '/devices/%s/ips' % node.id params = {'include': include} return self.connection.request(path, params=params).object def list_key_pairs(self): """ List all the available SSH keys. :return: Available SSH keys. :rtype: ``list`` of :class:`.KeyPair` objects """ data = self.connection.request('/ssh-keys').object['ssh_keys'] return list(map(self._to_key_pairs, data)) def create_key_pair(self, name, public_key): """ Create a new SSH key. :param name: Key name (required) :type name: ``str`` :param public_key: Valid public key string (required) :type public_key: ``str`` """ params = {'label': name, 'key': public_key} data = self.connection.request('/ssh-keys', method='POST', params=params).object return self._to_key_pairs(data) def delete_key_pair(self, key): """ Delete an existing SSH key. :param key: SSH key (required) :type key: :class:`KeyPair` """ key_id = key.name res = self.connection.request('/ssh-keys/%s' % (key_id), method='DELETE') return res.status == httplib.NO_CONTENT def _to_node(self, data): extra = {} extra_keys = ['created_at', 'updated_at', 'userdata', 'billing_cycle', 'locked', 'iqn', 'locked', 'project', 'description'] if 'state' in data: state = self.NODE_STATE_MAP.get(data['state'], NodeState.UNKNOWN) else: state = NodeState.UNKNOWN if 'ip_addresses' in data and data['ip_addresses'] is not None: ips = self._parse_ips(data['ip_addresses']) if 'operating_system' in data and data['operating_system'] is not None: image = self._to_image(data['operating_system']) extra['operating_system'] = data['operating_system'].get('name') else: image = None if 'plan' in data and data['plan'] is not None: size = self._to_size(data['plan']) extra['plan'] = data['plan'].get('slug') else: size = None if 'facility' in data: extra['facility'] = data['facility'] for key in extra_keys: if key in data: extra[key] = data[key] node = Node(id=data['id'], name=data['hostname'], state=state, public_ips=ips['public'], private_ips=ips['private'], size=size, image=image, extra=extra, driver=self) return node def _to_image(self, data): extra = {'distro': data['distro'], 'version': data['version']} return NodeImage(id=data['slug'], name=data['name'], extra=extra, driver=self) def _to_location(self, data): extra = data return NodeLocation(id=data['id'], name=data['name'], country=None, driver=self, extra=extra) def _to_size(self, data): cpus = data['specs']['cpus'][0].get('count') extra = {'description': data['description'], 'line': data['line'], 'cpus': cpus} ram = data['specs']['memory']['total'] disk = 0 for disks in data['specs']['drives']: disk_size = disks['size'].replace('GB', '') if 'TB' in disk_size: disk_size = float(disks['size'].replace('TB', '')) * 1000 disk += disks['count'] * int(disk_size) name = "%s - %s RAM" % (data.get('name'), ram) price = data['pricing'].get('hour') return NodeSize(id=data['slug'], name=name, ram=int(ram.replace('GB', '')) * 1024, disk=disk, bandwidth=0, price=price, extra=extra, driver=self) def _to_key_pairs(self, data): extra = {'label': data['label'], 'created_at': data['created_at'], 'updated_at': data['updated_at']} return KeyPair(name=data['id'], fingerprint=data['fingerprint'], public_key=data['key'], private_key=None, driver=self, extra=extra) def _parse_ips(self, data): public_ips = [] private_ips = [] for address in data: if 'address' in address and address['address'] is not None: if 'public' in address and address['public'] is True: public_ips.append(address['address']) else: private_ips.append(address['address']) return {'public': public_ips, 'private': private_ips} def ex_get_bgp_config_for_project(self, ex_project_id): path = '/projects/%s/bgp-config' % ex_project_id return self.connection.request(path).object def ex_get_bgp_config(self, ex_project_id=None): if ex_project_id: projects = [ex_project_id] elif self.project_id: projects = [self.project_id] else: projects = [p.id for p in self.projects] retval = [] for p in projects: config = self.ex_get_bgp_config_for_project(p) if config: retval.append(config) return retval def ex_get_bgp_session(self, session_uuid): path = '/bgp/sessions/%s' % session_uuid return self.connection.request(path).object def ex_list_bgp_sessions_for_node(self, node): path = '/devices/%s/bgp/sessions' % node.id return self.connection.request(path).object def ex_list_bgp_sessions_for_project(self, ex_project_id): path = '/projects/%s/bgp/sessions' % ex_project_id return self.connection.request(path).object def ex_list_bgp_sessions(self, ex_project_id=None): if ex_project_id: projects = [ex_project_id] elif self.project_id: projects = [self.project_id] else: projects = [p.id for p in self.projects] retval = [] for p in projects: retval.extend(self.ex_list_bgp_sessions_for_project( p)['bgp_sessions']) return retval def ex_create_bgp_session(self, node, address_family='ipv4'): path = '/devices/%s/bgp/sessions' % node.id params = {'address_family': address_family} res = self.connection.request(path, params=params, method='POST') return res.object def ex_delete_bgp_session(self, session_uuid): path = '/bgp/sessions/%s' % session_uuid res = self.connection.request(path, method='DELETE') return res.status == httplib.OK # or res.status == httplib.NO_CONTENT def ex_list_events_for_node(self, node, include=None, page=1, per_page=10): path = '/devices/%s/events' % node.id params = { 'include': include, 'page': page, 'per_page': per_page } return self.connection.request(path, params=params).object def ex_list_events_for_project(self, project, include=None, page=1, per_page=10): path = '/projects/%s/events' % project.id params = { 'include': include, 'page': page, 'per_page': per_page } return self.connection.request(path, params=params).object def ex_describe_all_addresses(self, ex_project_id=None, only_associated=False): if ex_project_id: projects = [ex_project_id] elif self.project_id: projects = [self.project_id] else: projects = [p.id for p in self.projects] retval = [] for project in projects: retval.extend(self.ex_describe_all_addresses_for_project( project, only_associated)) return retval def ex_describe_all_addresses_for_project(self, ex_project_id, include=None, only_associated=False): """ Returns all the reserved IP addresses for this project optionally, returns only addresses associated with nodes. :param only_associated: If true, return only the addresses that are associated with an instance. :type only_associated: ``bool`` :return: List of IP addresses. :rtype: ``list`` of :class:`dict` """ path = '/projects/%s/ips' % ex_project_id params = { 'include': include, } ip_addresses = self.connection.request(path, params=params).object result = [a for a in ip_addresses.get('ip_addresses', []) if not only_associated or len(a.get('assignments', [])) > 0] return result def ex_describe_address(self, ex_address_id, include=None): path = '/ips/%s' % ex_address_id params = { 'include': include, } result = self.connection.request(path, params=params).object return result def ex_request_address_reservation(self, ex_project_id, location_id=None, address_family='global_ipv4', quantity=1, comments='', customdata=''): path = '/projects/%s/ips' % ex_project_id params = { 'type': address_family, 'quantity': quantity, } if location_id: params['facility'] = location_id if comments: params['comments'] = comments if customdata: params['customdata'] = customdata result = self.connection.request( path, params=params, method='POST').object return result def ex_associate_address_with_node(self, node, address, manageable=False, customdata=''): path = '/devices/%s/ips' % node.id params = { 'address': address, 'manageable': manageable, 'customdata': customdata } result = self.connection.request( path, params=params, method='POST').object return result def ex_disassociate_address(self, address_uuid, include=None): path = '/ips/%s' % address_uuid params = {} if include: params['include'] = include result = self.connection.request( path, params=params, method='DELETE').object return result def list_volumes(self, ex_project_id=None): if ex_project_id: return self.ex_list_volumes_for_project( ex_project_id=ex_project_id) # if project has been specified during driver initialization, then # return nodes for this project only if self.project_id: return self.ex_list_volumes_for_project( ex_project_id=self.project_id) # In case of Python2 perform requests serially if not use_asyncio(): nodes = [] for project in self.projects: nodes.extend( self.ex_list_volumes_for_project(ex_project_id=project.id) ) return nodes # In case of Python3 use asyncio to perform requests in parallel return self.list_resources_async('volumes') def ex_list_volumes_for_project(self, ex_project_id, include='plan', page=1, per_page=1000): params = { 'include': include, 'page': page, 'per_page': per_page } data = self.connection.request( '/projects/%s/storage' % (ex_project_id), params=params).object['volumes'] return list(map(self._to_volume, data)) def _to_volume(self, data): return StorageVolume(id=data['id'], name=data['name'], size=data['size'], driver=self, extra=data) def create_volume(self, size, location, plan='storage_1', description='', ex_project_id=None, locked=False, billing_cycle=None, customdata='', snapshot_policies=None, **kwargs): """ Create a new volume. :param size: Size of volume in gigabytes (required) :type size: ``int`` :param location: Which data center to create a volume in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :return: The newly created volume. :rtype: :class:`StorageVolume` """ path = '/projects/%s/storage' % (ex_project_id or self.projects[0].id) try: facility = location.extra['code'] except AttributeError: facility = location params = { 'facility': facility, 'plan': plan, 'size': size, 'locked': locked } params.update(kwargs) if description: params['description'] = description if customdata: params['customdata'] = customdata if billing_cycle: params['billing_cycle'] = billing_cycle if snapshot_policies: params['snapshot_policies'] = snapshot_policies data = self.connection.request( path, params=params, method='POST').object return self._to_volume(data) def destroy_volume(self, volume): """ Destroys a storage volume. :param volume: Volume to be destroyed :type volume: :class:`StorageVolume` :rtype: ``bool`` """ path = '/storage/%s' % volume.id res = self.connection.request(path, method='DELETE') return res.status == httplib.NO_CONTENT def attach_volume(self, node, volume): """ Attaches volume to node. :param node: Node to attach volume to. :type node: :class:`.Node` :param volume: Volume to attach. :type volume: :class:`.StorageVolume` :rytpe: ``bool`` """ path = '/storage/%s/attachments' % volume.id params = { 'device_id': node.id } res = self.connection.request(path, params=params, method='POST') return res.status == httplib.OK def detach_volume(self, volume, ex_node=None, ex_attachment_id=''): """ Detaches a volume from a node. :param volume: Volume to be detached :type volume: :class:`.StorageVolume` :param ex_attachment_id: Attachment id to be detached, if empty detach all attachments :type name: ``str`` :rtype: ``bool`` """ path = '/storage/%s/attachments' % volume.id attachments = volume.extra['attachments'] assert len(attachments) > 0, "Volume is not attached to any node" success = True result = None for attachment in attachments: if not ex_attachment_id or ex_attachment_id in attachment['href']: attachment_id = attachment['href'].split('/')[-1] if ex_node: node_id = self.ex_describe_attachment( attachment_id)['device']['href'].split('/')[-1] if node_id != ex_node.id: continue path = '/storage/attachments/%s' % ( ex_attachment_id or attachment_id) result = self.connection.request(path, method='DELETE') success = success and result.status == httplib.NO_CONTENT return result and success def create_volume_snapshot(self, volume, name=''): """ Create a new volume snapshot. :param volume: Volume to create a snapshot for :type volume: class:`StorageVolume` :return: The newly created volume snapshot. :rtype: :class:`VolumeSnapshot` """ path = '/storage/%s/snapshots' % volume.id res = self.connection.request(path, method='POST') assert res.status == httplib.ACCEPTED return volume.list_snapshots()[-1] def destroy_volume_snapshot(self, snapshot): """ Delete a volume snapshot :param snapshot: volume snapshot to delete :type snapshot: class:`VolumeSnapshot` :rtype: ``bool`` """ volume_id = snapshot.extra['volume']['href'].split('/')[-1] path = '/storage/%s/snapshots/%s' % (volume_id, snapshot.id) res = self.connection.request(path, method='DELETE') return res.status == httplib.NO_CONTENT def list_volume_snapshots(self, volume, include=''): """ List snapshots for a volume. :param volume: Volume to list snapshots for :type volume: class:`StorageVolume` :return: List of volume snapshots. :rtype: ``list`` of :class: `VolumeSnapshot` """ path = '/storage/%s/snapshots' % volume.id params = {} if include: params['include'] = include data = self.connection.request(path, params=params).object['snapshots'] return list(map(self._to_volume_snapshot, data)) def _to_volume_snapshot(self, data): created = datetime.datetime.strptime( data['created_at'], "%Y-%m-%dT%H:%M:%S") return VolumeSnapshot(id=data['id'], name=data['id'], created=created, state=data['status'], driver=self, extra=data) def ex_modify_volume(self, volume, description=None, size=None, locked=None, billing_cycle=None, customdata=None): path = '/storage/%s' % volume.id params = {} if description: params['description'] = description if size: params['size'] = size if locked is not None: params['locked'] = locked if billing_cycle: params['billing_cycle'] = billing_cycle res = self.connection.request(path, params=params, method='PUT') return self._to_volume(res.object) def ex_restore_volume(self, snapshot): volume_id = snapshot.extra['volume']['href'].split('/')[-1] ts = snapshot.extra['timestamp'] path = '/storage/%s/restore?restore_point=%s' % (volume_id, ts) res = self.connection.request(path, method='POST') return res.status == httplib.NO_CONTENT def ex_clone_volume(self, volume, snapshot=None): path = '/storage/%s/clone' % volume.id if snapshot: path += '?snapshot_timestamp=%s' % snapshot.extra['timestamp'] res = self.connection.request(path, method='POST') return res.status == httplib.NO_CONTENT def ex_describe_volume(self, volume_id): path = '/storage/%s' % volume_id data = self.connection.request(path).object return self._to_volume(data) def ex_describe_attachment(self, attachment_id): path = '/storage/attachments/%s' % attachment_id data = self.connection.request(path).object return data class Project(object): def __init__(self, project): self.id = project.get('id') self.name = project.get('name') self.extra = {} self.extra['max_devices'] = project.get('max_devices') self.extra['payment_method'] = project.get('payment_method') self.extra['created_at'] = project.get('created_at') self.extra['credit_amount'] = project.get('credit_amount') self.extra['devices'] = project.get('devices') self.extra['invitations'] = project.get('invitations') self.extra['memberships'] = project.get('memberships') self.extra['href'] = project.get('href') self.extra['members'] = project.get('members') self.extra['ssh_keys'] = project.get('ssh_keys') def __repr__(self): return (('') % (self.id, self.name)) apache-libcloud-2.8.0/libcloud/compute/drivers/profitbricks.py0000664000175000017500000035374613576514553024465 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ProfitBricks Compute driver """ import base64 import json import copy import time from libcloud.utils.py3 import b from libcloud.utils.py3 import urlencode from libcloud.compute.providers import Provider from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize from libcloud.compute.base import NodeImage, StorageVolume, VolumeSnapshot from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey from libcloud.compute.base import UuidMixin from libcloud.compute.types import NodeState from libcloud.common.types import LibcloudError, MalformedResponseError from libcloud.common.exceptions import BaseHTTPError from collections import defaultdict __all__ = [ 'API_VERSION', 'API_HOST', 'ProfitBricksNodeDriver', 'Datacenter', 'ProfitBricksNetworkInterface', 'ProfitBricksFirewallRule', 'ProfitBricksLan', 'ProfitBricksIPFailover', 'ProfitBricksLoadBalancer', 'ProfitBricksAvailabilityZone', 'ProfitBricksIPBlock' ] API_HOST = 'api.profitbricks.com' API_VERSION = '/cloudapi/v4/' class ProfitBricksResponse(JsonResponse): """ ProfitBricks response parsing. """ def parse_error(self): http_code = None fault_code = None message = None try: body = json.loads(self.body) if 'httpStatus' in body: http_code = body['httpStatus'] else: http_code = 'unknown' if 'messages' in body: message = ', '.join(list(map( lambda item: item['message'], body['messages']))) fault_code = ', '.join(list(map( lambda item: item['errorCode'], body['messages']))) else: message = 'No messages returned.' fault_code = 'unknown' except Exception: raise MalformedResponseError('Failed to parse Json', body=self.body, driver=ProfitBricksNodeDriver) return LibcloudError( ''' HTTP Code: %s, Fault Code(s): %s, Message(s): %s ''' % (http_code, fault_code, message), driver=self) class ProfitBricksConnection(ConnectionUserAndKey): """ Represents a single connection to the ProfitBricks endpoint. """ host = API_HOST api_prefix = API_VERSION responseCls = ProfitBricksResponse def add_default_headers(self, headers): headers['Authorization'] = 'Basic %s' % (base64.b64encode( b('%s:%s' % (self.user_id, self.key))).decode('utf-8')) return headers def encode_data(self, data): """ If a string is passed in, just return it or else if a dict is passed in, encode it as a json string. """ if type(data) is str: return data elif type(data) is dict: return json.dumps(data) else: return '' def request(self, action, params=None, data=None, headers=None, method='GET', raw=False, with_full_url=False): """ Some requests will use the href attribute directly. If this is not the case, then we should formulate the url based on the action specified. If we are using a full url, we need to remove the host and protocol components. """ if not with_full_url or with_full_url is False: action = self.api_prefix + action.lstrip('/') else: action = action.replace( 'https://{host}'.format(host=self.host), '' ) return super(ProfitBricksConnection, self).request( action=action, params=params, data=data, headers=headers, method=method, raw=raw ) class Datacenter(UuidMixin): """ Class which stores information about ProfitBricks datacenter instances. :param id: The datacenter ID. :type id: ``str`` :param href: The datacenter href. :type href: ``str`` :param name: The datacenter name. :type name: ``str`` :param version: Datacenter version. :type version: ``str`` :param driver: ProfitBricks Node Driver. :type driver: :class:`ProfitBricksNodeDriver` :param extra: Extra properties for the Datacenter. :type extra: ``dict`` Note: This class is ProfitBricks specific. """ def __init__(self, id, href, name, version, driver, extra=None): self.id = str(id) self.href = href self.name = name self.version = version self.driver = driver self.extra = extra or {} UuidMixin.__init__(self) def __repr__(self): return (( ' ...>') % (self.id, self.href, self.name, self.version, self.driver.name)) class ProfitBricksNetworkInterface(object): """ Class which stores information about ProfitBricks network interfaces. :param id: The network interface ID. :type id: ``str`` :param name: The network interface name. :type name: ``str`` :param href: The network interface href. :type href: ``str`` :param state: The network interface name. :type state: ``int`` :param extra: Extra properties for the network interface. :type extra: ``dict`` Note: This class is ProfitBricks specific. """ def __init__(self, id, name, href, state, extra=None): self.id = id self.name = name self.href = href self.state = state self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.name, self.href)) class ProfitBricksFirewallRule(object): """ Extension class which stores information about a ProfitBricks firewall rule. :param id: The firewall rule ID. :type id: ``str`` :param name: The firewall rule name. :type name: ``str`` :param href: The firewall rule href. :type href: ``str`` :param state: The current state of the firewall rule. :type state: ``int`` :param extra: Extra properties for the firewall rule. :type extra: ``dict`` Note: This class is ProfitBricks specific. """ def __init__(self, id, name, href, state, extra=None): self.id = id self.name = name self.href = href self.state = state self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.name, self.href)) class ProfitBricksLan(object): """ Extension class which stores information about a ProfitBricks LAN :param id: The ID of the lan. :param id: ``str`` :param name: The name of the lan. :type name: ``str`` :param href: The lan href. :type href: ``str`` :param is_public: If public, the lan faces the public internet. :type is_public: ``bool`` :param state: The current state of the lan. :type state: ``int`` :param extra: Extra properties for the lan. :type extra: ``dict`` Note: This class is ProfitBricks specific. """ def __init__(self, id, name, href, is_public, state, driver, extra=None): self.id = id self.name = name self.href = href self.is_public = is_public self.state = state self.driver = driver self.extra = extra or {} def __repr__(self): return (('') % (self.id, self.name, self.href)) class ProfitBricksIPFailover(object): """ Extension class which stores information about a ProfitBricks LAN's failover :param ip: The IP address to fail over. :type ip: ``str`` :param nic_uuid: The ID of the NIC to fail over. :param nic_uuid: ``str`` Note: This class is ProfitBricks specific. """ def __init__(self, ip, nic_uuid): self.ip = ip self.nic_uuid = nic_uuid def __repr__(self): return (('') % (self.ip, self.nic_uuid)) class ProfitBricksLoadBalancer(object): """ Extention class which stores information about a ProfitBricks load balancer :param id: The ID of the load balancer. :param id: ``str`` :param name: The name of the load balancer. :type name: ``str`` :param href: The load balancer href. :type href: ``str`` :param state: The current state of the load balancer. :type state: ``int`` :param extra: Extra properties for the load balancer. :type extra: ``dict`` Note: This class is ProfitBricks specific """ def __init__(self, id, name, href, state, driver, extra=None): self.id = id self.name = name self.href = href self.state = state self.driver = driver self.extra = extra or {} def __repr__(self): return (('ProfitBricksLoadbalancer: id=%s, name=%s, href=%s>') % (self.id, self.name, self.href)) class ProfitBricksAvailabilityZone(object): """ Extension class which stores information about a ProfitBricks availability zone. :param name: The availability zone name. :type name: ``str`` Note: This class is ProfitBricks specific. """ def __init__(self, name): self.name = name def __repr__(self): return (('') % (self.name)) class ProfitBricksIPBlock(object): """ Extension class which stores information about a ProfitBricks IP block. :param id: The ID of the IP block. :param id: ``str`` :param name: The name of the IP block. :type name: ``str`` :param href: The IP block href. :type href: ``str`` :param location: The location of the IP block. :type location: ``str`` :param size: Number of IP addresses in the block. :type size: ``int`` :param ips: A collection of IPs associated with the block. :type ips: ``list`` :param state: The current state of the IP block. :type state: ``int`` :param extra: Extra properties for the IP block. :type extra: ``dict`` Note: This class is ProfitBricks specific """ def __init__( self, id, name, href, location, size, ips, state, driver, extra=None ): self.id = id self.name = name self.href = href self.location = location self.size = size self.ips = ips self.state = state self.driver = driver self.extra = extra or {} def __repr__(self): return ( ( '' ) % (self.id, self.name, self.href, self.location, self.size) ) class ProfitBricksNodeDriver(NodeDriver): """ Base ProfitBricks node driver. """ connectionCls = ProfitBricksConnection name = 'ProfitBricks' website = 'http://www.profitbricks.com' type = Provider.PROFIT_BRICKS PROVISIONING_STATE = { 'AVAILABLE': NodeState.RUNNING, 'BUSY': NodeState.PENDING, 'INACTIVE': NodeState.PENDING } NODE_STATE_MAP = { 'NOSTATE': NodeState.UNKNOWN, 'RUNNING': NodeState.RUNNING, 'BLOCKED': NodeState.STOPPED, 'PAUSE': NodeState.PAUSED, 'SHUTDOWN': NodeState.STOPPING, 'SHUTOFF': NodeState.STOPPED, 'CRASHED': NodeState.ERROR, 'AVAILABLE': NodeState.RUNNING, 'BUSY': NodeState.PENDING } AVAILABILITY_ZONE = { '1': {'name': 'AUTO'}, '2': {'name': 'ZONE_1'}, '3': {'name': 'ZONE_2'}, } """ ProfitBricks is unique in that they allow the user to define all aspects of the instance size, i.e. disk size, core size, and memory size. These are instance types that match up with what other providers support. You can configure disk size, core size, and memory size using the ``ex_`` parameters on the create_node method. """ PROFIT_BRICKS_GENERIC_SIZES = { '1': { 'id': '1', 'name': 'Micro', 'ram': 1024, 'disk': 50, 'cores': 1 }, '2': { 'id': '2', 'name': 'Small Instance', 'ram': 2048, 'disk': 50, 'cores': 1 }, '3': { 'id': '3', 'name': 'Medium Instance', 'ram': 4096, 'disk': 50, 'cores': 2 }, '4': { 'id': '4', 'name': 'Large Instance', 'ram': 7168, 'disk': 50, 'cores': 4 }, '5': { 'id': '5', 'name': 'ExtraLarge Instance', 'ram': 14336, 'disk': 50, 'cores': 8 }, '6': { 'id': '6', 'name': 'Memory Intensive Instance Medium', 'ram': 28672, 'disk': 50, 'cores': 4 }, '7': { 'id': '7', 'name': 'Memory Intensive Instance Large', 'ram': 57344, 'disk': 50, 'cores': 8 } } """ Core Functions """ def list_sizes(self): """ Lists all sizes :return: A list of all configurable node sizes. :rtype: ``list`` of :class:`NodeSize` """ sizes = [] for key, values in self.PROFIT_BRICKS_GENERIC_SIZES.items(): node_size = self._to_node_size(values) sizes.append(node_size) return sizes def list_images(self, image_type=None, is_public=True): """ List all images with an optional filter. :param image_type: The image type (HDD, CDROM) :type image_type: ``str`` :param is_public: Image is public :type is_public: ``bool`` :return: ``list`` of :class:`NodeImage` :rtype: ``list`` """ response = self.connection.request( action='images', params={'depth': 1}, method='GET' ) return self._to_images(response.object, image_type, is_public) def list_locations(self): """ List all locations. :return: ``list`` of :class:`NodeLocation` :rtype: ``list`` """ return self._to_locations(self.connection.request( action='locations', params={'depth': 1}, method='GET').object ) """ Node functions """ def list_nodes(self): """ List all nodes. :return: ``list`` of :class:`Node` :rtype: ``list`` """ datacenters = self.ex_list_datacenters() nodes = list() for datacenter in datacenters: servers_href = datacenter.extra['entities']['servers']['href'] response = self.connection.request( action=servers_href, params={'depth': 3}, method='GET', with_full_url=True ) mapped_nodes = self._to_nodes(response.object) nodes += mapped_nodes return nodes def reboot_node(self, node): """ Reboots the node. :rtype: ``bool`` """ action = node.extra['href'] + '/reboot' self.connection.request( action=action, method='POST', with_full_url=True ) return True def create_node( self, name, image=None, size=None, location=None, ex_cpu_family=None, volume=None, ex_datacenter=None, ex_network_interface=True, ex_internet_access=True, ex_exposed_public_ports=[], ex_exposed_private_ports=[22], ex_availability_zone=None, ex_ram=None, ex_cores=None, ex_disk=None, ex_password=None, ex_ssh_keys=None, ex_bus_type=None, ex_disk_type=None, **kwargs ): """ Creates a node. image is optional as long as you pass ram, cores, and disk to the method. ProfitBricks allows you to adjust compute resources at a much more granular level. :param name: The name for the new node. :param type: ``str`` :param image: The image to create the node with. :type image: :class:`NodeImage` :param size: Standard configured size offered by ProfitBricks - containing configuration for the number of cpu cores, amount of ram and disk size. :param size: :class:`NodeSize` :param location: The location of the new data center if one is not supplied. :type location: :class:`NodeLocation` :param ex_cpu_family: The CPU family to use (AMD_OPTERON, INTEL_XEON) :type ex_cpu_family: ``str`` :param volume: If the volume already exists then pass this in. :type volume: :class:`StorageVolume` :param ex_datacenter: If you've already created the DC then pass it in. :type ex_datacenter: :class:`Datacenter` :param ex_network_interface: Create with a network interface. :type ex_network_interface: : ``bool`` :param ex_internet_access: Configure public Internet access. :type ex_internet_access: : ``bool`` :param ex_exposed_public_ports: Ports to be opened for the public nic. :param ex_exposed_public_ports: ``list`` of ``int`` :param ex_exposed_private_ports: Ports to be opened for the private nic. :param ex_exposed_private_ports: ``list`` of ``int`` :param ex_availability_zone: The availability zone. :type ex_availability_zone: class: `ProfitBricksAvailabilityZone` :param ex_ram: The amount of ram required. :type ex_ram: : ``int`` :param ex_cores: The number of cores required. :type ex_cores: ``int`` :param ex_disk: The amount of disk required. :type ex_disk: ``int`` :param ex_password: The password for the volume. :type ex_password: :class:`NodeAuthPassword` or ``str`` :param ex_ssh_keys: Optional SSH keys for the volume. :type ex_ssh_keys: ``list`` of :class:`NodeAuthSSHKey` or ``list`` of ``str`` :param ex_bus_type: Volume bus type (VIRTIO, IDE). :type ex_bus_type: ``str`` :param ex_disk_type: Volume disk type (SSD, HDD). :type ex_disk_type: ``str`` :return: Instance of class ``Node`` :rtype: :class: `Node` """ """ If we have a volume we can determine the DC that it belongs to and set accordingly. """ if volume is not None: dc_url_pruned = volume.extra['href'].split('/')[:-2] dc_url = '/'.join(item for item in dc_url_pruned) ex_datacenter = self.ex_describe_datacenter( ex_href=dc_url ) if not ex_datacenter: ''' Determine location for new DC by getting the location of the image. ''' if not location: if image is not None: location = self.ex_describe_location( ex_location_id=image.extra['location'] ) ''' Creating a Datacenter for the node since one was not provided. ''' new_datacenter = self._create_new_datacenter_for_node( name=name, location=location ) ''' Then wait for the operation to finish, assigning the full data center on completion. ''' ex_datacenter = self._wait_for_datacenter_state( datacenter=new_datacenter ) if not size: if not ex_ram: raise ValueError('You need to either pass a ' 'NodeSize or specify ex_ram as ' 'an extra parameter.') if not ex_cores: raise ValueError('You need to either pass a ' 'NodeSize or specify ex_cores as ' 'an extra parameter.') ''' If passing in an image we need to enforce a password or ssh keys. ''' if not volume and image is not None: if ex_password is None and ex_ssh_keys is None: raise ValueError( ( 'When creating a server without a ' 'volume, you need to specify either an ' 'array of SSH keys or a volume password.' ) ) if not size: if not ex_disk: raise ValueError('You need to either pass a ' 'StorageVolume, a NodeSize, or specify ' 'ex_disk as an extra parameter.') ''' You can override the suggested sizes by passing in unique values for ram, cores, and disk allowing you to size it for your specific use. ''' if image is not None: if not ex_disk: ex_disk = size.disk if not ex_disk_type: ex_disk_type = 'HDD' if not ex_bus_type: ex_bus_type = 'VIRTIO' if not ex_ram: ex_ram = size.ram if not ex_cores: ex_cores = size.extra['cores'] action = ex_datacenter.href + '/servers' body = { 'properties': { 'name': name, 'ram': ex_ram, 'cores': ex_cores }, 'entities': { 'volumes': { 'items': [] } } } ''' If we are using a pre-existing storage volume. ''' if volume is not None: body['entities']['volumes']['items'].append({'id': volume.id}) elif image is not None: new_volume = { 'properties': { 'size': ex_disk, 'name': name + ' - volume', 'image': image.id, 'type': ex_disk_type, 'bus': ex_bus_type } } if ex_password is not None: if isinstance(ex_password, NodeAuthPassword): new_volume['properties']['imagePassword'] = \ ex_password.password else: new_volume['properties']['imagePassword'] = ex_password if ex_ssh_keys is not None: if isinstance(ex_ssh_keys[0], NodeAuthSSHKey): new_volume['properties']['sshKeys'] = \ [ssh_key.pubkey for ssh_key in ex_ssh_keys] else: new_volume['properties']['sshKeys'] = ex_ssh_keys body['entities']['volumes']['items'].append(new_volume) if ex_network_interface is True: body['entities']['nics'] = {} body['entities']['nics']['items'] = list() ''' Get the LANs for the data center this node will be provisioned at. ''' dc_lans = self.ex_list_lans( datacenter=ex_datacenter ) private_lans = [lan for lan in dc_lans if lan.is_public is False] private_lan = None if private_lans: private_lan = private_lans[0] if private_lan is not None: private_nic = { 'properties': { 'name': name + ' - private nic', 'lan': private_lan.id, }, 'entities': { 'firewallrules': { 'items': [] } } } for port in ex_exposed_private_ports: private_nic['entities']['firewallrules']['items'].append( { 'properties': { 'name': ( '{name} - firewall rule:{port}'.format( name=name, port=port ) ), 'protocol': 'TCP', 'portRangeStart': port, 'portRangeEnd': port } } ) body['entities']['nics']['items'].append(private_nic) if ex_internet_access is not None and ex_internet_access is True: public_lans = [lan for lan in dc_lans if lan.is_public] public_lan = None if public_lans: public_lan = public_lans[0] if public_lan is not None: pub_nic = { 'properties': { 'name': name + ' - public nic', 'lan': public_lan.id, }, 'entities': { 'firewallrules': { 'items': [] } } } for port in ex_exposed_public_ports: pub_nic['entities']['firewallrules']['items'].append( { 'properties': { 'name': ( '{name} - firewall rule:{port}'.format( name=name, port=port ) ), 'protocol': 'TCP', 'portRangeStart': port, 'portRangeEnd': port } } ) body['entities']['nics']['items'].append(pub_nic) if ex_cpu_family is not None: body['properties']['cpuFamily'] = ex_cpu_family if ex_availability_zone is not None: body['properties']['availabilityZone'] = ex_availability_zone.name response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return self._to_node(response.object, response.headers) def destroy_node(self, node, ex_remove_attached_disks=False): """ Destroys a node. :param node: The node you wish to destroy. :type volume: :class:`Node` :param ex_remove_attached_disks: True to destroy all attached volumes. :type ex_remove_attached_disks: : ``bool`` :rtype: : ``bool`` """ if ex_remove_attached_disks is True: for volume in self.ex_list_attached_volumes(node): self.destroy_volume(volume) action = node.extra['href'] self.connection.request( action=action, method='DELETE', with_full_url=True ) return True def start_node(self, node): """ Starts a node. :param node: The node you wish to start. :type node: :class:`Node` :rtype: ``bool`` """ action = node.extra['href'] + '/start' self.connection.request( action=action, method='POST', with_full_url=True ) return True def stop_node(self, node): """ Stops a node. This also deallocates the public IP space. :param node: The node you wish to halt. :type node: :class:`Node` :rtype: : ``bool`` """ action = node.extra['href'] + '/stop' self.connection.request( action=action, method='POST', with_full_url=True ) return True """ Volume Functions """ def list_volumes(self): """ List all volumes attached to a data center. :return: ``list`` of :class:`StorageVolume` :rtype: ``list`` """ datacenters = self.ex_list_datacenters() volumes = list() for datacenter in datacenters: volumes_href = datacenter.extra['entities']['volumes']['href'] response = self.connection.request( action=volumes_href, params={'depth': 3}, method='GET', with_full_url=True ) mapped_volumes = self._to_volumes(response.object) volumes += mapped_volumes return volumes def attach_volume(self, node, volume): """ Attaches a volume. :param node: The node to which you're attaching the volume. :type node: :class:`Node` :param volume: The volume you're attaching. :type volume: :class:`StorageVolume` :return: Instance of class ``StorageVolume`` :rtype: :class:`StorageVolume` """ action = node.extra['href'] + '/volumes' body = { 'id': volume.id } data = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return self._to_volume(data.object, data.headers) def create_volume( self, size, ex_datacenter, name=None, image=None, ex_image_alias=None, ex_type=None, ex_bus_type=None, ex_ssh_keys=None, ex_password=None, ex_availability_zone=None ): """ Creates a volume. :param size: The size of the volume in GB. :type size: ``int`` :param ex_datacenter: The datacenter you're placing the storage in. (req) :type ex_datacenter: :class:`Datacenter` :param name: The name to be given to the volume. :param name: ``str`` :param image: The OS image for the volume. :type image: :class:`NodeImage` :param ex_image_alias: An alias to a ProfitBricks public image. Use instead of 'image'. :type ex_image_alias: ``str`` :param ex_type: The type to be given to the volume (SSD or HDD). :param ex_type: ``str`` :param ex_bus_type: Bus type. Either IDE or VIRTIO (default). :type ex_bus_type: ``str`` :param ex_ssh_keys: Optional SSH keys. :type ex_ssh_keys: ``list`` of :class:`NodeAuthSSHKey` or ``list`` of ``str`` :param ex_password: Optional password for root. :type ex_password: :class:`NodeAuthPassword` or ``str`` :param ex_availability_zone: Volume Availability Zone. :type ex_availability_zone: ``str`` :return: Instance of class ``StorageVolume`` :rtype: :class:`StorageVolume` """ if not ex_datacenter: raise ValueError('You need to specify a data center' ' to attach this volume to.') if image is not None: if image.extra['image_type'] != 'HDD': raise ValueError('Invalid type of {image_type} specified for ' '{image_name}, which needs to be of type HDD' .format(image_type=image.extra['image_type'], image_name=image.name)) if ex_datacenter.extra['location'] != image.extra['location']: raise ValueError( 'The image {image_name} ' '(location: {image_location}) you specified ' 'is not available at the data center ' '{datacenter_name} ' '(location: {datacenter_location}).' .format( image_name=image.extra['name'], datacenter_name=ex_datacenter.extra['name'], image_location=image.extra['location'], datacenter_location=ex_datacenter.extra['location'] ) ) else: if not ex_image_alias: raise ValueError('You need to specify an image or image alias' ' to create this volume from.') action = ex_datacenter.href + '/volumes' body = { 'properties': { 'size': size } } if image is not None: body['properties']['image'] = image.id else: body['properties']['imageAlias'] = ex_image_alias if name is not None: body['properties']['name'] = name if ex_type is not None: body['properties']['type'] = ex_type if ex_bus_type is not None: body['properties']['bus'] = ex_bus_type if ex_ssh_keys is not None: if isinstance(ex_ssh_keys[0], NodeAuthSSHKey): body['properties']['sshKeys'] = \ [ssh_key.pubkey for ssh_key in ex_ssh_keys] else: body['properties']['sshKeys'] = ex_ssh_keys if ex_password is not None: if isinstance(ex_password, NodeAuthPassword): body['properties']['imagePassword'] = ex_password.password else: body['properties']['imagePassword'] = ex_password if ex_availability_zone is not None: body['properties']['availabilityZone'] = ex_availability_zone response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return self._to_volume(response.object, response.headers) def detach_volume(self, node, volume): """ Detaches a volume. :param node: The node to which you're detaching the volume. :type node: :class:`Node` :param volume: The volume you're detaching. :type volume: :class:`StorageVolume` :rtype: :``bool`` """ action = node.extra['href'] + '/volumes/{volume_id}'.format( volume_id=volume.id ) self.connection.request( action=action, method='DELETE', with_full_url=True ) return True def destroy_volume(self, volume): """ Destroys a volume. :param volume: The volume you're destroying. :type volume: :class:`StorageVolume` :rtype: : ``bool`` """ action = volume.extra['href'] self.connection.request( action=action, method='DELETE', with_full_url=True ) return True """ Volume snapshot functions """ def list_snapshots(self): """ Fetches as a list of all snapshots :return: ``list`` of class ``VolumeSnapshot`` :rtype: `list` """ response = self.connection.request( action='snapshots', params={'depth': 3}, method='GET' ) return self._to_snapshots(response.object) def create_volume_snapshot(self, volume): """ Creates a snapshot for a volume :param volume: The volume you're creating a snapshot for. :type volume: :class:`StorageVolume` :return: Instance of class ``VolumeSnapshot`` :rtype: :class:`VolumeSnapshot` """ action = volume.extra['href'] + '/create-snapshot' response = self.connection.request( action=action, headers={ 'Content-Type': 'application/x-www-form-urlencoded' }, method='POST', with_full_url=True ) return self._to_snapshot(response.object, response.headers) def destroy_volume_snapshot(self, snapshot): """ Delete a snapshot :param snapshot: The snapshot you wish to delete. :type: snapshot: :class:`VolumeSnapshot` :rtype ``bool`` """ action = snapshot.extra['href'] self.connection.request( action=action, method='DELETE', with_full_url=True ) return True """ Extension Functions """ """ Server Extension Functions """ def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def ex_list_availability_zones(self): """ Returns a list of availability zones. :return: ``list`` of :class:`ProfitBricksAvailabilityZone` :rtype: ``list`` """ availability_zones = [] for key, values in self.AVAILABILITY_ZONE.items(): name = copy.deepcopy(values)["name"] availability_zone = ProfitBricksAvailabilityZone( name=name ) availability_zones.append(availability_zone) return availability_zones def ex_list_attached_volumes(self, node): """ Returns a list of attached volumes for a server :param node: The node with the attached volumes. :type node: :class:`Node` :return: ``list`` of :class:`StorageVolume` :rtype: ``list`` """ action = node.extra['entities']['volumes']['href'] response = self.connection.request( action=action, params={'depth': 3}, method='GET', with_full_url=True ) return self._to_volumes(response.object) def ex_describe_node( self, ex_href=None, ex_datacenter_id=None, ex_node_id=None ): """ Fetches a node directly by href or by a combination of the datacenter ID and the server ID. :param ex_href: The href (url) of the node you wish to describe. :type ex_href: ``str`` :param ex_datacenter_id: The ID for the data center. :type ex_datacenter_id: ``str`` :param ex_node_id: The ID for the node (server). :type ex_node_id: ``str`` :return: Instance of class ``Node`` :rtype: :class:`Node` """ use_full_url = True if ex_href is None: if ex_datacenter_id is None or ex_node_id is None: raise ValueError( 'IDs for the data center and node are required.' ) else: use_full_url = False ex_href = ( 'datacenters/{datacenter_id}/' 'servers/{server_id}' ).format( datacenter_id=ex_datacenter_id, server_id=ex_node_id ) response = self.connection.request( action=ex_href, method='GET', params={'depth': 3}, with_full_url=use_full_url ) return self._to_node(response.object) def ex_update_node(self, node, name=None, cores=None, ram=None, availability_zone=None, ex_licence_type=None, ex_boot_volume=None, ex_boot_cdrom=None, ex_cpu_family=None): """ Updates a node. :param node: The node you wish to update. :type node: :class:`Node` :param name: The new name for the node. :type name: ``str`` :param cores: The number of CPUs the node should have. :type cores: : ``int`` :param ram: The amount of ram the node should have. :type ram: : ``int`` :param availability_zone: Update the availability zone. :type availability_zone: :class:`ProfitBricksAvailabilityZone` :param ex_licence_type: Licence type (WINDOWS, WINDOWS2016, LINUX, OTHER, UNKNOWN). :type ex_licence_type: ``str`` :param ex_boot_volume: Setting the new boot (HDD) volume. :type ex_boot_volume: :class:`StorageVolume` :param ex_boot_cdrom: Setting the new boot (CDROM) volume. :type ex_boot_cdrom: :class:`StorageVolume` :param ex_cpu_family: CPU family (INTEL_XEON, AMD_OPTERON). :type ex_cpu_family: ``str`` :return: Instance of class ``Node`` :rtype: :class: `Node` """ action = node.extra['href'] body = {} if name is not None: body['name'] = name if cores is not None: body['cores'] = cores if ram is not None: body['ram'] = ram if availability_zone is not None: body['availabilityZone'] = availability_zone.name if ex_licence_type is not None: body['licencetype'] = ex_licence_type if ex_boot_volume is not None: body['bootVolume'] = ex_boot_volume.id if ex_boot_cdrom is not None: body['bootCdrom'] = ex_boot_cdrom.id if ex_cpu_family is not None: body['allowReboot'] = True body['cpuFamily'] = ex_cpu_family response = self.connection.request( action=action, data=body, headers={ 'Content-Type': 'application/json' }, method='PATCH', with_full_url=True ) return self._to_node(response.object, response.headers) """ Data center Extension Functions """ def ex_create_datacenter( self, name, location, description=None ): """ Creates a datacenter. ProfitBricks has a concept of datacenters. These represent buckets into which you can place various compute resources. :param name: The datacenter name. :type name: : ``str`` :param location: instance of class ``NodeLocation``. :type location: : ``NodeLocation`` :param description: The datacenter description. :type description: : ``str`` :return: Instance of class ``Datacenter`` :rtype: :class:`Datacenter` """ body = { 'properties': { 'name': name, 'location': location.id } } if description is not None: body['properties']['description'] = description body['entities'] = defaultdict(dict) body['entities']['lans']['items'] = [ { 'properties': { 'name': name + ' - public lan', 'public': True } }, { 'properties': { 'name': name + ' - private lan', 'public': False } } ] response = self.connection.request( action='datacenters', headers={ 'Content-Type': 'application/json' }, data=body, method='POST' ) return self._to_datacenter(response.object, response.headers) def ex_destroy_datacenter(self, datacenter): """ Destroys a datacenter. :param datacenter: The DC you're destroying. :type datacenter: :class:`Datacenter` :rtype: : ``bool`` """ action = datacenter.href self.connection.request( action=action, method='DELETE', with_full_url=True ) return True def ex_describe_datacenter(self, ex_href=None, ex_datacenter_id=None): """ Fetches the details for a data center. :param ex_href: The href for the data center you are describing. :type ex_href: ``str`` :param ex_datacenter_id: The ID for the data center you are describing. :type ex_datacenter_id: ``str`` :return: Instance of class ``Datacenter`` :rtype: :class:`Datacenter` """ use_full_url = True if ex_href is None: if ex_datacenter_id is None: raise ValueError( 'The data center ID is required.' ) else: use_full_url = False ex_href = ( 'datacenters/{datacenter_id}' ).format( datacenter_id=ex_datacenter_id ) response = self.connection.request( action=ex_href, method='GET', params={'depth': 3}, with_full_url=use_full_url ) return self._to_datacenter(response.object) def ex_list_datacenters(self): """ Lists all datacenters. :return: ``list`` of :class:`DataCenter` :rtype: ``list`` """ response = self.connection.request( action='datacenters', params={'depth': 2}, method='GET' ) return self._to_datacenters(response.object) def ex_rename_datacenter(self, datacenter, name): """ Update a datacenter. :param datacenter: The DC you are renaming. :type datacenter: :class:`Datacenter` :param name: The DC name. :type name: : ``str`` :return: Instance of class ``Datacenter`` :rtype: :class:`Datacenter` """ action = datacenter.href body = { 'name': name } response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_datacenter(response.object, response.headers) """ Image Extension Functions """ def ex_describe_image(self, ex_href=None, ex_image_id=None): """ Describe a ProfitBricks image :param ex_href: The href for the image you are describing :type ex_href: ``str`` :param ex_image_id: The ID for the image you are describing :type ex_image_id: ``str`` :return: Instance of class ``Image`` :rtype: :class:`Image` """ use_full_url = True if ex_href is None: if ex_image_id is None: raise ValueError( 'The image ID is required.' ) else: use_full_url = False ex_href = ( 'images/{image_id}' ).format( image_id=ex_image_id ) response = self.connection.request( action=ex_href, method='GET', with_full_url=use_full_url ) return self._to_image(response.object) def ex_delete_image(self, image): """ Delete a private image :param image: The private image you are deleting. :type image: :class:`NodeImage` :rtype: : ``bool`` """ self.connection.request( action=image.extra['href'], method='DELETE', with_full_url=True ) return True def ex_update_image( self, image, name=None, description=None, licence_type=None, cpu_hot_plug=None, cpu_hot_unplug=None, ram_hot_plug=None, ram_hot_unplug=None, nic_hot_plug=None, nic_hot_unplug=None, disc_virtio_hot_plug=None, disc_virtio_hot_unplug=None, disc_scsi_hot_plug=None, disc_scsi_hot_unplug=None ): """ Update a private image :param image: The private image you are deleting. :type image: :class:`NodeImage` :return: Instance of class ``Image`` :rtype: :class:`Image` """ action = image.extra['href'] body = {} if name is not None: body['name'] = name if description is not None: body['description'] = description if licence_type is not None: body['licenceType'] = licence_type if cpu_hot_plug is not None: body['cpuHotPlug'] = cpu_hot_plug if cpu_hot_unplug is not None: body['cpuHotUnplug'] = cpu_hot_unplug if ram_hot_plug is not None: body['ramHotPlug'] = ram_hot_plug if ram_hot_unplug is not None: body['ramHotUnplug'] = ram_hot_unplug if nic_hot_plug is not None: body['nicHotPlug'] = nic_hot_plug if nic_hot_unplug is not None: body['nicHotUnplug'] = nic_hot_unplug if disc_virtio_hot_plug is not None: body['discVirtioHotPlug'] = disc_virtio_hot_plug if disc_virtio_hot_unplug is not None: body['discVirtioHotUnplug'] = disc_virtio_hot_unplug if disc_scsi_hot_plug is not None: body['discScsiHotPlug'] = disc_scsi_hot_plug if disc_scsi_hot_unplug is not None: body['discScsiHotUnplug'] = disc_scsi_hot_unplug response = self.connection.request( action=action, headers={ 'Content-type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_image(response.object, response.headers) """ Location Extension Functions """ def ex_describe_location(self, ex_href=None, ex_location_id=None): """ Fetch details for a ProfitBricks location. :param ex_href: The href for the location you are describing. :type ex_href: ``str`` :param ex_location_id: The id for the location you are describing ('de/fra', 'de/fkb', 'us/las', 'us/ewr') :type ex_location_id: ``str`` :return: Instance of class ``NodeLocation`` :rtype: :class:`NodeLocation` """ use_full_url = True if ex_href is None: if ex_location_id is None: raise ValueError( 'The location ID is required.' ) else: use_full_url = False ex_href = ( 'locations/{location_id}' ).format( location_id=ex_location_id ) response = self.connection.request( action=ex_href, method='GET', with_full_url=use_full_url ) return self._to_location(response.object) """ Network Interface Extension Functions """ def ex_list_network_interfaces(self): """ Fetch a list of all network interfaces from all data centers. :return: ``list`` of class ``ProfitBricksNetworkInterface`` :rtype: `list` """ nodes = self.list_nodes() nics = list() for node in nodes: action = node.extra['entities']['nics']['href'] nics += self._to_interfaces( self.connection.request( action=action, params={'depth': 1}, method='GET', with_full_url=True ).object) return nics def ex_describe_network_interface( self, ex_href=None, ex_datacenter_id=None, ex_server_id=None, ex_nic_id=None ): """ Fetch information on a network interface. :param ex_href: The href of the NIC you wish to describe. :type ex_href: ``str`` :param ex_datacenter_id: The ID of parent data center of the NIC you wish to describe. :type ex_datacenter_id: ``str`` :param ex_server_id: The server the NIC is connected to. :type ex_server_id: ``str`` :param ex_nic_id: The ID of the NIC :type ex_nic_id: ``str`` :return: Instance of class ``ProfitBricksNetworkInterface`` :rtype: :class:`ProfitBricksNetworkInterface` """ use_full_url = True if ex_href is None: if ( ex_datacenter_id is None or ex_server_id is None or ex_nic_id is None ): raise ValueError( ( 'IDs are required for the data center', 'server and network interface.' ) ) else: use_full_url = False ex_href = ( 'datacenters/{datacenter_id}' '/servers/{server_id}' '/nics/{nic_id}' ).format( datacenter_id=ex_datacenter_id, server_id=ex_server_id, nic_id=ex_nic_id ) response = self.connection.request( action=ex_href, method='GET', with_full_url=use_full_url ) return self._to_interface(response.object) def ex_create_network_interface(self, node, lan_id=None, ips=None, nic_name=None, dhcp_active=True): """ Creates a network interface. :param lan_id: The ID for the LAN. :type lan_id: : ``int`` :param ips: The IP addresses for the NIC. :type ips: ``list`` :param nic_name: The name of the NIC, e.g. PUBLIC. :type nic_name: ``str`` :param dhcp_active: Set to false to disable. :type dhcp_active: ``bool`` :return: Instance of class ``ProfitBricksNetworkInterface`` :rtype: :class:`ProfitBricksNetworkInterface` """ if lan_id is not None: lan_id = str(lan_id) else: lan_id = str(1) action = node.extra['href'] + '/nics' body = { 'properties': { 'lan': lan_id, 'dhcp': dhcp_active } } if ips is not None: body['properties']['ips'] = ips if nic_name is not None: body['properties']['name'] = nic_name response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return self._to_interface(response.object, response.headers) def ex_update_network_interface(self, network_interface, name=None, lan_id=None, ips=None, dhcp_active=None): """ Updates a network interface. :param network_interface: The network interface being updated. :type network_interface: :class:`ProfitBricksNetworkInterface` :param name: The name of the NIC, e.g. PUBLIC. :type name: ``str`` :param lan_id: The ID for the LAN. :type lan_id: : ``int`` :param ips: The IP addresses for the NIC as a list. :type ips: ``list`` :param dhcp_active: Set to false to disable. :type dhcp_active: ``bool`` :return: Instance of class ``ProfitBricksNetworkInterface`` :rtype: :class:`ProfitBricksNetworkInterface` """ if lan_id: lan_id = str(lan_id) action = network_interface.href body = {} if name is not None: body['name'] = name if lan_id is not None: body['lan'] = str(lan_id) if ips is not None: body['ips'] = ips if dhcp_active is not None: body['dhcp'] = dhcp_active response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_interface(response.object, response.headers) def ex_destroy_network_interface(self, network_interface): """ Destroy a network interface. :param network_interface: The NIC you wish to describe. :type network_interface: :class:`ProfitBricksNetworkInterface` :rtype: : ``bool`` """ action = network_interface.href self.connection.request( action=action, method='DELETE', with_full_url=True ) return True def ex_set_inet_access(self, network_interface, internet_access=True): """ Add/remove public internet access to an interface. :param network_interface: The NIC you wish to update. :type network_interface: :class:`ProfitBricksNetworkInterface` :return: Instance of class ``ProfitBricksNetworkInterface`` :rtype: :class:`ProfitBricksNetworkInterface` """ action = network_interface.href body = { 'nat': internet_access } response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_interface(response.object, response.headers) """ Firewall Rule Extension Functions """ def ex_list_firewall_rules(self, network_interface): """ Fetch firewall rules for a network interface. :param network_interface: The network interface. :type network_interface: :class:`ProfitBricksNetworkInterface` :return: ``list`` of class ``ProfitBricksFirewallRule`` :rtype: `list` """ action = network_interface.href + '/firewallrules' response = self.connection.request( action=action, method='GET', params={'depth': 3}, with_full_url=True ) return self._to_firewall_rules(response.object) def ex_describe_firewall_rule( self, ex_href=None, ex_datacenter_id=None, ex_server_id=None, ex_nic_id=None, ex_firewall_rule_id=None ): """ Fetch data for a firewall rule. :param href: The href of the firewall rule you wish to describe. :type href: ``str`` :param ex_datacenter_id: The ID of parent data center of the NIC you wish to describe. :type ex_datacenter_id: ``str`` :param ex_server_id: The server the NIC is connected to. :type ex_server_id: ``str`` :param ex_nic_id: The ID of the NIC. :type ex_nic_id: ``str`` :param ex_firewall_rule_id: The ID of the firewall rule. :type ex_firewall_rule_id: ``str`` :return: Instance class ``ProfitBricksFirewallRule`` :rtype: :class:`ProfitBricksFirewallRule` """ use_full_url = True if ex_href is None: if ( ex_datacenter_id is None or ex_server_id is None or ex_nic_id is None or ex_firewall_rule_id is None ): raise ValueError( ( 'IDs are required for the data ' 'center, server, network interface', 'and firewall rule.' ) ) else: use_full_url = False ex_href = ( 'datacenters/{datacenter_id}' '/servers/{server_id}' '/nics/{nic_id}' '/firewallrules/{firewall_rule_id}' ).format( datacenter_id=ex_datacenter_id, server_id=ex_server_id, nic_id=ex_nic_id, firewall_rule_id=ex_firewall_rule_id ) response = self.connection.request( action=ex_href, method='GET', with_full_url=use_full_url ) return self._to_firewall_rule(response.object) def ex_create_firewall_rule(self, network_interface, protocol, name=None, source_mac=None, source_ip=None, target_ip=None, port_range_start=None, port_range_end=None, icmp_type=None, icmp_code=None): """ Create a firewall rule for a network interface. :param network_interface: The network interface to attach the firewall rule to. :type: network_interface: :class:`ProfitBricksNetworkInterface` :param protocol: The protocol for the rule (TCP, UDP, ICMP, ANY) :type protocol: ``str`` :param name: The name for the firewall rule :type name: ``str`` :param source_mac: Only traffic originating from the respective MAC address is allowed. Valid format: aa:bb:cc:dd:ee:ff. Value null allows all source MAC address. :type source_mac: ``str`` :param source_ip: Only traffic originating from the respective IPv4 address is allowed. Value null allows all source IPs. :type source_ip: ``str`` :param target_ip: In case the target NIC has multiple IP addresses, only traffic directed to the respective IP address of the NIC is allowed. Value null allows all target IPs. :type target_ip: ``str`` :param port_range_start: Defines the start range of the allowed port (from 1 to 65534) if protocol TCP or UDP is chosen. Leave portRangeStart and portRangeEnd value null to allow all ports. type: port_range_start: ``int`` :param port_range_end: Defines the end range of the allowed port (from 1 to 65534) if protocol TCP or UDP is chosen. Leave portRangeStart and portRangeEnd value null to allow all ports. type: port_range_end: ``int`` :param icmp_type: Defines the allowed type (from 0 to 254) if the protocol ICMP is chosen. Value null allows all types. :type icmp_type: ``int`` :param icmp_code: Defines the allowed code (from 0 to 254) if protocol ICMP is chosen. Value null allows all codes. :type icmp_code: ``int`` :return: Instance class ``ProfitBricksFirewallRule`` :rtype: :class:`ProfitBricksFirewallRule` """ action = network_interface.href + '/firewallrules' body = { 'properties': { 'protocol': protocol } } if name is not None: body['properties']['name'] = name if source_mac is not None: body['properties']['sourceMac'] = source_mac if source_ip is not None: body['properties']['sourceIp'] = source_ip if target_ip is not None: body['properties']['targetIp'] = target_ip if port_range_start is not None: body['properties']['portRangeStart'] = str(port_range_start) if port_range_end is not None: body['properties']['portRangeEnd'] = str(port_range_end) if icmp_type is not None: body['properties']['icmpType'] = str(icmp_type) if icmp_code is not None: body['properties']['icmpType'] = str(icmp_code) response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return self._to_firewall_rule(response.object, response.headers) def ex_update_firewall_rule(self, firewall_rule, name=None, source_mac=None, source_ip=None, target_ip=None, port_range_start=None, port_range_end=None, icmp_type=None, icmp_code=None): """ Update a firewall rule :param firewall_rule: The firewall rule to update :type: firewall_rule: :class:`ProfitBricksFirewallRule` :param name: The name for the firewall rule :type name: ``str`` :param source_mac: Only traffic originating from the respective MAC address is allowed. Valid format: aa:bb:cc:dd:ee:ff. Value null allows all source MAC address. :type source_mac: ``str`` :param source_ip: Only traffic originating from the respective IPv4 address is allowed. Value null allows all source IPs. :type source_ip: ``str`` :param target_ip: In case the target NIC has multiple IP addresses, only traffic directed to the respective IP address of the NIC is allowed. Value null allows all target IPs. :type target_ip: ``str`` :param port_range_start: Defines the start range of the allowed port (from 1 to 65534) if protocol TCP or UDP is chosen. Leave portRangeStart and portRangeEnd value null to allow all ports. type: port_range_start: ``int`` :param port_range_end: Defines the end range of the allowed port (from 1 to 65534) if protocol TCP or UDP is chosen. Leave portRangeStart and portRangeEnd value null to allow all ports. type: port_range_end: ``int`` :param icmp_type: Defines the allowed type (from 0 to 254) if the protocol ICMP is chosen. Value null allows all types. :type icmp_type: ``int`` :param icmp_code: Defines the allowed code (from 0 to 254) if protocol ICMP is chosen. Value null allows all codes. :type icmp_code: ``int`` :return: Instance class ``ProfitBricksFirewallRule`` :rtype: :class:`ProfitBricksFirewallRule` """ action = firewall_rule.href body = {} if name is not None: body['name'] = name if source_mac is not None: body['sourceMac'] = source_mac if source_ip is not None: body['sourceIp'] = source_ip if target_ip is not None: body['targetIp'] = target_ip if port_range_start is not None: body['portRangeStart'] = str(port_range_start) if port_range_end is not None: body['portRangeEnd'] = str(port_range_end) if icmp_type is not None: body['icmpType'] = str(icmp_type) if icmp_code is not None: body['icmpType'] = str(icmp_code) response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_firewall_rule(response.object, response.headers) def ex_delete_firewall_rule(self, firewall_rule): """ Delete a firewall rule :param firewall_rule: The firewall rule to delete. :type: firewall_rule: :class:`ProfitBricksFirewallRule` :rtype ``bool`` """ action = firewall_rule.href self.connection.request( action=action, method='DELETE', with_full_url=True ) return True """ LAN extension functions """ def ex_list_lans(self, datacenter=None): """ List local area network on: - a datacenter if one is specified - all datacenters if none specified :param datacenter: The parent DC for the LAN. :type datacenter: :class:`Datacenter` :return: ``list`` of class ``ProfitBricksLan`` :rtype: `list` """ if datacenter is not None: action = datacenter.extra['entities']['lans']['href'] request = self.connection.request( action=action, params={'depth': 3}, method='GET', with_full_url=True ) lans = self._to_lans(request.object) else: datacenters = self.ex_list_datacenters() lans = [] for datacenter in datacenters: action = datacenter.extra['entities']['lans']['href'] request = self.connection.request( action=action, params={'depth': 3}, method='GET', with_full_url=True ) lans += self._to_lans(request.object) return lans def ex_create_lan(self, datacenter, name=None, is_public=False, nics=None): """ Create and attach a Lan to a data center. :param datacenter: The parent DC for the LAN.. :type datacenter: :class:`Datacenter` :param name: LAN name. :type name: ``str`` :param is_public: True if the Lan is to have internet access. :type is_public: ``bool`` :param nics: Optional network interfaces to attach to the lan. :param nics: ``list`` of class ``ProfitBricksNetworkInterface`` :return: Instance class ``ProfitBricksLan`` :rtype: :class:`ProfitBricksLan` """ action = datacenter.extra['entities']['lans']['href'] body = { 'properties': { 'name': name or 'LAN - {datacenter_name}'.format( datacenter_name=datacenter.name ), 'public': is_public } } if nics is not None: body['entities'] = defaultdict(dict) body['entities']['nics']['items'] = [ {'id': nic.id} for nic in nics ] request = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return self._to_lan(request.object, request.headers) def ex_describe_lan( self, ex_href=None, ex_datacenter_id=None, ex_lan_id=None ): """ Fetch data on a local area network :param ex_href: The href of the lan you wish to describe. :type ex_href: ``str`` :param ex_datacenter_id: The ID of the parent datacenter for the LAN. :type ex_datacenter_id: ``str`` :param ex_lan_id: The ID of LAN. :type ex_lan_id: ``str`` :return: Instance class ``ProfitBricksLan`` :rtype: :class:`ProfitBricksLan` """ use_full_url = True if ex_href is None: if ex_datacenter_id is None or ex_lan_id is None: raise ValueError( 'IDs for the data center and LAN are required.' ) else: use_full_url = False ex_href = ( 'datacenters/{datacenter_id}/' 'lans/{lan_id}' ).format( datacenter_id=ex_datacenter_id, lan_id=ex_lan_id ) response = self.connection.request( action=ex_href, method='GET', params={'depth': 1}, with_full_url=use_full_url ) return self._to_lan(response.object) def ex_update_lan(self, lan, is_public, name=None, ip_failover=None): """ Update a local area network :param lan: The lan you wish to update. :type: lan: :class:`ProfitBricksLan` :param is_public: Boolean indicating if the lan faces the public internet. :type is_public: ``bool`` :param name: The name of the lan. :type name: ``str`` :param ip_failover: The IP to fail over. :type ip_failover: ``list`` of :class: ``ProfitBricksIPFailover`` :return: Instance class ``ProfitBricksLan`` :rtype: :class:`ProfitBricksLan` """ action = lan.href body = { 'public': is_public } if name is not None: body['name'] = name if ip_failover is not None: body['ipFailover'] = [{'ip': item.ip, 'nicUuid': item.nic_uuid} for item in ip_failover] request = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_lan(request.object, request.headers) def ex_delete_lan(self, lan): """ Delete a local area network :param lan: The lan you wish to delete. :type: lan: :class:`ProfitBrickLan` :rtype ``bool`` """ action = lan.href self.connection.request( action=action, method='DELETE', with_full_url=True ) return True """ Volume extension functions """ def ex_update_volume( self, volume, ex_storage_name=None, size=None, ex_bus_type=None ): """ Updates a volume. :param volume: The volume you're updating. :type volume: :class:`StorageVolume` :param ex_storage_name: The name of the volume. :type ex_storage_name: ``str`` :param size: The desired size. :type size: ``int`` :param ex_bus_type: Volume bus type (VIRTIO, IDE). :type ex_bus_type: ``str`` :return: Instance of class ``StorageVolume`` :rtype: :class:`StorageVolume` """ if not ex_storage_name: ex_storage_name = volume.name if not size: size = str(volume.size) action = volume.extra['href'] body = { 'name': ex_storage_name, 'size': size } if ex_bus_type is not None: body['bus'] = ex_bus_type response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_volume(response.object, response.headers) def ex_describe_volume( self, ex_href=None, ex_datacenter_id=None, ex_volume_id=None ): """ Fetches and returns a volume :param ex_href: The full href (url) of the volume. :type ex_href: ``str`` :param ex_datacenter_id: The ID of the parent datacenter for the volume. :type ex_datacenter_id: ``str`` :param ex_volume_id: The ID of the volume. :type ex_volume_id: ``str`` :return: Instance of class ``StorageVolume`` :rtype: :class:`StorageVolume` """ use_full_url = True if ex_href is None: if ex_datacenter_id is None or ex_volume_id is None: raise ValueError( 'IDs for the data center and volume are required.' ) else: use_full_url = False ex_href = ( 'datacenters/{datacenter_id}/' 'volumes/{volume_id}' ).format( datacenter_id=ex_datacenter_id, volume_id=ex_volume_id ) response = self.connection.request( action=ex_href, method='GET', params={'depth': 3}, with_full_url=use_full_url ) return self._to_volume(response.object) def ex_restore_volume_snapshot(self, volume, snapshot): """ Restores a snapshot for a volume :param volume: The volume you're restoring the snapshot to. :type volume: :class:`StorageVolume` :param snapshot: The snapshot you're restoring to the volume. :type snapshot: :class:`ProfitBricksSnapshot` :rtype ``bool`` """ action = volume.extra['href'] + '/restore-snapshot' data = {'snapshotId': snapshot.id} body = urlencode(data) self.connection.request( action=action, headers={ 'Content-Type': 'application/x-www-form-urlencoded' }, data=body, method='POST', with_full_url=True ) return True """ Volume snapshot extension functions """ def ex_describe_snapshot(self, ex_href=None, ex_snapshot_id=None): """ Fetches and returns a volume snapshot :param ex_href: The full href (url) of the snapshot. :type ex_href: ``str`` :param ex_snapshot_id: The ID of the snapshot. :type ex_snapshot_id: ``str`` :return: Instance of class ``ProfitBricksSnapshot`` :rtype: :class:`ProfitBricksSnapshot` """ use_full_url = True if ex_href is None: if ex_snapshot_id is None: raise ValueError( 'The snapshot ID is required.' ) else: use_full_url = False ex_href = ( 'snapshots/{snapshot_id}' ).format( snapshot_id=ex_snapshot_id ) response = self.connection.request( action=ex_href, params={'depth': 3}, method='GET', with_full_url=use_full_url ) return self._to_snapshot(response.object) def ex_update_snapshot( self, snapshot, name=None, description=None, cpu_hot_plug=None, cpu_hot_unplug=None, ram_hot_plug=None, ram_hot_unplug=None, nic_hot_plug=None, nic_hot_unplug=None, disc_virtio_hot_plug=None, disc_virtio_hot_unplug=None, disc_scsi_hot_plug=None, disc_scsi_hot_unplug=None, licence_type=None ): """ Updates a snapshot :param snapshot: The snapshot you're restoring to the volume. :type snapshot: :class:`VolumeSnapshot` :param name: The snapshot name :type name: `str` :param description: The snapshot description :type description: `str` :param cpu_hot_plug: Snapshot CPU is hot pluggalbe :type cpu_hot_plug: `str` :param cpu_hot_unplug: Snapshot CPU is hot unpluggalbe :type cpu_hot_unplug: `str` :param ram_hot_plug: Snapshot RAM is hot pluggalbe :type ram_hot_plug: `str` :param ram_hot_unplug: Snapshot RAM is hot unpluggalbe :type ram_hot_unplug: `str` :param nic_hot_plug: Snapshot Network Interface is hot pluggalbe :type nic_hot_plug: `str` :param nic_hot_unplug: Snapshot Network Interface is hot unpluggalbe :type nic_hot_unplug: `str` :param disc_virtio_hot_plug: Snapshot VIRTIO disk is hot pluggalbe :type disc_virtio_hot_plug: `str` :param disc_virtio_hot_unplug: Snapshot VIRTIO disk is hot unpluggalbe :type disc_virtio_hot_unplug: `str` :param disc_scsi_hot_plug: Snapshot SCSI disk is hot pluggalbe :type disc_scsi_hot_plug: `str` :param disc_scsi_hot_unplug: Snapshot SCSI disk is hot unpluggalbe :type disc_scsi_hot_unplug: `str` :param licence_type: The snapshot licence_type :type licence_type: `str` :return: Instance of class ``VolumeSnapshot`` :rtype: :class:`VolumeSnapshot` """ action = snapshot.extra['href'] body = {} if name is not None: body['name'] = name if description is not None: body['description'] = description if cpu_hot_plug is not None: body['cpuHotPlug'] = cpu_hot_plug if cpu_hot_unplug is not None: body['cpuHotUnplug'] = cpu_hot_unplug if ram_hot_plug is not None: body['ramHotPlug'] = ram_hot_plug if ram_hot_unplug is not None: body['ramHotUnplug'] = ram_hot_unplug if nic_hot_plug is not None: body['nicHotPlug'] = nic_hot_plug if nic_hot_unplug is not None: body['nicHotUnplug'] = nic_hot_unplug if disc_virtio_hot_plug is not None: body['discVirtioHotPlug'] = disc_virtio_hot_plug if disc_virtio_hot_unplug is not None: body['discVirtioHotUnplug'] = disc_virtio_hot_unplug if disc_scsi_hot_plug is not None: body['discScsiHotPlug'] = disc_scsi_hot_plug if disc_scsi_hot_unplug is not None: body['discScsiHotUnplug'] = disc_scsi_hot_unplug if licence_type is not None: body['licenceType'] = licence_type response = self.connection.request( action=action, params={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_snapshot(response.object, response.headers) """ Load balancer extension functions """ def ex_list_load_balancers(self): """ Fetches as a list of load balancers :return: ``list`` of class ``ProfitBricksLoadBalancer`` :rtype: `list` """ datacenters = self.ex_list_datacenters() load_balancers = list() for datacenter in datacenters: extra = datacenter.extra load_balancers_href = extra['entities']['loadbalancers']['href'] response = self.connection.request( action=load_balancers_href, params={'depth': 3}, method='GET', with_full_url=True ) mapped_load_balancers = self._to_load_balancers(response.object) load_balancers += mapped_load_balancers return load_balancers def ex_describe_load_balancer( self, ex_href=None, ex_datacenter_id=None, ex_load_balancer_id=None ): """ Fetches and returns a load balancer :param href: The full href (url) of the load balancer. :type href: ``str`` :param ex_datacenter_id: The ID of the parent data center for the load balancer. :type ex_datacenter_id: ``str`` :param ex_load_balancer_id: The load balancer ID. :type ex_load_balancer_id: ``str`` :return: Instance of class ``ProfitBricksLoadBalancer`` :rtype: :class:`ProfitBricksLoadBalancer` """ use_full_url = True if ex_href is None: if ( ex_datacenter_id is None or ex_load_balancer_id is None ): raise ValueError( ( 'IDs for the data center and ' 'load balancer are required.' ) ) else: use_full_url = False ex_href = ( 'datacenters/{datacenter_id}/' 'loadbalancers/{load_balancer_id}' ).format( datacenter_id=ex_datacenter_id, load_balancer_id=ex_load_balancer_id ) response = self.connection.request( action=ex_href, params={'depth': 3}, method='GET', with_full_url=use_full_url ) return self._to_load_balancer(response.object) def ex_create_load_balancer( self, datacenter, name=None, ip=None, dhcp=None, nics=None ): """ Create and attach a load balancer to a data center. :param datacenter: The parent DC for the load balancer. :type datacenter: :class:`Datacenter` :param name: Load balancer name. :type name: ``str`` :param ip: Load balancer IPV4 address. :type ip: ``str`` :param dhcp: If true, the load balancer will reserve an IP address using DHCP. :type dhcp: ``bool`` :param nics: Optional network interfaces taking part in load balancing. :param nics: ``list`` of class ``ProfitBricksNetworkInterface`` :return: Instance class ``ProfitBricksLoadBalancer`` :rtype: :class:`ProfitBricksLoadBalancer` """ action = datacenter.extra['entities']['loadbalancers']['href'] body = { 'properties': { 'name': name or 'Load Balancer - {datacenter_name}' .format(datacenter_name=datacenter.name) } } if ip is not None: body['properties']['ip'] = ip if dhcp is not None: body['properties']['dhcp'] = dhcp if nics is not None: body['entities'] = defaultdict(dict) body['entities']['balancednics']['items'] = [ {'id': nic.id} for nic in nics ] response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return self._to_load_balancer(response.object, response.headers) def ex_update_load_balancer( self, load_balancer, name=None, ip=None, dhcp=None ): """ Update a load balancer :param load_balancer: The load balancer you wish to update. :type: load_balancer: :class:`ProfitBricksLoadBalancer` :param name: The name of the load balancer. :type name: ``str`` :param ip: The IPV4 address of the load balancer. :type ip: ``str`` :param dhcp: If true, the load balancer will reserve an IP address using DHCP. :type dhcp: ``bool`` :return: Instance class ``ProfitBricksLoadBalancer`` :rtype: :class:`ProfitBricksLoadBalancer` """ action = load_balancer.href body = {} if name is not None: body['name'] = name if ip is not None: body['ip'] = ip if dhcp is not None: body['dhcp'] = dhcp response = self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='PATCH', with_full_url=True ) return self._to_load_balancer(response.object, response.headers) def ex_list_load_balanced_nics(self, load_balancer): """ List balanced network interfaces for a load balancer. :param load_balancer: The load balancer you wish to update. :type: load_balancer: :class:`ProfitBricksLoadBalancer` :return: ``list`` of class ``ProfitBricksNetorkInterface`` :rtype: `list` """ action = load_balancer.extra['entities']['balancednics']['href'] response = self.connection.request( action=action, params={'depth': 3}, method='GET', with_full_url=True ) return self._to_interfaces(response.object) def ex_describe_load_balanced_nic( self, ex_href=None, ex_datacenter_id=None, ex_server_id=None, ex_nic_id=None ): """ Fetch information on a load balanced network interface. :param ex_href: The href of the load balanced NIC you wish to describe. :type ex_href: ``str`` :param ex_datacenter_id: The ID of parent data center of the NIC you wish to describe. :type ex_datacenter_id: ``str`` :param ex_server_id: The server the NIC is connected to. :type ex_server_id: ``str`` :param ex_nic_id: The ID of the NIC :type ex_nic_id: ``str`` :return: Instance of class ``ProfitBricksNetworkInterface`` :rtype: :class:`ProfitBricksNetworkInterface` """ return self.ex_describe_network_interface( ex_href=ex_href, ex_datacenter_id=ex_datacenter_id, ex_server_id=ex_server_id, ex_nic_id=ex_nic_id ) def ex_attach_nic_to_load_balancer( self, load_balancer, network_interface ): """ Attaches a network interface to a load balancer :param load_balancer: The load balancer you wish to attach the network interface to. :type: load_balancer: :class:`ProfitBricksLoadBalancer` :param network_interface: The network interface being attached. :type: network_interface: :class:`ProfitBricksNetworkInterface` :rtype ``bool`` """ action = load_balancer.extra['entities']['balancednics']['href'] body = { 'id': network_interface.id } self.connection.request( action=action, headers={ 'Content-Type': 'application/json' }, data=body, method='POST', with_full_url=True ) return True def ex_remove_nic_from_load_balancer( self, load_balancer, network_interface ): """ Removed a network interface from a load balancer :param load_balancer: The load balancer you wish to remove the network interface from. :type: load_balancer: :class:`ProfitBricksLoadBalancer` :param network_interface: The network interface being removed. :type: network_interface: :class:`ProfitBricksNetworkInterface` :rtype ``bool`` """ action = load_balancer.href + '/balancednics/' + network_interface.id self.connection.request( action=action, method='DELETE', with_full_url=True ) return True def ex_delete_load_balancer(self, load_balancer): """ Delete a load balancer :param load_balancer: The load balancer you wish to delete. :type: load_balancer: :class:`ProfitBricksLoadBalancer` :rtype ``bool`` """ action = load_balancer.href self.connection.request( action=action, method='DELETE', with_full_url=True ) return True """ IP Block extension functions """ def ex_list_ip_blocks(self): """ List all IP blocks :return: ``list`` of class ``ProfitBricksIPBlock`` :rtype: `list` """ response = self.connection.request( action='ipblocks', params={'depth': 3}, method='GET' ) return self._to_ip_blocks(response.object) def ex_create_ip_block(self, location, size, name=None): """ Create an IP block :param location: The location of the IP block. :type location: :class:`NodeLocation` :param size: The size of the IP block. :type size: ``int`` :param name: The name of the IP block. :type name: ``str`` :return: Instance class ``ProfitBricksIPBlock`` :rtype: :class:`ProfitBricksIPBlock` """ body = { 'properties': { 'location': location.id, 'size': size } } if name is not None: body['properties']['name'] = name response = self.connection.request( action='ipblocks', headers={ 'Content-Type': 'application/json' }, data=body, method='POST' ) return self._to_ip_block(response.object, response.headers) def ex_describe_ip_block(self, ex_href=None, ex_ip_block_id=None): """ Fetch an IP block :param ex_href: The href of the IP block. :type ex_href: ``str`` :param ex_ip_block_id: The ID of the IP block. :type ex_ip_block_id: ``str`` :return: Instance class ``ProfitBricksIPBlock`` :rtype: :class:`ProfitBricksIPBlock` """ use_full_url = True if ex_href is None: if ex_ip_block_id is None: raise ValueError( 'The IP block ID is required.' ) else: use_full_url = False ex_href = ( 'ipblocks/{ip_block_id}' ).format( ip_block_id=ex_ip_block_id ) response = self.connection.request( action=ex_href, params={'depth': 3}, method='GET', with_full_url=use_full_url ) return self._to_ip_block(response.object) def ex_delete_ip_block(self, ip_block): """ Delete an IP block :param ip_block: The IP block you wish to delete. :type: ip_block: :class:`ProfitBricksIPBlock` :rtype ``bool`` """ self.connection.request( action=ip_block.href, method='DELETE', with_full_url=True ) return True """ Private Functions """ def _to_ip_blocks(self, object): return [self._to_ip_block( ip_block) for ip_block in object['items']] def _to_ip_block(self, ip_block, headers=None): nested = { 'metadata': ip_block['metadata'] } extra = {} MAPPED_ATTRS = { 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedDate': 'last_modified_date', 'lastModifiedBy': 'last_modified_by', 'state': 'state' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] state = self.NODE_STATE_MAP.get( ip_block['metadata']['state'], NodeState.UNKNOWN ) # self, id, name, href, location, size, ips, state, driver, extra=None return ProfitBricksIPBlock( id=ip_block['id'], name=ip_block['properties']['name'], href=ip_block['href'], location=ip_block['properties']['location'], size=ip_block['properties']['size'], ips=ip_block['properties']['ips'] or [], state=state, driver=self.connection.driver, extra=extra ) def _to_load_balancers(self, object): return [self._to_load_balancer( load_balancer) for load_balancer in object['items']] def _to_load_balancer(self, load_balancer, headers=None): nested = { 'props': load_balancer['properties'], 'metadata': load_balancer['metadata'] } extra = {} MAPPED_ATTRS = { 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedDate': 'last_modified_date', 'lastModifiedBy': 'last_modified_by', 'state': 'state' }, 'props': { 'name': 'name', 'ip': 'ip', 'dhcp': 'dhcp' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] if 'entities' in load_balancer: extra['entities'] = load_balancer['entities'] state = self.NODE_STATE_MAP.get( load_balancer['metadata']['state'], NodeState.UNKNOWN ) return ProfitBricksLoadBalancer( id=load_balancer['id'], name=load_balancer['properties']['name'], href=load_balancer['href'], state=state, driver=self.connection.driver, extra=extra ) def _to_snapshots(self, object): return [self._to_snapshot( snapshot) for snapshot in object['items']] def _to_snapshot(self, snapshot, headers=None): nested = { 'props': snapshot['properties'], 'metadata': snapshot['metadata'] } extra = {} MAPPED_ATTRS = { 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedDate': 'last_modified_date', 'lastModifiedBy': 'last_modified_by', 'state': 'state' }, 'props': { 'name': 'name', 'description': 'description', 'location': 'location', 'size': 'size', 'cpuHotPlug': 'cpu_hot_plug', 'cpuHotUnplug': 'cpu_hot_unplug', 'ramHotPlug': 'ram_hot_plug', 'ramHotUnplug': 'ram_hot_unplug', 'nicHotPlug': 'nic_hot_plug', 'nicHotUnplug': 'nic_hot_unplug', 'discVirtioHotPlug': 'disc_virtio_hot_plug', 'discVirtioHotUnplug': 'disc_virtio_hot_unplug', 'discScsiHotPlug': 'disc_scsi_hot_plug', 'discScsiHotUnplug': 'disc_scsi_hot_unplug', 'licenceType': 'licence_type' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] state = self.NODE_STATE_MAP.get( snapshot['metadata']['state'], NodeState.UNKNOWN ) extra['href'] = snapshot['href'] return VolumeSnapshot( id=snapshot['id'], driver=self.connection.driver, size=extra['size'], extra=extra, created=extra['created_date'], state=state, name=extra['name'] ) def _to_lans(self, object): return [self._to_lan( lan) for lan in object['items']] def _to_lan(self, lan, headers=None): nested = { 'props': lan['properties'], 'metadata': lan['metadata'] } extra = {} MAPPED_ATTRS = { 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedDate': 'last_modified_date', 'lastModifiedBy': 'last_modified_by', 'state': 'state' }, 'props': { 'name': 'name', 'public': 'is_public' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if 'entities' in lan: extra['entities'] = lan['entities'] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] extra['provisioning_state'] = self.PROVISIONING_STATE.get( lan['metadata']['state'], NodeState.UNKNOWN ) state = self.NODE_STATE_MAP.get( lan['metadata']['state'], NodeState.UNKNOWN ) return ProfitBricksLan( id=lan['id'], name=lan['properties']['name'], href=lan['href'], is_public=lan['properties']['public'], state=state, driver=self.connection.driver, extra=extra ) def _to_datacenters(self, object): return [self._to_datacenter( datacenter) for datacenter in object['items']] def _to_datacenter(self, datacenter, headers=None): nested = { 'props': datacenter['properties'], 'metadata': datacenter['metadata'] } if 'entities' in datacenter: nested['entities'] = datacenter['entities'] extra = {} MAPPED_ATTRS = { 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedDate': 'last_modified_date', 'lastModifiedBy': 'last_modified_by', 'state': 'state' }, 'props': { 'description': 'description', 'features': 'features', 'location': 'location', 'name': 'name', 'version': 'version' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if 'entities' in datacenter: extra['entities'] = datacenter['entities'] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] extra['provisioning_state'] = self.PROVISIONING_STATE.get( datacenter['metadata']['state'], NodeState.UNKNOWN ) return Datacenter( id=datacenter['id'], href=datacenter['href'], name=datacenter['properties']['name'], version=datacenter['properties']['version'], driver=self.connection.driver, extra=extra ) def _to_images(self, object, image_type=None, is_public=True): if image_type is not None: images = [ image for image in object['items'] if image['properties']['imageType'] == image_type and image['properties']['public'] == is_public ] else: images = [ image for image in object['items'] if image['properties']['public'] == is_public ] return [self._to_image(image) for image in images] def _to_image(self, image, headers=None): nested = { 'props': image['properties'], 'metadata': image['metadata'] } extra = {} MAPPED_ATTRS = { 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedDate': 'last_modified_date', 'lastModifiedBy': 'last_modified_by', 'state': 'state' }, 'props': { 'name': 'name', 'description': 'description', 'location': 'location', 'size': 'size', 'cpuHotPlug': 'cpu_hot_plug', 'cpuHotUnplug': 'cpu_hot_unplug', 'ramHotPlug': 'ram_hot_plug', 'ramHotUnplug': 'ram_hot_unplug', 'nicHotPlug': 'nic_hot_plug', 'nicHotUnplug': 'nic_hot_unplug', 'discVirtioHotPlug': 'disc_virtio_hot_plug', 'discVirtioHotUnplug': 'disc_virtio_hot_unplug', 'discScsiHotPlug': 'disc_scsi_hot_plug', 'discScsiHotUnplug': 'disc_scsi_hot_unplug', 'licenceType': 'licence_type', 'imageType': 'image_type', 'imageAliases': 'image_aliases', 'public': 'public' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] """ Put the href inside extra because we cannot assign it to the NodeImage type. """ extra['href'] = image['href'] return NodeImage( id=image['id'], name=image['properties']['name'], driver=self.connection.driver, extra=extra ) def _to_nodes(self, object): return [self._to_node(n) for n in object['items']] def _to_node(self, node, headers=None): """ Convert the request into a node Node """ nested = { 'props': node['properties'], 'metadata': node['metadata'], 'entities': node['entities'] } extra = {} MAPPED_ATTRS = { 'props': { 'name': 'name', 'availabilityZone': 'availability_zone', 'bootCdrom': 'boot_cdrom', 'bootVolume': 'boot_volume', 'cores': 'cores', 'cpuFamily': 'cpu_family', 'ram': 'ram', 'vmState': 'vm_state' }, 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedBy': 'last_modified_by', 'lastModifiedDate': 'last_modified_date', 'state': 'state' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] state = self.NODE_STATE_MAP.get( node['properties']['vmState'], NodeState.UNKNOWN ) extra['entities'] = nested['entities'] extra['href'] = node['href'] public_ips = [] private_ips = [] if 'nics' in nested['entities']: if 'items' in nested['entities']['nics']: for nic in nested['entities']['nics']['items']: if nic['properties']['nat'] is True: public_ips += nic['properties']['ips'] elif nic['properties']['nat'] is False: private_ips += nic['properties']['ips'] return Node( id=node['id'], name=nested['props']['name'], state=state, public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver, extra=extra ) def _to_volumes(self, object): return [self._to_volume( volume) for volume in object['items']] def _to_volume(self, volume, headers=None): nested = { 'props': volume['properties'], 'metadata': volume['metadata'] } extra = {} MAPPED_ATTRS = { 'props': { 'bus': 'bus', 'size': 'size', 'cpuHotPlug': 'cpu_hot_plug', 'cpuHotUnplug': 'cpu_hot_unplug', 'discScsiHotPlug': 'disc_scsi_hot_plug', 'discScsiHotUnplug': 'disc_scsi_hot_unplug', 'discVirtioHotPlug': 'disc_virtio_hot_plug', 'discVirtioHotUnplug': 'disc_virtio_hot_unplug', 'image': 'image', 'imagePassword': 'image_password', 'licenceType': 'licence_type', 'name': 'name', 'nicHotPlug': 'nic_hot_plug', 'nicHotUnplug': 'nic_hot_unplug', 'ramHotPlug': 'ram_hot_plug', 'ramHotUnplug': 'ram_hot_unplug', 'sshKeys': 'ssh_keys', 'type': 'type', 'deviceNumber': 'device_number' }, 'metadata': { 'createdBy': 'created_by', 'createdDate': 'created_date', 'etag': 'etag', 'lastModifiedBy': 'last_modified_by', 'lastModifiedDate': 'last_modified_date', 'state': 'state' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] extra['provisioning_state'] = self.PROVISIONING_STATE.get( volume['metadata']['state'], NodeState.UNKNOWN ) extra['href'] = volume['href'] if 'availabilityZone' in volume['properties']: properties = volume['properties'] extra['availability_zone'] = properties['availabilityZone'] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] return StorageVolume( id=volume['id'], name=volume['properties']['name'], size=volume['properties']['size'], driver=self.connection.driver, extra=extra ) def _to_interfaces(self, object): return [self._to_interface( interface) for interface in object['items']] def _to_interface(self, interface, headers=None): nested = { 'props': interface['properties'], 'metadata': interface['metadata'] } extra = {} MAPPED_ATTRS = { 'props': { 'dhcp': 'dhcp', 'firewallActive': 'firewall_active', 'ips': 'ips', 'lan': 'lan', 'mac': 'mac', 'name': 'name', 'nat': 'nat' }, 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedBy': 'last_modified_by', 'lastModifiedDate': 'last_modified_date', 'state': 'state' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if 'entities' in interface: extra['entities'] = interface['entities'] state = self.NODE_STATE_MAP.get( interface['metadata']['state'], NodeState.UNKNOWN ) if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] return ProfitBricksNetworkInterface( id=interface['id'], name=interface['properties']['name'], href=interface['href'], state=state, extra=extra ) def _to_firewall_rules(self, object): return [self._to_firewall_rule( firewall_rule) for firewall_rule in object['items']] def _to_firewall_rule(self, firewallrule, headers=None): nested = { 'props': firewallrule['properties'], 'metadata': firewallrule['metadata'] } extra = {} MAPPED_ATTRS = { 'props': { 'name': 'name', 'protocol': 'protocol', 'sourceMac': 'source_mac', 'sourceIp': 'source_ip', 'targetIp': 'target_ip', 'icmpCode': 'icmp_code', 'icmpType': 'icmp_type', 'portRangeStart': 'port_range_start', 'portRangeEnd': 'port_range_end' }, 'metadata': { 'createdDate': 'created_date', 'createdBy': 'created_by', 'etag': 'etag', 'lastModifiedDate': 'last_modified_date', 'lastModifiedBy': 'last_modified_by', 'state': 'state' } } for k, v in MAPPED_ATTRS.items(): for original_name, altered_name in v.items(): extra[altered_name] = nested[k][original_name] if headers is not None: if 'location' in headers: extra['status_url'] = headers['location'] state = self.NODE_STATE_MAP.get( firewallrule['metadata']['state'], NodeState.UNKNOWN ) return ProfitBricksFirewallRule( id=firewallrule['id'], name=firewallrule['properties']['name'], href=firewallrule['href'], state=state, extra=extra ) def _to_locations(self, object): return [self._to_location(location) for location in object['items']] def _to_location(self, location): return NodeLocation( id=location['id'], name=location['properties']['name'], country=location['id'].split('/')[0], driver=self.connection.driver ) def _to_node_size(self, data): """ Convert the PROFIT_BRICKS_GENERIC_SIZES into NodeSize """ return NodeSize( id=data["id"], name=data["name"], ram=data["ram"], disk=data["disk"], bandwidth=None, price=None, driver=self.connection.driver, extra={'cores': data["cores"]} ) def _wait_for_datacenter_state( self, datacenter, state=NodeState.RUNNING, timeout=300, interval=5 ): """ Private function that waits the datacenter to transition into the specified state. :return: Datacenter object on success. :rtype: :class:`.Datacenter` """ wait_time = 0 attempts = 0 while attempts < 5: attempts += 1 try: datacenter = self.ex_describe_datacenter( ex_datacenter_id=datacenter.id ) break except BaseHTTPError: time.sleep(interval) if datacenter is None: raise Exception( 'Data center was not ready in time to ' 'complete this operation.' ) while (datacenter.extra['provisioning_state'] != state): datacenter = \ self.ex_describe_datacenter(ex_href=datacenter.href) if datacenter.extra['provisioning_state'] == state: break if wait_time >= timeout: raise Exception( 'Datacenter didn\'t transition to %s state ' 'in %s seconds' % (state, timeout) ) wait_time += interval time.sleep(interval) return datacenter def _create_new_datacenter_for_node( self, name, location=None ): """ Creates a Datacenter for a node. """ dc_name = name + '-DC' if location is None: location = self.ex_describe_location( ex_location_id='us/las' ) return self.ex_create_datacenter( name=dc_name, location=location ) apache-libcloud-2.8.0/libcloud/compute/drivers/rackspace.py0000664000175000017500000002234213535474530023674 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Rackspace driver """ from libcloud.compute.types import Provider, LibcloudError, VolumeSnapshotState from libcloud.compute.base import NodeLocation, VolumeSnapshot from libcloud.compute.drivers.openstack import OpenStack_1_0_Connection,\ OpenStack_1_0_NodeDriver, OpenStack_1_0_Response from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection,\ OpenStack_1_1_NodeDriver from libcloud.common.rackspace import AUTH_URL from libcloud.utils.iso8601 import parse_date SERVICE_TYPE = 'compute' SERVICE_NAME_GEN1 = 'cloudServers' SERVICE_NAME_GEN2 = 'cloudServersOpenStack' ENDPOINT_ARGS_MAP = { 'dfw': {'service_type': SERVICE_TYPE, 'name': SERVICE_NAME_GEN2, 'region': 'DFW'}, 'ord': {'service_type': SERVICE_TYPE, 'name': SERVICE_NAME_GEN2, 'region': 'ORD'}, 'iad': {'service_type': SERVICE_TYPE, 'name': SERVICE_NAME_GEN2, 'region': 'IAD'}, 'lon': {'service_type': SERVICE_TYPE, 'name': SERVICE_NAME_GEN2, 'region': 'LON'}, 'syd': {'service_type': SERVICE_TYPE, 'name': SERVICE_NAME_GEN2, 'region': 'SYD'}, 'hkg': {'service_type': SERVICE_TYPE, 'name': SERVICE_NAME_GEN2, 'region': 'HKG'}, } class RackspaceFirstGenConnection(OpenStack_1_0_Connection): """ Connection class for the Rackspace first-gen driver. """ responseCls = OpenStack_1_0_Response XML_NAMESPACE = 'http://docs.rackspacecloud.com/servers/api/v1.0' auth_url = AUTH_URL _auth_version = '2.0' cache_busting = True def __init__(self, *args, **kwargs): self.region = kwargs.pop('region', None) super(RackspaceFirstGenConnection, self).__init__(*args, **kwargs) def get_endpoint(self): if '2.0' in self._auth_version: ep = self.service_catalog.get_endpoint(service_type=SERVICE_TYPE, name=SERVICE_NAME_GEN1) else: raise LibcloudError( 'Auth version "%s" not supported' % (self._auth_version)) public_url = ep.url if not public_url: raise LibcloudError('Could not find specified endpoint') # This is a nasty hack, but it's required because of how the # auth system works. # Old US accounts can access UK API endpoint, but they don't # have this endpoint in the service catalog. Same goes for the # old UK accounts and US endpoint. if self.region == 'us': # Old UK account, which only have uk endpoint in the catalog public_url = public_url.replace('https://lon.servers.api', 'https://servers.api') elif self.region == 'uk': # Old US account, which only has us endpoints in the catalog public_url = public_url.replace('https://servers.api', 'https://lon.servers.api') return public_url def get_service_name(self): return SERVICE_NAME_GEN1 class RackspaceFirstGenNodeDriver(OpenStack_1_0_NodeDriver): name = 'Rackspace Cloud (First Gen)' website = 'http://www.rackspace.com' connectionCls = RackspaceFirstGenConnection type = Provider.RACKSPACE_FIRST_GEN api_name = 'rackspace' def __init__(self, key, secret=None, secure=True, host=None, port=None, region='us', **kwargs): """ @inherits: :class:`NodeDriver.__init__` :param region: Region ID which should be used :type region: ``str`` """ if region not in ['us', 'uk']: raise ValueError('Invalid region: %s' % (region)) super(RackspaceFirstGenNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) def list_locations(self): """ Lists available locations Locations cannot be set or retrieved via the API, but currently there are two locations, DFW and ORD. @inherits: :class:`OpenStack_1_0_NodeDriver.list_locations` """ if self.region == 'us': locations = [NodeLocation(0, "Rackspace DFW1/ORD1", 'US', self)] elif self.region == 'uk': locations = [NodeLocation(0, 'Rackspace UK London', 'UK', self)] return locations def _ex_connection_class_kwargs(self): kwargs = self.openstack_connection_kwargs() kwargs['region'] = self.region return kwargs class RackspaceConnection(OpenStack_1_1_Connection): """ Connection class for the Rackspace next-gen OpenStack base driver. """ auth_url = AUTH_URL _auth_version = '2.0' def __init__(self, *args, **kwargs): self.region = kwargs.pop('region', None) self.get_endpoint_args = kwargs.pop('get_endpoint_args', None) super(RackspaceConnection, self).__init__(*args, **kwargs) def get_service_name(self): if not self.get_endpoint_args: # if they used ex_force_base_url, assume the Rackspace default return SERVICE_NAME_GEN2 return self.get_endpoint_args.get('name', SERVICE_NAME_GEN2) def get_endpoint(self): if not self.get_endpoint_args: raise LibcloudError( 'RackspaceConnection must have get_endpoint_args set') if '2.0' in self._auth_version: ep = self.service_catalog.get_endpoint(**self.get_endpoint_args) else: raise LibcloudError( 'Auth version "%s" not supported' % (self._auth_version)) public_url = ep.url if not public_url: raise LibcloudError('Could not find specified endpoint') return public_url class RackspaceNodeDriver(OpenStack_1_1_NodeDriver): name = 'Rackspace Cloud (Next Gen)' website = 'http://www.rackspace.com' connectionCls = RackspaceConnection type = Provider.RACKSPACE _networks_url_prefix = '/os-networksv2' def __init__(self, key, secret=None, secure=True, host=None, port=None, region='dfw', **kwargs): """ @inherits: :class:`NodeDriver.__init__` :param region: ID of the region which should be used. :type region: ``str`` """ valid_regions = ENDPOINT_ARGS_MAP.keys() if region not in valid_regions: raise ValueError('Invalid region: %s' % (region)) if region == 'lon': self.api_name = 'rackspacenovalon' elif region == 'syd': self.api_name = 'rackspacenovasyd' else: self.api_name = 'rackspacenovaus' super(RackspaceNodeDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) def _to_snapshot(self, api_node): if 'snapshot' in api_node: api_node = api_node['snapshot'] extra = {'volume_id': api_node['volumeId'], 'name': api_node['displayName'], 'created': api_node['createdAt'], 'description': api_node['displayDescription'], 'status': api_node['status']} state = self.SNAPSHOT_STATE_MAP.get( api_node['status'], VolumeSnapshotState.UNKNOWN ) try: created_td = parse_date(api_node['createdAt']) except ValueError: created_td = None snapshot = VolumeSnapshot(id=api_node['id'], driver=self, size=api_node['size'], extra=extra, created=created_td, state=state, name=api_node['displayName']) return snapshot def _ex_connection_class_kwargs(self): endpoint_args = ENDPOINT_ARGS_MAP[self.region] kwargs = self.openstack_connection_kwargs() kwargs['region'] = self.region kwargs['get_endpoint_args'] = endpoint_args return kwargs apache-libcloud-2.8.0/libcloud/compute/drivers/rimuhosting.py0000664000175000017500000002764213600144066024307 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ RimuHosting Driver """ try: import simplejson as json except ImportError: import json from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.common.types import InvalidCredsError from libcloud.compute.types import Provider, NodeState from libcloud.compute.base import NodeDriver, NodeSize, Node, NodeLocation from libcloud.compute.base import NodeImage API_CONTEXT = '/r' API_HOST = 'rimuhosting.com' class RimuHostingException(Exception): """ Exception class for RimuHosting driver """ def __str__(self): return self.args[0] def __repr__(self): return "" % (self.args[0]) class RimuHostingResponse(JsonResponse): """ Response Class for RimuHosting driver """ def success(self): if self.status == 403: raise InvalidCredsError() return True def parse_body(self): try: js = super(RimuHostingResponse, self).parse_body() keys = list(js.keys()) if js[keys[0]]['response_type'] == "ERROR": raise RimuHostingException( js[keys[0]]['human_readable_message'] ) return js[keys[0]] except KeyError: raise RimuHostingException('Could not parse body: %s' % (self.body)) class RimuHostingConnection(ConnectionKey): """ Connection class for the RimuHosting driver """ api_context = API_CONTEXT host = API_HOST port = 443 responseCls = RimuHostingResponse def __init__(self, key, secure=True, retry_delay=None, backoff=None, timeout=None): # override __init__ so that we can set secure of False for testing ConnectionKey.__init__(self, key, secure, timeout=timeout, retry_delay=retry_delay, backoff=backoff) def add_default_headers(self, headers): # We want JSON back from the server. Could be application/xml # (but JSON is better). headers['Accept'] = 'application/json' # Must encode all data as json, or override this header. headers['Content-Type'] = 'application/json' headers['Authorization'] = 'rimuhosting apikey=%s' % (self.key) return headers def request(self, action, params=None, data='', headers=None, method='GET'): if not headers: headers = {} if not params: params = {} # Override this method to prepend the api_context return ConnectionKey.request(self, self.api_context + action, params, data, headers, method) class RimuHostingNodeDriver(NodeDriver): """ RimuHosting node driver """ type = Provider.RIMUHOSTING name = 'RimuHosting' website = 'http://rimuhosting.com/' connectionCls = RimuHostingConnection features = {'create_node': ['password']} def __init__(self, key, host=API_HOST, port=443, api_context=API_CONTEXT, secure=True): """ :param key: API key (required) :type key: ``str`` :param host: hostname for connection :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :param api_context: Optional API context. :type api_context: ``str`` :param secure: Whether to use HTTPS or HTTP. :type secure: ``bool`` :rtype: ``None`` """ # Pass in some extra vars so that self.key = key self.secure = secure self.connection = self.connectionCls(key, secure) self.connection.host = host self.connection.api_context = api_context self.connection.port = port self.connection.driver = self self.connection.connect() def _order_uri(self, node, resource): # Returns the order uri with its resourse appended. return "/orders/%s/%s" % (node.id, resource) # TODO: Get the node state. def _to_node(self, order): n = Node(id=order['slug'], name=order['domain_name'], state=NodeState.RUNNING, public_ips=( [order['allocated_ips']['primary_ip']] + order['allocated_ips']['secondary_ips']), private_ips=[], driver=self.connection.driver, extra={ 'order_oid': order['order_oid'], 'monthly_recurring_fee': order.get( 'billing_info').get('monthly_recurring_fee')}) return n def _to_size(self, plan): return NodeSize( id=plan['pricing_plan_code'], name=plan['pricing_plan_description'], ram=plan['minimum_memory_mb'], disk=plan['minimum_disk_gb'], bandwidth=plan['minimum_data_transfer_allowance_gb'], price=plan['monthly_recurring_amt']['amt_usd'], driver=self.connection.driver ) def _to_image(self, image): return NodeImage(id=image['distro_code'], name=image['distro_description'], driver=self.connection.driver) def list_sizes(self, location=None): # Returns a list of sizes (aka plans) # Get plans. Note this is really just for libcloud. # We are happy with any size. if location is None: location = '' else: location = ";dc_location=%s" % (location.id) res = self.connection.request( '/pricing-plans;server-type=VPS%s' % (location)).object return list(map(lambda x: self._to_size(x), res['pricing_plan_infos'])) def list_nodes(self): # Returns a list of Nodes # Will only include active ones. res = self.connection.request('/orders;include_inactive=N').object return list(map(lambda x: self._to_node(x), res['about_orders'])) def list_images(self, location=None): # Get all base images. # TODO: add other image sources. (Such as a backup of a VPS) # All Images are available for use at all locations res = self.connection.request('/distributions').object return list(map(lambda x: self._to_image(x), res['distro_infos'])) def reboot_node(self, node): # Reboot # PUT the state of RESTARTING to restart a VPS. # All data is encoded as JSON data = {'reboot_request': {'running_state': 'RESTARTING'}} uri = self._order_uri(node, 'vps/running-state') self.connection.request(uri, data=json.dumps(data), method='PUT') # XXX check that the response was actually successful return True def destroy_node(self, node): # Shutdown a VPS. uri = self._order_uri(node, 'vps') self.connection.request(uri, method='DELETE') # XXX check that the response was actually successful return True def create_node(self, name, size, image, auth=None, ex_billing_oid=None, ex_host_server_oid=None, ex_vps_order_oid_to_clone=None, ex_num_ips=1, ex_extra_ip_reason=None, ex_memory_mb=None, ex_disk_space_mb=None, ex_disk_space_2_mb=None, ex_control_panel=None): """Creates a RimuHosting instance @inherits: :class:`NodeDriver.create_node` :keyword name: Must be a FQDN. e.g example.com. :type name: ``str`` :keyword ex_billing_oid: If not set, a billing method is automatically picked. :type ex_billing_oid: ``str`` :keyword ex_host_server_oid: The host server to set the VPS up on. :type ex_host_server_oid: ``str`` :keyword ex_vps_order_oid_to_clone: Clone another VPS to use as the image for the new VPS. :type ex_vps_order_oid_to_clone: ``str`` :keyword ex_num_ips: Number of IPs to allocate. Defaults to 1. :type ex_num_ips: ``int`` :keyword ex_extra_ip_reason: Reason for needing the extra IPs. :type ex_extra_ip_reason: ``str`` :keyword ex_memory_mb: Memory to allocate to the VPS. :type ex_memory_mb: ``int`` :keyword ex_disk_space_mb: Diskspace to allocate to the VPS. Defaults to 4096 (4GB). :type ex_disk_space_mb: ``int`` :keyword ex_disk_space_2_mb: Secondary disk size allocation. Disabled by default. :type ex_disk_space_2_mb: ``int`` :keyword ex_control_panel: Control panel to install on the VPS. :type ex_control_panel: ``str`` """ # Note we don't do much error checking in this because we # expect the API to error out if there is a problem. data = { 'instantiation_options': { 'domain_name': name, 'distro': image.id }, 'pricing_plan_code': size.id, 'vps_parameters': {} } if ex_control_panel: data['instantiation_options']['control_panel'] = \ ex_control_panel auth = self._get_and_check_auth(auth) data['instantiation_options']['password'] = auth.password if ex_billing_oid: # TODO check for valid oid. data['billing_oid'] = ex_billing_oid if ex_host_server_oid: data['host_server_oid'] = ex_host_server_oid if ex_vps_order_oid_to_clone: data['vps_order_oid_to_clone'] = ex_vps_order_oid_to_clone if ex_num_ips and int(ex_num_ips) > 1: if not ex_extra_ip_reason: raise RimuHostingException( 'Need an reason for having an extra IP') else: if 'ip_request' not in data: data['ip_request'] = {} data['ip_request']['num_ips'] = int('ex_num_ips') data['ip_request']['extra_ip_reason'] = ex_extra_ip_reason if ex_memory_mb: data['vps_parameters']['memory_mb'] = ex_memory_mb if ex_disk_space_mb: data['vps_parameters']['disk_space_mb'] = ex_disk_space_mb if ex_disk_space_2_mb: data['vps_parameters']['disk_space_2_mb'] = ex_disk_space_2_mb # Don't send empty 'vps_parameters' attribute if not data['vps_parameters']: del data['vps_parameters'] res = self.connection.request( '/orders/new-vps', method='POST', data=json.dumps({"new-vps": data}) ).object node = self._to_node(res['about_order']) node.extra['password'] = \ res['new_order_request']['instantiation_options']['password'] return node def list_locations(self): return [ NodeLocation('DCAUCKLAND', "RimuHosting Auckland", 'NZ', self), NodeLocation('DCDALLAS', "RimuHosting Dallas", 'US', self), NodeLocation('DCLONDON', "RimuHosting London", 'GB', self), NodeLocation('DCSYDNEY', "RimuHosting Sydney", 'AU', self), ] apache-libcloud-2.8.0/libcloud/compute/drivers/scaleway.py0000664000175000017500000005724713570310635023556 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Scaleway Driver """ import copy try: import simplejson as json except ImportError: import json from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.common.types import ProviderError from libcloud.compute.base import NodeDriver, NodeImage, Node, NodeSize from libcloud.compute.base import NodeLocation from libcloud.compute.base import StorageVolume, VolumeSnapshot, KeyPair from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState, VolumeSnapshotState from libcloud.utils.iso8601 import parse_date from libcloud.utils.py3 import httplib __all__ = [ 'ScalewayResponse', 'ScalewayConnection', 'ScalewayNodeDriver' ] SCALEWAY_API_HOSTS = { 'default': 'cp-par1.scaleway.com', 'account': 'account.scaleway.com', 'par1': 'cp-par1.scaleway.com', 'ams1': 'cp-ams1.scaleway.com', } # The API doesn't give location info, so we provide it ourselves, instead. SCALEWAY_LOCATION_DATA = [ {'id': 'par1', 'name': 'Paris 1', 'country': 'FR'}, {'id': 'ams1', 'name': 'Amsterdam 1', 'country': 'NL'}, ] class ScalewayResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_error(self): return super(ScalewayResponse, self).parse_error()['message'] def success(self): return self.status in self.valid_response_codes class ScalewayConnection(ConnectionUserAndKey): """ Connection class for the Scaleway driver. """ host = SCALEWAY_API_HOSTS['default'] allow_insecure = False responseCls = ScalewayResponse def request(self, action, params=None, data=None, headers=None, method='GET', raw=False, stream=False, region=None): if region: old_host = self.host self.host = SCALEWAY_API_HOSTS[region.id if isinstance(region, NodeLocation) else region] if not self.host == old_host: self.connect() return super(ScalewayConnection, self).request(action, params, data, headers, method, raw, stream) def _request_paged(self, action, params=None, data=None, headers=None, method='GET', raw=False, stream=False, region=None): if params is None: params = {} if isinstance(params, dict): params['per_page'] = 100 elif isinstance(params, list): params.append(('per_page', 100)) # pylint: disable=no-member results = self.request(action, params, data, headers, method, raw, stream, region).object links = self.connection.getresponse().links while links and 'next' in links: next = self.request(links['next']['url'], data=data, headers=headers, method=method, raw=raw, stream=stream).object links = self.connection.getresponse().links merged = {root: child + next[root] for root, child in list(results.items())} results = merged return results def add_default_headers(self, headers): """ Add headers that are necessary for every request """ headers['X-Auth-Token'] = self.key headers['Content-Type'] = 'application/json' return headers def _to_lib_size(size): return int(size / 1000 / 1000 / 1000) def _to_api_size(size): return int(size * 1000 * 1000 * 1000) class ScalewayNodeDriver(NodeDriver): """ Scaleway Node Driver Class This is the primary driver for interacting with Scaleway. It contains all of the standard libcloud methods that Scaleway's API supports. """ type = Provider.SCALEWAY connectionCls = ScalewayConnection name = 'Scaleway' website = 'https://www.scaleway.com/' SNAPSHOT_STATE_MAP = { 'snapshotting': VolumeSnapshotState.CREATING, 'available': VolumeSnapshotState.AVAILABLE, 'error': VolumeSnapshotState.ERROR } def list_locations(self): """ List data centers available. :return: list of node location objects :rtype: ``list`` of :class:`.NodeLocation` """ return [NodeLocation(driver=self, **copy.deepcopy(location)) for location in SCALEWAY_LOCATION_DATA] def list_sizes(self, region=None): """ List available VM sizes. :param region: The region in which to list sizes (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: list of node size objects :rtype: ``list`` of :class:`.NodeSize` """ response = self.connection._request_paged('/products/servers', region=region) sizes = response['servers'] response = self.connection._request_paged( '/products/servers/availability', region=region) availability = response['servers'] return sorted([self._to_size(name, sizes[name], availability[name]) for name in sizes], key=lambda x: x.name) def _to_size(self, name, size, availability): min_disk = (_to_lib_size(size['volumes_constraint']['min_size'] or 0) if size['volumes_constraint'] else 25) max_disk = (_to_lib_size(size['volumes_constraint']['max_size'] or 0) if size['volumes_constraint'] else min_disk) extra = { 'cores': size['ncpus'], 'monthly': size['monthly_price'], 'arch': size['arch'], 'baremetal': size['baremetal'], 'availability': availability['availability'], 'max_disk': max_disk, 'internal_bandwidth': int( (size['network']['sum_internal_bandwidth'] or 0) / (1024 * 1024)), 'ipv6': size['network']['ipv6_support'], 'alt_names': size['alt_names'], } return NodeSize(id=name, name=name, ram=int((size['ram'] or 0) / (1024 * 1024)), disk=min_disk, bandwidth=int( (size['network']['sum_internet_bandwidth'] or 0) / (1024 * 1024)), price=size['hourly_price'], driver=self, extra=extra) def list_images(self, region=None): """ List available VM images. :param region: The region in which to list images (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: list of image objects :rtype: ``list`` of :class:`.NodeImage` """ response = self.connection._request_paged('/images', region=region) images = response['images'] return [self._to_image(image) for image in images] def create_image(self, node, name, region=None): """ Create a VM image from an existing node's root volume. :param node: The node from which to create the image :type node: :class:`.Node` :param name: The name to give the image :type name: ``str`` :param region: The region in which to create the image (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: the newly created image object :rtype: :class:`.NodeImage` """ data = { 'organization': self.key, 'name': name, 'arch': node.extra['arch'], 'root_volume': node.extra['volumes']['0']['id'] } response = self.connection.request('/images', data=json.dumps(data), region=region, method='POST') image = response.object['image'] return self._to_image(image) def delete_image(self, node_image, region=None): """ Delete a VM image. :param node_image: The image to delete :type node_image: :class:`.NodeImage` :param region: The region in which to find/delete the image (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: True if the image was deleted, otherwise False :rtype: ``bool`` """ return self.connection.request('/images/%s' % node_image.id, region=region, method='DELETE').success() def get_image(self, image_id, region=None): """ Retrieve a specific VM image. :param image_id: The id of the image to retrieve :type image_id: ``int`` :param region: The region in which to create the image (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: the requested image object :rtype: :class:`.NodeImage` """ response = self.connection.request('/images/%s' % image_id, region=region) image = response.object['image'] return self._to_image(image) def _to_image(self, image): extra = { 'arch': image['arch'], 'size': _to_lib_size(image.get('root_volume', {}) .get('size', 0)) or 50, 'creation_date': parse_date(image['creation_date']), 'modification_date': parse_date(image['modification_date']), 'organization': image['organization'], } return NodeImage(id=image['id'], name=image['name'], driver=self, extra=extra) def list_nodes(self, region=None): """ List all nodes. :param region: The region in which to look for nodes (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: list of node objects :rtype: ``list`` of :class:`.Node` """ response = self.connection._request_paged('/servers', region=region) servers = response['servers'] return [self._to_node(server) for server in servers] def _to_node(self, server): public_ip = server['public_ip'] private_ip = server['private_ip'] location = server['location'] or {} return Node(id=server['id'], name=server['name'], state=NodeState.fromstring(server['state']), public_ips=[public_ip['address']] if public_ip else [], private_ips=[private_ip] if private_ip else [], driver=self, extra={'volumes': server['volumes'], 'tags': server['tags'], 'arch': server['arch'], 'organization': server['organization'], 'region': location.get('zone_id', 'par1')}, created_at=parse_date(server['creation_date'])) def create_node(self, name, size, image, ex_volumes=None, ex_tags=None, region=None): """ Create a new node. :param name: The name to give the node :type name: ``str`` :param size: The size of node to create :type size: :class:`.NodeSize` :param image: The image to create the node with :type image: :class:`.NodeImage` :param ex_volumes: Additional volumes to create the node with :type ex_volumes: ``dict`` of :class:`.StorageVolume`s :param ex_tags: Tags to assign to the node :type ex_tags: ``list`` of ``str`` :param region: The region in which to create the node (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: the newly created node object :rtype: :class:`.Node` """ data = { 'name': name, 'organization': self.key, 'image': image.id, 'volumes': ex_volumes or {}, 'commercial_type': size.id, 'tags': ex_tags or [] } allocate_space = image.extra.get('size', 50) for volume in data['volumes']: allocate_space += _to_lib_size(volume['size']) while allocate_space < size.disk: if size.disk - allocate_space > 150: bump = 150 else: bump = size.disk - allocate_space vol_num = len(data['volumes']) + 1 data['volumes'][str(vol_num)] = { "name": "%s-%d" % (name, vol_num), "organization": self.key, "size": _to_api_size(bump), "volume_type": "l_ssd" } allocate_space += bump if allocate_space > size.extra.get('max_disk', size.disk): range = ("of %dGB" % size.disk if size.extra.get('max_disk', size.disk) == size.disk else "between %dGB and %dGB" % (size.extra.get('max_disk', size.disk), size.disk)) raise ProviderError( value=("%s only supports a total volume size %s; tried %dGB" % (size.id, range, allocate_space)), http_code=400, driver=self) response = self.connection.request('/servers', data=json.dumps(data), region=region, method='POST') server = response.object['server'] node = self._to_node(server) node.extra['region'] = (region.id if isinstance(region, NodeLocation) else region) or 'par1' # Scaleway doesn't start servers by default, let's do it self._action(node.id, 'poweron') return node def _action(self, server_id, action, region=None): return self.connection.request('/servers/%s/action' % server_id, region=region, data=json.dumps({'action': action}), method='POST').success() def reboot_node(self, node): """ Reboot a node. :param node: The node to be rebooted :type node: :class:`Node` :return: True if the reboot was successful, otherwise False :rtype: ``bool`` """ return self._action(node.id, 'reboot') def destroy_node(self, node): """ Destroy a node. :param node: The node to be destroyed :type node: :class:`Node` :return: True if the destroy was successful, otherwise False :rtype: ``bool`` """ return self._action(node.id, 'terminate') def list_volumes(self, region=None): """ Return a list of volumes. :param region: The region in which to look for volumes (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: A list of volume objects. :rtype: ``list`` of :class:`StorageVolume` """ response = self.connection._request_paged('/volumes', region=region) volumes = response['volumes'] return [self._to_volume(volume) for volume in volumes] def _to_volume(self, volume): extra = { 'organization': volume['organization'], 'volume_type': volume['volume_type'], 'creation_date': parse_date(volume['creation_date']), 'modification_date': parse_date(volume['modification_date']), } return StorageVolume(id=volume['id'], name=volume['name'], size=_to_lib_size(volume['size']), driver=self, extra=extra) def list_volume_snapshots(self, volume, region=None): """ List snapshots for a storage volume. @inherits :class:`NodeDriver.list_volume_snapshots` :param region: The region in which to look for snapshots (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` """ response = self.connection._request_paged('/snapshots', region=region) snapshots = filter(lambda s: s['base_volume']['id'] == volume.id, response['snapshots']) return [self._to_snapshot(snapshot) for snapshot in snapshots] def _to_snapshot(self, snapshot): state = self.SNAPSHOT_STATE_MAP.get(snapshot['state'], VolumeSnapshotState.UNKNOWN) extra = { 'organization': snapshot['organization'], 'volume_type': snapshot['volume_type'], } return VolumeSnapshot(id=snapshot['id'], driver=self, size=_to_lib_size(snapshot['size']), created=parse_date(snapshot['creation_date']), state=state, extra=extra) def create_volume(self, size, name, region=None): """ Create a new volume. :param size: Size of volume in gigabytes. :type size: ``int`` :param name: Name of the volume to be created. :type name: ``str`` :param region: The region in which to create the volume (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: The newly created volume. :rtype: :class:`StorageVolume` """ data = { 'name': name, 'organization': self.key, 'volume_type': 'l_ssd', 'size': _to_api_size(size) } response = self.connection.request('/volumes', region=region, data=json.dumps(data), method='POST') volume = response.object['volume'] return self._to_volume(volume) def create_volume_snapshot(self, volume, name, region=None): """ Create snapshot from volume. :param volume: The volume to create a snapshot from :type volume: :class`StorageVolume` :param name: The name to give the snapshot :type name: ``str`` :param region: The region in which to create the snapshot (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: The newly created snapshot. :rtype: :class:`VolumeSnapshot` """ data = { 'name': name, 'organization': self.key, 'volume_id': volume.id } response = self.connection.request('/snapshots', region=region, data=json.dumps(data), method='POST') snapshot = response.object['snapshot'] return self._to_snapshot(snapshot) def destroy_volume(self, volume, region=None): """ Destroys a storage volume. :param volume: Volume to be destroyed :type volume: :class:`StorageVolume` :param region: The region in which to look for the volume (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: True if the destroy was successful, otherwise False :rtype: ``bool`` """ return self.connection.request('/volumes/%s' % volume.id, region=region, method='DELETE').success() def destroy_volume_snapshot(self, snapshot, region=None): """ Dostroy a volume snapshot :param snapshot: volume snapshot to destroy :type snapshot: class:`VolumeSnapshot` :param region: The region in which to look for the snapshot (if None, use default region specified in __init__) :type region: :class:`.NodeLocation` :return: True if the destroy was successful, otherwise False :rtype: ``bool`` """ return self.connection.request('/snapshots/%s' % snapshot.id, region=region, method='DELETE').success() def list_key_pairs(self): """ List all the available SSH keys. :return: Available SSH keys. :rtype: ``list`` of :class:`KeyPair` """ response = self.connection.request('/users/%s' % (self._get_user_id()), region='account') keys = response.object['user']['ssh_public_keys'] return [KeyPair(name=' '.join(key['key'].split(' ')[2:]), public_key=' '.join(key['key'].split(' ')[:2]), fingerprint=key['fingerprint'], driver=self) for key in keys] def import_key_pair_from_string(self, name, key_material): """ Import a new public key from string. :param name: Key pair name. :type name: ``str`` :param key_material: Public key material. :type key_material: ``str`` :return: Imported key pair object. :rtype: :class:`KeyPair` """ new_key = KeyPair(name=name, public_key=' '.join(key_material.split(' ')[:2]), fingerprint=None, driver=self) keys = [key for key in self.list_key_pairs() if not key.name == name] keys.append(new_key) return self._save_keys(keys) def delete_key_pair(self, key_pair): """ Delete an existing key pair. :param key_pair: Key pair object. :type key_pair: :class:`KeyPair` :return: True of False based on success of Keypair deletion :rtype: ``bool`` """ keys = [key for key in self.list_key_pairs() if not key.name == key_pair.name] return self._save_keys(keys) def _get_user_id(self): response = self.connection.request('/tokens/%s' % self.secret, region='account') return response.object['token']['user_id'] def _save_keys(self, keys): data = { 'ssh_public_keys': [{'key': '%s %s' % (key.public_key, key.name)} for key in keys] } response = self.connection.request('/users/%s' % (self._get_user_id()), region='account', method='PATCH', data=json.dumps(data)) return response.success() apache-libcloud-2.8.0/libcloud/compute/drivers/serverlove.py0000664000175000017500000000556613535474530024145 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ ServerLove Driver """ from libcloud.compute.types import Provider from libcloud.compute.drivers.elasticstack import ElasticStackBaseNodeDriver from libcloud.compute.drivers.elasticstack import ElasticStackBaseConnection # API end-points API_ENDPOINTS = { 'uk-1': { 'name': 'United Kingdom, Manchester', 'country': 'United Kingdom', 'host': 'api.z1-man.serverlove.com' } } # Default API end-point for the base connection class. DEFAULT_ENDPOINT = 'uk-1' # Retrieved from http://www.serverlove.com/cloud-server-faqs/api-questions/ STANDARD_DRIVES = { '679f5f44-0be7-4745-a658-cccd4334c1aa': { 'uuid': '679f5f44-0be7-4745-a658-cccd4334c1aa', 'description': 'CentOS 5.5', 'size_gunzipped': '1GB', 'supports_deployment': True, }, '5f2e0e29-2937-42b9-b362-d2d07eddbdeb': { 'uuid': '5f2e0e29-2937-42b9-b362-d2d07eddbdeb', 'description': 'Ubuntu Linux 10.04', 'size_gunzipped': '1GB', 'supports_deployment': True, }, '5795b68f-ed26-4639-b41d-c93235062b6b': { 'uuid': '5795b68f-ed26-4639-b41d-c93235062b6b', 'description': 'Debian Linux 5', 'size_gunzipped': '1GB', 'supports_deployment': True, }, '41993a02-0b22-4e49-bb47-0aa8975217e4': { 'uuid': '41993a02-0b22-4e49-bb47-0aa8975217e4', 'description': 'Windows Server 2008 R2 Standard', 'size_gunzipped': '15GB', 'supports_deployment': False, }, '85623ca1-9c2a-4398-a771-9a43c347e86b': { 'uuid': '85623ca1-9c2a-4398-a771-9a43c347e86b', 'description': 'Windows Web Server 2008 R2', 'size_gunzipped': '15GB', 'supports_deployment': False, } } class ServerLoveConnection(ElasticStackBaseConnection): host = API_ENDPOINTS[DEFAULT_ENDPOINT]['host'] class ServerLoveNodeDriver(ElasticStackBaseNodeDriver): type = Provider.SERVERLOVE api_name = 'serverlove' website = 'http://www.serverlove.com/' name = 'ServerLove' connectionCls = ServerLoveConnection features = {'create_node': ['generates_password']} _standard_drives = STANDARD_DRIVES apache-libcloud-2.8.0/libcloud/compute/drivers/skalicloud.py0000664000175000017500000000554513535474530024100 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ skalicloud Driver """ from libcloud.compute.types import Provider from libcloud.compute.drivers.elasticstack import ElasticStackBaseNodeDriver from libcloud.compute.drivers.elasticstack import ElasticStackBaseConnection # API end-points API_ENDPOINTS = { 'my-1': { 'name': 'Malaysia, Kuala Lumpur', 'country': 'Malaysia', 'host': 'api.sdg-my.skalicloud.com' } } # Default API end-point for the base connection class. DEFAULT_ENDPOINT = 'my-1' # Retrieved from http://www.skalicloud.com/cloud-api/ STANDARD_DRIVES = { '90aa51f2-15c0-4cff-81ee-e93aa20b9468': { 'uuid': '90aa51f2-15c0-4cff-81ee-e93aa20b9468', 'description': 'CentOS 5.5 -64bit', 'size_gunzipped': '1GB', 'supports_deployment': True, }, 'c144d7a7-e24b-48ab-954b-6b6ec514ed6f': { 'uuid': 'c144d7a7-e24b-48ab-954b-6b6ec514ed6f', 'description': 'Debian 5 -64bit', 'size_gunzipped': '1GB', 'supports_deployment': True, }, '3051699a-a536-4220-aeb5-67f2ec101a09': { 'uuid': '3051699a-a536-4220-aeb5-67f2ec101a09', 'description': 'Ubuntu Server 10.10 -64bit', 'size_gunzipped': '1GB', 'supports_deployment': True, }, '11c4c922-5ff8-4094-b06c-eb8ffaec1ea9': { 'uuid': '11c4c922-5ff8-4094-b06c-eb8ffaec1ea9', 'description': 'Windows 2008R2 Web Edition', 'size_gunzipped': '13GB', 'supports_deployment': False, }, '93bf390e-4f46-4252-a8bc-9d6d80e3f955': { 'uuid': '93bf390e-4f46-4252-a8bc-9d6d80e3f955', 'description': 'Windows Server 2008R2 Standard', 'size_gunzipped': '13GB', 'supports_deployment': False, } } class SkaliCloudConnection(ElasticStackBaseConnection): host = API_ENDPOINTS[DEFAULT_ENDPOINT]['host'] class SkaliCloudNodeDriver(ElasticStackBaseNodeDriver): type = Provider.SKALICLOUD api_name = 'skalicloud' name = 'skalicloud' website = 'http://www.skalicloud.com/' connectionCls = SkaliCloudConnection features = {"create_node": ["generates_password"]} _standard_drives = STANDARD_DRIVES apache-libcloud-2.8.0/libcloud/compute/drivers/softlayer.py0000664000175000017500000004300113577507766023761 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Softlayer driver """ import time try: from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization crypto = True except ImportError: crypto = False from libcloud.common.softlayer import SoftLayerConnection, SoftLayerException from libcloud.compute.types import Provider, NodeState from libcloud.compute.base import NodeDriver, Node, NodeLocation, NodeSize, \ NodeImage, KeyPair from libcloud.compute.types import KeyPairDoesNotExistError DEFAULT_DOMAIN = 'example.com' DEFAULT_CPU_SIZE = 1 DEFAULT_RAM_SIZE = 2048 DEFAULT_DISK_SIZE = 100 DATACENTERS = { 'hou02': {'country': 'US'}, 'sea01': {'country': 'US', 'name': 'Seattle - West Coast U.S.'}, 'wdc01': {'country': 'US', 'name': 'Washington, DC - East Coast U.S.'}, 'dal01': {'country': 'US'}, 'dal02': {'country': 'US'}, 'dal04': {'country': 'US'}, 'dal05': {'country': 'US', 'name': 'Dallas - Central U.S.'}, 'dal06': {'country': 'US'}, 'dal07': {'country': 'US'}, 'sjc01': {'country': 'US', 'name': 'San Jose - West Coast U.S.'}, 'sng01': {'country': 'SG', 'name': 'Singapore - Southeast Asia'}, 'ams01': {'country': 'NL', 'name': 'Amsterdam - Western Europe'}, 'tok02': {'country': 'JP', 'name': 'Tokyo - Japan'}, } NODE_STATE_MAP = { 'RUNNING': NodeState.RUNNING, 'HALTED': NodeState.UNKNOWN, 'PAUSED': NodeState.UNKNOWN, 'INITIATING': NodeState.PENDING } SL_BASE_TEMPLATES = [ { 'name': '1 CPU, 1GB ram, 25GB', 'ram': 1024, 'disk': 25, 'cpus': 1, }, { 'name': '1 CPU, 1GB ram, 100GB', 'ram': 1024, 'disk': 100, 'cpus': 1, }, { 'name': '1 CPU, 2GB ram, 100GB', 'ram': 2 * 1024, 'disk': 100, 'cpus': 1, }, { 'name': '1 CPU, 4GB ram, 100GB', 'ram': 4 * 1024, 'disk': 100, 'cpus': 1, }, { 'name': '2 CPU, 2GB ram, 100GB', 'ram': 2 * 1024, 'disk': 100, 'cpus': 2, }, { 'name': '2 CPU, 4GB ram, 100GB', 'ram': 4 * 1024, 'disk': 100, 'cpus': 2, }, { 'name': '2 CPU, 8GB ram, 100GB', 'ram': 8 * 1024, 'disk': 100, 'cpus': 2, }, { 'name': '4 CPU, 4GB ram, 100GB', 'ram': 4 * 1024, 'disk': 100, 'cpus': 4, }, { 'name': '4 CPU, 8GB ram, 100GB', 'ram': 8 * 1024, 'disk': 100, 'cpus': 4, }, { 'name': '6 CPU, 4GB ram, 100GB', 'ram': 4 * 1024, 'disk': 100, 'cpus': 6, }, { 'name': '6 CPU, 8GB ram, 100GB', 'ram': 8 * 1024, 'disk': 100, 'cpus': 6, }, { 'name': '8 CPU, 8GB ram, 100GB', 'ram': 8 * 1024, 'disk': 100, 'cpus': 8, }, { 'name': '8 CPU, 16GB ram, 100GB', 'ram': 16 * 1024, 'disk': 100, 'cpus': 8, }] SL_TEMPLATES = {} for i, template in enumerate(SL_BASE_TEMPLATES): # Add local disk templates local = template.copy() local['local_disk'] = True SL_TEMPLATES[i] = local class SoftLayerNodeDriver(NodeDriver): """ SoftLayer node driver Extra node attributes: - password: root password - hourlyRecurringFee: hourly price (if applicable) - recurringFee : flat rate (if applicable) - recurringMonths : The number of months in which the recurringFee will be incurred. """ connectionCls = SoftLayerConnection name = 'SoftLayer' website = 'http://www.softlayer.com/' type = Provider.SOFTLAYER features = {'create_node': ['generates_password', 'ssh_key']} api_name = 'softlayer' def _to_node(self, host): try: password = \ host['operatingSystem']['passwords'][0]['password'] except (IndexError, KeyError): password = None hourlyRecurringFee = host.get('billingItem', {}).get( 'hourlyRecurringFee', 0) recurringFee = host.get('billingItem', {}).get('recurringFee', 0) recurringMonths = host.get('billingItem', {}).get('recurringMonths', 0) createDate = host.get('createDate', None) # When machine is launching it gets state halted # we change this to pending state = NODE_STATE_MAP.get(host['powerState']['keyName'], NodeState.UNKNOWN) if not password and state == NodeState.UNKNOWN: state = NODE_STATE_MAP['INITIATING'] public_ips = [] private_ips = [] if 'primaryIpAddress' in host: public_ips.append(host['primaryIpAddress']) if 'primaryBackendIpAddress' in host: private_ips.append(host['primaryBackendIpAddress']) image = host.get('operatingSystem', {}).get('softwareLicense', {}) \ .get('softwareDescription', {}) \ .get('longDescription', None) return Node( id=host['id'], name=host['fullyQualifiedDomainName'], state=state, public_ips=public_ips, private_ips=private_ips, driver=self, extra={ 'hostname': host['hostname'], 'fullyQualifiedDomainName': host['fullyQualifiedDomainName'], 'password': password, 'maxCpu': host.get('maxCpu', None), 'datacenter': host.get('datacenter', {}).get('longName', None), 'maxMemory': host.get('maxMemory', None), 'image': image, 'hourlyRecurringFee': hourlyRecurringFee, 'recurringFee': recurringFee, 'recurringMonths': recurringMonths, 'created': createDate, } ) def destroy_node(self, node): self.connection.request( 'SoftLayer_Virtual_Guest', 'deleteObject', id=node.id ) return True def reboot_node(self, node): self.connection.request( 'SoftLayer_Virtual_Guest', 'rebootSoft', id=node.id ) return True def start_node(self, node): self.connection.request( 'SoftLayer_Virtual_Guest', 'powerOn', id=node.id ) return True def stop_node(self, node): self.connection.request( 'SoftLayer_Virtual_Guest', 'powerOff', id=node.id ) return True def ex_start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.start_node(node=node) def ex_stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 return self.stop_node(node=node) def _get_order_information(self, node_id, timeout=1200, check_interval=5): mask = { 'billingItem': '', 'powerState': '', 'operatingSystem': {'passwords': ''}, 'provisionDate': '', } for i in range(0, timeout, check_interval): res = self.connection.request( 'SoftLayer_Virtual_Guest', 'getObject', id=node_id, object_mask=mask ).object if res.get('provisionDate', None): return res time.sleep(check_interval) raise SoftLayerException('Timeout on getting node details') def create_node(self, name, size=None, image=None, location=None, ex_domain=None, ex_cpus=None, ex_disk=None, ex_ram=None, ex_bandwidth=None, ex_local_disk=None, ex_datacenter=None, ex_os=None, ex_keyname=None, ex_hourly=True): """Create a new SoftLayer node @inherits: :class:`NodeDriver.create_node` :keyword ex_domain: e.g. libcloud.org :type ex_domain: ``str`` :keyword ex_cpus: e.g. 2 :type ex_cpus: ``int`` :keyword ex_disk: e.g. 100 :type ex_disk: ``int`` :keyword ex_ram: e.g. 2048 :type ex_ram: ``int`` :keyword ex_bandwidth: e.g. 100 :type ex_bandwidth: ``int`` :keyword ex_local_disk: e.g. True :type ex_local_disk: ``bool`` :keyword ex_datacenter: e.g. Dal05 :type ex_datacenter: ``str`` :keyword ex_os: e.g. UBUNTU_LATEST :type ex_os: ``str`` :keyword ex_keyname: The name of the key pair :type ex_keyname: ``str`` """ os = 'DEBIAN_LATEST' if ex_os: os = ex_os elif image: os = image.id size = size or NodeSize(id=123, name='Custom', ram=None, disk=None, bandwidth=None, price=None, driver=self.connection.driver) ex_size_data = SL_TEMPLATES.get(int(size.id)) or {} # plan keys are ints cpu_count = ex_cpus or ex_size_data.get('cpus') or \ DEFAULT_CPU_SIZE ram = ex_ram or ex_size_data.get('ram') or \ DEFAULT_RAM_SIZE bandwidth = ex_bandwidth or size.bandwidth or 10 hourly = ex_hourly local_disk = 'true' if ex_size_data.get('local_disk') is False: local_disk = 'false' if ex_local_disk is False: local_disk = 'false' disk_size = DEFAULT_DISK_SIZE if size.disk: disk_size = size.disk if ex_disk: disk_size = ex_disk datacenter = '' if ex_datacenter: datacenter = ex_datacenter elif location: datacenter = location.id domain = ex_domain if domain is None: if name.find('.') != -1: domain = name[name.find('.') + 1:] if domain is None: # TODO: domain is a required argument for the Sofylayer API, but it # it shouldn't be. domain = DEFAULT_DOMAIN newCCI = { 'hostname': name, 'domain': domain, 'startCpus': cpu_count, 'maxMemory': ram, 'networkComponents': [{'maxSpeed': bandwidth}], 'hourlyBillingFlag': hourly, 'operatingSystemReferenceCode': os, 'localDiskFlag': local_disk, 'blockDevices': [ { 'device': '0', 'diskImage': { 'capacity': disk_size, } } ] } if datacenter: newCCI['datacenter'] = {'name': datacenter} if ex_keyname: newCCI['sshKeys'] = [ { 'id': self._key_name_to_id(ex_keyname) } ] res = self.connection.request( 'SoftLayer_Virtual_Guest', 'createObject', newCCI ).object node_id = res['id'] raw_node = self._get_order_information(node_id) return self._to_node(raw_node) def list_key_pairs(self): result = self.connection.request( 'SoftLayer_Account', 'getSshKeys' ).object elems = [x for x in result] key_pairs = self._to_key_pairs(elems=elems) return key_pairs def get_key_pair(self, name): key_id = self._key_name_to_id(name=name) result = self.connection.request( 'SoftLayer_Security_Ssh_Key', 'getObject', id=key_id ).object return self._to_key_pair(result) # TODO: Check this with the libcloud guys, # can we create new dependencies? def create_key_pair(self, name, ex_size=4096): if crypto is False: raise NotImplementedError('create_key_pair needs' 'the cryptography library') key = rsa.generate_private_key( public_exponent=65537, key_size=4096, backend=default_backend() ) public_key = key.public_key().public_bytes( encoding=serialization.Encoding.OpenSSH, format=serialization.PublicFormat.OpenSSH ) new_key = { 'key': public_key, 'label': name, 'notes': '', } result = self.connection.request( 'SoftLayer_Security_Ssh_Key', 'createObject', new_key ).object result['private'] = key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() ) return self._to_key_pair(result) def import_key_pair_from_string(self, name, key_material): new_key = { 'key': key_material, 'label': name, 'notes': '', } result = self.connection.request( 'SoftLayer_Security_Ssh_Key', 'createObject', new_key ).object key_pair = self._to_key_pair(result) return key_pair def delete_key_pair(self, key_pair): key = self._key_name_to_id(key_pair) result = self.connection.request( 'SoftLayer_Security_Ssh_Key', 'deleteObject', id=key ).object return result def _to_image(self, img): return NodeImage( id=img['template']['operatingSystemReferenceCode'], name=img['itemPrice']['item']['description'], driver=self.connection.driver ) def list_images(self, location=None): result = self.connection.request( 'SoftLayer_Virtual_Guest', 'getCreateObjectOptions' ).object return [self._to_image(i) for i in result['operatingSystems']] def get_image(self, image_id): """ Gets an image based on an image_id. :param image_id: Image identifier :type image_id: ``str`` :return: A NodeImage object :rtype: :class:`NodeImage` """ images = self.list_images() images = [image for image in images if image.id == image_id] if len(images) < 1: raise SoftLayerException('could not find the image with id %s' % image_id) image = images[0] return image def _to_size(self, id, size): return NodeSize( id=id, name=size['name'], ram=size['ram'], disk=size['disk'], bandwidth=size.get('bandwidth'), price=self._get_size_price(str(id)), driver=self.connection.driver, ) def list_sizes(self, location=None): return [self._to_size(id, s) for id, s in SL_TEMPLATES.items()] def _to_loc(self, loc): country = 'UNKNOWN' loc_id = loc['template']['datacenter']['name'] name = loc_id if loc_id in DATACENTERS: country = DATACENTERS[loc_id]['country'] name = DATACENTERS[loc_id].get('name', loc_id) return NodeLocation(id=loc_id, name=name, country=country, driver=self) def list_locations(self): res = self.connection.request( 'SoftLayer_Virtual_Guest', 'getCreateObjectOptions' ).object return [self._to_loc(l) for l in res['datacenters']] def list_nodes(self): mask = { 'virtualGuests': { 'powerState': '', 'hostname': '', 'maxMemory': '', 'datacenter': '', 'operatingSystem': {'passwords': ''}, 'billingItem': '', }, } res = self.connection.request( 'SoftLayer_Account', 'getVirtualGuests', object_mask=mask ).object return [self._to_node(h) for h in res] def _to_key_pairs(self, elems): key_pairs = [self._to_key_pair(elem=elem) for elem in elems] return key_pairs def _to_key_pair(self, elem): key_pair = KeyPair(name=elem['label'], public_key=elem['key'], fingerprint=elem['fingerprint'], private_key=elem.get('private', None), driver=self, extra={'id': elem['id']}) return key_pair def _key_name_to_id(self, name): result = self.connection.request( 'SoftLayer_Account', 'getSshKeys' ).object key_id = [x for x in result if x['label'] == name] if len(key_id) == 0: raise KeyPairDoesNotExistError(name, self) else: return int(key_id[0]['id']) apache-libcloud-2.8.0/libcloud/compute/drivers/upcloud.py0000664000175000017500000002562413577507766023437 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Upcloud node driver """ import base64 import json from libcloud.utils.py3 import httplib, b from libcloud.compute.base import NodeDriver, NodeLocation, NodeSize from libcloud.compute.base import NodeImage, Node, NodeState from libcloud.compute.types import Provider from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.common.types import InvalidCredsError from libcloud.common.upcloud import UpcloudCreateNodeRequestBody from libcloud.common.upcloud import UpcloudNodeDestroyer from libcloud.common.upcloud import UpcloudNodeOperations from libcloud.common.upcloud import PlanPrice class UpcloudResponse(JsonResponse): """ Response class for UpcloudDriver """ def success(self): if self.status == httplib.NO_CONTENT: return True return super(UpcloudResponse, self).success() def parse_error(self): data = self.parse_body() if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError(value=data['error']['error_message']) return data class UpcloudConnection(ConnectionUserAndKey): """ Connection class for UpcloudDriver """ host = 'api.upcloud.com' responseCls = UpcloudResponse def add_default_headers(self, headers): """Adds headers that are needed for all requests""" headers['Authorization'] = self._basic_auth() headers['Accept'] = 'application/json' headers['Content-Type'] = 'application/json' return headers def _basic_auth(self): """Constructs basic auth header content string""" credentials = b("{0}:{1}".format(self.user_id, self.key)) credentials = base64.b64encode(credentials) return 'Basic {0}'.format(credentials.decode('ascii')) class UpcloudDriver(NodeDriver): """ Upcloud node driver :keyword username: Username required for authentication :type username: ``str`` :keyword password: Password required for authentication :type password: ``str`` """ type = Provider.UPCLOUD name = 'Upcloud' website = 'https://www.upcloud.com' connectionCls = UpcloudConnection features = {'create_node': ['ssh_key', 'generates_password']} NODE_STATE_MAP = { 'started': NodeState.RUNNING, 'stopped': NodeState.STOPPED, 'maintenance': NodeState.RECONFIGURING, 'error': NodeState.ERROR } def __init__(self, username, password, **kwargs): super(UpcloudDriver, self).__init__(key=username, secret=password, **kwargs) def list_locations(self): """ List available locations for deployment :rtype: ``list`` of :class:`NodeLocation` """ response = self.connection.request('1.2/zone') return self._to_node_locations(response.object['zones']['zone']) def list_sizes(self, location=None): """ List available plans :param location: Location of the deployement. Price depends on location. lf location is not given or price not found for location, price will be None (optional) :type location: :class:`.NodeLocation` :rtype: ``list`` of :class:`NodeSize` """ prices_response = self.connection.request('1.2/price') response = self.connection.request('1.2/plan') return self._to_node_sizes(response.object['plans']['plan'], prices_response.object['prices']['zone'], location) def list_images(self): """ List available distributions. :rtype: ``list`` of :class:`NodeImage` """ response = self.connection.request('1.2/storage/template') obj = response.object response = self.connection.request('1.2/storage/cdrom') storage = response.object['storages']['storage'] obj['storages']['storage'].extend(storage) return self._to_node_images(obj['storages']['storage']) def create_node(self, name, size, image, location, auth=None, ex_hostname='localhost', ex_username='root'): """ Creates instance to upcloud. If auth is not given then password will be generated. :param name: String with a name for this new node (required) :type name: ``str`` :param size: The size of resources allocated to this node. (required) :type size: :class:`.NodeSize` :param image: OS Image to boot on node. (required) :type image: :class:`.NodeImage` :param location: Which data center to create a node in. If empty, undefined behavior will be selected. (optional) :type location: :class:`.NodeLocation` :param auth: Initial authentication information for the node (optional) :type auth: :class:`.NodeAuthSSHKey` :param ex_hostname: Hostname. Default is 'localhost'. (optional) :type ex_hostname: ``str`` :param ex_username: User's username, which is created. Default is 'root'. (optional) :type ex_username: ``str`` :return: The newly created node. :rtype: :class:`.Node` """ body = UpcloudCreateNodeRequestBody(name=name, size=size, image=image, location=location, auth=auth, ex_hostname=ex_hostname, ex_username=ex_username) response = self.connection.request('1.2/server', method='POST', data=body.to_json()) server = response.object['server'] # Upcloud server's are in maintenace state when goind # from state to other, it is safe to assume STARTING state return self._to_node(server, state=NodeState.STARTING) def list_nodes(self): """ List nodes :return: List of node objects :rtype: ``list`` of :class:`Node` """ servers = [] for nid in self._node_ids(): response = self.connection.request('1.2/server/{0}'.format(nid)) servers.append(response.object['server']) return self._to_nodes(servers) def reboot_node(self, node): """ Reboot the given node :param node: the node to reboot :type node: :class:`Node` :rtype: ``bool`` """ body = { 'restart_server': { 'stop_type': 'hard' } } self.connection.request('1.2/server/{0}/restart'.format(node.id), method='POST', data=json.dumps(body)) return True def destroy_node(self, node): """ Destroy the given node The disk resources, attached to node, will not be removed. :param node: the node to destroy :type node: :class:`Node` :rtype: ``bool`` """ operations = UpcloudNodeOperations(self.connection) destroyer = UpcloudNodeDestroyer(operations) return destroyer.destroy_node(node.id) def _node_ids(self): """ Returns list of server uids currently on upcloud """ response = self.connection.request('1.2/server') servers = response.object['servers']['server'] return [server['uuid'] for server in servers] def _to_nodes(self, servers): return [self._to_node(server) for server in servers] def _to_node(self, server, state=None): ip_addresses = server['ip_addresses']['ip_address'] public_ips = [ip['address'] for ip in ip_addresses if ip['access'] == 'public'] private_ips = [ip['address'] for ip in ip_addresses if ip['access'] == 'private'] extra = {'vnc_password': server['vnc_password']} if 'password' in server: extra['password'] = server['password'] return Node(id=server['uuid'], name=server['title'], state=state or self.NODE_STATE_MAP[server['state']], public_ips=public_ips, private_ips=private_ips, driver=self, extra=extra) def _to_node_locations(self, zones): return [self._construct_node_location(zone) for zone in zones] def _construct_node_location(self, zone): return NodeLocation(id=zone['id'], name=zone['description'], country=self._parse_country(zone['id']), driver=self) def _parse_country(self, zone_id): """Parses the country information out of zone_id. Zone_id format [country]_[city][number], like fi_hel1""" return zone_id.split('-')[0].upper() def _to_node_sizes(self, plans, prices, location): plan_price = PlanPrice(prices) return [self._to_node_size(plan, plan_price, location) for plan in plans] def _to_node_size(self, plan, plan_price, location): extra = self._copy_dict(('core_number', 'storage_tier'), plan) return NodeSize(id=plan['name'], name=plan['name'], ram=plan['memory_amount'], disk=plan['storage_size'], bandwidth=plan['public_traffic_out'], price=plan_price.get_price(plan['name'], location), driver=self, extra=extra) def _to_node_images(self, images): return [self._construct_node_image(image) for image in images] def _construct_node_image(self, image): extra = self._copy_dict(('access', 'license', 'size', 'state', 'type'), image) return NodeImage(id=image['uuid'], name=image['title'], driver=self, extra=extra) def _copy_dict(self, keys, d): extra = {} for key in keys: extra[key] = d[key] return extra apache-libcloud-2.8.0/libcloud/compute/drivers/vcl.py0000664000175000017500000002121313577507766022536 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ VCL driver """ import time from libcloud.common.base import ConnectionUserAndKey from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.compute.types import Provider, NodeState from libcloud.compute.base import NodeDriver, Node from libcloud.compute.base import NodeSize, NodeImage class VCLResponse(XMLRPCResponse): exceptions = { 'VCL_Account': InvalidCredsError, } class VCLConnection(XMLRPCConnection, ConnectionUserAndKey): endpoint = '/index.php?mode=xmlrpccall' def add_default_headers(self, headers): headers['X-APIVERSION'] = '2' headers['X-User'] = self.user_id headers['X-Pass'] = self.key return headers class VCLNodeDriver(NodeDriver): """ VCL node driver :keyword host: The VCL host to which you make requests(required) :type host: ``str`` """ NODE_STATE_MAP = { 'ready': NodeState.RUNNING, 'failed': NodeState.TERMINATED, 'timedout': NodeState.TERMINATED, 'loading': NodeState.PENDING, 'time': NodeState.PENDING, 'future': NodeState.PENDING, 'error': NodeState.UNKNOWN, 'notready': NodeState.PENDING, 'notavailable': NodeState.TERMINATED, 'success': NodeState.PENDING } connectionCls = VCLConnection name = 'VCL' website = 'http://incubator.apache.org/vcl/' type = Provider.VCL def __init__(self, key, secret, secure=True, host=None, port=None, *args, **kwargs): """ :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. :type secure: ``bool`` :param host: Override hostname used for connections. (required) :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :rtype: ``None`` """ if not host: raise Exception('When instantiating VCL driver directly ' + 'you also need to provide host') super(VCLNodeDriver, self).__init__(key, secret, secure=True, host=None, port=None, *args, **kwargs) def _vcl_request(self, method, *args): res = self.connection.request( method, *args ).object if(res['status'] == 'error'): raise LibcloudError(res['errormsg'], driver=self) return res def create_node(self, image, start=None, length='60'): """Create a new VCL reservation size and name ignored, image is the id from list_image @inherits: :class:`NodeDriver.create_node` :keyword image: image is the id from list_image :type image: ``str`` :keyword start: start time as unix timestamp :type start: ``str`` :keyword length: length of time in minutes :type length: ``str`` """ # Special case for xmlrpclib not handling 64 bit integers when writting # XML - we always cast value to string. start = start or str(time.time()) length = length or '60' res = self._vcl_request( "XMLRPCaddRequest", image.id, start, length ) return Node( id=res['requestid'], name=image.name, state=self.NODE_STATE_MAP[res['status']], public_ips=[], private_ips=[], driver=self, image=image.name ) def destroy_node(self, node): """ End VCL reservation for the node passed in. Throws error if request fails. :param node: The node to be destroyed :type node: :class:`Node` :rtype: ``bool`` """ try: self._vcl_request( 'XMLRPCendRequest', node.id ) except LibcloudError: return False return True def _to_image(self, img): return NodeImage( id=img['id'], name=img['name'], driver=self.connection.driver ) def list_images(self, location=None): """ List images available to the user provided credentials @inherits: :class:`NodeDriver.list_images` """ res = self.connection.request( "XMLRPCgetImages" ).object return [self._to_image(i) for i in res] def list_sizes(self, location=None): """ VCL does not choosing sizes for node creation. Size of images are statically set by administrators. @inherits: :class:`NodeDriver.list_sizes` """ return [NodeSize( 't1.micro', 'none', '512', 0, 0, 0, self) ] def _to_connect_data(self, request_id, ipaddr): res = self._vcl_request( "XMLRPCgetRequestConnectData", request_id, ipaddr ) return res def _to_status(self, requestid, imagename, ipaddr): res = self._vcl_request( "XMLRPCgetRequestStatus", requestid ) public_ips = [] extra = [] if(res['status'] == 'ready'): cdata = self._to_connect_data(requestid, ipaddr) public_ips = [cdata['serverIP']] extra = { 'user': cdata['user'], 'pass': cdata['password'] } return Node( id=requestid, name=imagename, state=self.NODE_STATE_MAP[res['status']], public_ips=public_ips, private_ips=[], driver=self, image=imagename, extra=extra ) def _to_nodes(self, res, ipaddr): return [self._to_status( h['requestid'], h['imagename'], ipaddr ) for h in res] def list_nodes(self, ipaddr): """ List nodes :param ipaddr: IP address which should be used :type ipaddr: ``str`` :rtype: ``list`` of :class:`Node` """ res = self._vcl_request( "XMLRPCgetRequestIds" ) return self._to_nodes(res['requests'], ipaddr) def ex_update_node_access(self, node, ipaddr): """ Update the remote ip accessing the node. :param node: the reservation node to update :type node: :class:`Node` :param ipaddr: the ipaddr used to access the node :type ipaddr: ``str`` :return: node with updated information :rtype: :class:`Node` """ return self._to_status(node.id, node.image, ipaddr) def ex_extend_request_time(self, node, minutes): """ Time in minutes to extend the requested node's reservation time :param node: the reservation node to update :type node: :class:`Node` :param minutes: the number of mintes to update :type minutes: ``str`` :return: true on success, throws error on failure :rtype: ``bool`` """ return self._vcl_request( "XMLRPCextendRequest", node.id, minutes ) def ex_get_request_end_time(self, node): """ Get the ending time of the node reservation. :param node: the reservation node to update :type node: :class:`Node` :return: unix timestamp :rtype: ``int`` """ res = self._vcl_request( "XMLRPCgetRequestIds" ) time = 0 for i in res['requests']: if i['requestid'] == node.id: time = i['end'] return time apache-libcloud-2.8.0/libcloud/compute/drivers/vcloud.py0000664000175000017500000027100213577507766023251 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ VMware vCloud driver. """ import copy import datetime import re import base64 import os from libcloud.utils.iso8601 import parse_date from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlencode from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import b from libcloud.utils.py3 import next from libcloud.utils.py3 import ET urlparse = urlparse.urlparse import time from xml.parsers.expat import ExpatError from libcloud.common.base import XmlResponse, ConnectionUserAndKey from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState from libcloud.compute.base import Node, NodeDriver, NodeLocation from libcloud.compute.base import NodeSize, NodeImage """ From vcloud api "The VirtualQuantity element defines the number of MB of memory. This should be either 512 or a multiple of 1024 (1 GB)." """ VIRTUAL_MEMORY_VALS = [512] + [1024 * i for i in range(1, 9)] # Default timeout (in seconds) for long running tasks DEFAULT_TASK_COMPLETION_TIMEOUT = 600 DEFAULT_API_VERSION = '0.8' """ Valid vCloud API v1.5 input values. """ VIRTUAL_CPU_VALS_1_5 = [i for i in range(1, 9)] FENCE_MODE_VALS_1_5 = ['bridged', 'isolated', 'natRouted'] IP_MODE_VALS_1_5 = ['POOL', 'DHCP', 'MANUAL', 'NONE'] def fixxpath(root, xpath): """ElementTree wants namespaces in its xpaths, so here we add them.""" namespace, root_tag = root.tag[1:].split("}", 1) fixed_xpath = "/".join(["{%s}%s" % (namespace, e) for e in xpath.split("/")]) return fixed_xpath def get_url_path(url): return urlparse(url.strip()).path class Vdc(object): """ Virtual datacenter (vDC) representation """ def __init__(self, id, name, driver, allocation_model=None, cpu=None, memory=None, storage=None): self.id = id self.name = name self.driver = driver self.allocation_model = allocation_model self.cpu = cpu self.memory = memory self.storage = storage def __repr__(self): return ('' % (self.id, self.name, self.driver.name)) class Capacity(object): """ Represents CPU, Memory or Storage capacity of vDC. """ def __init__(self, limit, used, units): self.limit = limit self.used = used self.units = units def __repr__(self): return ('' % (self.limit, self.used, self.units)) class ControlAccess(object): """ Represents control access settings of a node """ class AccessLevel(object): READ_ONLY = 'ReadOnly' CHANGE = 'Change' FULL_CONTROL = 'FullControl' def __init__(self, node, everyone_access_level, subjects=None): self.node = node self.everyone_access_level = everyone_access_level if not subjects: subjects = [] self.subjects = subjects def __repr__(self): return ('' % (self.node, self.everyone_access_level, self.subjects)) class Subject(object): """ User or group subject """ def __init__(self, type, name, access_level, id=None): self.type = type self.name = name self.access_level = access_level self.id = id def __repr__(self): return ('' % (self.type, self.name, self.access_level)) class Lease(object): """ Lease information for vApps. More info at: 'https://www.vmware.com/support/vcd/doc/ rest-api-doc-1.5-html/types/LeaseSettingsSectionType.html' """ def __init__(self, lease_id, deployment_lease=None, storage_lease=None, deployment_lease_expiration=None, storage_lease_expiration=None): """ :param lease_id: ID (link) to the lease settings section of a vApp. :type lease_id: ``str`` :param deployment_lease: Deployment lease time in seconds :type deployment_lease: ``int`` or ``None`` :param storage_lease: Storage lease time in seconds :type storage_lease: ``int`` or ``None`` :param deployment_lease_expiration: Deployment lease expiration time :type deployment_lease_expiration: ``datetime.datetime`` or ``None`` :param storage_lease_expiration: Storage lease expiration time :type storage_lease_expiration: ``datetime.datetime`` or ``None`` """ self.lease_id = lease_id self.deployment_lease = deployment_lease self.storage_lease = storage_lease self.deployment_lease_expiration = deployment_lease_expiration self.storage_lease_expiration = storage_lease_expiration @classmethod def to_lease(cls, lease_element): """ Convert lease settings element to lease instance. :param lease_element: "LeaseSettingsSection" XML element :type lease_element: ``ET.Element`` :return: Lease instance :rtype: :class:`Lease` """ lease_id = lease_element.get('href') deployment_lease = lease_element.find( fixxpath(lease_element, 'DeploymentLeaseInSeconds') ) storage_lease = lease_element.find( fixxpath(lease_element, 'StorageLeaseInSeconds') ) deployment_lease_expiration = lease_element.find( fixxpath(lease_element, 'DeploymentLeaseExpiration') ) storage_lease_expiration = lease_element.find( fixxpath(lease_element, 'StorageLeaseExpiration') ) def apply_if_elem_not_none(elem, function): return function(elem.text) if elem is not None else None return cls( lease_id=lease_id, deployment_lease=apply_if_elem_not_none(deployment_lease, int), storage_lease=apply_if_elem_not_none(storage_lease, int), deployment_lease_expiration=apply_if_elem_not_none( deployment_lease_expiration, parse_date ), storage_lease_expiration=apply_if_elem_not_none( storage_lease_expiration, parse_date ) ) def get_deployment_time(self): """ Gets the date and time a vApp was deployed. Time is inferred from the deployment lease and expiration or the storage lease and expiration. :return: Date and time the vApp was deployed or None if unable to calculate :rtype: ``datetime.datetime`` or ``None`` """ if (self.deployment_lease is not None and self.deployment_lease_expiration is not None): return self.deployment_lease_expiration - datetime.timedelta( seconds=self.deployment_lease ) if (self.storage_lease is not None and self.storage_lease_expiration is not None): return self.storage_lease_expiration - datetime.timedelta( seconds=self.storage_lease ) raise Exception('Cannot get time deployed. ' 'Missing complete lease and expiration information.') def __repr__(self): return ( ''.format( lease_id=self.lease_id, deployment_lease=self.deployment_lease, storage_lease=self.storage_lease, deployment_lease_expiration=self.deployment_lease_expiration, storage_lease_expiration=self.storage_lease_expiration ) ) def __eq__(self, other): if not isinstance(other, Lease): return False return ( self.lease_id == other.lease_id and self.deployment_lease == other.deployment_lease and self.storage_lease == other.storage_lease and (self.deployment_lease_expiration == other.deployment_lease_expiration) and self.storage_lease_expiration == other.storage_lease_expiration ) def __ne__(self, other): return not self == other class InstantiateVAppXML(object): def __init__(self, name, template, net_href, cpus, memory, password=None, row=None, group=None): self.name = name self.template = template self.net_href = net_href self.cpus = cpus self.memory = memory self.password = password self.row = row self.group = group self._build_xmltree() def tostring(self): return ET.tostring(self.root) def _build_xmltree(self): self.root = self._make_instantiation_root() self._add_vapp_template(self.root) instantiation_params = ET.SubElement(self.root, "InstantiationParams") # product and virtual hardware self._make_product_section(instantiation_params) self._make_virtual_hardware(instantiation_params) network_config_section = ET.SubElement(instantiation_params, "NetworkConfigSection") network_config = ET.SubElement(network_config_section, "NetworkConfig") self._add_network_association(network_config) def _make_instantiation_root(self): return ET.Element( "InstantiateVAppTemplateParams", {'name': self.name, 'xml:lang': 'en', 'xmlns': "http://www.vmware.com/vcloud/v0.8", 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} ) def _add_vapp_template(self, parent): return ET.SubElement( parent, "VAppTemplate", {'href': self.template} ) def _make_product_section(self, parent): prod_section = ET.SubElement( parent, "ProductSection", {'xmlns:q1': "http://www.vmware.com/vcloud/v0.8", 'xmlns:ovf': "http://schemas.dmtf.org/ovf/envelope/1"} ) if self.password: self._add_property(prod_section, 'password', self.password) if self.row: self._add_property(prod_section, 'row', self.row) if self.group: self._add_property(prod_section, 'group', self.group) return prod_section def _add_property(self, parent, ovfkey, ovfvalue): return ET.SubElement( parent, "Property", {'xmlns': 'http://schemas.dmtf.org/ovf/envelope/1', 'ovf:key': ovfkey, 'ovf:value': ovfvalue} ) def _make_virtual_hardware(self, parent): vh = ET.SubElement( parent, "VirtualHardwareSection", {'xmlns:q1': "http://www.vmware.com/vcloud/v0.8"} ) self._add_cpu(vh) self._add_memory(vh) return vh def _add_cpu(self, parent): cpu_item = ET.SubElement( parent, "Item", {'xmlns': "http://schemas.dmtf.org/ovf/envelope/1"} ) self._add_instance_id(cpu_item, '1') self._add_resource_type(cpu_item, '3') self._add_virtual_quantity(cpu_item, self.cpus) return cpu_item def _add_memory(self, parent): mem_item = ET.SubElement( parent, 'Item', {'xmlns': "http://schemas.dmtf.org/ovf/envelope/1"} ) self._add_instance_id(mem_item, '2') self._add_resource_type(mem_item, '4') self._add_virtual_quantity(mem_item, self.memory) return mem_item def _add_instance_id(self, parent, id): elm = ET.SubElement( parent, 'InstanceID', {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' 'CIM_ResourceAllocationSettingData'} ) elm.text = id return elm def _add_resource_type(self, parent, type): elm = ET.SubElement( parent, 'ResourceType', {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' 'CIM_ResourceAllocationSettingData'} ) elm.text = type return elm def _add_virtual_quantity(self, parent, amount): elm = ET.SubElement( parent, 'VirtualQuantity', {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' 'CIM_ResourceAllocationSettingData'} ) elm.text = amount return elm def _add_network_association(self, parent): return ET.SubElement( parent, 'NetworkAssociation', {'href': self.net_href} ) class VCloudResponse(XmlResponse): def success(self): return self.status in (httplib.OK, httplib.CREATED, httplib.NO_CONTENT, httplib.ACCEPTED) class VCloudConnection(ConnectionUserAndKey): """ Connection class for the vCloud driver """ responseCls = VCloudResponse token = None host = None def request(self, *args, **kwargs): self._get_auth_token() return super(VCloudConnection, self).request(*args, **kwargs) def check_org(self): # the only way to get our org is by logging in. self._get_auth_token() def _get_auth_headers(self): """Some providers need different headers than others""" return { 'Authorization': "Basic %s" % base64.b64encode( b('%s:%s' % (self.user_id, self.key))).decode('utf-8'), 'Content-Length': '0', 'Accept': 'application/*+xml' } def _get_auth_token(self): if not self.token: self.connection.request(method='POST', url='/api/v0.8/login', headers=self._get_auth_headers()) resp = self.connection.getresponse() headers = resp.headers body = ET.XML(resp.text) try: self.token = headers['set-cookie'] except KeyError: raise InvalidCredsError() self.driver.org = get_url_path( body.find(fixxpath(body, 'Org')).get('href') ) def add_default_headers(self, headers): headers['Cookie'] = self.token headers['Accept'] = 'application/*+xml' return headers class VCloudNodeDriver(NodeDriver): """ vCloud node driver """ type = Provider.VCLOUD name = 'vCloud' website = 'http://www.vmware.com/products/vcloud/' connectionCls = VCloudConnection org = None _vdcs = None NODE_STATE_MAP = {'0': NodeState.PENDING, '1': NodeState.PENDING, '2': NodeState.PENDING, '3': NodeState.PENDING, '4': NodeState.RUNNING} features = {'create_node': ['password']} def __new__(cls, key, secret=None, secure=True, host=None, port=None, api_version=DEFAULT_API_VERSION, **kwargs): if cls is VCloudNodeDriver: if api_version == '0.8': cls = VCloudNodeDriver elif api_version == '1.5': cls = VCloud_1_5_NodeDriver elif api_version == '5.1': cls = VCloud_5_1_NodeDriver elif api_version == '5.5': cls = VCloud_5_5_NodeDriver else: raise NotImplementedError( "No VCloudNodeDriver found for API version %s" % (api_version)) return super(VCloudNodeDriver, cls).__new__(cls) @property def vdcs(self): """ vCloud virtual data centers (vDCs). :return: list of vDC objects :rtype: ``list`` of :class:`Vdc` """ if not self._vdcs: self.connection.check_org() # make sure the org is set. res = self.connection.request(self.org) self._vdcs = [ self._to_vdc( self.connection.request(get_url_path(i.get('href'))).object ) for i in res.object.findall(fixxpath(res.object, "Link")) if i.get('type') == 'application/vnd.vmware.vcloud.vdc+xml' ] return self._vdcs def _to_vdc(self, vdc_elm): return Vdc(vdc_elm.get('href'), vdc_elm.get('name'), self) def _get_vdc(self, vdc_name): vdc = None if not vdc_name: # Return the first organisation VDC found vdc = self.vdcs[0] else: for v in self.vdcs: if v.name == vdc_name or v.id == vdc_name: vdc = v if vdc is None: raise ValueError('%s virtual data centre could not be found' % (vdc_name)) return vdc @property def networks(self): networks = [] for vdc in self.vdcs: res = self.connection.request(get_url_path(vdc.id)).object networks.extend( [network for network in res.findall( fixxpath(res, 'AvailableNetworks/Network') )] ) return networks def _to_image(self, image): image = NodeImage(id=image.get('href'), name=image.get('name'), driver=self.connection.driver) return image def _to_node(self, elm): state = self.NODE_STATE_MAP[elm.get('status')] name = elm.get('name') public_ips = [] private_ips = [] # Following code to find private IPs works for Terremark connections = elm.findall('%s/%s' % ( '{http://schemas.dmtf.org/ovf/envelope/1}NetworkConnectionSection', fixxpath(elm, 'NetworkConnection')) ) if not connections: connections = elm.findall( fixxpath( elm, 'Children/Vm/NetworkConnectionSection/NetworkConnection')) for connection in connections: ips = [ip.text for ip in connection.findall(fixxpath(elm, "IpAddress"))] if connection.get('Network') == 'Internal': private_ips.extend(ips) else: public_ips.extend(ips) node = Node(id=elm.get('href'), name=name, state=state, public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver) return node def _get_catalog_hrefs(self): res = self.connection.request(self.org) catalogs = [ i.get('href') for i in res.object.findall(fixxpath(res.object, "Link")) if i.get('type') == 'application/vnd.vmware.vcloud.catalog+xml' ] return catalogs def _wait_for_task_completion(self, task_href, timeout=DEFAULT_TASK_COMPLETION_TIMEOUT): start_time = time.time() res = self.connection.request(get_url_path(task_href)) status = res.object.get('status') while status != 'success': if status == 'error': # Get error reason from the response body error_elem = res.object.find(fixxpath(res.object, 'Error')) error_msg = "Unknown error" if error_elem is not None: error_msg = error_elem.get('message') raise Exception("Error status returned by task %s.: %s" % (task_href, error_msg)) if status == 'canceled': raise Exception("Canceled status returned by task %s." % task_href) if (time.time() - start_time >= timeout): raise Exception("Timeout (%s sec) while waiting for task %s." % (timeout, task_href)) time.sleep(5) res = self.connection.request(get_url_path(task_href)) status = res.object.get('status') def destroy_node(self, node): node_path = get_url_path(node.id) # blindly poweroff node, it will throw an exception if already off try: res = self.connection.request('%s/power/action/poweroff' % node_path, method='POST') self._wait_for_task_completion(res.object.get('href')) except Exception: pass try: res = self.connection.request('%s/action/undeploy' % node_path, method='POST') self._wait_for_task_completion(res.object.get('href')) except ExpatError: # The undeploy response is malformed XML atm. # We can remove this whent he providers fix the problem. pass except Exception: # Some vendors don't implement undeploy at all yet, # so catch this and move on. pass res = self.connection.request(node_path, method='DELETE') return res.status == httplib.ACCEPTED def reboot_node(self, node): res = self.connection.request('%s/power/action/reset' % get_url_path(node.id), method='POST') return res.status in [httplib.ACCEPTED, httplib.NO_CONTENT] def list_nodes(self): return self.ex_list_nodes() def ex_list_nodes(self, vdcs=None): """ List all nodes across all vDCs. Using 'vdcs' you can specify which vDCs should be queried. :param vdcs: None, vDC or a list of vDCs to query. If None all vDCs will be queried. :type vdcs: :class:`Vdc` :rtype: ``list`` of :class:`Node` """ if not vdcs: vdcs = self.vdcs if not isinstance(vdcs, (list, tuple)): vdcs = [vdcs] nodes = [] for vdc in vdcs: res = self.connection.request(get_url_path(vdc.id)) elms = res.object.findall(fixxpath( res.object, "ResourceEntities/ResourceEntity") ) vapps = [ (i.get('name'), i.get('href')) for i in elms if i.get('type') == 'application/vnd.vmware.vcloud.vApp+xml' and i.get('name') ] for vapp_name, vapp_href in vapps: try: res = self.connection.request( get_url_path(vapp_href), headers={'Content-Type': 'application/vnd.vmware.vcloud.vApp+xml'} ) nodes.append(self._to_node(res.object)) except Exception as e: # The vApp was probably removed since the previous vDC # query, ignore # pylint: disable=no-member if not (e.args[0].tag.endswith('Error') and e.args[0].get('minorErrorCode') == 'ACCESS_TO_RESOURCE_IS_FORBIDDEN'): raise return nodes def _to_size(self, ram): ns = NodeSize( id=None, name="%s Ram" % ram, ram=ram, disk=None, bandwidth=None, price=None, driver=self.connection.driver ) return ns def list_sizes(self, location=None): sizes = [self._to_size(i) for i in VIRTUAL_MEMORY_VALS] return sizes def _get_catalogitems_hrefs(self, catalog): """Given a catalog href returns contained catalog item hrefs""" res = self.connection.request( get_url_path(catalog), headers={ 'Content-Type': 'application/vnd.vmware.vcloud.catalog+xml' } ).object cat_items = res.findall(fixxpath(res, "CatalogItems/CatalogItem")) cat_item_hrefs = [i.get('href') for i in cat_items if i.get('type') == 'application/vnd.vmware.vcloud.catalogItem+xml'] return cat_item_hrefs def _get_catalogitem(self, catalog_item): """Given a catalog item href returns elementree""" res = self.connection.request( get_url_path(catalog_item), headers={ 'Content-Type': 'application/vnd.vmware.vcloud.catalogItem+xml' } ).object return res def list_images(self, location=None): images = [] for vdc in self.vdcs: res = self.connection.request(get_url_path(vdc.id)).object res_ents = res.findall(fixxpath( res, "ResourceEntities/ResourceEntity") ) images += [ self._to_image(i) for i in res_ents if i.get('type') == 'application/vnd.vmware.vcloud.vAppTemplate+xml' ] for catalog in self._get_catalog_hrefs(): for cat_item in self._get_catalogitems_hrefs(catalog): res = self._get_catalogitem(cat_item) res_ents = res.findall(fixxpath(res, 'Entity')) images += [ self._to_image(i) for i in res_ents if i.get('type') == 'application/vnd.vmware.vcloud.vAppTemplate+xml' ] def idfun(image): return image.id return self._uniquer(images, idfun) def _uniquer(self, seq, idfun=None): if idfun is None: def idfun(x): # pylint: disable=function-redefined return x seen = {} result = [] for item in seq: marker = idfun(item) if marker in seen: continue seen[marker] = 1 result.append(item) return result def create_node(self, name, size, image, auth=None, ex_network=None, ex_vdc=None, ex_cpus=1, ex_row=None, ex_group=None): """ Creates and returns node. :keyword ex_network: link to a "Network" e.g., ``https://services.vcloudexpress...`` :type ex_network: ``str`` :keyword ex_vdc: Name of organisation's virtual data center where vApp VMs will be deployed. :type ex_vdc: ``str`` :keyword ex_cpus: number of virtual cpus (limit depends on provider) :type ex_cpus: ``int`` :type ex_row: ``str`` :type ex_group: ``str`` """ # Some providers don't require a network link try: network = ex_network or self.networks[0].get('href') except IndexError: network = '' password = None auth = self._get_and_check_auth(auth) password = auth.password instantiate_xml = InstantiateVAppXML( name=name, template=image.id, net_href=network, cpus=str(ex_cpus), memory=str(size.ram), password=password, row=ex_row, group=ex_group ) vdc = self._get_vdc(ex_vdc) # Instantiate VM and get identifier. content_type = \ 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml' res = self.connection.request( '%s/action/instantiateVAppTemplate' % get_url_path(vdc.id), data=instantiate_xml.tostring(), method='POST', headers={'Content-Type': content_type} ) vapp_path = get_url_path(res.object.get('href')) # Deploy the VM from the identifier. res = self.connection.request('%s/action/deploy' % vapp_path, method='POST') self._wait_for_task_completion(res.object.get('href')) # Power on the VM. res = self.connection.request('%s/power/action/powerOn' % vapp_path, method='POST') res = self.connection.request(vapp_path) node = self._to_node(res.object) if getattr(auth, "generated", False): node.extra['password'] = auth.password return node class HostingComConnection(VCloudConnection): """ vCloud connection subclass for Hosting.com """ host = "vcloud.safesecureweb.com" def _get_auth_headers(self): """hosting.com doesn't follow the standard vCloud authentication API""" return { 'Authentication': base64.b64encode(b('%s:%s' % (self.user_id, self.key))), 'Content-Length': '0' } class HostingComDriver(VCloudNodeDriver): """ vCloud node driver for Hosting.com """ connectionCls = HostingComConnection class TerremarkConnection(VCloudConnection): """ vCloud connection subclass for Terremark """ host = "services.vcloudexpress.terremark.com" class TerremarkDriver(VCloudNodeDriver): """ vCloud node driver for Terremark """ connectionCls = TerremarkConnection def list_locations(self): return [NodeLocation(0, "Terremark Texas", 'US', self)] class VCloud_1_5_Connection(VCloudConnection): def _get_auth_headers(self): """Compatibility for using v1.5 API under vCloud Director 5.1""" return { 'Authorization': "Basic %s" % base64.b64encode( b('%s:%s' % (self.user_id, self.key))).decode('utf-8'), 'Content-Length': '0', 'Accept': 'application/*+xml;version=1.5' } def _get_auth_token(self): if not self.token: # Log In self.connection.request(method='POST', url='/api/sessions', headers=self._get_auth_headers()) resp = self.connection.getresponse() headers = resp.headers # Set authorization token try: self.token = headers['x-vcloud-authorization'] except KeyError: raise InvalidCredsError() # Get the URL of the Organization body = ET.XML(resp.text) self.org_name = body.get('org') # pylint: disable=no-member org_list_url = get_url_path( next((link for link in body.findall(fixxpath(body, 'Link')) if link.get('type') == 'application/vnd.vmware.vcloud.orgList+xml')).get('href') ) if self.proxy_url is not None: self.connection.set_http_proxy(self.proxy_url) self.connection.request(method='GET', url=org_list_url, headers=self.add_default_headers({})) body = ET.XML(self.connection.getresponse().text) # pylint: disable=no-member self.driver.org = get_url_path( next((org for org in body.findall(fixxpath(body, 'Org')) if org.get('name') == self.org_name)).get('href') ) def add_default_headers(self, headers): headers['Accept'] = 'application/*+xml;version=1.5' headers['x-vcloud-authorization'] = self.token return headers class VCloud_5_5_Connection(VCloud_1_5_Connection): def _get_auth_headers(self): """Compatibility for using v5.5 of the API""" auth_headers = super(VCloud_5_5_Connection, self)._get_auth_headers() auth_headers['Accept'] = 'application/*+xml;version=5.5' return auth_headers def add_default_headers(self, headers): headers['Accept'] = 'application/*+xml;version=5.5' headers['x-vcloud-authorization'] = self.token return headers class Instantiate_1_5_VAppXML(object): def __init__(self, name, template, network, vm_network=None, vm_fence=None, description=None): self.name = name self.template = template self.network = network self.vm_network = vm_network self.vm_fence = vm_fence self.description = description self._build_xmltree() def tostring(self): return ET.tostring(self.root) def _build_xmltree(self): self.root = self._make_instantiation_root() if self.network is not None: instantiation_params = ET.SubElement(self.root, 'InstantiationParams') network_config_section = ET.SubElement(instantiation_params, 'NetworkConfigSection') ET.SubElement( network_config_section, 'Info', {'xmlns': 'http://schemas.dmtf.org/ovf/envelope/1'} ) network_config = ET.SubElement(network_config_section, 'NetworkConfig') self._add_network_association(network_config) if self.description is not None: ET.SubElement(self.root, 'Description').text = self.description self._add_vapp_template(self.root) def _make_instantiation_root(self): return ET.Element( 'InstantiateVAppTemplateParams', {'name': self.name, 'deploy': 'false', 'powerOn': 'false', 'xml:lang': 'en', 'xmlns': 'http://www.vmware.com/vcloud/v1.5', 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'} ) def _add_vapp_template(self, parent): return ET.SubElement( parent, 'Source', {'href': self.template} ) def _add_network_association(self, parent): if self.vm_network is None: # Don't set a custom vApp VM network name parent.set('networkName', self.network.get('name')) else: # Set a custom vApp VM network name parent.set('networkName', self.vm_network) configuration = ET.SubElement(parent, 'Configuration') ET.SubElement(configuration, 'ParentNetwork', {'href': self.network.get('href')}) if self.vm_fence is None: fencemode = self.network.find(fixxpath(self.network, 'Configuration/FenceMode')).text else: fencemode = self.vm_fence ET.SubElement(configuration, 'FenceMode').text = fencemode class VCloud_1_5_NodeDriver(VCloudNodeDriver): connectionCls = VCloud_1_5_Connection # Based on # http://pubs.vmware.com/vcloud-api-1-5/api_prog/ # GUID-843BE3AD-5EF6-4442-B864-BCAE44A51867.html NODE_STATE_MAP = {'-1': NodeState.UNKNOWN, '0': NodeState.PENDING, '1': NodeState.PENDING, '2': NodeState.PENDING, '3': NodeState.PENDING, '4': NodeState.RUNNING, '5': NodeState.RUNNING, '6': NodeState.UNKNOWN, '7': NodeState.UNKNOWN, '8': NodeState.STOPPED, '9': NodeState.UNKNOWN, '10': NodeState.UNKNOWN} def list_locations(self): return [NodeLocation(id=self.connection.host, name=self.connection.host, country="N/A", driver=self)] def ex_find_node(self, node_name, vdcs=None): """ Searches for node across specified vDCs. This is more effective than querying all nodes to get a single instance. :param node_name: The name of the node to search for :type node_name: ``str`` :param vdcs: None, vDC or a list of vDCs to search in. If None all vDCs will be searched. :type vdcs: :class:`Vdc` :return: node instance or None if not found :rtype: :class:`Node` or ``None`` """ if not vdcs: vdcs = self.vdcs if not getattr(vdcs, '__iter__', False): vdcs = [vdcs] for vdc in vdcs: res = self.connection.request(get_url_path(vdc.id)) xpath = fixxpath(res.object, "ResourceEntities/ResourceEntity") entity_elems = res.object.findall(xpath) for entity_elem in entity_elems: if entity_elem.get('type') == \ 'application/vnd.vmware.vcloud.vApp+xml' and \ entity_elem.get('name') == node_name: path = entity_elem.get('href') return self._ex_get_node(path) return None def ex_find_vm_nodes(self, vm_name, max_results=50): """ Finds nodes that contain a VM with the specified name. :param vm_name: The VM name to find nodes for :type vm_name: ``str`` :param max_results: Maximum number of results up to 128 :type max_results: ``int`` :return: List of node instances :rtype: `list` of :class:`Node` """ vms = self.ex_query( 'vm', filter='name=={vm_name}'.format(vm_name=vm_name), page=1, page_size=max_results ) return [self._ex_get_node(vm['container']) for vm in vms] def destroy_node(self, node, shutdown=True): try: self.ex_undeploy_node(node, shutdown=shutdown) except Exception: # Some vendors don't implement undeploy at all yet, # so catch this and move on. pass res = self.connection.request(get_url_path(node.id), method='DELETE') return res.status == httplib.ACCEPTED def reboot_node(self, node): res = self.connection.request('%s/power/action/reset' % get_url_path(node.id), method='POST') if res.status in [httplib.ACCEPTED, httplib.NO_CONTENT]: self._wait_for_task_completion(res.object.get('href')) return True else: return False def ex_deploy_node(self, node, ex_force_customization=False): """ Deploys existing node. Equal to vApp "start" operation. :param node: The node to be deployed :type node: :class:`Node` :param ex_force_customization: Used to specify whether to force customization on deployment, if not set default value is False. :type ex_force_customization: ``bool`` :rtype: :class:`Node` """ if ex_force_customization: vms = self._get_vm_elements(node.id) for vm in vms: self._ex_deploy_node_or_vm(vm.get('href'), ex_force_customization=True) else: self._ex_deploy_node_or_vm(node.id) res = self.connection.request(get_url_path(node.id)) return self._to_node(res.object) def _ex_deploy_node_or_vm(self, vapp_or_vm_path, ex_force_customization=False): data = {'powerOn': 'true', 'forceCustomization': str(ex_force_customization).lower(), 'xmlns': 'http://www.vmware.com/vcloud/v1.5'} deploy_xml = ET.Element('DeployVAppParams', data) path = get_url_path(vapp_or_vm_path) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.deployVAppParams+xml' } res = self.connection.request('%s/action/deploy' % path, data=ET.tostring(deploy_xml), method='POST', headers=headers) self._wait_for_task_completion(res.object.get('href')) def ex_undeploy_node(self, node, shutdown=True): """ Undeploys existing node. Equal to vApp "stop" operation. :param node: The node to be deployed :type node: :class:`Node` :param shutdown: Whether to shutdown or power off the guest when undeploying :type shutdown: ``bool`` :rtype: :class:`Node` """ data = {'xmlns': 'http://www.vmware.com/vcloud/v1.5'} undeploy_xml = ET.Element('UndeployVAppParams', data) undeploy_power_action_xml = ET.SubElement(undeploy_xml, 'UndeployPowerAction') headers = { 'Content-Type': 'application/vnd.vmware.vcloud.undeployVAppParams+xml' } def undeploy(action): undeploy_power_action_xml.text = action undeploy_res = self.connection.request( '%s/action/undeploy' % get_url_path(node.id), data=ET.tostring(undeploy_xml), method='POST', headers=headers) self._wait_for_task_completion(undeploy_res.object.get('href')) if shutdown: try: undeploy('shutdown') except Exception: undeploy('powerOff') else: undeploy('powerOff') res = self.connection.request(get_url_path(node.id)) return self._to_node(res.object) def ex_power_off_node(self, node): """ Powers on all VMs under specified node. VMs need to be This operation is allowed only when the vApp/VM is powered on. :param node: The node to be powered off :type node: :class:`Node` :rtype: :class:`Node` """ return self._perform_power_operation(node, 'powerOff') def ex_power_on_node(self, node): """ Powers on all VMs under specified node. This operation is allowed only when the vApp/VM is powered off or suspended. :param node: The node to be powered on :type node: :class:`Node` :rtype: :class:`Node` """ return self._perform_power_operation(node, 'powerOn') def ex_shutdown_node(self, node): """ Shutdowns all VMs under specified node. This operation is allowed only when the vApp/VM is powered on. :param node: The node to be shut down :type node: :class:`Node` :rtype: :class:`Node` """ return self._perform_power_operation(node, 'shutdown') def ex_suspend_node(self, node): """ Suspends all VMs under specified node. This operation is allowed only when the vApp/VM is powered on. :param node: The node to be suspended :type node: :class:`Node` :rtype: :class:`Node` """ return self._perform_power_operation(node, 'suspend') def _perform_power_operation(self, node, operation): res = self.connection.request( '%s/power/action/%s' % (get_url_path(node.id), operation), method='POST') self._wait_for_task_completion(res.object.get('href')) res = self.connection.request(get_url_path(node.id)) return self._to_node(res.object) def ex_get_control_access(self, node): """ Returns the control access settings for specified node. :param node: node to get the control access for :type node: :class:`Node` :rtype: :class:`ControlAccess` """ res = self.connection.request( '%s/controlAccess' % get_url_path(node.id)) everyone_access_level = None is_shared_elem = res.object.find( fixxpath(res.object, "IsSharedToEveryone")) if is_shared_elem is not None and is_shared_elem.text == 'true': everyone_access_level = res.object.find( fixxpath(res.object, "EveryoneAccessLevel")).text # Parse all subjects subjects = [] xpath = fixxpath(res.object, "AccessSettings/AccessSetting") for elem in res.object.findall(xpath): access_level = elem.find(fixxpath(res.object, "AccessLevel")).text subject_elem = elem.find(fixxpath(res.object, "Subject")) if subject_elem.get('type') == \ 'application/vnd.vmware.admin.group+xml': subj_type = 'group' else: subj_type = 'user' path = get_url_path(subject_elem.get('href')) res = self.connection.request(path) name = res.object.get('name') subject = Subject(type=subj_type, name=name, access_level=access_level, id=subject_elem.get('href')) subjects.append(subject) return ControlAccess(node, everyone_access_level, subjects) def ex_set_control_access(self, node, control_access): """ Sets control access for the specified node. :param node: node :type node: :class:`Node` :param control_access: control access settings :type control_access: :class:`ControlAccess` :rtype: ``None`` """ xml = ET.Element('ControlAccessParams', {'xmlns': 'http://www.vmware.com/vcloud/v1.5'}) shared_to_everyone = ET.SubElement(xml, 'IsSharedToEveryone') if control_access.everyone_access_level: shared_to_everyone.text = 'true' everyone_access_level = ET.SubElement(xml, 'EveryoneAccessLevel') everyone_access_level.text = control_access.everyone_access_level else: shared_to_everyone.text = 'false' # Set subjects if control_access.subjects: access_settings_elem = ET.SubElement(xml, 'AccessSettings') for subject in control_access.subjects: setting = ET.SubElement(access_settings_elem, 'AccessSetting') if subject.id: href = subject.id else: res = self.ex_query(type=subject.type, filter='name==' + subject.name) if not res: raise LibcloudError('Specified subject "%s %s" not found ' % (subject.type, subject.name)) href = res[0]['href'] ET.SubElement(setting, 'Subject', {'href': href}) ET.SubElement(setting, 'AccessLevel').text = subject.access_level headers = { 'Content-Type': 'application/vnd.vmware.vcloud.controlAccess+xml' } self.connection.request( '%s/action/controlAccess' % get_url_path(node.id), data=ET.tostring(xml), headers=headers, method='POST') def ex_get_metadata(self, node): """ :param node: node :type node: :class:`Node` :return: dictionary mapping metadata keys to metadata values :rtype: dictionary mapping ``str`` to ``str`` """ res = self.connection.request('%s/metadata' % (get_url_path(node.id))) xpath = fixxpath(res.object, 'MetadataEntry') metadata_entries = res.object.findall(xpath) res_dict = {} for entry in metadata_entries: key = entry.findtext(fixxpath(res.object, 'Key')) value = entry.findtext(fixxpath(res.object, 'Value')) res_dict[key] = value return res_dict def ex_set_metadata_entry(self, node, key, value): """ :param node: node :type node: :class:`Node` :param key: metadata key to be set :type key: ``str`` :param value: metadata value to be set :type value: ``str`` :rtype: ``None`` """ metadata_elem = ET.Element( 'Metadata', {'xmlns': "http://www.vmware.com/vcloud/v1.5", 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} ) entry = ET.SubElement(metadata_elem, 'MetadataEntry') key_elem = ET.SubElement(entry, 'Key') key_elem.text = key value_elem = ET.SubElement(entry, 'Value') value_elem.text = value # send it back to the server res = self.connection.request( '%s/metadata' % get_url_path(node.id), data=ET.tostring(metadata_elem), headers={ 'Content-Type': 'application/vnd.vmware.vcloud.metadata+xml' }, method='POST') self._wait_for_task_completion(res.object.get('href')) def ex_query(self, type, filter=None, page=1, page_size=100, sort_asc=None, sort_desc=None): """ Queries vCloud for specified type. See http://www.vmware.com/pdf/vcd_15_api_guide.pdf for details. Each element of the returned list is a dictionary with all attributes from the record. :param type: type to query (r.g. user, group, vApp etc.) :type type: ``str`` :param filter: filter expression (see documentation for syntax) :type filter: ``str`` :param page: page number :type page: ``int`` :param page_size: page size :type page_size: ``int`` :param sort_asc: sort in ascending order by specified field :type sort_asc: ``str`` :param sort_desc: sort in descending order by specified field :type sort_desc: ``str`` :rtype: ``list`` of dict """ # This is a workaround for filter parameter encoding # the urllib encodes (name==Developers%20Only) into # %28name%3D%3DDevelopers%20Only%29) which is not accepted by vCloud params = { 'type': type, 'pageSize': page_size, 'page': page, } if sort_asc: params['sortAsc'] = sort_asc if sort_desc: params['sortDesc'] = sort_desc url = '/api/query?' + urlencode(params) if filter: if not filter.startswith('('): filter = '(' + filter + ')' url += '&filter=' + filter.replace(' ', '+') results = [] res = self.connection.request(url) for elem in res.object: if not elem.tag.endswith('Link'): result = elem.attrib result['type'] = elem.tag.split('}')[1] results.append(result) return results def create_node(self, **kwargs): """ Creates and returns node. If the source image is: - vApp template - a new vApp is instantiated from template - existing vApp - a new vApp is cloned from the source vApp. Can not clone more vApps is parallel otherwise resource busy error is raised. @inherits: :class:`NodeDriver.create_node` :keyword image: OS Image to boot on node. (required). Can be a NodeImage or existing Node that will be cloned. :type image: :class:`NodeImage` or :class:`Node` :keyword ex_network: Organisation's network name for attaching vApp VMs to. :type ex_network: ``str`` :keyword ex_vdc: Name of organisation's virtual data center where vApp VMs will be deployed. :type ex_vdc: ``str`` :keyword ex_vm_names: list of names to be used as a VM and computer name. The name must be max. 15 characters long and follow the host name requirements. :type ex_vm_names: ``list`` of ``str`` :keyword ex_vm_cpu: number of virtual CPUs/cores to allocate for each vApp VM. :type ex_vm_cpu: ``int`` :keyword ex_vm_memory: amount of memory in MB to allocate for each vApp VM. :type ex_vm_memory: ``int`` :keyword ex_vm_script: full path to file containing guest customisation script for each vApp VM. Useful for creating users & pushing out public SSH keys etc. :type ex_vm_script: ``str`` :keyword ex_vm_script_text: content of guest customisation script for each vApp VM. Overrides ex_vm_script parameter. :type ex_vm_script_text: ``str`` :keyword ex_vm_network: Override default vApp VM network name. Useful for when you've imported an OVF originating from outside of the vCloud. :type ex_vm_network: ``str`` :keyword ex_vm_fence: Fence mode for connecting the vApp VM network (ex_vm_network) to the parent organisation network (ex_network). :type ex_vm_fence: ``str`` :keyword ex_vm_ipmode: IP address allocation mode for all vApp VM network connections. :type ex_vm_ipmode: ``str`` :keyword ex_deploy: set to False if the node shouldn't be deployed (started) after creation :type ex_deploy: ``bool`` :keyword ex_force_customization: Used to specify whether to force customization on deployment, if not set default value is False. :type ex_force_customization: ``bool`` :keyword ex_clone_timeout: timeout in seconds for clone/instantiate VM operation. Cloning might be a time consuming operation especially when linked clones are disabled or VMs are created on different datastores. Overrides the default task completion value. :type ex_clone_timeout: ``int`` :keyword ex_admin_password: set the node admin password explicitly. :type ex_admin_password: ``str`` :keyword ex_description: Set a description for the vApp. :type ex_description: ``str`` """ name = kwargs['name'] image = kwargs['image'] ex_vm_names = kwargs.get('ex_vm_names') ex_vm_cpu = kwargs.get('ex_vm_cpu') ex_vm_memory = kwargs.get('ex_vm_memory') ex_vm_script = kwargs.get('ex_vm_script') ex_vm_script_text = kwargs.get('ex_vm_script_text', None) ex_vm_fence = kwargs.get('ex_vm_fence', None) ex_network = kwargs.get('ex_network', None) ex_vm_network = kwargs.get('ex_vm_network', None) ex_vm_ipmode = kwargs.get('ex_vm_ipmode', None) ex_deploy = kwargs.get('ex_deploy', True) ex_force_customization = kwargs.get('ex_force_customization', False) ex_vdc = kwargs.get('ex_vdc', None) ex_clone_timeout = kwargs.get('ex_clone_timeout', DEFAULT_TASK_COMPLETION_TIMEOUT) ex_admin_password = kwargs.get('ex_admin_password', None) ex_description = kwargs.get('ex_description', None) self._validate_vm_names(ex_vm_names) self._validate_vm_cpu(ex_vm_cpu) self._validate_vm_memory(ex_vm_memory) self._validate_vm_fence(ex_vm_fence) self._validate_vm_ipmode(ex_vm_ipmode) ex_vm_script = self._validate_vm_script(ex_vm_script) # Some providers don't require a network link if ex_network: network_href = self._get_network_href(ex_network) network_elem = self.connection.request( get_url_path(network_href)).object else: network_elem = None vdc = self._get_vdc(ex_vdc) if self._is_node(image): vapp_name, vapp_href = self._clone_node( name, image, vdc, ex_clone_timeout ) else: vapp_name, vapp_href = self._instantiate_node( name, image, network_elem, vdc, ex_vm_network, ex_vm_fence, ex_clone_timeout, description=ex_description ) self._change_vm_names(vapp_href, ex_vm_names) self._change_vm_cpu(vapp_href, ex_vm_cpu) self._change_vm_memory(vapp_href, ex_vm_memory) self._change_vm_script(vapp_href, ex_vm_script, ex_vm_script_text) self._change_vm_ipmode(vapp_href, ex_vm_ipmode) if ex_admin_password is not None: self.ex_change_vm_admin_password(vapp_href, ex_admin_password) # Power on the VM. if ex_deploy: res = self.connection.request(get_url_path(vapp_href)) node = self._to_node(res.object) # Retry 3 times: when instantiating large number of VMs at the same # time some may fail on resource allocation retry = 3 while True: try: self.ex_deploy_node(node, ex_force_customization) break except Exception: if retry <= 0: raise retry -= 1 time.sleep(10) res = self.connection.request(get_url_path(vapp_href)) node = self._to_node(res.object) return node def _instantiate_node(self, name, image, network_elem, vdc, vm_network, vm_fence, instantiate_timeout, description=None): instantiate_xml = Instantiate_1_5_VAppXML( name=name, template=image.id, network=network_elem, vm_network=vm_network, vm_fence=vm_fence, description=description ) # Instantiate VM and get identifier. headers = { 'Content-Type': 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml' } res = self.connection.request( '%s/action/instantiateVAppTemplate' % get_url_path(vdc.id), data=instantiate_xml.tostring(), method='POST', headers=headers ) vapp_name = res.object.get('name') vapp_href = res.object.get('href') task_href = res.object.find(fixxpath(res.object, "Tasks/Task")).get( 'href') self._wait_for_task_completion(task_href, instantiate_timeout) return vapp_name, vapp_href def _clone_node(self, name, sourceNode, vdc, clone_timeout): clone_xml = ET.Element( "CloneVAppParams", {'name': name, 'deploy': 'false', 'powerOn': 'false', 'xmlns': "http://www.vmware.com/vcloud/v1.5", 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} ) ET.SubElement(clone_xml, 'Description').text = 'Clone of ' + sourceNode.name ET.SubElement(clone_xml, 'Source', {'href': sourceNode.id}) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.cloneVAppParams+xml' } res = self.connection.request( '%s/action/cloneVApp' % get_url_path(vdc.id), data=ET.tostring(clone_xml), method='POST', headers=headers ) vapp_name = res.object.get('name') vapp_href = res.object.get('href') task_href = res.object.find( fixxpath(res.object, "Tasks/Task")).get('href') self._wait_for_task_completion(task_href, clone_timeout) res = self.connection.request(get_url_path(vapp_href)) vms = res.object.findall(fixxpath(res.object, "Children/Vm")) # Fix the networking for VMs for i, vm in enumerate(vms): # Remove network network_xml = ET.Element("NetworkConnectionSection", { 'ovf:required': 'false', 'xmlns': "http://www.vmware.com/vcloud/v1.5", 'xmlns:ovf': 'http://schemas.dmtf.org/ovf/envelope/1'}) ET.SubElement(network_xml, "ovf:Info").text = \ 'Specifies the available VM network connections' headers = { 'Content-Type': 'application/vnd.vmware.vcloud.networkConnectionSection+xml' } res = self.connection.request( '%s/networkConnectionSection' % get_url_path(vm.get('href')), data=ET.tostring(network_xml), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) # Re-add network network_xml = vm.find(fixxpath(vm, 'NetworkConnectionSection')) network_conn_xml = network_xml.find( fixxpath(network_xml, 'NetworkConnection')) network_conn_xml.set('needsCustomization', 'true') network_conn_xml.remove( network_conn_xml.find(fixxpath(network_xml, 'IpAddress'))) network_conn_xml.remove( network_conn_xml.find(fixxpath(network_xml, 'MACAddress'))) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.networkConnectionSection+xml' } res = self.connection.request( '%s/networkConnectionSection' % get_url_path(vm.get('href')), data=ET.tostring(network_xml), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) return vapp_name, vapp_href def ex_set_vm_cpu(self, vapp_or_vm_id, vm_cpu): """ Sets the number of virtual CPUs for the specified VM or VMs under the vApp. If the vapp_or_vm_id param represents a link to an vApp all VMs that are attached to this vApp will be modified. Please ensure that hot-adding a virtual CPU is enabled for the powered on virtual machines. Otherwise use this method on undeployed vApp. :keyword vapp_or_vm_id: vApp or VM ID that will be modified. If a vApp ID is used here all attached VMs will be modified :type vapp_or_vm_id: ``str`` :keyword vm_cpu: number of virtual CPUs/cores to allocate for specified VMs :type vm_cpu: ``int`` :rtype: ``None`` """ self._validate_vm_cpu(vm_cpu) self._change_vm_cpu(vapp_or_vm_id, vm_cpu) def ex_set_vm_memory(self, vapp_or_vm_id, vm_memory): """ Sets the virtual memory in MB to allocate for the specified VM or VMs under the vApp. If the vapp_or_vm_id param represents a link to an vApp all VMs that are attached to this vApp will be modified. Please ensure that hot-change of virtual memory is enabled for the powered on virtual machines. Otherwise use this method on undeployed vApp. :keyword vapp_or_vm_id: vApp or VM ID that will be modified. If a vApp ID is used here all attached VMs will be modified :type vapp_or_vm_id: ``str`` :keyword vm_memory: virtual memory in MB to allocate for the specified VM or VMs :type vm_memory: ``int`` :rtype: ``None`` """ self._validate_vm_memory(vm_memory) self._change_vm_memory(vapp_or_vm_id, vm_memory) def ex_add_vm_disk(self, vapp_or_vm_id, vm_disk_size): """ Adds a virtual disk to the specified VM or VMs under the vApp. If the vapp_or_vm_id param represents a link to an vApp all VMs that are attached to this vApp will be modified. :keyword vapp_or_vm_id: vApp or VM ID that will be modified. If a vApp ID is used here all attached VMs will be modified :type vapp_or_vm_id: ``str`` :keyword vm_disk_size: the disk capacity in GB that will be added to the specified VM or VMs :type vm_disk_size: ``int`` :rtype: ``None`` """ self._validate_vm_disk_size(vm_disk_size) self._add_vm_disk(vapp_or_vm_id, vm_disk_size) @staticmethod def _validate_vm_names(names): if names is None: return hname_re = re.compile( r'^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9]*)[\-])*([A-Za-z]|[A-Za-z][A-Za-z0-9]*[A-Za-z0-9])$') # NOQA for name in names: if len(name) > 15: raise ValueError( 'The VM name "' + name + '" is too long for the computer ' 'name (max 15 chars allowed).') if not hname_re.match(name): raise ValueError('The VM name "' + name + '" can not be ' 'used. "' + name + '" is not a valid ' 'computer name for the VM.') @staticmethod def _validate_vm_memory(vm_memory): if vm_memory is None: return elif vm_memory not in VIRTUAL_MEMORY_VALS: raise ValueError( '%s is not a valid vApp VM memory value' % vm_memory) @staticmethod def _validate_vm_cpu(vm_cpu): if vm_cpu is None: return elif vm_cpu not in VIRTUAL_CPU_VALS_1_5: raise ValueError('%s is not a valid vApp VM CPU value' % vm_cpu) @staticmethod def _validate_vm_disk_size(vm_disk): if vm_disk is None: return elif int(vm_disk) < 0: raise ValueError('%s is not a valid vApp VM disk space value', vm_disk) @staticmethod def _validate_vm_script(vm_script): if vm_script is None: return # Try to locate the script file if not os.path.isabs(vm_script): vm_script = os.path.expanduser(vm_script) vm_script = os.path.abspath(vm_script) if not os.path.isfile(vm_script): raise LibcloudError( "%s the VM script file does not exist" % vm_script) try: open(vm_script).read() except Exception: raise return vm_script @staticmethod def _validate_vm_fence(vm_fence): if vm_fence is None: return elif vm_fence not in FENCE_MODE_VALS_1_5: raise ValueError('%s is not a valid fencing mode value' % vm_fence) @staticmethod def _validate_vm_ipmode(vm_ipmode): if vm_ipmode is None: return elif vm_ipmode == 'MANUAL': raise NotImplementedError( 'MANUAL IP mode: The interface for supplying ' 'IPAddress does not exist yet') elif vm_ipmode not in IP_MODE_VALS_1_5: raise ValueError( '%s is not a valid IP address allocation mode value' % vm_ipmode) def _change_vm_names(self, vapp_or_vm_id, vm_names): if vm_names is None: return vms = self._get_vm_elements(vapp_or_vm_id) for i, vm in enumerate(vms): if len(vm_names) <= i: return # Get GuestCustomizationSection res = self.connection.request( '%s/guestCustomizationSection' % get_url_path(vm.get('href'))) # Update GuestCustomizationSection res.object.find( fixxpath(res.object, 'ComputerName')).text = vm_names[i] # Remove AdminPassword from customization section if it would be # invalid to include it self._remove_admin_password(res.object) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.guestCustomizationSection+xml' } res = self.connection.request( '%s/guestCustomizationSection' % get_url_path(vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) # Update Vm name req_xml = ET.Element("Vm", { 'name': vm_names[i], 'xmlns': "http://www.vmware.com/vcloud/v1.5"}) res = self.connection.request( get_url_path(vm.get('href')), data=ET.tostring(req_xml), method='PUT', headers={ 'Content-Type': 'application/vnd.vmware.vcloud.vm+xml'} ) self._wait_for_task_completion(res.object.get('href')) def _change_vm_cpu(self, vapp_or_vm_id, vm_cpu): if vm_cpu is None: return vms = self._get_vm_elements(vapp_or_vm_id) for vm in vms: # Get virtualHardwareSection/cpu section res = self.connection.request( '%s/virtualHardwareSection/cpu' % get_url_path(vm.get('href'))) # Update VirtualQuantity field xpath = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' 'CIM_ResourceAllocationSettingData}VirtualQuantity') res.object.find(xpath).text = str(vm_cpu) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.rasdItem+xml' } res = self.connection.request( '%s/virtualHardwareSection/cpu' % get_url_path(vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) def _change_vm_memory(self, vapp_or_vm_id, vm_memory): if vm_memory is None: return vms = self._get_vm_elements(vapp_or_vm_id) for vm in vms: # Get virtualHardwareSection/memory section res = self.connection.request( '%s/virtualHardwareSection/memory' % get_url_path(vm.get('href'))) # Update VirtualQuantity field xpath = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' 'CIM_ResourceAllocationSettingData}VirtualQuantity') res.object.find(xpath).text = str(vm_memory) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.rasdItem+xml' } res = self.connection.request( '%s/virtualHardwareSection/memory' % get_url_path( vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) def _add_vm_disk(self, vapp_or_vm_id, vm_disk): if vm_disk is None: return rasd_ns = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/' 'CIM_ResourceAllocationSettingData}') vms = self._get_vm_elements(vapp_or_vm_id) for vm in vms: # Get virtualHardwareSection/disks section res = self.connection.request( '%s/virtualHardwareSection/disks' % get_url_path(vm.get('href'))) existing_ids = [] new_disk = None for item in res.object.findall(fixxpath(res.object, 'Item')): # Clean Items from unnecessary stuff for elem in item: if elem.tag == '%sInstanceID' % rasd_ns: existing_ids.append(int(elem.text)) if elem.tag in ['%sAddressOnParent' % rasd_ns, '%sParent' % rasd_ns]: item.remove(elem) if item.find('%sHostResource' % rasd_ns) is not None: new_disk = item new_disk = copy.deepcopy(new_disk) disk_id = max(existing_ids) + 1 new_disk.find('%sInstanceID' % rasd_ns).text = str(disk_id) new_disk.find('%sElementName' % rasd_ns).text = 'Hard Disk ' + str(disk_id) new_disk.find('%sHostResource' % rasd_ns).set( fixxpath(new_disk, 'capacity'), str(int(vm_disk) * 1024)) res.object.append(new_disk) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.rasditemslist+xml' } res = self.connection.request( '%s/virtualHardwareSection/disks' % get_url_path( vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) def _change_vm_script(self, vapp_or_vm_id, vm_script, vm_script_text=None): if vm_script is None and vm_script_text is None: return if vm_script_text is not None: script = vm_script_text else: try: with open(vm_script, 'r') as fp: script = fp.read() except Exception: return vms = self._get_vm_elements(vapp_or_vm_id) # ElementTree escapes script characters automatically. Escape # requirements: # http://www.vmware.com/support/vcd/doc/rest-api-doc-1.5-html/types/ # GuestCustomizationSectionType.html for vm in vms: # Get GuestCustomizationSection res = self.connection.request( '%s/guestCustomizationSection' % get_url_path(vm.get('href'))) # Attempt to update any existing CustomizationScript element try: res.object.find( fixxpath(res.object, 'CustomizationScript')).text = script except Exception: # CustomizationScript section does not exist, insert it just # before ComputerName for i, e in enumerate(res.object): if e.tag == \ '{http://www.vmware.com/vcloud/v1.5}ComputerName': break e = ET.Element( '{http://www.vmware.com/vcloud/v1.5}CustomizationScript') e.text = script res.object.insert(i, e) # Remove AdminPassword from customization section if it would be # invalid to include it self._remove_admin_password(res.object) # Update VM's GuestCustomizationSection headers = { 'Content-Type': 'application/vnd.vmware.vcloud.guestCustomizationSection+xml' } res = self.connection.request( '%s/guestCustomizationSection' % get_url_path(vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) def _change_vm_ipmode(self, vapp_or_vm_id, vm_ipmode): if vm_ipmode is None: return vms = self._get_vm_elements(vapp_or_vm_id) for vm in vms: res = self.connection.request( '%s/networkConnectionSection' % get_url_path(vm.get('href'))) net_conns = res.object.findall( fixxpath(res.object, 'NetworkConnection')) for c in net_conns: c.find(fixxpath(c, 'IpAddressAllocationMode')).text = vm_ipmode headers = { 'Content-Type': 'application/vnd.vmware.vcloud.networkConnectionSection+xml' } res = self.connection.request( '%s/networkConnectionSection' % get_url_path(vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) @staticmethod def _remove_admin_password(guest_customization_section): """ Remove AdminPassword element from GuestCustomizationSection if it would be invalid to include it. This was originally done unconditionally due to an "API quirk" of unknown origin or effect. When AdminPasswordEnabled is set to true and AdminPasswordAuto is false, the admin password must be set or an error will ensue, and vice versa. :param guest_customization_section: GuestCustomizationSection element to remove password from (if valid to do so) :type guest_customization_section: ``ET.Element`` """ admin_pass_enabled = guest_customization_section.find( fixxpath(guest_customization_section, 'AdminPasswordEnabled') ) admin_pass_auto = guest_customization_section.find( fixxpath(guest_customization_section, 'AdminPasswordAuto') ) admin_pass = guest_customization_section.find( fixxpath(guest_customization_section, 'AdminPassword') ) if ( admin_pass is not None and ( admin_pass_enabled is None or admin_pass_enabled.text != 'true' or admin_pass_auto is None or admin_pass_auto.text != 'false' ) ): guest_customization_section.remove(admin_pass) def _update_or_insert_section(self, res, section, prev_section, text): try: res.object.find( fixxpath(res.object, section)).text = text except Exception: # "section" section does not exist, insert it just # before "prev_section" for i, e in enumerate(res.object): tag = '{http://www.vmware.com/vcloud/v1.5}%s' % prev_section if e.tag == tag: break e = ET.Element( '{http://www.vmware.com/vcloud/v1.5}%s' % section) e.text = text res.object.insert(i, e) return res def ex_change_vm_admin_password(self, vapp_or_vm_id, ex_admin_password): """ Changes the admin (or root) password of VM or VMs under the vApp. If the vapp_or_vm_id param represents a link to an vApp all VMs that are attached to this vApp will be modified. :keyword vapp_or_vm_id: vApp or VM ID that will be modified. If a vApp ID is used here all attached VMs will be modified :type vapp_or_vm_id: ``str`` :keyword ex_admin_password: admin password to be used. :type ex_admin_password: ``str`` :rtype: ``None`` """ if ex_admin_password is None: return vms = self._get_vm_elements(vapp_or_vm_id) for vm in vms: # Get GuestCustomizationSection res = self.connection.request( '%s/guestCustomizationSection' % get_url_path(vm.get('href'))) headers = { 'Content-Type': 'application/vnd.vmware.vcloud.guestCustomizationSection+xml' } # Fix API quirk. # If AdminAutoLogonEnabled==False the guestCustomizationSection # must have AdminAutoLogonCount==0, even though # it might have AdminAutoLogonCount==1 when requesting it for # the first time. auto_logon = res.object.find( fixxpath(res.object, "AdminAutoLogonEnabled")) if auto_logon is not None and auto_logon.text == 'false': self._update_or_insert_section(res, "AdminAutoLogonCount", "ResetPasswordRequired", '0') # If we are establishing a password we do not want it # to be automatically chosen. self._update_or_insert_section(res, 'AdminPasswordAuto', 'AdminPassword', 'false') # API does not allow to set AdminPassword if # AdminPasswordEnabled is not enabled. self._update_or_insert_section(res, 'AdminPasswordEnabled', 'AdminPasswordAuto', 'true') self._update_or_insert_section(res, 'AdminPassword', 'AdminAutoLogonEnabled', ex_admin_password) res = self.connection.request( '%s/guestCustomizationSection' % get_url_path(vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href')) def _get_network_href(self, network_name): network_href = None # Find the organisation's network href res = self.connection.request(self.org) links = res.object.findall(fixxpath(res.object, 'Link')) for l in links: if l.attrib['type'] == \ 'application/vnd.vmware.vcloud.orgNetwork+xml' \ and l.attrib['name'] == network_name: network_href = l.attrib['href'] if network_href is None: raise ValueError( '%s is not a valid organisation network name' % network_name) else: return network_href def _ex_get_node(self, node_id): """ Get a node instance from a node ID. :param node_id: ID of the node :type node_id: ``str`` :return: node instance or None if not found :rtype: :class:`Node` or ``None`` """ res = self.connection.request( get_url_path(node_id), headers={'Content-Type': 'application/vnd.vmware.vcloud.vApp+xml'} ) return self._to_node(res.object) def _get_vm_elements(self, vapp_or_vm_id): res = self.connection.request(get_url_path(vapp_or_vm_id)) if res.object.tag.endswith('VApp'): vms = res.object.findall(fixxpath(res.object, 'Children/Vm')) elif res.object.tag.endswith('Vm'): vms = [res.object] else: raise ValueError( 'Specified ID value is not a valid VApp or Vm identifier.') return vms def _is_node(self, node_or_image): return isinstance(node_or_image, Node) def _to_node(self, node_elm): # Parse snapshots and VMs as extra if node_elm.find(fixxpath(node_elm, "SnapshotSection")) is None: snapshots = None else: snapshots = [] for snapshot_elem in node_elm.findall( fixxpath(node_elm, 'SnapshotSection/Snapshot')): snapshots.append({ "created": snapshot_elem.get("created"), "poweredOn": snapshot_elem.get("poweredOn"), "size": snapshot_elem.get("size"), }) vms = [] for vm_elem in node_elm.findall(fixxpath(node_elm, 'Children/Vm')): public_ips = [] private_ips = [] xpath = fixxpath(vm_elem, 'NetworkConnectionSection/NetworkConnection') for connection in vm_elem.findall(xpath): ip = connection.find(fixxpath(connection, "IpAddress")) if ip is not None: private_ips.append(ip.text) external_ip = connection.find( fixxpath(connection, "ExternalIpAddress")) if external_ip is not None: public_ips.append(external_ip.text) elif ip is not None: public_ips.append(ip.text) xpath = ('{http://schemas.dmtf.org/ovf/envelope/1}' 'OperatingSystemSection') os_type_elem = vm_elem.find(xpath) if os_type_elem is not None: os_type = os_type_elem.get( '{http://www.vmware.com/schema/ovf}osType') else: os_type = None vm = { 'id': vm_elem.get('href'), 'name': vm_elem.get('name'), 'state': self.NODE_STATE_MAP[vm_elem.get('status')], 'public_ips': public_ips, 'private_ips': private_ips, 'os_type': os_type } vms.append(vm) # Take the node IP addresses from all VMs public_ips = [] private_ips = [] for vm in vms: public_ips.extend(vm['public_ips']) private_ips.extend(vm['private_ips']) # Find vDC vdc_id = next(link.get('href') for link in node_elm.findall(fixxpath(node_elm, 'Link')) if link.get('type') == 'application/vnd.vmware.vcloud.vdc+xml' ) # pylint: disable=no-member vdc = next(vdc for vdc in self.vdcs if vdc.id == vdc_id) extra = {'vdc': vdc.name, 'vms': vms} description = node_elm.find(fixxpath(node_elm, 'Description')) if description is not None: extra['description'] = description.text else: extra['description'] = '' lease_settings = node_elm.find( fixxpath(node_elm, 'LeaseSettingsSection') ) if lease_settings is not None: extra['lease_settings'] = Lease.to_lease(lease_settings) else: extra['lease_settings'] = None if snapshots is not None: extra['snapshots'] = snapshots node = Node(id=node_elm.get('href'), name=node_elm.get('name'), state=self.NODE_STATE_MAP[node_elm.get('status')], public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver, extra=extra) return node def _to_vdc(self, vdc_elm): def get_capacity_values(capacity_elm): if capacity_elm is None: return None limit = int(capacity_elm.findtext(fixxpath(capacity_elm, 'Limit'))) used = int(capacity_elm.findtext(fixxpath(capacity_elm, 'Used'))) units = capacity_elm.findtext(fixxpath(capacity_elm, 'Units')) return Capacity(limit, used, units) cpu = get_capacity_values( vdc_elm.find(fixxpath(vdc_elm, 'ComputeCapacity/Cpu'))) memory = get_capacity_values( vdc_elm.find(fixxpath(vdc_elm, 'ComputeCapacity/Memory'))) storage = get_capacity_values( vdc_elm.find(fixxpath(vdc_elm, 'StorageCapacity'))) return Vdc(id=vdc_elm.get('href'), name=vdc_elm.get('name'), driver=self, allocation_model=vdc_elm.findtext( fixxpath(vdc_elm, 'AllocationModel')), cpu=cpu, memory=memory, storage=storage) class VCloud_5_1_NodeDriver(VCloud_1_5_NodeDriver): @staticmethod def _validate_vm_memory(vm_memory): if vm_memory is None: return None elif (vm_memory % 4) != 0: # The vcd 5.1 virtual machine memory size must be a multiple of 4 # MB raise ValueError( '%s is not a valid vApp VM memory value' % (vm_memory)) class VCloud_5_5_NodeDriver(VCloud_5_1_NodeDriver): """Use 5.5 Connection class to explicitly set 5.5 for the version in Accept headers """ connectionCls = VCloud_5_5_Connection def ex_create_snapshot(self, node): """ Creates new snapshot of a virtual machine or of all the virtual machines in a vApp. Prior to creation of the new snapshots, any existing user created snapshots associated with the virtual machines are removed. :param node: node :type node: :class:`Node` :rtype: :class:`Node` """ snapshot_xml = ET.Element( "CreateSnapshotParams", {'memory': 'true', 'name': 'name', 'quiesce': 'true', 'xmlns': "http://www.vmware.com/vcloud/v1.5", 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} ) ET.SubElement(snapshot_xml, 'Description').text = 'Description' content_type = 'application/vnd.vmware.vcloud.createSnapshotParams+xml' headers = { 'Content-Type': content_type } return self._perform_snapshot_operation(node, "createSnapshot", snapshot_xml, headers) def ex_remove_snapshots(self, node): """ Removes all user created snapshots for a vApp or virtual machine. :param node: node :type node: :class:`Node` :rtype: :class:`Node` """ return self._perform_snapshot_operation(node, "removeAllSnapshots", None, None) def ex_revert_to_snapshot(self, node): """ Reverts a vApp or virtual machine to the current snapshot, if any. :param node: node :type node: :class:`Node` :rtype: :class:`Node` """ return self._perform_snapshot_operation(node, "revertToCurrentSnapshot", None, None) def _perform_snapshot_operation(self, node, operation, xml_data, headers): res = self.connection.request( '%s/action/%s' % (get_url_path(node.id), operation), data=ET.tostring(xml_data) if xml_data is not None else None, method='POST', headers=headers) self._wait_for_task_completion(res.object.get('href')) res = self.connection.request(get_url_path(node.id)) return self._to_node(res.object) def ex_acquire_mks_ticket(self, vapp_or_vm_id, vm_num=0): """ Retrieve a mks ticket that you can use to gain access to the console of a running VM. If successful, returns a dict with the following keys: - host: host (or proxy) through which the console connection is made - vmx: a reference to the VMX file of the VM for which this ticket was issued - ticket: screen ticket to use to authenticate the client - port: host port to be used for console access :param vapp_or_vm_id: vApp or VM ID you want to connect to. :type vapp_or_vm_id: ``str`` :param vm_num: If a vApp ID is provided, vm_num is position in the vApp VM list of the VM you want to get a screen ticket. Default is 0. :type vm_num: ``int`` :rtype: ``dict`` """ vm = self._get_vm_elements(vapp_or_vm_id)[vm_num] try: res = self.connection.request('%s/screen/action/acquireMksTicket' % (get_url_path(vm.get('href'))), method='POST') output = { "host": res.object.find(fixxpath(res.object, 'Host')).text, "vmx": res.object.find(fixxpath(res.object, 'Vmx')).text, "ticket": res.object.find(fixxpath(res.object, 'Ticket')).text, "port": res.object.find(fixxpath(res.object, 'Port')).text, } return output except Exception: return None apache-libcloud-2.8.0/libcloud/compute/drivers/voxel.py0000664000175000017500000002525713577507766023123 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Voxel VoxCloud driver """ import datetime import hashlib from libcloud.utils.py3 import b from libcloud.common.base import XmlResponse, ConnectionUserAndKey from libcloud.common.types import InvalidCredsError from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState from libcloud.compute.base import Node, NodeDriver from libcloud.compute.base import NodeSize, NodeImage, NodeLocation VOXEL_API_HOST = "api.voxel.net" class VoxelResponse(XmlResponse): def __init__(self, response, connection): self.parsed = None super(VoxelResponse, self).__init__(response=response, connection=connection) def parse_body(self): if not self.body: return None if self.parsed is None: self.parsed = super(VoxelResponse, self).parse_body() return self.parsed def parse_error(self): err_list = [] if not self.body: return None if self.parsed is None: self.parsed = super(VoxelResponse, self).parse_body() for err in self.parsed.findall('err'): code = err.get('code') err_list.append("(%s) %s" % (code, err.get('msg'))) # From voxel docs: # 1: Invalid login or password # 9: Permission denied: user lacks access rights for this method if code == "1" or code == "9": # sucks, but only way to detect # bad authentication tokens so far raise InvalidCredsError(err_list[-1]) return "\n".join(err_list) def success(self): if not self.parsed: self.parsed = super(VoxelResponse, self).parse_body() stat = self.parsed.get('stat') if stat != "ok": return False return True class VoxelConnection(ConnectionUserAndKey): """ Connection class for the Voxel driver """ host = VOXEL_API_HOST responseCls = VoxelResponse def add_default_params(self, params): params = dict([(k, v) for k, v in list(params.items()) if v is not None]) params["key"] = self.user_id params["timestamp"] = datetime.datetime.utcnow().isoformat() + "+0000" keys = list(params.keys()) keys.sort() md5 = hashlib.md5() md5.update(b(self.key)) for key in keys: if params[key]: if not params[key] is None: md5.update(b("%s%s" % (key, params[key]))) else: md5.update(b(key)) params['api_sig'] = md5.hexdigest() return params VOXEL_INSTANCE_TYPES = {} RAM_PER_CPU = 2048 NODE_STATE_MAP = { 'IN_PROGRESS': NodeState.PENDING, 'QUEUED': NodeState.PENDING, 'SUCCEEDED': NodeState.RUNNING, 'shutting-down': NodeState.TERMINATED, 'terminated': NodeState.TERMINATED, 'unknown': NodeState.UNKNOWN, } class VoxelNodeDriver(NodeDriver): """ Voxel VoxCLOUD node driver """ connectionCls = VoxelConnection type = Provider.VOXEL name = 'Voxel VoxCLOUD' website = 'http://www.voxel.net/' def _initialize_instance_types(): # pylint: disable=no-method-argument for cpus in range(1, 14): if cpus == 1: name = "Single CPU" else: name = "%d CPUs" % cpus id = "%dcpu" % cpus ram = cpus * RAM_PER_CPU VOXEL_INSTANCE_TYPES[id] = { 'id': id, 'name': name, 'ram': ram, 'disk': None, 'bandwidth': None, 'price': None} features = {"create_node": [], "list_sizes": ["variable_disk"]} _initialize_instance_types() def list_nodes(self): params = {"method": "voxel.devices.list"} result = self.connection.request('/', params=params).object return self._to_nodes(result) def list_sizes(self, location=None): return [NodeSize(driver=self.connection.driver, **i) for i in list(VOXEL_INSTANCE_TYPES.values())] def list_images(self, location=None): params = {"method": "voxel.images.list"} result = self.connection.request('/', params=params).object return self._to_images(result) def create_node(self, name, size, image, location, ex_privateip=None, ex_publicip=None, ex_rootpass=None, ex_consolepass=None, ex_sshuser=None, ex_sshpass=None, ex_voxel_access=None): """Create Voxel Node :keyword name: the name to assign the node (mandatory) :type name: ``str`` :keyword image: distribution to deploy :type image: :class:`NodeImage` :keyword size: the plan size to create (mandatory) Requires size.disk (GB) to be set manually :type size: :class:`NodeSize` :keyword location: which datacenter to create the node in :type location: :class:`NodeLocation` :keyword ex_privateip: Backend IP address to assign to node; must be chosen from the customer's private VLAN assignment. :type ex_privateip: ``str`` :keyword ex_publicip: Public-facing IP address to assign to node; must be chosen from the customer's public VLAN assignment. :type ex_publicip: ``str`` :keyword ex_rootpass: Password for root access; generated if unset. :type ex_rootpass: ``str`` :keyword ex_consolepass: Password for remote console; generated if unset. :type ex_consolepass: ``str`` :keyword ex_sshuser: Username for SSH access :type ex_sshuser: ``str`` :keyword ex_sshpass: Password for SSH access; generated if unset. :type ex_sshpass: ``str`` :keyword ex_voxel_access: Allow access Voxel administrative access. Defaults to False. :type ex_voxel_access: ``bool`` :rtype: :class:`Node` or ``None`` """ # assert that disk > 0 if not size.disk: raise ValueError("size.disk must be non-zero") # convert voxel_access to string boolean if needed if ex_voxel_access is not None: ex_voxel_access = "true" if ex_voxel_access else "false" params = { 'method': 'voxel.voxcloud.create', 'hostname': name, 'disk_size': int(size.disk), 'facility': location.id, 'image_id': image.id, 'processing_cores': size.ram / RAM_PER_CPU, 'backend_ip': ex_privateip, 'frontend_ip': ex_publicip, 'admin_password': ex_rootpass, 'console_password': ex_consolepass, 'ssh_username': ex_sshuser, 'ssh_password': ex_sshpass, 'voxel_access': ex_voxel_access, } object = self.connection.request('/', params=params).object if self._getstatus(object): return Node( id=object.findtext("device/id"), name=name, state=NODE_STATE_MAP[object.findtext("device/status")], public_ips=ex_publicip, private_ips=ex_privateip, driver=self.connection.driver ) else: return None def reboot_node(self, node): params = {'method': 'voxel.devices.power', 'device_id': node.id, 'power_action': 'reboot'} return self._getstatus( self.connection.request('/', params=params).object) def destroy_node(self, node): params = {'method': 'voxel.voxcloud.delete', 'device_id': node.id} return self._getstatus( self.connection.request('/', params=params).object) def list_locations(self): params = {"method": "voxel.voxcloud.facilities.list"} result = self.connection.request('/', params=params).object nodes = self._to_locations(result) return nodes def _getstatus(self, element): status = element.attrib["stat"] return status == "ok" def _to_locations(self, object): return [NodeLocation(element.attrib["label"], element.findtext("description"), element.findtext("description"), self) for element in object.findall('facilities/facility')] def _to_nodes(self, object): nodes = [] for element in object.findall('devices/device'): if element.findtext("type") == "Virtual Server": try: state = self.NODE_STATE_MAP[element.attrib['status']] except KeyError: state = NodeState.UNKNOWN public_ip = private_ip = None ipassignments = element.findall("ipassignments/ipassignment") for ip in ipassignments: if ip.attrib["type"] == "frontend": public_ip = ip.text elif ip.attrib["type"] == "backend": private_ip = ip.text nodes.append(Node(id=element.attrib['id'], name=element.attrib['label'], state=state, public_ips=public_ip, private_ips=private_ip, driver=self.connection.driver)) return nodes def _to_images(self, object): images = [] for element in object.findall("images/image"): images.append(NodeImage(id=element.attrib["id"], name=element.attrib["summary"], driver=self.connection.driver)) return images apache-libcloud-2.8.0/libcloud/compute/drivers/vpsnet.py0000664000175000017500000001510113577507766023270 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ VPS.net driver """ import base64 try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import b from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.common.types import InvalidCredsError, MalformedResponseError from libcloud.compute.providers import Provider from libcloud.compute.types import NodeState from libcloud.compute.base import Node, NodeDriver from libcloud.compute.base import NodeSize, NodeImage, NodeLocation API_HOST = 'api.vps.net' API_VERSION = 'api10json' RAM_PER_NODE = 256 DISK_PER_NODE = 10 BANDWIDTH_PER_NODE = 250 class VPSNetResponse(JsonResponse): def parse_body(self): try: return super(VPSNetResponse, self).parse_body() except MalformedResponseError: return self.body def success(self): # vps.net wrongly uses 406 for invalid auth creds if self.status == 406 or self.status == 403: raise InvalidCredsError() return True def parse_error(self): try: errors = super(VPSNetResponse, self).parse_body()['errors'][0] except MalformedResponseError: return self.body else: return "\n".join(errors) class VPSNetConnection(ConnectionUserAndKey): """ Connection class for the VPS.net driver """ host = API_HOST responseCls = VPSNetResponse allow_insecure = False def add_default_headers(self, headers): user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) return headers class VPSNetNodeDriver(NodeDriver): """ VPS.net node driver """ type = Provider.VPSNET api_name = 'vps_net' name = "vps.net" website = 'http://vps.net/' connectionCls = VPSNetConnection def _to_node(self, vm): if vm['running']: state = NodeState.RUNNING else: state = NodeState.PENDING n = Node(id=vm['id'], name=vm['label'], state=state, public_ips=[vm.get('primary_ip_address', None)], private_ips=[], extra={'slices_count': vm['slices_count']}, # Number of nodes consumed by VM driver=self.connection.driver) return n def _to_image(self, image, cloud): image = NodeImage(id=image['id'], name="%s: %s" % (cloud, image['label']), driver=self.connection.driver) return image def _to_size(self, num): size = NodeSize(id=num, name="%d Node" % (num,), ram=RAM_PER_NODE * num, disk=DISK_PER_NODE, bandwidth=BANDWIDTH_PER_NODE * num, price=self._get_price_per_node(num) * num, driver=self.connection.driver) return size def _get_price_per_node(self, num): single_node_price = self._get_size_price(size_id='1') return num * single_node_price def create_node(self, name, image, size, ex_backups_enabled=False, ex_fqdn=None): """Create a new VPS.net node @inherits: :class:`NodeDriver.create_node` :keyword ex_backups_enabled: Enable automatic backups :type ex_backups_enabled: ``bool`` :keyword ex_fqdn: Fully Qualified domain of the node :type ex_fqdn: ``str`` """ ex_backups_enabled = 1 if ex_backups_enabled else 0 headers = {'Content-Type': 'application/json'} request = {'virtual_machine': {'label': name, 'fqdn': ex_fqdn or '', 'system_template_id': image.id, 'backups_enabled': ex_backups_enabled, 'slices_required': size.id}} res = self.connection.request('/virtual_machines.%s' % (API_VERSION,), data=json.dumps(request), headers=headers, method='POST') node = self._to_node(res.object['virtual_machine']) return node def reboot_node(self, node): res = self.connection.request( '/virtual_machines/%s/%s.%s' % (node.id, 'reboot', API_VERSION), method="POST") node = self._to_node(res.object['virtual_machine']) return True def list_sizes(self, location=None): res = self.connection.request('/nodes.%s' % (API_VERSION,)) available_nodes = len([size for size in res.object if size['slice']['virtual_machine_id']]) sizes = [self._to_size(i) for i in range(1, available_nodes + 1)] return sizes def destroy_node(self, node): res = self.connection.request('/virtual_machines/%s.%s' % (node.id, API_VERSION), method='DELETE') return res.status == 200 def list_nodes(self): res = self.connection.request('/virtual_machines.%s' % (API_VERSION,)) return [self._to_node(i['virtual_machine']) for i in res.object] def list_images(self, location=None): res = self.connection.request('/available_clouds.%s' % (API_VERSION,)) images = [] for cloud in res.object: label = cloud['cloud']['label'] templates = cloud['cloud']['system_templates'] images.extend([self._to_image(image, label) for image in templates]) return images def list_locations(self): return [NodeLocation(0, "VPS.net Western US", 'US', self)] apache-libcloud-2.8.0/libcloud/compute/drivers/vsphere.py0000664000175000017500000004374713600144066023417 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ VMware vSphere driver supporting vSphere v5.5. Note: This driver requires pysphere package (https://pypi.python.org/pypi/pysphere) which can be installed using pip. For more information, please refer to the official documentation. """ import os import atexit try: import pysphere pysphere except ImportError: raise ImportError('Missing "pysphere" dependency. You can install it ' 'using pip - pip install pysphere') from pysphere import VIServer from pysphere.vi_task import VITask from pysphere.vi_mor import VIMor, MORTypes from pysphere.resources import VimService_services as VI from pysphere.vi_virtual_machine import VIVirtualMachine from libcloud.utils.decorators import wrap_non_libcloud_exceptions from libcloud.common.base import ConnectionUserAndKey from libcloud.common.types import LibcloudError from libcloud.common.types import InvalidCredsError from libcloud.compute.base import NodeDriver from libcloud.compute.base import NodeLocation from libcloud.compute.base import NodeImage from libcloud.compute.base import Node from libcloud.compute.types import NodeState, Provider from libcloud.utils.networking import is_public_subnet __all__ = [ 'VSphereNodeDriver', 'VSphere_5_5_NodeDriver' ] DEFAULT_API_VERSION = '5.5' DEFAULT_CONNECTION_TIMEOUT = 5 # default connection timeout in seconds class VSphereConnection(ConnectionUserAndKey): def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, **kwargs): if host and url: raise ValueError('host and url arguments are mutually exclusive') if host: host_or_url = host elif url: host_or_url = url else: raise ValueError('Either "host" or "url" argument must be ' 'provided') self.host_or_url = host_or_url self.client = None super(VSphereConnection, self).__init__(user_id=user_id, key=key, secure=secure, host=host, port=port, url=url, timeout=timeout, **kwargs) def connect(self): self.client = VIServer() trace_file = os.environ.get('LIBCLOUD_DEBUG', None) try: self.client.connect(host=self.host_or_url, user=self.user_id, password=self.key, sock_timeout=DEFAULT_CONNECTION_TIMEOUT, trace_file=trace_file) except Exception as e: message = e.message if hasattr(e, 'strerror'): message = getattr(e, 'strerror', e.message) fault = getattr(e, 'fault', None) if fault == 'InvalidLoginFault': raise InvalidCredsError(message) raise LibcloudError(value=message, driver=self.driver) atexit.register(self.disconnect) def disconnect(self): if not self.client: return try: self.client.disconnect() except Exception: # Ignore all the disconnect errors pass def run_client_method(self, method_name, **method_kwargs): method = getattr(self.client, method_name, None) return method(**method_kwargs) class VSphereNodeDriver(NodeDriver): name = 'VMware vSphere' website = 'http://www.vmware.com/products/vsphere/' type = Provider.VSPHERE connectionCls = VSphereConnection NODE_STATE_MAP = { 'POWERED ON': NodeState.RUNNING, 'POWERED OFF': NodeState.STOPPED, 'SUSPENDED': NodeState.SUSPENDED, 'POWERING ON': NodeState.PENDING, 'POWERING OFF': NodeState.PENDING, 'SUSPENDING': NodeState.PENDING, 'RESETTING': NodeState.PENDING, 'BLOCKED ON MSG': NodeState.ERROR, 'REVERTING TO SNAPSHOT': NodeState.PENDING } def __new__(cls, username, password, secure=True, host=None, port=None, url=None, api_version=DEFAULT_API_VERSION, **kwargs): if cls is VSphereNodeDriver: if api_version == '5.5': cls = VSphere_5_5_NodeDriver else: raise NotImplementedError('Unsupported API version: %s' % (api_version)) return super(VSphereNodeDriver, cls).__new__(cls) def __init__(self, username, password, secure=True, host=None, port=None, url=None, timeout=None): self.url = url super(VSphereNodeDriver, self).__init__(key=username, secret=password, secure=secure, host=host, port=port, url=url) @wrap_non_libcloud_exceptions def list_locations(self): """ List available locations. In vSphere case, a location represents a datacenter. """ datacenters = self.connection.client.get_datacenters() locations = [] for id, name in datacenters.items(): location = NodeLocation(id=id, name=name, country=None, driver=self) locations.append(location) return locations @wrap_non_libcloud_exceptions def list_images(self): """ List available images (templates). """ server = self.connection.client names = ['name', 'config.uuid', 'config.template'] properties = server._retrieve_properties_traversal( property_names=names, from_node=None, obj_type=MORTypes.VirtualMachine) images = [] for prop in properties: id = None name = None is_template = False for item in prop.PropSet: if item.Name == 'config.uuid': id = item.Val if item.Name == 'name': name = item.Val elif item.Name == 'config.template': is_template = item.Val if is_template: image = NodeImage(id=id, name=name, driver=self) images.append(image) return images @wrap_non_libcloud_exceptions def list_nodes(self): vm_paths = self.connection.client.get_registered_vms() nodes = self._to_nodes(vm_paths=vm_paths) return nodes @wrap_non_libcloud_exceptions @wrap_non_libcloud_exceptions def ex_clone_node(self, node, name, power_on=True, template=False): """ Clone the provided node. :param node: Node to clone. :type node: :class:`libcloud.compute.base.Node` :param name: Name of the new node. :type name: ``str`` :param power_on: Power the new node on after being created. :type power_on: ``bool`` :param template: Specifies whether or not the new virtual machine should be marked as a template. :type template: ``bool`` :return: New node. :rtype: :class:`libcloud.compute.base.Node` """ vm = self._get_vm_for_node(node=node) new_vm = vm.clone(name=name, power_on=power_on, template=template) new_node = self._to_node(vm=new_vm) return new_node @wrap_non_libcloud_exceptions def ex_migrate_node(self, node, resource_pool=None, host=None, priority='default'): """ Migrate provided node to a new host or resource pool. :param node: Node to clone. :type node: :class:`libcloud.compute.base.Node` :param resource_pool: ID of the target resource pool to migrate the node into. :type resource_pool: ``str`` :param host: Target host to migrate the host to. :type host: ``str`` :param priority: Migration task priority. Possible values: default, high, low. :type priority: ``str`` :return: True on success. :rtype: ``bool`` """ vm = self._get_vm_for_node(node=node) vm.migrate(priority=priority, resource_pool=resource_pool, host=host) return True @wrap_non_libcloud_exceptions def reboot_node(self, node): vm = self._get_vm_for_node(node=node) vm.reset() return True @wrap_non_libcloud_exceptions def destroy_node(self, node, ex_remove_files=True): """ :param ex_remove_files: Remove all the files from the datastore. :type ex_remove_files: ``bool`` """ ex_remove_files = False vm = self._get_vm_for_node(node=node) server = self.connection.client # Based on code from # https://pypi.python.org/pypi/pyxenter if ex_remove_files: request = VI.Destroy_TaskRequestMsg() _this = request.new__this(vm._mor) _this.set_attribute_type(vm._mor.get_attribute_type()) request.set_element__this(_this) # pylint: disable=no-member ret = server._proxy.Destroy_Task(request)._returnva # pylint: enable=no-member task = VITask(ret, server) # Wait for the task to finish status = task.wait_for_state([task.STATE_SUCCESS, task.STATE_ERROR]) if status == task.STATE_ERROR: raise LibcloudError('Error destroying node: %s' % (task.get_error_message())) else: request = VI.UnregisterVMRequestMsg() _this = request.new__this(vm._mor) _this.set_attribute_type(vm._mor.get_attribute_type()) request.set_element__this(_this) ret = server._proxy.UnregisterVM(request) task = VITask(ret, server) return True @wrap_non_libcloud_exceptions def start_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 vm = self._get_vm_for_node(node=node) vm.power_on() return True @wrap_non_libcloud_exceptions def stop_node(self, node): # NOTE: This method is here for backward compatibility reasons after # this method was promoted to be part of the standard compute API in # Libcloud v2.7.0 vm = self._get_vm_for_node(node=node) vm.power_off() return True @wrap_non_libcloud_exceptions def ex_start_node(self, node): return self.start_node(node=node) @wrap_non_libcloud_exceptions def ex_stop_node(self, node): return self.stop_node(node=node) @wrap_non_libcloud_exceptions def ex_suspend_node(self, node): vm = self._get_vm_for_node(node=node) vm.suspend() return True @wrap_non_libcloud_exceptions def ex_get_resource_pools(self): """ Return all the available resource pools. :rtype: ``dict`` """ result = self.connection.client.get_resource_pools() return result @wrap_non_libcloud_exceptions def ex_get_resource_pool_name(self, node): """ Retrieve resource pool name for the provided node. :rtype: ``str`` """ vm = self._get_vm_for_node(node=node) return vm.get_resource_pool_name() @wrap_non_libcloud_exceptions def ex_get_hosts(self): """ Return all the available hosts. :rtype: ``dict`` """ result = self.connection.client.get_hosts() return result @wrap_non_libcloud_exceptions def ex_get_datastores(self): """ Return all the available datastores. :rtype: ``dict`` """ result = self.connection.client.get_datastores() return result @wrap_non_libcloud_exceptions def ex_get_node_by_path(self, path): """ Retrieve Node object for a VM with a provided path. :type path: ``str`` :rtype: :class:`libcloud.compute.base.Node` """ vm = self.connection.client.get_vm_by_path(path) node = self._to_node(vm=vm) return node def ex_get_node_by_uuid(self, uuid): """ Retrieve Node object for a VM with a provided uuid. :type uuid: ``str`` """ vm = self._get_vm_for_uuid(uuid=uuid) node = self._to_node(vm=vm) return node @wrap_non_libcloud_exceptions def ex_get_server_type(self): """ Return VMware installation type. :rtype: ``str`` """ return self.connection.client.get_server_type() @wrap_non_libcloud_exceptions def ex_get_api_version(self): """ Return API version of the vmware provider. :rtype: ``str`` """ return self.connection.client.get_api_version() def _get_vm_for_uuid(self, uuid, datacenter=None): """ Retrieve VM for the provided UUID. :type uuid: ``str`` """ server = self.connection.client dc_list = [] if datacenter and VIMor.is_mor(datacenter): dc_list.append(datacenter) else: dc = server.get_datacenters() if datacenter: dc_list = [k for k, v in dc.iteritems() if v == datacenter] else: dc_list = list(dc.iterkeys()) for mor_dc in dc_list: request = VI.FindByUuidRequestMsg() search_index = server._do_service_content.SearchIndex mor_search_index = request.new__this(search_index) mor_search_index.set_attribute_type(MORTypes.SearchIndex) request.set_element__this(mor_search_index) mor_datacenter = request.new_datacenter(mor_dc) mor_datacenter.set_attribute_type(MORTypes.Datacenter) request.set_element_datacenter(mor_datacenter) request.set_element_vmSearch(True) request.set_element_uuid(uuid) try: # pylint: disable=no-member vm = server._proxy.FindByUuid(request)._returnval # pylint: enable=no-member except VI.ZSI.FaultException: pass else: if vm: return VIVirtualMachine(server, vm) return None def _to_nodes(self, vm_paths): nodes = [] for vm_path in vm_paths: vm = self.connection.client.get_vm_by_path(vm_path) node = self._to_node(vm=vm) nodes.append(node) return nodes def _to_node(self, vm): assert(isinstance(vm, VIVirtualMachine)) properties = vm.get_properties() status = vm.get_status() uuid = vm.properties.config.uuid instance_uuid = vm.properties.config.instanceUuid id = uuid name = properties['name'] public_ips = [] private_ips = [] state = self.NODE_STATE_MAP.get(status, NodeState.UNKNOWN) ip_address = properties.get('ip_address', None) net = properties.get('net', []) resource_pool_id = str(vm.properties.resourcePool._obj) try: operating_system = vm.properties.summary.guest.guestFullName, except Exception: operating_system = 'unknown' extra = { 'uuid': uuid, 'instance_uuid': instance_uuid, 'path': properties['path'], 'resource_pool_id': resource_pool_id, 'hostname': properties.get('hostname', None), 'guest_id': properties['guest_id'], 'devices': properties.get('devices', {}), 'disks': properties.get('disks', []), 'net': net, 'overall_status': vm.properties.overallStatus, 'operating_system': operating_system, 'cpus': vm.properties.config.hardware.numCPU, 'memory_mb': vm.properties.config.hardware.memoryMB } # Add primary IP if ip_address: if is_public_subnet(ip_address): public_ips.append(ip_address) else: private_ips.append(ip_address) # Add other IP addresses for nic in net: ip_addresses = nic['ip_addresses'] for ip_address in ip_addresses: try: is_public = is_public_subnet(ip_address) except Exception: # TODO: Better support for IPv6 is_public = False if is_public: public_ips.append(ip_address) else: private_ips.append(ip_address) # Remove duplicate IPs public_ips = list(set(public_ips)) private_ips = list(set(private_ips)) node = Node(id=id, name=name, state=state, public_ips=public_ips, private_ips=private_ips, driver=self, extra=extra) return node def _get_vm_for_node(self, node): uuid = node.id vm = self._get_vm_for_uuid(uuid=uuid) return vm def _ex_connection_class_kwargs(self): kwargs = { 'url': self.url } return kwargs class VSphere_5_5_NodeDriver(VSphereNodeDriver): name = 'VMware vSphere v5.5' apache-libcloud-2.8.0/libcloud/compute/drivers/vultr.py0000664000175000017500000003202013570310635023100 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Vultr Driver """ import time from functools import update_wrapper from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlencode from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.compute.types import Provider, NodeState from libcloud.common.types import InvalidCredsError from libcloud.common.types import LibcloudError from libcloud.common.types import ServiceUnavailableError from libcloud.compute.base import NodeDriver from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation class rate_limited: """ Decorator for retrying Vultr calls that are rate-limited. :param int sleep: Seconds to sleep after being rate-limited. :param int retries: Number of retries. """ def __init__(self, sleep=0.5, retries=1): self.sleep = sleep self.retries = retries def __call__(self, call): """ Run ``call`` method until it's not rate-limited. The method is invoked while it returns 503 Service Unavailable or the allowed number of retries is reached. :param callable call: Method to be decorated. """ def wrapper(*args, **kwargs): last_exception = None for i in range(self.retries + 1): try: return call(*args, **kwargs) except ServiceUnavailableError as e: last_exception = e time.sleep(self.sleep) # hit by rate limit, let's sleep if last_exception: raise last_exception # pylint: disable=raising-bad-type update_wrapper(wrapper, call) return wrapper class VultrResponse(JsonResponse): def parse_error(self): if self.status == httplib.OK: body = self.parse_body() return body elif self.status == httplib.FORBIDDEN: raise InvalidCredsError(self.body) elif self.status == httplib.SERVICE_UNAVAILABLE: raise ServiceUnavailableError(self.body) else: raise LibcloudError(self.body) class SSHKey(object): def __init__(self, id, name, pub_key): self.id = id self.name = name self.pub_key = pub_key def __repr__(self): return (('') % (self.id, self.name, self.pub_key)) class VultrConnection(ConnectionKey): """ Connection class for the Vultr driver. """ host = 'api.vultr.com' responseCls = VultrResponse unauthenticated_endpoints = { # {action: methods} '/v1/app/list': ['GET'], '/v1/os/list': ['GET'], '/v1/plans/list': ['GET'], '/v1/plans/list_vc2': ['GET'], '/v1/plans/list_vdc2': ['GET'], '/v1/regions/availability': ['GET'], '/v1/regions/list': ['GET'] } def add_default_headers(self, headers): """ Adds ``API-Key`` default header. :return: Updated headers. :rtype: dict """ if self.require_api_key(): headers.update({'API-Key': self.key}) return headers def encode_data(self, data): return urlencode(data) @rate_limited() def get(self, url): return self.request(url) @rate_limited() def post(self, url, data): headers = {'Content-Type': 'application/x-www-form-urlencoded'} return self.request(url, data=data, headers=headers, method='POST') def require_api_key(self): """ Check whether this call (method + action) must be authenticated. :return: True if ``API-Key`` header required, False otherwise. :rtype: bool """ try: return self.method \ not in self.unauthenticated_endpoints[self.action] except KeyError: return True class VultrNodeDriver(NodeDriver): """ VultrNode node driver. """ connectionCls = VultrConnection type = Provider.VULTR name = 'Vultr' website = 'https://www.vultr.com' NODE_STATE_MAP = {'pending': NodeState.PENDING, 'active': NodeState.RUNNING} EX_CREATE_YES_NO_ATTRIBUTES = ['enable_ipv6', 'enable_private_network', 'auto_backups', 'notify_activate', 'ddos_protection'] EX_CREATE_ID_ATTRIBUTES = {'iso_id': 'ISOID', 'script_id': 'SCRIPTID', 'snapshot_id': 'SNAPSHOTID', 'app_id': 'APPID'} EX_CREATE_ATTRIBUTES = ['ipxe_chain_url', 'label', 'userdata', 'reserved_ip_v4', 'hostname', 'tag'] EX_CREATE_ATTRIBUTES.extend(EX_CREATE_YES_NO_ATTRIBUTES) EX_CREATE_ATTRIBUTES.extend(EX_CREATE_ID_ATTRIBUTES.keys()) def list_nodes(self): return self._list_resources('/v1/server/list', self._to_node) def list_key_pairs(self): """ List all the available SSH keys. :return: Available SSH keys. :rtype: ``list`` of :class:`SSHKey` """ return self._list_resources('/v1/sshkey/list', self._to_ssh_key) def create_key_pair(self, name, public_key=''): """ Create a new SSH key. :param name: Name of the new SSH key :type name: ``str`` :key public_key: Public part of the new SSH key :type name: ``str`` :return: True on success :rtype: ``bool`` """ params = {'name': name, 'ssh_key': public_key} res = self.connection.post('/v1/sshkey/create', params) return res.status == httplib.OK def delete_key_pair(self, key_pair): """ Delete an SSH key. :param key_pair: The SSH key to delete :type key_pair: :class:`SSHKey` :return: True on success :rtype: ``bool`` """ params = {'SSHKEYID': key_pair.id} res = self.connection.post('/v1/sshkey/destroy', params) return res.status == httplib.OK def list_locations(self): return self._list_resources('/v1/regions/list', self._to_location) def list_sizes(self): return self._list_resources('/v1/plans/list', self._to_size) def list_images(self): return self._list_resources('/v1/os/list', self._to_image) def create_node(self, name, size, image, location, ex_ssh_key_ids=None, ex_create_attr=None): """ Create a node :param name: Name for the new node :type name: ``str`` :param size: Size of the new node :type size: :class:`NodeSize` :param image: Image for the new node :type image: :class:`NodeImage` :param location: Location of the new node :type location: :class:`NodeLocation` :param ex_ssh_key_ids: IDs of the SSH keys to initialize :type ex_sshkeyid: ``list`` of ``str`` :param ex_create_attr: Extra attributes for node creation :type ex_create_attr: ``dict`` The `ex_create_attr` parameter can include the following dictionary key and value pairs: * `ipxe_chain_url`: ``str`` for specifying URL to boot via IPXE * `iso_id`: ``str`` the ID of a specific ISO to mount, only meaningful with the `Custom` `NodeImage` * `script_id`: ``int`` ID of a startup script to execute on boot, only meaningful when the `NodeImage` is not `Custom` * 'snapshot_id`: ``str`` Snapshot ID to restore for the initial installation, only meaningful with the `Snapshot` `NodeImage` * `enable_ipv6`: ``bool`` Whether an IPv6 subnet should be assigned * `enable_private_network`: ``bool`` Whether private networking support should be added * `label`: ``str`` Text label to be shown in the control panel * `auto_backups`: ``bool`` Whether automatic backups should be enabled * `app_id`: ``int`` App ID to launch if launching an application, only meaningful when the `NodeImage` is `Application` * `userdata`: ``str`` Base64 encoded cloud-init user-data * `notify_activate`: ``bool`` Whether an activation email should be sent when the server is ready * `ddos_protection`: ``bool`` Whether DDOS protection should be enabled * `reserved_ip_v4`: ``str`` IP address of the floating IP to use as the main IP of this server * `hostname`: ``str`` The hostname to assign to this server * `tag`: ``str`` The tag to assign to this server :return: The newly created node. :rtype: :class:`Node` """ params = {'DCID': location.id, 'VPSPLANID': size.id, 'OSID': image.id, 'label': name} if ex_ssh_key_ids is not None: params['SSHKEYID'] = ','.join(ex_ssh_key_ids) ex_create_attr = ex_create_attr or {} for key, value in ex_create_attr.items(): if key in self.EX_CREATE_ATTRIBUTES: if key in self.EX_CREATE_YES_NO_ATTRIBUTES: params[key] = 'yes' if value else 'no' else: if key in self.EX_CREATE_ID_ATTRIBUTES: key = self.EX_CREATE_ID_ATTRIBUTES[key] params[key] = value result = self.connection.post('/v1/server/create', params) if result.status != httplib.OK: return False subid = result.object['SUBID'] retry_count = 3 created_node = None for i in range(retry_count): try: nodes = self.list_nodes() created_node = [n for n in nodes if n.id == subid][0] except IndexError: time.sleep(1) else: break return created_node def reboot_node(self, node): params = {'SUBID': node.id} res = self.connection.post('/v1/server/reboot', params) return res.status == httplib.OK def destroy_node(self, node): params = {'SUBID': node.id} res = self.connection.post('/v1/server/destroy', params) return res.status == httplib.OK def _list_resources(self, url, tranform_func): data = self.connection.get(url).object sorted_key = sorted(data) return [tranform_func(data[key]) for key in sorted_key] def _to_node(self, data): if 'status' in data: state = self.NODE_STATE_MAP.get(data['status'], NodeState.UNKNOWN) if state == NodeState.RUNNING and \ data['power_status'] != 'running': state = NodeState.STOPPED else: state = NodeState.UNKNOWN if 'main_ip' in data and data['main_ip'] is not None: public_ips = [data['main_ip']] else: public_ips = [] extra_keys = [] extra = {} for key in extra_keys: if key in data: extra[key] = data[key] node = Node(id=data['SUBID'], name=data['label'], state=state, public_ips=public_ips, private_ips=None, extra=extra, driver=self) return node def _to_location(self, data): return NodeLocation(id=data['DCID'], name=data['name'], country=data['country'], driver=self) def _to_size(self, data): extra = { 'vcpu_count': int(data['vcpu_count']), 'plan_type': data['plan_type'], 'available_locations': data['available_locations'] } ram = int(data['ram']) disk = int(data['disk']) bandwidth = float(data['bandwidth']) price = float(data['price_per_month']) return NodeSize(id=data['VPSPLANID'], name=data['name'], ram=ram, disk=disk, bandwidth=bandwidth, price=price, extra=extra, driver=self) def _to_image(self, data): extra = {'arch': data['arch'], 'family': data['family']} return NodeImage(id=data['OSID'], name=data['name'], extra=extra, driver=self) def _to_ssh_key(self, data): return SSHKey(id=data['SSHKEYID'], name=data['name'], pub_key=data['ssh_key']) apache-libcloud-2.8.0/libcloud/compute/providers.py0000664000175000017500000001664113600144066022273 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Provider related utilities """ from __future__ import absolute_import from typing import Type from typing import Union from types import ModuleType from typing import TYPE_CHECKING from libcloud.compute.types import Provider from libcloud.common.providers import get_driver as _get_provider_driver from libcloud.common.providers import set_driver as _set_provider_driver from libcloud.compute.types import OLD_CONSTANT_TO_NEW_MAPPING from libcloud.compute.deprecated import DEPRECATED_DRIVERS if TYPE_CHECKING: # NOTE: This is needed to avoid having setup.py depend on requests from libcloud.compute.base import NodeDriver __all__ = [ "Provider", "DRIVERS", "get_driver"] DRIVERS = { Provider.AZURE: ('libcloud.compute.drivers.azure', 'AzureNodeDriver'), Provider.AZURE_ARM: ('libcloud.compute.drivers.azure_arm', 'AzureNodeDriver'), Provider.DUMMY: ('libcloud.compute.drivers.dummy', 'DummyNodeDriver'), Provider.EC2: ('libcloud.compute.drivers.ec2', 'EC2NodeDriver'), Provider.ECP: ('libcloud.compute.drivers.ecp', 'ECPNodeDriver'), Provider.ELASTICHOSTS: ('libcloud.compute.drivers.elastichosts', 'ElasticHostsNodeDriver'), Provider.SKALICLOUD: ('libcloud.compute.drivers.skalicloud', 'SkaliCloudNodeDriver'), Provider.SERVERLOVE: ('libcloud.compute.drivers.serverlove', 'ServerLoveNodeDriver'), Provider.CLOUDSIGMA: ('libcloud.compute.drivers.cloudsigma', 'CloudSigmaNodeDriver'), Provider.GCE: ('libcloud.compute.drivers.gce', 'GCENodeDriver'), Provider.GOGRID: ('libcloud.compute.drivers.gogrid', 'GoGridNodeDriver'), Provider.RACKSPACE: ('libcloud.compute.drivers.rackspace', 'RackspaceNodeDriver'), Provider.RACKSPACE_FIRST_GEN: ('libcloud.compute.drivers.rackspace', 'RackspaceFirstGenNodeDriver'), Provider.KILI: ('libcloud.compute.drivers.kili', 'KiliCloudNodeDriver'), Provider.VPSNET: ('libcloud.compute.drivers.vpsnet', 'VPSNetNodeDriver'), Provider.LINODE: ('libcloud.compute.drivers.linode', 'LinodeNodeDriver'), Provider.RIMUHOSTING: ('libcloud.compute.drivers.rimuhosting', 'RimuHostingNodeDriver'), Provider.VOXEL: ('libcloud.compute.drivers.voxel', 'VoxelNodeDriver'), Provider.SOFTLAYER: ('libcloud.compute.drivers.softlayer', 'SoftLayerNodeDriver'), Provider.EUCALYPTUS: ('libcloud.compute.drivers.ec2', 'EucNodeDriver'), Provider.OPENNEBULA: ('libcloud.compute.drivers.opennebula', 'OpenNebulaNodeDriver'), Provider.BRIGHTBOX: ('libcloud.compute.drivers.brightbox', 'BrightboxNodeDriver'), Provider.NIMBUS: ('libcloud.compute.drivers.ec2', 'NimbusNodeDriver'), Provider.BLUEBOX: ('libcloud.compute.drivers.bluebox', 'BlueboxNodeDriver'), Provider.GANDI: ('libcloud.compute.drivers.gandi', 'GandiNodeDriver'), Provider.DIMENSIONDATA: ('libcloud.compute.drivers.dimensiondata', 'DimensionDataNodeDriver'), Provider.OPENSTACK: ('libcloud.compute.drivers.openstack', 'OpenStackNodeDriver'), Provider.VCLOUD: ('libcloud.compute.drivers.vcloud', 'VCloudNodeDriver'), Provider.TERREMARK: ('libcloud.compute.drivers.vcloud', 'TerremarkDriver'), Provider.CLOUDSTACK: ('libcloud.compute.drivers.cloudstack', 'CloudStackNodeDriver'), Provider.LIBVIRT: ('libcloud.compute.drivers.libvirt_driver', 'LibvirtNodeDriver'), Provider.JOYENT: ('libcloud.compute.drivers.joyent', 'JoyentNodeDriver'), Provider.VCL: ('libcloud.compute.drivers.vcl', 'VCLNodeDriver'), Provider.KTUCLOUD: ('libcloud.compute.drivers.ktucloud', 'KTUCloudNodeDriver'), Provider.HOSTVIRTUAL: ('libcloud.compute.drivers.hostvirtual', 'HostVirtualNodeDriver'), Provider.ABIQUO: ('libcloud.compute.drivers.abiquo', 'AbiquoNodeDriver'), Provider.DIGITAL_OCEAN: ('libcloud.compute.drivers.digitalocean', 'DigitalOceanNodeDriver'), Provider.NEPHOSCALE: ('libcloud.compute.drivers.nephoscale', 'NephoscaleNodeDriver'), Provider.EXOSCALE: ('libcloud.compute.drivers.exoscale', 'ExoscaleNodeDriver'), Provider.IKOULA: ('libcloud.compute.drivers.ikoula', 'IkoulaNodeDriver'), Provider.OUTSCALE_SAS: ('libcloud.compute.drivers.ec2', 'OutscaleSASNodeDriver'), Provider.OUTSCALE_INC: ('libcloud.compute.drivers.ec2', 'OutscaleINCNodeDriver'), Provider.VSPHERE: ('libcloud.compute.drivers.vsphere', 'VSphereNodeDriver'), Provider.PROFIT_BRICKS: ('libcloud.compute.drivers.profitbricks', 'ProfitBricksNodeDriver'), Provider.VULTR: ('libcloud.compute.drivers.vultr', 'VultrNodeDriver'), Provider.AURORACOMPUTE: ('libcloud.compute.drivers.auroracompute', 'AuroraComputeNodeDriver'), Provider.CLOUDWATT: ('libcloud.compute.drivers.cloudwatt', 'CloudwattNodeDriver'), Provider.PACKET: ('libcloud.compute.drivers.packet', 'PacketNodeDriver'), Provider.ONAPP: ('libcloud.compute.drivers.onapp', 'OnAppNodeDriver'), Provider.OVH: ('libcloud.compute.drivers.ovh', 'OvhNodeDriver'), Provider.INTERNETSOLUTIONS: ('libcloud.compute.drivers.internetsolutions', 'InternetSolutionsNodeDriver'), Provider.INDOSAT: ('libcloud.compute.drivers.indosat', 'IndosatNodeDriver'), Provider.MEDONE: ('libcloud.compute.drivers.medone', 'MedOneNodeDriver'), Provider.BSNL: ('libcloud.compute.drivers.bsnl', 'BSNLNodeDriver'), Provider.NTTA: ('libcloud.compute.drivers.ntta', 'NTTAmericaNodeDriver'), Provider.ALIYUN_ECS: ('libcloud.compute.drivers.ecs', 'ECSDriver'), Provider.CLOUDSCALE: ('libcloud.compute.drivers.cloudscale', 'CloudscaleNodeDriver'), Provider.ONEANDONE: ('libcloud.compute.drivers.oneandone', 'OneAndOneNodeDriver'), Provider.UPCLOUD: ('libcloud.compute.drivers.upcloud', 'UpcloudDriver'), Provider.NTTCIS: ('libcloud.compute.drivers.nttcis', 'NttCisNodeDriver'), Provider.SCALEWAY: ('libcloud.compute.drivers.scaleway', 'ScalewayNodeDriver'), Provider.MAXIHOST: ('libcloud.compute.drivers.maxihost', 'MaxihostNodeDriver'), Provider.GRIDSCALE: ('libcloud.compute.drivers.gridscale', 'GridscaleNodeDriver') } def get_driver(provider): # type: (Union[Provider, str]) -> Type[NodeDriver] deprecated_constants = OLD_CONSTANT_TO_NEW_MAPPING return _get_provider_driver(drivers=DRIVERS, provider=provider, deprecated_providers=DEPRECATED_DRIVERS, deprecated_constants=deprecated_constants) def set_driver(provider, module, klass): # type: (Union[Provider, str], ModuleType, type) -> Type[NodeDriver] return _set_provider_driver(drivers=DRIVERS, provider=provider, module=module, klass=klass) apache-libcloud-2.8.0/libcloud/compute/ssh.py0000664000175000017500000005306213600144066021051 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Wraps multiple ways to communicate over SSH. """ from typing import Type from typing import Optional from typing import Tuple from typing import List from typing import Union from typing import cast have_paramiko = False try: import paramiko have_paramiko = True except ImportError: pass # Depending on your version of Paramiko, it may cause a deprecation # warning on Python 2.6. # Ref: https://bugs.launchpad.net/paramiko/+bug/392973 import os import time import subprocess import logging import warnings from os.path import split as psplit from os.path import join as pjoin from libcloud.utils.logging import ExtraLogFormatter from libcloud.utils.py3 import StringIO from libcloud.utils.py3 import b __all__ = [ 'BaseSSHClient', 'ParamikoSSHClient', 'ShellOutSSHClient', 'SSHCommandTimeoutError' ] SUPPORTED_KEY_TYPES_URL = 'https://libcloud.readthedocs.io/en/latest/compute/deployment.html#supported-private-ssh-key-types' # NOQA class SSHCommandTimeoutError(Exception): """ Exception which is raised when an SSH command times out. """ def __init__(self, cmd, timeout): # type: (str, float) -> None self.cmd = cmd self.timeout = timeout message = 'Command didn\'t finish in %s seconds' % (timeout) super(SSHCommandTimeoutError, self).__init__(message) def __repr__(self): return ('' % (self.cmd, self.timeout)) def __str__(self): return self.message class BaseSSHClient(object): """ Base class representing a connection over SSH/SCP to a remote node. """ def __init__(self, hostname, # type: str port=22, # type: int username='root', # type: str password=None, # type: Optional[str] key=None, # type: Optional[str] key_files=None, # type: Optional[Union[str, List[str]]] timeout=None # type: Optional[float] ): """ :type hostname: ``str`` :keyword hostname: Hostname or IP address to connect to. :type port: ``int`` :keyword port: TCP port to communicate on, defaults to 22. :type username: ``str`` :keyword username: Username to use, defaults to root. :type password: ``str`` :keyword password: Password to authenticate with or a password used to unlock a private key if a password protected key is used. :param key: Deprecated in favor of ``key_files`` argument. :type key_files: ``str`` or ``list`` :keyword key_files: A list of paths to the private key files to use. """ if key is not None: message = ('You are using deprecated "key" argument which has ' 'been replaced with "key_files" argument') warnings.warn(message, DeprecationWarning) # key_files has precedent key_files = key if not key_files else key_files self.hostname = hostname self.port = port self.username = username self.password = password self.key_files = key_files self.timeout = timeout def connect(self): # type: () -> bool """ Connect to the remote node over SSH. :return: True if the connection has been successfully established, False otherwise. :rtype: ``bool`` """ raise NotImplementedError( 'connect not implemented for this ssh client') def put(self, path, contents=None, chmod=None, mode='w'): # type: (str, Optional[Union[str, bytes]], Optional[int], str) -> str """ Upload a file to the remote node. :type path: ``str`` :keyword path: File path on the remote node. :type contents: ``str`` :keyword contents: File Contents. :type chmod: ``int`` :keyword chmod: chmod file to this after creation. :type mode: ``str`` :keyword mode: Mode in which the file is opened. :return: Full path to the location where a file has been saved. :rtype: ``str`` """ raise NotImplementedError( 'put not implemented for this ssh client') def delete(self, path): # type: (str) -> bool """ Delete/Unlink a file on the remote node. :type path: ``str`` :keyword path: File path on the remote node. :return: True if the file has been successfully deleted, False otherwise. :rtype: ``bool`` """ raise NotImplementedError( 'delete not implemented for this ssh client') def run(self, cmd): # type: (str) -> Tuple[str, str, int] """ Run a command on a remote node. :type cmd: ``str`` :keyword cmd: Command to run. :return ``list`` of [stdout, stderr, exit_status] """ raise NotImplementedError( 'run not implemented for this ssh client') def close(self): # type: () -> bool """ Shutdown connection to the remote node. :return: True if the connection has been successfully closed, False otherwise. :rtype: ``bool`` """ raise NotImplementedError( 'close not implemented for this ssh client') def _get_and_setup_logger(self): # type: () -> logging.Logger logger = logging.getLogger('libcloud.compute.ssh') path = os.getenv('LIBCLOUD_DEBUG') if path: handler = logging.FileHandler(path) handler.setFormatter(ExtraLogFormatter()) logger.addHandler(handler) logger.setLevel(logging.DEBUG) return logger class ParamikoSSHClient(BaseSSHClient): """ A SSH Client powered by Paramiko. """ # Maximum number of bytes to read at once from a socket CHUNK_SIZE = 4096 # How long to sleep while waiting for command to finish (to prevent busy # waiting) SLEEP_DELAY = 0.2 def __init__(self, hostname, # type: str port=22, # type: int username='root', # type: str password=None, # type: Optional[str] key=None, # type: Optional[str] key_files=None, # type: Optional[Union[str, List[str]]] key_material=None, # type: Optional[str] timeout=None # type: Optional[float] ): """ Authentication is always attempted in the following order: - The key passed in (if key is provided) - Any key we can find through an SSH agent (only if no password and key is provided) - Any "id_rsa" or "id_dsa" key discoverable in ~/.ssh/ (only if no password and key is provided) - Plain username/password auth, if a password was given (if password is provided) """ if key_files and key_material: raise ValueError(('key_files and key_material arguments are ' 'mutually exclusive')) super(ParamikoSSHClient, self).__init__(hostname=hostname, port=port, username=username, password=password, key=key, key_files=key_files, timeout=timeout) self.key_material = key_material self.client = paramiko.SSHClient() self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.logger = self._get_and_setup_logger() def connect(self): conninfo = {'hostname': self.hostname, 'port': self.port, 'username': self.username, 'allow_agent': False, 'look_for_keys': False} if self.password: conninfo['password'] = self.password if self.key_files: conninfo['key_filename'] = self.key_files if self.key_material: conninfo['pkey'] = self._get_pkey_object(key=self.key_material) if not self.password and not (self.key_files or self.key_material): conninfo['allow_agent'] = True conninfo['look_for_keys'] = True if self.timeout: conninfo['timeout'] = self.timeout # This is a workaround for paramiko only supporting key files in # format staring with "BEGIN RSA PRIVATE KEY". # If key_files are provided and a key looks like a PEM formatted key # we try to convert it into a format supported by paramiko if (self.key_files and not isinstance(self.key_files, (list, tuple)) and os.path.isfile(self.key_files)): with open(self.key_files, 'r') as fp: key_material = fp.read() try: pkey = self._get_pkey_object(key=key_material) except Exception: pass else: # It appears key is valid, but it was passed in in an invalid # format. Try to use the converted key directly del conninfo['key_filename'] conninfo['pkey'] = pkey extra = {'_hostname': self.hostname, '_port': self.port, '_username': self.username, '_timeout': self.timeout} if self.password: extra['_auth_method'] = 'password' else: extra['_auth_method'] = 'key_file' if self.key_files: extra['_key_file'] = self.key_files self.logger.debug('Connecting to server', extra=extra) self.client.connect(**conninfo) return True def put(self, path, contents=None, chmod=None, mode='w'): extra = {'_path': path, '_mode': mode, '_chmod': chmod} self.logger.debug('Uploading file', extra=extra) sftp = self.client.open_sftp() # less than ideal, but we need to mkdir stuff otherwise file() fails head, tail = psplit(path) if path[0] == "/": sftp.chdir("/") else: # Relative path - start from a home directory (~) sftp.chdir('.') for part in head.split("/"): if part != "": try: sftp.mkdir(part) except IOError: # so, there doesn't seem to be a way to # catch EEXIST consistently *sigh* pass sftp.chdir(part) cwd = sftp.getcwd() ak = sftp.file(tail, mode=mode) ak.write(contents) if chmod is not None: ak.chmod(chmod) ak.close() sftp.close() if path[0] == '/': file_path = path else: file_path = pjoin(cwd, path) return file_path def delete(self, path): extra = {'_path': path} self.logger.debug('Deleting file', extra=extra) sftp = self.client.open_sftp() sftp.unlink(path) sftp.close() return True def run(self, cmd, timeout=None): # type: (str, Optional[float]) -> Tuple[str, str, int] """ Note: This function is based on paramiko's exec_command() method. :param timeout: How long to wait (in seconds) for the command to finish (optional). :type timeout: ``float`` """ extra1 = {'_cmd': cmd} self.logger.debug('Executing command', extra=extra1) # Use the system default buffer size bufsize = -1 transport = self.client.get_transport() chan = transport.open_session() start_time = time.time() chan.exec_command(cmd) stdout = StringIO() stderr = StringIO() # Create a stdin file and immediately close it to prevent any # interactive script from hanging the process. stdin = chan.makefile('wb', bufsize) stdin.close() # Receive all the output # Note #1: This is used instead of chan.makefile approach to prevent # buffering issues and hanging if the executed command produces a lot # of output. # # Note #2: If you are going to remove "ready" checks inside the loop # you are going to have a bad time. Trying to consume from a channel # which is not ready will block for indefinitely. exit_status_ready = chan.exit_status_ready() if exit_status_ready: # It's possible that some data is already available when exit # status is ready stdout.write(self._consume_stdout(chan).getvalue()) stderr.write(self._consume_stderr(chan).getvalue()) while not exit_status_ready: current_time = time.time() elapsed_time = (current_time - start_time) if timeout and (elapsed_time > timeout): # TODO: Is this the right way to clean up? chan.close() raise SSHCommandTimeoutError(cmd=cmd, timeout=timeout) stdout.write(self._consume_stdout(chan).getvalue()) stderr.write(self._consume_stderr(chan).getvalue()) # We need to check the exist status here, because the command could # print some output and exit during this sleep below. exit_status_ready = chan.exit_status_ready() if exit_status_ready: break # Short sleep to prevent busy waiting time.sleep(self.SLEEP_DELAY) # Receive the exit status code of the command we ran. status = chan.recv_exit_status() # type: int stdout_str = stdout.getvalue() # type: str stderr_str = stderr.getvalue() # type: str extra2 = {'_status': status, '_stdout': stdout_str, '_stderr': stderr_str} self.logger.debug('Command finished', extra=extra2) result = (stdout_str, stderr_str, status) # type: Tuple[str, str, int] return result def close(self): self.logger.debug('Closing server connection') self.client.close() return True def _consume_stdout(self, chan): """ Try to consume stdout data from chan if it's receive ready. """ stdout = self._consume_data_from_channel( chan=chan, recv_method=chan.recv, recv_ready_method=chan.recv_ready) return stdout def _consume_stderr(self, chan): """ Try to consume stderr data from chan if it's receive ready. """ stderr = self._consume_data_from_channel( chan=chan, recv_method=chan.recv_stderr, recv_ready_method=chan.recv_stderr_ready) return stderr def _consume_data_from_channel(self, chan, recv_method, recv_ready_method): """ Try to consume data from the provided channel. Keep in mind that data is only consumed if the channel is receive ready. """ result = StringIO() result_bytes = bytearray() if recv_ready_method(): data = recv_method(self.CHUNK_SIZE) result_bytes += b(data) while data: ready = recv_ready_method() if not ready: break data = recv_method(self.CHUNK_SIZE) result_bytes += b(data) # We only decode data at the end because a single chunk could contain # a part of multi byte UTF-8 character (whole multi bytes character # could be split over two chunks) result.write(result_bytes.decode('utf-8')) return result def _get_pkey_object(self, key, passpharse=None): """ Try to detect private key type and return paramiko.PKey object. # NOTE: Paramiko only supports key in PKCS#1 PEM format. """ for cls, key_type in [(paramiko.RSAKey, 'RSA'), (paramiko.DSSKey, 'DSA'), (paramiko.ECDSAKey, 'EC')]: # Work around for paramiko not recognizing keys which start with # "----BEGIN PRIVATE KEY-----" # Since key is already in PEM format, we just try changing the # header and footer key_split = key.strip().splitlines() if (key_split[0] == '-----BEGIN PRIVATE KEY-----' and key_split[-1] == '-----END PRIVATE KEY-----'): key_split[0] = '-----BEGIN %s PRIVATE KEY-----' % (key_type) key_split[-1] = '-----END %s PRIVATE KEY-----' % (key_type) key_value = '\n'.join(key_split) else: # Already a valid key, us it as is key_value = key try: key = cls.from_private_key(StringIO(key_value), passpharse) except (paramiko.ssh_exception.SSHException, AssertionError): # Invalid key, try other key type pass else: return key msg = ('Invalid or unsupported key type (only RSA, DSS and ECDSA keys' ' in PEM format are supported). For more information on ' ' supported key file types, see %s' % (SUPPORTED_KEY_TYPES_URL)) raise paramiko.ssh_exception.SSHException(msg) class ShellOutSSHClient(BaseSSHClient): """ This client shells out to "ssh" binary to run commands on the remote server. Note: This client should not be used in production. """ def __init__(self, hostname, # type: str port=22, # type: int username='root', # type: str password=None, # type: Optional[str] key=None, # type: Optional[str] key_files=None, # type: Optional[str] timeout=None # type: Optional[float] ): super(ShellOutSSHClient, self).__init__(hostname=hostname, port=port, username=username, password=password, key=key, key_files=key_files, timeout=timeout) if self.password: raise ValueError('ShellOutSSHClient only supports key auth') child = subprocess.Popen(['ssh'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) child.communicate() if child.returncode == 127: raise ValueError('ssh client is not available') self.logger = self._get_and_setup_logger() def connect(self): """ This client doesn't support persistent connections establish a new connection every time "run" method is called. """ return True def run(self, cmd): return self._run_remote_shell_command([cmd]) def put(self, path, contents=None, chmod=None, mode='w'): if mode == 'w': redirect = '>' elif mode == 'a': redirect = '>>' else: raise ValueError('Invalid mode: ' + mode) cmd = ['echo "%s" %s %s' % (contents, redirect, path)] self._run_remote_shell_command(cmd) return path def delete(self, path): cmd = ['rm', '-rf', path] self._run_remote_shell_command(cmd) return True def close(self): return True def _get_base_ssh_command(self): # type: () -> List[str] cmd = ['ssh'] if self.key_files: self.key_files = cast(str, self.key_files) cmd += ['-i', self.key_files] if self.timeout: cmd += ['-oConnectTimeout=%s' % (self.timeout)] cmd += ['%s@%s' % (self.username, self.hostname)] return cmd def _run_remote_shell_command(self, cmd): # type: (List[str]) -> Tuple[str, str, int] """ Run a command on a remote server. :param cmd: Command to run. :type cmd: ``list`` of ``str`` :return: Command stdout, stderr and status code. :rtype: ``tuple`` """ base_cmd = self._get_base_ssh_command() full_cmd = base_cmd + [' '.join(cmd)] self.logger.debug('Executing command: "%s"' % (' '.join(full_cmd))) child = subprocess.Popen(full_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = child.communicate() stdout_str = cast(str, stdout) stderr_str = cast(str, stdout) return (stdout_str, stderr_str, child.returncode) class MockSSHClient(BaseSSHClient): pass SSHClient = ParamikoSSHClient # type: Type[BaseSSHClient] if not have_paramiko: SSHClient = MockSSHClient # type: ignore apache-libcloud-2.8.0/libcloud/compute/types.py0000664000175000017500000003117013600144066021414 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Base types used by other parts of libcloud """ from typing import Union from typing import cast from enum import Enum from libcloud.utils.py3 import _real_unicode from libcloud.common.types import LibcloudError, MalformedResponseError from libcloud.common.types import InvalidCredsError, InvalidCredsException __all__ = [ "Provider", "NodeState", "DeploymentError", "DeploymentException", # @@TR: should the unused imports below be exported? "LibcloudError", "MalformedResponseError", "InvalidCredsError", "InvalidCredsException", "OLD_CONSTANT_TO_NEW_MAPPING" ] class Type(Enum): @classmethod def tostring(cls, value): # type: (Union[Enum, str]) -> str """Return the string representation of the state object attribute :param str value: the state object to turn into string :return: the uppercase string that represents the state object :rtype: str """ value = cast(Enum, value) return str(value._value_).upper() @classmethod def fromstring(cls, value): # type: (str) -> str """Return the state object attribute that matches the string :param str value: the string to look up :return: the state object attribute that matches the string :rtype: str """ return getattr(cls, value.upper(), None) """ NOTE: These methods are here for backward compatibility reasons where Type values were simple strings and Type didn't inherit from Enum. """ def __eq__(self, other): if isinstance(other, Type): return other.value == self.value elif isinstance(other, (str, _real_unicode)): return self.value == other return super(Type, self).__eq__(other) def upper(self): return self.value.upper() def lower(self): return self.value.lower() def __ne__(self, other): return not self.__eq__(other) def __str__(self): return str(self.value) def __repr__(self): return self.value def __hash__(self): return id(self) class Provider(Type): """ Defines for each of the supported providers Non-Dummy drivers are sorted in alphabetical order. Please preserve this ordering when adding new drivers. :cvar DUMMY: Example provider :cvar ABIQUO: Abiquo driver :cvar ALIYUN_ECS: Aliyun ECS driver. :cvar AURORACOMPUTE: Aurora Compute driver. :cvar AZURE: Azure (classic) driver. :cvar AZURE_ARM: Azure Resource Manager (modern) driver. :cvar BLUEBOX: Bluebox :cvar CLOUDSIGMA: CloudSigma :cvar CLOUDSCALE: cloudscale.ch :cvar CLOUDSTACK: CloudStack :cvar DIMENSIONDATA: Dimension Data Cloud :cvar EC2: Amazon AWS. :cvar ECP: Enomaly :cvar ELASTICHOSTS: ElasticHosts.com :cvar EXOSCALE: Exoscale driver. :cvar GCE: Google Compute Engine :cvar GOGRID: GoGrid :cvar GRIDSCALE: gridscale :cvar GRIDSPOT: Gridspot driver :cvar IBM: IBM Developer Cloud :cvar IKOULA: Ikoula driver. :cvar JOYENT: Joyent driver :cvar KTUCLOUD: kt ucloud driver :cvar LIBVIRT: Libvirt driver :cvar LINODE: Linode.com :cvar NEPHOSCALE: NephoScale driver :cvar NIMBUS: Nimbus :cvar NINEFOLD: Ninefold :cvar NTTC-CIS: NTT Communications CIS :cvar OPENNEBULA: OpenNebula.org :cvar OPSOURCE: Opsource Cloud :cvar OUTSCALE_INC: Outscale INC driver. :cvar OUTSCALE_SAS: Outscale SAS driver. :cvar PROFIT_BRICKS: ProfitBricks driver. :cvar RACKSPACE: Rackspace next-gen OpenStack based Cloud Servers :cvar RACKSPACE_FIRST_GEN: Rackspace First Gen Cloud Servers :cvar RIMUHOSTING: RimuHosting.com :cvar TERREMARK: Terremark :cvar UPCLOUD: UpCloud :cvar VCL: VCL driver :cvar VCLOUD: vmware vCloud :cvar VPSNET: VPS.net :cvar VULTR: vultr driver. """ AZURE = 'azure' AZURE_ARM = 'azure_arm' DUMMY = 'dummy' ABIQUO = 'abiquo' ALIYUN_ECS = 'aliyun_ecs' AURORACOMPUTE = 'aurora_compute' BLUEBOX = 'bluebox' BRIGHTBOX = 'brightbox' BSNL = 'bsnl' CISCOCCS = 'ciscoccs' CLOUDFRAMES = 'cloudframes' CLOUDSIGMA = 'cloudsigma' CLOUDSCALE = 'cloudscale' CLOUDSTACK = 'cloudstack' DIGITAL_OCEAN = 'digitalocean' DIMENSIONDATA = 'dimensiondata' EC2 = 'ec2' ECP = 'ecp' ELASTICHOSTS = 'elastichosts' EUCALYPTUS = 'eucalyptus' EXOSCALE = 'exoscale' GANDI = 'gandi' GCE = 'gce' GOGRID = 'gogrid' GRIDSCALE = 'gridscale' GRIDSPOT = 'gridspot' HOSTVIRTUAL = 'hostvirtual' IBM = 'ibm' IKOULA = 'ikoula' INDOSAT = 'indosat' INTERNETSOLUTIONS = 'internetsolutions' JOYENT = 'joyent' KTUCLOUD = 'ktucloud' LIBVIRT = 'libvirt' LINODE = 'linode' MAXIHOST = 'maxihost' MEDONE = 'medone' NEPHOSCALE = 'nephoscale' NIMBUS = 'nimbus' NINEFOLD = 'ninefold' NTTA = 'ntta' NTTCIS = 'nttcis' ONEANDONE = 'oneandone' OPENNEBULA = 'opennebula' OPENSTACK = 'openstack' OPSOURCE = 'opsource' OUTSCALE_INC = 'outscale_inc' OUTSCALE_SAS = 'outscale_sas' OVH = 'ovh' PACKET = 'packet' PROFIT_BRICKS = 'profitbricks' RACKSPACE = 'rackspace' RACKSPACE_FIRST_GEN = 'rackspace_first_gen' RIMUHOSTING = 'rimuhosting' RUNABOVE = 'runabove' SCALEWAY = 'scaleway' SERVERLOVE = 'serverlove' SKALICLOUD = 'skalicloud' SOFTLAYER = 'softlayer' TERREMARK = 'terremark' UPCLOUD = 'upcloud' VCL = 'vcl' VCLOUD = 'vcloud' VOXEL = 'voxel' VPSNET = 'vpsnet' VSPHERE = 'vsphere' VULTR = 'vultr' # OpenStack based providers CLOUDWATT = 'cloudwatt' HPCLOUD = 'hpcloud' KILI = 'kili' ONAPP = 'onapp' # Deprecated constants which aren't supported anymore RACKSPACE_UK = 'rackspace_uk' RACKSPACE_NOVA_BETA = 'rackspace_nova_beta' RACKSPACE_NOVA_DFW = 'rackspace_nova_dfw' RACKSPACE_NOVA_LON = 'rackspace_nova_lon' RACKSPACE_NOVA_ORD = 'rackspace_nova_ord' EC2_US_EAST = 'ec2_us_east' EC2_US_EAST_OHIO = 'ec2_us_east_ohio' EC2_EU = 'ec2_eu_west' # deprecated name EC2_EU_WEST = 'ec2_eu_west' EC2_EU_WEST2 = 'ec2_eu_west_london' EC2_US_WEST = 'ec2_us_west' EC2_AP_SOUTHEAST = 'ec2_ap_southeast' EC2_AP_NORTHEAST = 'ec2_ap_northeast' EC2_AP_NORTHEAST1 = 'ec2_ap_northeast_1' EC2_AP_NORTHEAST2 = 'ec2_ap_northeast_2' EC2_US_WEST_OREGON = 'ec2_us_west_oregon' EC2_SA_EAST = 'ec2_sa_east' EC2_AP_SOUTHEAST2 = 'ec2_ap_southeast_2' EC2_CA_CENTRAL1 = 'ec2_ca_central_1' ELASTICHOSTS_UK1 = 'elastichosts_uk1' ELASTICHOSTS_UK2 = 'elastichosts_uk2' ELASTICHOSTS_US1 = 'elastichosts_us1' ELASTICHOSTS_US2 = 'elastichosts_us2' ELASTICHOSTS_US3 = 'elastichosts_us3' ELASTICHOSTS_CA1 = 'elastichosts_ca1' ELASTICHOSTS_AU1 = 'elastichosts_au1' ELASTICHOSTS_CN1 = 'elastichosts_cn1' CLOUDSIGMA_US = 'cloudsigma_us' # Removed # SLICEHOST = 'slicehost' DEPRECATED_RACKSPACE_PROVIDERS = [Provider.RACKSPACE_UK, Provider.RACKSPACE_NOVA_BETA, Provider.RACKSPACE_NOVA_DFW, Provider.RACKSPACE_NOVA_LON, Provider.RACKSPACE_NOVA_ORD] OLD_CONSTANT_TO_NEW_MAPPING = { # Rackspace Provider.RACKSPACE_UK: Provider.RACKSPACE_FIRST_GEN, Provider.RACKSPACE_NOVA_BETA: Provider.RACKSPACE, Provider.RACKSPACE_NOVA_DFW: Provider.RACKSPACE, Provider.RACKSPACE_NOVA_LON: Provider.RACKSPACE, Provider.RACKSPACE_NOVA_ORD: Provider.RACKSPACE, # AWS Provider.EC2_US_EAST: Provider.EC2, Provider.EC2_US_EAST_OHIO: Provider.EC2, Provider.EC2_EU: Provider.EC2, Provider.EC2_EU_WEST: Provider.EC2, Provider.EC2_EU_WEST2: Provider.EC2, Provider.EC2_US_WEST: Provider.EC2, Provider.EC2_AP_SOUTHEAST: Provider.EC2, Provider.EC2_AP_SOUTHEAST2: Provider.EC2, Provider.EC2_AP_NORTHEAST: Provider.EC2, Provider.EC2_AP_NORTHEAST1: Provider.EC2, Provider.EC2_AP_NORTHEAST2: Provider.EC2, Provider.EC2_US_WEST_OREGON: Provider.EC2, Provider.EC2_SA_EAST: Provider.EC2, Provider.EC2_CA_CENTRAL1: Provider.EC2, # ElasticHosts Provider.ELASTICHOSTS_UK1: Provider.ELASTICHOSTS, Provider.ELASTICHOSTS_UK2: Provider.ELASTICHOSTS, Provider.ELASTICHOSTS_US1: Provider.ELASTICHOSTS, Provider.ELASTICHOSTS_US2: Provider.ELASTICHOSTS, Provider.ELASTICHOSTS_US3: Provider.ELASTICHOSTS, Provider.ELASTICHOSTS_CA1: Provider.ELASTICHOSTS, Provider.ELASTICHOSTS_AU1: Provider.ELASTICHOSTS, Provider.ELASTICHOSTS_CN1: Provider.ELASTICHOSTS, } class NodeState(Type): """ Standard states for a node :cvar RUNNING: Node is running. :cvar STARTING: Node is starting up. :cvar REBOOTING: Node is rebooting. :cvar TERMINATED: Node is terminated. This node can't be started later on. :cvar STOPPING: Node is currently trying to stop. :cvar STOPPED: Node is stopped. This node can be started later on. :cvar PENDING: Node is pending. :cvar SUSPENDED: Node is suspended. :cvar ERROR: Node is an error state. Usually no operations can be performed on the node once it ends up in the error state. :cvar PAUSED: Node is paused. :cvar RECONFIGURING: Node is being reconfigured. :cvar UNKNOWN: Node state is unknown. """ RUNNING = 'running' STARTING = 'starting' REBOOTING = 'rebooting' TERMINATED = 'terminated' PENDING = 'pending' UNKNOWN = 'unknown' STOPPING = 'stopping' STOPPED = 'stopped' SUSPENDED = 'suspended' ERROR = 'error' PAUSED = 'paused' RECONFIGURING = 'reconfiguring' MIGRATING = 'migrating' NORMAL = 'normal' UPDATING = 'updating' class StorageVolumeState(Type): """ Standard states of a StorageVolume """ AVAILABLE = 'available' ERROR = 'error' INUSE = 'inuse' CREATING = 'creating' DELETING = 'deleting' DELETED = 'deleted' BACKUP = 'backup' ATTACHING = 'attaching' UNKNOWN = 'unknown' MIGRATING = 'migrating' UPDATING = 'updating' class VolumeSnapshotState(Type): """ Standard states of VolumeSnapshots """ AVAILABLE = 'available' ERROR = 'error' CREATING = 'creating' DELETING = 'deleting' RESTORING = 'restoring' UNKNOWN = 'unknown' UPDATING = 'updating' class NodeImageMemberState(Type): """ Standard states of VolumeSnapshots """ ACCEPTED = 'accepted' PENDING = 'pending' REJECTED = 'rejected' class Architecture(object): """ Image and size architectures. :cvar I386: i386 (32 bt) :cvar X86_64: x86_64 (64 bit) """ I386 = 0 X86_X64 = 1 class DeploymentError(LibcloudError): """ Exception used when a Deployment Task failed. :ivar node: :class:`Node` on which this exception happened, you might want to call :func:`Node.destroy` """ def __init__(self, node, original_exception=None, driver=None): self.node = node self.value = original_exception self.driver = driver def __str__(self): return self.__repr__() def __repr__(self): return (('' % (self.node.id, str(self.value), str(self.driver)))) class KeyPairError(LibcloudError): error_type = 'KeyPairError' def __init__(self, name, driver): self.name = name self.value = 'Key pair with name %s does not exist' % (name) super(KeyPairError, self).__init__(value=self.value, driver=driver) def __str__(self): return self.__repr__() def __repr__(self): return ('<%s name=%s, value=%s, driver=%s>' % (self.error_type, self.name, self.value, self.driver.name)) class KeyPairDoesNotExistError(KeyPairError): error_type = 'KeyPairDoesNotExistError' """Deprecated alias of :class:`DeploymentException`""" DeploymentException = DeploymentError apache-libcloud-2.8.0/libcloud/container/0000775000175000017500000000000013600223624020200 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/container/__init__.py0000664000175000017500000000000013535474530022312 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/container/base.py0000664000175000017500000003001713535474530021500 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement from libcloud.common.base import ConnectionUserAndKey, BaseDriver __all__ = [ 'Container', 'ContainerImage', 'ContainerCluster', 'ClusterLocation', 'ContainerDriver' ] class Container(object): """ Container. """ def __init__(self, id, name, image, state, ip_addresses, driver, extra=None): """ :param id: Container id. :type id: ``str`` :param name: The name of the container. :type name: ``str`` :param image: The image this container was deployed using. :type image: :class:`.ContainerImage` :param state: The state of the container, e.g. running :type state: :class:`libcloud.container.types.ContainerState` :param ip_addresses: A list of IP addresses for this container :type ip_addresses: ``list`` of ``str`` :param driver: ContainerDriver instance. :type driver: :class:`.ContainerDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.name = name self.image = image self.state = state self.ip_addresses = ip_addresses self.driver = driver self.extra = extra or {} def start(self): return self.driver.start_container(container=self) def stop(self): return self.driver.stop_container(container=self) def restart(self): return self.driver.restart_container(container=self) def destroy(self): return self.driver.destroy_container(container=self) def __repr__(self): return ('' % (self.id, self.name, self.state, self.driver.name)) class ContainerImage(object): """ Container Image. """ def __init__(self, id, name, path, version, driver, extra=None): """ :param id: Container Image id. :type id: ``str`` :param name: The name of the image. :type name: ``str`` :param path: The path to the image :type path: ``str`` :param version: The version of the image :type version: ``str`` :param driver: ContainerDriver instance. :type driver: :class:`.ContainerDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.name = name self.path = path self.version = version self.driver = driver self.extra = extra or {} def deploy(self, name, parameters, *args, **kwargs): return self.driver.deploy_container(name=name, image=self, parameters=parameters, *args, **kwargs) def __repr__(self): return ('' % (self.id, self.name, self.path)) class ContainerCluster(object): """ A cluster group for containers """ def __init__(self, id, name, driver, extra=None): """ :param id: Container Image id. :type id: ``str`` :param name: The name of the image. :type name: ``str`` :param driver: ContainerDriver instance. :type driver: :class:`.ContainerDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.name = name self.driver = driver self.extra = extra or {} def list_containers(self): return self.driver.list_containers(cluster=self) def destroy(self): return self.driver.destroy_cluster(cluster=self) def __repr__(self): return ('' % (self.id, self.name, self.driver.name)) class ClusterLocation(object): """ A physical location where clusters can be. >>> from libcloud.container.drivers.dummy import DummyContainerDriver >>> driver = DummyContainerDriver(0) >>> location = driver.list_locations()[0] >>> location.country 'US' """ def __init__(self, id, name, country, driver): """ :param id: Location ID. :type id: ``str`` :param name: Location name. :type name: ``str`` :param country: Location country. :type country: ``str`` :param driver: Driver this location belongs to. :type driver: :class:`.ContainerDriver` """ self.id = str(id) self.name = name self.country = country self.driver = driver def __repr__(self): return (('') % (self.id, self.name, self.country, self.driver.name)) class ContainerDriver(BaseDriver): """ A base ContainerDriver class to derive from This class is always subclassed by a specific driver. """ connectionCls = ConnectionUserAndKey name = None website = None supports_clusters = False """ Whether the driver supports containers being deployed into clusters """ def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs): """ :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Some providers only support HTTPS, and it is on by default. :type secure: ``bool`` :param host: Override hostname used for connections. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :return: ``None`` """ super(ContainerDriver, self).__init__( key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def install_image(self, path): """ Install a container image from a remote path. :param path: Path to the container image :type path: ``str`` :rtype: :class:`.ContainerImage` """ raise NotImplementedError( 'install_image not implemented for this driver') def list_images(self): """ List the installed container images :rtype: ``list`` of :class:`.ContainerImage` """ raise NotImplementedError( 'list_images not implemented for this driver') def list_containers(self, image=None, cluster=None): """ List the deployed container images :param image: Filter to containers with a certain image :type image: :class:`.ContainerImage` :param cluster: Filter to containers in a cluster :type cluster: :class:`.ContainerCluster` :rtype: ``list`` of :class:`.Container` """ raise NotImplementedError( 'list_containers not implemented for this driver') def deploy_container(self, name, image, cluster=None, parameters=None, start=True): """ Deploy an installed container image :param name: The name of the new container :type name: ``str`` :param image: The container image to deploy :type image: :class:`.ContainerImage` :param cluster: The cluster to deploy to, None is default :type cluster: :class:`.ContainerCluster` :param parameters: Container Image parameters :type parameters: ``str`` :param start: Start the container on deployment :type start: ``bool`` :rtype: :class:`.Container` """ raise NotImplementedError( 'deploy_container not implemented for this driver') def get_container(self, id): """ Get a container by ID :param id: The ID of the container to get :type id: ``str`` :rtype: :class:`.Container` """ raise NotImplementedError( 'get_container not implemented for this driver') def start_container(self, container): """ Start a deployed container :param container: The container to start :type container: :class:`.Container` :rtype: :class:`.Container` """ raise NotImplementedError( 'start_container not implemented for this driver') def stop_container(self, container): """ Stop a deployed container :param container: The container to stop :type container: :class:`.Container` :rtype: :class:`.Container` """ raise NotImplementedError( 'stop_container not implemented for this driver') def restart_container(self, container): """ Restart a deployed container :param container: The container to restart :type container: :class:`.Container` :rtype: :class:`.Container` """ raise NotImplementedError( 'restart_container not implemented for this driver') def destroy_container(self, container): """ Destroy a deployed container :param container: The container to destroy :type container: :class:`.Container` :rtype: :class:`.Container` """ raise NotImplementedError( 'destroy_container not implemented for this driver') def list_locations(self): """ Get a list of potential locations to deploy clusters into :rtype: ``list`` of :class:`.ClusterLocation` """ raise NotImplementedError( 'list_locations not implemented for this driver') def create_cluster(self, name, location=None): """ Create a container cluster :param name: The name of the cluster :type name: ``str`` :param location: The location to create the cluster in :type location: :class:`.ClusterLocation` :rtype: :class:`.ContainerCluster` """ raise NotImplementedError( 'create_cluster not implemented for this driver') def destroy_cluster(self, cluster): """ Delete a cluster :return: ``True`` if the destroy was successful, otherwise ``False``. :rtype: ``bool`` """ raise NotImplementedError( 'destroy_cluster not implemented for this driver') def list_clusters(self, location=None): """ Get a list of potential locations to deploy clusters into :param location: The location to search in :type location: :class:`.ClusterLocation` :rtype: ``list`` of :class:`.ContainerCluster` """ raise NotImplementedError( 'list_clusters not implemented for this driver') def get_cluster(self, id): """ Get a cluster by ID :param id: The ID of the cluster to get :type id: ``str`` :rtype: :class:`.ContainerCluster` """ raise NotImplementedError( 'list_clusters not implemented for this driver') apache-libcloud-2.8.0/libcloud/container/drivers/0000775000175000017500000000000013600223624021656 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/container/drivers/__init__.py0000664000175000017500000000000013535474530023770 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/container/drivers/docker.py0000664000175000017500000006422713600144066023514 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import datetime import shlex import re import os try: import simplejson as json except Exception: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.base import JsonResponse, ConnectionUserAndKey from libcloud.common.base import KeyCertificateConnection from libcloud.common.types import InvalidCredsError from libcloud.container.base import (Container, ContainerDriver, ContainerImage) from libcloud.container.providers import Provider from libcloud.container.types import ContainerState VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] class DockerResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_body(self): if len(self.body) == 0 and not self.parse_zero_length_body: return self.body try: # error responses are tricky in Docker. Eg response could be # an error, but response status could still be 200 content_type = self.headers.get('content-type', 'application/json') if content_type == 'application/json' or content_type == '': if self.headers.get('transfer-encoding') == 'chunked' and \ 'fromImage' in self.request.url: body = [json.loads(chunk) for chunk in self.body.strip().replace('\r', '').split('\n')] else: body = json.loads(self.body) else: body = self.body except ValueError: m = re.search('Error: (.+?)"', self.body) if m: error_msg = m.group(1) raise Exception(error_msg) else: raise Exception( 'ConnectionError: Failed to parse JSON response') return body def parse_error(self): if self.status == 401: raise InvalidCredsError('Invalid credentials') return self.body def success(self): return self.status in self.valid_response_codes class DockerException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "DockerException %s %s" % (self.code, self.message) class DockerConnection(ConnectionUserAndKey): responseCls = DockerResponse timeout = 60 def add_default_headers(self, headers): """ Add parameters that are necessary for every request If user and password are specified, include a base http auth header """ headers['Content-Type'] = 'application/json' if self.user_id and self.key: user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) return headers class DockertlsConnection(KeyCertificateConnection): responseCls = DockerResponse def __init__(self, key, secret, secure=True, host='localhost', port=4243, key_file='', cert_file='', **kwargs): super(DockertlsConnection, self).__init__(key_file=key_file, cert_file=cert_file, secure=secure, host=host, port=port, url=None, proxy_url=None, timeout=None, backoff=None, retry_delay=None) if key_file: keypath = os.path.expanduser(key_file) is_file_path = os.path.exists(keypath) and os.path.isfile(keypath) if not is_file_path: raise InvalidCredsError( 'You need an key PEM file to authenticate with ' 'Docker tls. This can be found in the server.' ) self.key_file = key_file certpath = os.path.expanduser(cert_file) is_file_path = os.path.exists( certpath) and os.path.isfile(certpath) if not is_file_path: raise InvalidCredsError( 'You need an certificate PEM file to authenticate with ' 'Docker tls. This can be found in the server.' ) self.cert_file = cert_file def add_default_headers(self, headers): headers['Content-Type'] = 'application/json' return headers class DockerContainerDriver(ContainerDriver): """ Docker container driver class. >>> from libcloud.container.providers import get_driver >>> driver = get_driver('docker') >>> conn = driver(host='198.61.239.128', port=4243) >>> conn.list_containers() or connecting to http basic auth protected https host: >>> conn = driver('user', 'pass', host='https://198.61.239.128', port=443) connect with tls authentication, by providing a hostname, port, a private key file (.pem) and certificate (.pem) file >>> conn = driver(host='https://198.61.239.128', >>> port=4243, key_file='key.pem', cert_file='cert.pem') """ type = Provider.DOCKER name = 'Docker' website = 'http://docker.io' connectionCls = DockerConnection supports_clusters = False version = '1.24' def __init__(self, key='', secret='', secure=False, host='localhost', port=4243, key_file=None, cert_file=None): """ :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Some providers only support HTTPS, and it is on by default. :type secure: ``bool`` :param host: Override hostname used for connections. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :param key_file: Path to private key for TLS connection (optional) :type key_file: ``str`` :param cert_file: Path to public key for TLS connection (optional) :type cert_file: ``str`` :return: ``None`` """ if key_file: self.connectionCls = DockertlsConnection self.key_file = key_file self.cert_file = cert_file secure = True if host.startswith('https://'): secure = True # strip the prefix prefixes = ['http://', 'https://'] for prefix in prefixes: if host.startswith(prefix): host = host.strip(prefix) super(DockerContainerDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, key_file=key_file, cert_file=cert_file) if key_file or cert_file: # docker tls authentication- # https://docs.docker.com/articles/https/ # We pass two files, a key_file with the # private key and cert_file with the certificate # libcloud will handle them through LibcloudHTTPSConnection if not (key_file and cert_file): raise Exception( 'Needs both private key file and ' 'certificate file for tls authentication') self.connection.secure = secure self.connection.host = host self.connection.port = port # set API version self.version = self._get_api_version() def _ex_connection_class_kwargs(self): kwargs = {} if hasattr(self, 'key_file'): kwargs['key_file'] = self.key_file if hasattr(self, 'cert_file'): kwargs['cert_file'] = self.cert_file return kwargs def install_image(self, path): """ Install a container image from a remote path. :param path: Path to the container image :type path: ``str`` :rtype: :class:`libcloud.container.base.ContainerImage` """ payload = { } data = json.dumps(payload) result = self.connection.request('/v%s/images/create?fromImage=%s' % (self.version, path), data=data, method='POST') if "errorDetail" in result.body: raise DockerException(None, result.body) image_id = None # the response is slightly different if the image is already present # and it's not downloaded. both messages below indicate that the image # is available for use to the daemon if re.search(r'Downloaded newer image', result.body) or \ re.search(r'"Status: Image is up to date', result.body): if re.search(r'sha256:(?P[a-z0-9]{64})', result.body): image_id = re.findall(r'sha256:(?P[a-z0-9]{64})', result.body)[-1] # if there is a failure message or if there is not an image id in the # response then throw an exception. if image_id is None: raise DockerException(None, 'failed to install image') image = ContainerImage( id=image_id, name=path, path=path, version=None, driver=self.connection.driver, extra={}) return image def list_images(self): """ List the installed container images :rtype: ``list`` of :class:`libcloud.container.base.ContainerImage` """ result = self.connection.request('/v%s/images/json' % (self.version)).object images = [] for image in result: try: name = image.get('RepoTags')[0] except Exception: name = image.get('Id') images.append(ContainerImage( id=image.get('Id'), name=name, path=name, version=None, driver=self.connection.driver, extra={ "created": image.get('Created'), "size": image.get('Size'), "virtual_size": image.get('VirtualSize'), }, )) return images def list_containers(self, image=None, all=True): """ List the deployed container images :param image: Filter to containers with a certain image :type image: :class:`libcloud.container.base.ContainerImage` :param all: Show all container (including stopped ones) :type all: ``bool`` :rtype: ``list`` of :class:`libcloud.container.base.Container` """ if all: ex = '?all=1' else: ex = '' try: result = self.connection.request( "/v%s/containers/json%s" % (self.version, ex)).object except Exception as exc: errno = getattr(exc, 'errno', None) if errno == 111: raise DockerException( errno, 'Make sure docker host is accessible' 'and the API port is correct') raise containers = [self._to_container(value) for value in result] return containers def deploy_container(self, name, image, parameters=None, start=True, command=None, hostname=None, user='', stdin_open=True, tty=True, mem_limit=0, ports=None, environment=None, dns=None, volumes=None, volumes_from=None, network_disabled=False, entrypoint=None, cpu_shares=None, working_dir='', domainname=None, memswap_limit=0, port_bindings=None, network_mode='bridge', labels=None): """ Deploy an installed container image For details on the additional parameters see : http://bit.ly/1PjMVKV :param name: The name of the new container :type name: ``str`` :param image: The container image to deploy :type image: :class:`libcloud.container.base.ContainerImage` :param parameters: Container Image parameters :type parameters: ``str`` :param start: Start the container on deployment :type start: ``bool`` :rtype: :class:`Container` """ command = shlex.split(str(command)) if port_bindings is None: port_bindings = {} params = { 'name': name } payload = { 'Hostname': hostname, 'Domainname': domainname, 'ExposedPorts': ports, 'User': user, 'Tty': tty, 'OpenStdin': stdin_open, 'StdinOnce': False, 'Memory': mem_limit, 'AttachStdin': True, 'AttachStdout': True, 'AttachStderr': True, 'Env': environment, 'Cmd': command, 'Dns': dns, 'Image': image.name, 'Volumes': volumes, 'VolumesFrom': volumes_from, 'NetworkDisabled': network_disabled, 'Entrypoint': entrypoint, 'CpuShares': cpu_shares, 'WorkingDir': working_dir, 'MemorySwap': memswap_limit, 'PublishAllPorts': True, 'PortBindings': port_bindings, 'NetworkMode': network_mode, 'Labels': labels, } data = json.dumps(payload) try: result = self.connection.request('/v%s/containers/create' % (self.version), data=data, params=params, method='POST') except Exception as e: message = e.message or str(e) if message.startswith('No such image:'): raise DockerException(None, 'No such image: %s' % image.name) else: raise DockerException(None, e) id_ = result.object['Id'] payload = { 'Binds': [], 'PublishAllPorts': True, 'PortBindings': port_bindings, } data = json.dumps(payload) if start: if float(self._get_api_version()) > 1.22: result = self.connection.request( '/v%s/containers/%s/start' % (self.version, id_), method='POST') else: result = self.connection.request( '/v%s/containers/%s/start' % (self.version, id_), data=data, method='POST') return self.get_container(id_) def get_container(self, id): """ Get a container by ID :param id: The ID of the container to get :type id: ``str`` :rtype: :class:`libcloud.container.base.Container` """ result = self.connection.request("/v%s/containers/%s/json" % (self.version, id)).object return self._to_container(result) def start_container(self, container): """ Start a container :param container: The container to be started :type container: :class:`libcloud.container.base.Container` :return: The container refreshed with current data :rtype: :class:`libcloud.container.base.Container` """ if float(self._get_api_version()) > 1.22: result = self.connection.request( '/v%s/containers/%s/start' % (self.version, container.id), method='POST') else: payload = { 'Binds': [], 'PublishAllPorts': True, } data = json.dumps(payload) result = self.connection.request( '/v%s/containers/%s/start' % (self.version, container.id), method='POST', data=data) if result.status in VALID_RESPONSE_CODES: return self.get_container(container.id) else: raise DockerException(result.status, 'failed to start container') def stop_container(self, container): """ Stop a container :param container: The container to be stopped :type container: :class:`libcloud.container.base.Container` :return: The container refreshed with current data :rtype: :class:`libcloud.container.base.Container` """ result = self.connection.request('/v%s/containers/%s/stop' % (self.version, container.id), method='POST') if result.status in VALID_RESPONSE_CODES: return self.get_container(container.id) else: raise DockerException(result.status, 'failed to stop container') def restart_container(self, container): """ Restart a container :param container: The container to be stopped :type container: :class:`libcloud.container.base.Container` :return: The container refreshed with current data :rtype: :class:`libcloud.container.base.Container` """ data = json.dumps({'t': 10}) # number of seconds to wait before killing the container result = self.connection.request('/v%s/containers/%s/restart' % (self.version, container.id), data=data, method='POST') if result.status in VALID_RESPONSE_CODES: return self.get_container(container.id) else: raise DockerException(result.status, 'failed to restart container') def destroy_container(self, container): """ Remove a container :param container: The container to be destroyed :type container: :class:`libcloud.container.base.Container` :return: True if the destroy was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request('/v%s/containers/%s' % (self.version, container.id), method='DELETE') return result.status in VALID_RESPONSE_CODES def ex_list_processes(self, container): """ List processes running inside a container :param container: The container to list processes for. :type container: :class:`libcloud.container.base.Container` :rtype: ``str`` """ result = self.connection.request("/v%s/containers/%s/top" % (self.version, container.id)).object return result def ex_rename_container(self, container, name): """ Rename a container :param container: The container to be renamed :type container: :class:`libcloud.container.base.Container` :param name: The new name :type name: ``str`` :rtype: :class:`libcloud.container.base.Container` """ result = self.connection.request('/v%s/containers/%s/rename?name=%s' % (self.version, container.id, name), method='POST') if result.status in VALID_RESPONSE_CODES: return self.get_container(container.id) def ex_get_logs(self, container, stream=False): """ Get container logs If stream == True, logs will be yielded as a stream From Api Version 1.11 and above we need a GET request to get the logs Logs are in different format of those of Version 1.10 and below :param container: The container to list logs for :type container: :class:`libcloud.container.base.Container` :param stream: Stream the output :type stream: ``bool`` :rtype: ``bool`` """ payload = {} data = json.dumps(payload) if float(self._get_api_version()) > 1.10: result = self.connection.request( "/v%s/containers/%s/logs?follow=%s&stdout=1&stderr=1" % (self.version, container.id, str(stream))).object logs = result else: result = self.connection.request( "/v%s/containers/%s/attach?logs=1&stream=%s&stdout=1&stderr=1" % (self.version, container.id, str(stream)), method='POST', data=data) logs = result.body return logs def ex_search_images(self, term): """Search for an image on Docker.io. Returns a list of ContainerImage objects >>> images = conn.ex_search_images(term='mistio') >>> images [, ] :param term: The search term :type term: ``str`` :rtype: ``list`` of :class:`libcloud.container.base.ContainerImage` """ term = term.replace(' ', '+') result = self.connection.request('/v%s/images/search?term=%s' % (self.version, term)).object images = [] for image in result: name = image.get('name') images.append( ContainerImage( id=name, path=name, version=None, name=name, driver=self.connection.driver, extra={ "description": image.get('description'), "is_official": image.get('is_official'), "is_trusted": image.get('is_trusted'), "star_count": image.get('star_count'), }, )) return images def ex_delete_image(self, image): """ Remove image from the filesystem :param image: The image to remove :type image: :class:`libcloud.container.base.ContainerImage` :rtype: ``bool`` """ result = self.connection.request('/v%s/images/%s' % (self.version, image.name), method='DELETE') return result.status in VALID_RESPONSE_CODES def _to_container(self, data): """ Convert container in Container instances """ try: name = data.get('Name').strip('/') except Exception: try: name = data.get('Names')[0].strip('/') except Exception: name = data.get('Id') state = data.get('State') if isinstance(state, dict): status = data.get( 'Status', state.get('Status') if state is not None else None) else: status = data.get('Status') if 'Exited' in status: state = ContainerState.STOPPED elif status.startswith('Up '): state = ContainerState.RUNNING elif 'running' in status: state = ContainerState.RUNNING else: state = ContainerState.STOPPED image = data.get('Image') ports = data.get('Ports', []) created = data.get('Created') if isinstance(created, float): created = ts_to_str(created) extra = { 'id': data.get('Id'), 'status': data.get('Status'), 'created': created, 'image': image, 'ports': ports, 'command': data.get('Command'), 'sizerw': data.get('SizeRw'), 'sizerootfs': data.get('SizeRootFs'), } ips = [] if ports is not None: for port in ports: if port.get('IP') is not None: ips.append(port.get('IP')) return Container( id=data['Id'], name=name, image=ContainerImage( id=data.get('ImageID', None), path=image, name=image, version=None, driver=self.connection.driver ), ip_addresses=ips, state=state, driver=self.connection.driver, extra=extra) def _get_api_version(self): """ Get the docker API version information """ result = self.connection.request('/version').object result = result or {} api_version = result.get('ApiVersion') return api_version def ts_to_str(timestamp): """ Return a timestamp as a nicely formated datetime string. """ date = datetime.datetime.fromtimestamp(timestamp) date_string = date.strftime("%d/%m/%Y %H:%M %Z") return date_string apache-libcloud-2.8.0/libcloud/container/drivers/dummy.py0000664000175000017500000000306613535474530023403 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.container.base import ContainerDriver class DummyContainerDriver(ContainerDriver): """ Dummy Container driver. >>> from libcloud.container.drivers.dummy import DummyContainerDriver >>> driver = DummyContainerDriver('key', 'secret') >>> driver.name 'Dummy Container Provider' """ name = 'Dummy Container Provider' website = 'http://example.com' supports_clusters = False def __init__(self, api_key, api_secret): """ :param api_key: API key or username to used (required) :type api_key: ``str`` :param api_secret: Secret password to be used (required) :type api_secret: ``str`` :rtype: ``None`` """ if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/container/drivers/ecs.py0000664000175000017500000005033613535474530023024 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. try: import simplejson as json except ImportError: import json from libcloud.container.base import (ContainerDriver, Container, ContainerCluster, ContainerImage) from libcloud.container.types import ContainerState from libcloud.container.utils.docker import RegistryClient from libcloud.common.aws import SignedAWSConnection, AWSJsonResponse __all__ = [ 'ElasticContainerDriver' ] ECS_VERSION = '2014-11-13' ECR_VERSION = '2015-09-21' ECS_HOST = 'ecs.%s.amazonaws.com' ECR_HOST = 'ecr.%s.amazonaws.com' ROOT = '/' ECS_TARGET_BASE = 'AmazonEC2ContainerServiceV%s' % \ (ECS_VERSION.replace('-', '')) ECR_TARGET_BASE = 'AmazonEC2ContainerRegistry_V%s' % \ (ECR_VERSION.replace('-', '')) class ECSJsonConnection(SignedAWSConnection): version = ECS_VERSION host = ECS_HOST responseCls = AWSJsonResponse service_name = 'ecs' class ECRJsonConnection(SignedAWSConnection): version = ECR_VERSION host = ECR_HOST responseCls = AWSJsonResponse service_name = 'ecr' class ElasticContainerDriver(ContainerDriver): name = 'Amazon Elastic Container Service' website = 'https://aws.amazon.com/ecs/details/' ecr_repository_host = '%s.dkr.ecr.%s.amazonaws.com' connectionCls = ECSJsonConnection ecrConnectionClass = ECRJsonConnection supports_clusters = False status_map = { 'RUNNING': ContainerState.RUNNING } def __init__(self, access_id, secret, region): super(ElasticContainerDriver, self).__init__(access_id, secret) self.region = region self.region_name = region self.connection.host = ECS_HOST % (region) # Setup another connection class for ECR conn_kwargs = self._ex_connection_class_kwargs() self.ecr_connection = self.ecrConnectionClass( access_id, secret, **conn_kwargs) self.ecr_connection.host = ECR_HOST % (region) self.ecr_connection.driver = self self.ecr_connection.connect() def _ex_connection_class_kwargs(self): return {'signature_version': '4'} def list_images(self, ex_repository_name): """ List the images in an ECR repository :param ex_repository_name: The name of the repository to check defaults to the default repository. :type ex_repository_name: ``str`` :return: a list of images :rtype: ``list`` of :class:`libcloud.container.base.ContainerImage` """ request = {} request['repositoryName'] = ex_repository_name list_response = self.ecr_connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_ecr_headers('ListImages') ).object repository_id = self.ex_get_repository_id(ex_repository_name) host = self._get_ecr_host(repository_id) return self._to_images(list_response['imageIds'], host, ex_repository_name) def list_clusters(self): """ Get a list of potential locations to deploy clusters into :param location: The location to search in :type location: :class:`libcloud.container.base.ClusterLocation` :rtype: ``list`` of :class:`libcloud.container.base.ContainerCluster` """ listdata = self.connection.request( ROOT, method='POST', data=json.dumps({}), headers=self._get_headers('ListClusters') ).object request = {'clusters': listdata['clusterArns']} data = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('DescribeClusters') ).object return self._to_clusters(data) def create_cluster(self, name, location=None): """ Create a container cluster :param name: The name of the cluster :type name: ``str`` :param location: The location to create the cluster in :type location: :class:`libcloud.container.base.ClusterLocation` :rtype: :class:`libcloud.container.base.ContainerCluster` """ request = {'clusterName': name} response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('CreateCluster') ).object return self._to_cluster(response['cluster']) def destroy_cluster(self, cluster): """ Delete a cluster :return: ``True`` if the destroy was successful, otherwise ``False``. :rtype: ``bool`` """ request = {'cluster': cluster.id} data = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('DeleteCluster') ).object return data['cluster']['status'] == 'INACTIVE' def list_containers(self, image=None, cluster=None): """ List the deployed container images :param image: Filter to containers with a certain image :type image: :class:`libcloud.container.base.ContainerImage` :param cluster: Filter to containers in a cluster :type cluster: :class:`libcloud.container.base.ContainerCluster` :rtype: ``list`` of :class:`libcloud.container.base.Container` """ request = {'cluster': 'default'} if cluster is not None: request['cluster'] = cluster.id if image is not None: request['family'] = image.name list_response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('ListTasks') ).object if len(list_response['taskArns']) == 0: return [] containers = self.ex_list_containers_for_task( list_response['taskArns']) return containers def deploy_container(self, name, image, cluster=None, parameters=None, start=True, ex_cpu=10, ex_memory=500, ex_container_port=None, ex_host_port=None): """ Creates a task definition from a container image that can be run in a cluster. :param name: The name of the new container :type name: ``str`` :param image: The container image to deploy :type image: :class:`libcloud.container.base.ContainerImage` :param cluster: The cluster to deploy to, None is default :type cluster: :class:`libcloud.container.base.ContainerCluster` :param parameters: Container Image parameters :type parameters: ``str`` :param start: Start the container on deployment :type start: ``bool`` :rtype: :class:`libcloud.container.base.Container` """ data = {} if ex_container_port is None and ex_host_port is None: port_maps = [] else: port_maps = [ { "containerPort": ex_container_port, "hostPort": ex_host_port } ] data['containerDefinitions'] = [ { "mountPoints": [], "name": name, "image": image.name, "cpu": ex_cpu, "environment": [], "memory": ex_memory, "portMappings": port_maps, "essential": True, "volumesFrom": [] } ] data['family'] = name response = self.connection.request( ROOT, method='POST', data=json.dumps(data), headers=self._get_headers('RegisterTaskDefinition') ).object if start: return self.ex_start_task( response['taskDefinition']['taskDefinitionArn'])[0] else: return Container( id=None, name=name, image=image, state=ContainerState.RUNNING, ip_addresses=[], extra={ 'taskDefinitionArn': response['taskDefinition']['taskDefinitionArn'] }, driver=self.connection.driver ) def get_container(self, id): """ Get a container by ID :param id: The ID of the container to get :type id: ``str`` :rtype: :class:`libcloud.container.base.Container` """ containers = self.ex_list_containers_for_task([id]) return containers[0] def start_container(self, container, count=1): """ Start a deployed task :param container: The container to start :type container: :class:`libcloud.container.base.Container` :param count: Number of containers to start :type count: ``int`` :rtype: :class:`libcloud.container.base.Container` """ return self.ex_start_task(container.extra['taskDefinitionArn'], count) def stop_container(self, container): """ Stop a deployed container :param container: The container to stop :type container: :class:`libcloud.container.base.Container` :rtype: :class:`libcloud.container.base.Container` """ request = {'task': container.extra['taskArn']} response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('StopTask') ).object containers = [] containers.extend(self._to_containers( response['task'], container.extra['taskDefinitionArn'])) return containers def restart_container(self, container): """ Restart a deployed container :param container: The container to restart :type container: :class:`libcloud.container.base.Container` :rtype: :class:`libcloud.container.base.Container` """ self.stop_container(container) return self.start_container(container) def destroy_container(self, container): """ Destroy a deployed container :param container: The container to destroy :type container: :class:`libcloud.container.base.Container` :rtype: :class:`libcloud.container.base.Container` """ return self.stop_container(container) def ex_start_task(self, task_arn, count=1): """ Run a task definition and get the containers :param task_arn: The task ARN to Run :type task_arn: ``str`` :param count: The number of containers to start :type count: ``int`` :rtype: ``list`` of :class:`libcloud.container.base.Container` """ request = None request = {'count': count, 'taskDefinition': task_arn} response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('RunTask') ).object containers = [] for task in response['tasks']: containers.extend(self._to_containers(task, task_arn)) return containers def ex_list_containers_for_task(self, task_arns): """ Get a list of containers by ID collection (ARN) :param task_arns: The list of ARNs :type task_arns: ``list`` of ``str`` :rtype: ``list`` of :class:`libcloud.container.base.Container` """ describe_request = {'tasks': task_arns} descripe_response = self.connection.request( ROOT, method='POST', data=json.dumps(describe_request), headers=self._get_headers('DescribeTasks') ).object containers = [] for task in descripe_response['tasks']: containers.extend(self._to_containers( task, task['taskDefinitionArn'])) return containers def ex_create_service(self, name, cluster, task_definition, desired_count=1): """ Runs and maintains a desired number of tasks from a specified task definition. If the number of tasks running in a service drops below desired_count, Amazon ECS spawns another instantiation of the task in the specified cluster. :param name: the name of the service :type name: ``str`` :param cluster: The cluster to run the service on :type cluster: :class:`libcloud.container.base.ContainerCluster` :param task_definition: The task definition name or ARN for the service :type task_definition: ``str`` :param desired_count: The desired number of tasks to be running at any one time :type desired_count: ``int`` :rtype: ``object`` The service object """ request = { 'serviceName': name, 'taskDefinition': task_definition, 'desiredCount': desired_count, 'cluster': cluster.id} response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('CreateService') ).object return response['service'] def ex_list_service_arns(self, cluster=None): """ List the services :param cluster: The cluster hosting the services :type cluster: :class:`libcloud.container.base.ContainerCluster` :rtype: ``list`` of ``str`` """ request = {} if cluster is not None: request['cluster'] = cluster.id response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('ListServices') ).object return response['serviceArns'] def ex_describe_service(self, service_arn): """ Get the details of a service :param cluster: The hosting cluster :type cluster: :class:`libcloud.container.base.ContainerCluster` :param service_arn: The service ARN to describe :type service_arn: ``str`` :return: The service object :rtype: ``object`` """ request = {'services': [service_arn]} response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('DescribeServices') ).object return response['services'][0] def ex_destroy_service(self, service_arn): """ Deletes a service :param cluster: The target cluster :type cluster: :class:`libcloud.container.base.ContainerCluster` :param service_arn: The service ARN to destroy :type service_arn: ``str`` """ request = { 'service': service_arn} response = self.connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_headers('DeleteService') ).object return response['service'] def ex_get_registry_client(self, repository_name): """ Get a client for an ECR repository :param repository_name: The unique name of the repository :type repository_name: ``str`` :return: a docker registry API client :rtype: :class:`libcloud.container.utils.docker.RegistryClient` """ repository_id = self.ex_get_repository_id(repository_name) token = self.ex_get_repository_token(repository_id) host = self._get_ecr_host(repository_id) return RegistryClient( host=host, username='AWS', password=token ) def ex_get_repository_token(self, repository_id): """ Get the authorization token (12 hour expiry) for a repository :param repository_id: The ID of the repository :type repository_id: ``str`` :return: A token for login :rtype: ``str`` """ request = {'RegistryIds': [repository_id]} response = self.ecr_connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_ecr_headers('GetAuthorizationToken') ).object return response['authorizationData'][0]['authorizationToken'] def ex_get_repository_id(self, repository_name): """ Get the ID of a repository :param repository_name: The unique name of the repository :type repository_name: ``str`` :return: The repository ID :rtype: ``str`` """ request = {'repositoryNames': [repository_name]} list_response = self.ecr_connection.request( ROOT, method='POST', data=json.dumps(request), headers=self._get_ecr_headers('DescribeRepositories') ).object repository_id = list_response['repositories'][0]['registryId'] return repository_id def _get_ecr_host(self, repository_id): return self.ecr_repository_host % ( repository_id, self.region) def _get_headers(self, action): """ Get the default headers for a request to the ECS API """ return {'x-amz-target': '%s.%s' % (ECS_TARGET_BASE, action), 'Content-Type': 'application/x-amz-json-1.1' } def _get_ecr_headers(self, action): """ Get the default headers for a request to the ECR API """ return {'x-amz-target': '%s.%s' % (ECR_TARGET_BASE, action), 'Content-Type': 'application/x-amz-json-1.1' } def _to_clusters(self, data): clusters = [] for cluster in data['clusters']: clusters.append(self._to_cluster(cluster)) return clusters def _to_cluster(self, data): return ContainerCluster( id=data['clusterArn'], name=data['clusterName'], driver=self.connection.driver ) def _to_containers(self, data, task_definition_arn): clusters = [] for cluster in data['containers']: clusters.append(self._to_container(cluster, task_definition_arn)) return clusters def _to_container(self, data, task_definition_arn): return Container( id=data['containerArn'], name=data['name'], image=ContainerImage( id=None, name=data['name'], path=None, version=None, driver=self.connection.driver ), ip_addresses=None, state=self.status_map.get(data['lastStatus'], None), extra={ 'taskArn': data['taskArn'], 'taskDefinitionArn': task_definition_arn }, driver=self.connection.driver ) def _to_images(self, data, host, repository_name): images = [] for image in data: images.append(self._to_image(image, host, repository_name)) return images def _to_image(self, data, host, repository_name): path = '%s/%s:%s' % ( host, repository_name, data['imageTag'] ) return ContainerImage( id=None, name=path, path=path, version=data['imageTag'], driver=self.connection.driver ) apache-libcloud-2.8.0/libcloud/container/drivers/gke.py0000664000175000017500000001722013570310635023005 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.google import GoogleOAuth2Credential from libcloud.container.providers import Provider from libcloud.container.drivers.kubernetes import KubernetesContainerDriver from libcloud.common.google import GoogleResponse from libcloud.common.google import GoogleBaseConnection API_VERSION = 'v1' class GKEResponse(GoogleResponse): pass class GKEConnection(GoogleBaseConnection): """ Connection class for the GKE driver. GKEConnection extends :class:`google.GoogleBaseConnection` for 3 reasons: 1. modify request_path for GKE URI. 2. Implement gce_params functionality described below. 3. Add request_aggregated_items method for making aggregated API calls. """ host = 'container.googleapis.com' responseCls = GKEResponse def __init__(self, user_id, key, secure, auth_type=None, credential_file=None, project=None, **kwargs): super(GKEConnection, self).__init__( user_id, key, secure=secure, auth_type=auth_type, credential_file=credential_file, **kwargs) self.request_path = '/%s/projects/%s' % (API_VERSION, project) self.gke_params = None def pre_connect_hook(self, params, headers): """ Update URL parameters with values from self.gke_params. @inherits: :class:`GoogleBaseConnection.pre_connect_hook` """ params, headers = super(GKEConnection, self).pre_connect_hook(params, headers) if self.gke_params: params.update(self.gke_params) return params, headers def request(self, *args, **kwargs): """ Perform request then do GKE-specific processing of URL params. @inherits: :class:`GoogleBaseConnection.request` """ response = super(GKEConnection, self).request(*args, **kwargs) # If gce_params has been set, then update the pageToken with the # nextPageToken so it can be used in the next request. if self.gke_params: if 'nextPageToken' in response.object: self.gke_params['pageToken'] = response.object['nextPageToken'] elif 'pageToken' in self.gke_params: del self.gke_params['pageToken'] self.gke_params = None return response class GKEContainerDriver(KubernetesContainerDriver): """ GKE Container Driver class. This is the primary driver for interacting with Google Container Engine. It contains all of the standard libcloud methods, plus additional ex_* methods for more features. Note that many methods allow either objects or strings (or lists of objects/strings). In most cases, passing strings instead of objects will result in additional GKE API calls. """ connectionCls = GKEConnection api_name = 'google' name = "Google Container Engine" type = Provider.GKE website = 'https://container.googleapis.com' supports_clusters = True AUTH_URL = "https://container.googleapis.com/auth/" def __init__(self, user_id, key=None, datacenter=None, project=None, auth_type=None, scopes=None, credential_file=None, host=None, port=443, **kwargs): """ :param user_id: The email address (for service accounts) or Client ID (for installed apps) to be used for authentication. :type user_id: ``str`` :param key: The RSA Key (for service accounts) or file path containing key or Client Secret (for installed apps) to be used for authentication. :type key: ``str`` :keyword datacenter: The name of the datacenter (zone) used for operations. :type datacenter: ``str`` :keyword project: Your GKE project name. (required) :type project: ``str`` :keyword auth_type: Accepted values are "SA" or "IA" or "GKE" ("Service Account" or "Installed Application" or "GKE" if libcloud is being used on a GKE instance with service account enabled). If not supplied, auth_type will be guessed based on value of user_id or if the code is being executed in a GKE instance. :type auth_type: ``str`` :keyword scopes: List of authorization URLs. Default is empty and grants read/write to Compute, Storage, DNS. :type scopes: ``list`` :keyword credential_file: Path to file for caching authentication information used by GKEConnection. :type credential_file: ``str`` """ if not project: raise ValueError('Project name must be specified using ' '"project" keyword.') if host is None: host = GKEContainerDriver.website self.auth_type = auth_type self.project = project self.scopes = scopes self.zone = None if datacenter is not None: self.zone = datacenter self.credential_file = credential_file or \ GoogleOAuth2Credential.default_credential_file + '.' + self.project super(GKEContainerDriver, self).__init__(user_id, key, secure=True, host=None, port=None, **kwargs) self.base_path = '/%s/projects/%s' % (API_VERSION, self.project) self.website = GKEContainerDriver.website def _ex_connection_class_kwargs(self): return {'auth_type': self.auth_type, 'project': self.project, 'scopes': self.scopes, 'credential_file': self.credential_file} def list_clusters(self, ex_zone=None): """ Return a list of cluster information in the current zone or all zones. :keyword ex_zone: Optional zone name or None :type ex_zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` """ request = "/zones/%s/clusters" % (ex_zone) if ex_zone is None: request = "/zones/clusters" response = self.connection.request(request, method='GET').object return response def get_server_config(self, ex_zone=None): """ Return configuration info about the Container Engine service. :keyword ex_zone: Optional zone name or None :type ex_zone: ``str`` or :class:`GCEZone` or :class:`NodeLocation` or ``None`` """ if ex_zone is None: ex_zone = self.zone request = "/zones/%s/serverconfig" % (ex_zone) response = self.connection.request(request, method='GET').object return response apache-libcloud-2.8.0/libcloud/container/drivers/joyent.py0000664000175000017500000000566613535474530023570 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.container.providers import Provider from libcloud.container.drivers.docker import (DockerContainerDriver, DockerConnection) class JoyentContainerDriver(DockerContainerDriver): """ Joyent Triton container driver class. >>> from libcloud.container.providers import get_driver >>> driver = get_driver('joyent') >>> conn = driver(host='https://us-east-1.docker.joyent.com', port=2376, key_file='key.pem', cert_file='cert.pem') """ type = Provider.JOYENT name = 'Joyent Triton' website = 'http://joyent.com' connectionCls = DockerConnection supports_clusters = False def __init__(self, key=None, secret=None, secure=False, host='localhost', port=2376, key_file=None, cert_file=None): super(JoyentContainerDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, key_file=key_file, cert_file=cert_file) if host.startswith('https://'): secure = True # strip the prefix prefixes = ['http://', 'https://'] for prefix in prefixes: if host.startswith(prefix): host = host.strip(prefix) if key_file or cert_file: # docker tls authentication- # https://docs.docker.com/articles/https/ # We pass two files, a key_file with the # private key and cert_file with the certificate # libcloud will handle them through LibcloudHTTPSConnection if not (key_file and cert_file): raise Exception( 'Needs both private key file and ' 'certificate file for tls authentication') self.connection.key_file = key_file self.connection.cert_file = cert_file self.connection.secure = True else: self.connection.secure = secure self.connection.host = host self.connection.port = port apache-libcloud-2.8.0/libcloud/container/drivers/kubernetes.py0000664000175000017500000003132613535474530024417 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import datetime try: import simplejson as json except Exception: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.base import JsonResponse, ConnectionUserAndKey from libcloud.common.types import InvalidCredsError from libcloud.container.base import (Container, ContainerDriver, ContainerImage, ContainerCluster) from libcloud.container.providers import Provider from libcloud.container.types import ContainerState VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] ROOT_URL = '/api/' class KubernetesResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_error(self): if self.status == 401: raise InvalidCredsError('Invalid credentials') return self.body def success(self): return self.status in self.valid_response_codes class KubernetesException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "KubernetesException %s %s" % (self.code, self.message) class KubernetesConnection(ConnectionUserAndKey): responseCls = KubernetesResponse timeout = 60 def add_default_headers(self, headers): """ Add parameters that are necessary for every request If user and password are specified, include a base http auth header """ headers['Content-Type'] = 'application/json' if self.key and self.secret: user_b64 = base64.b64encode(b('%s:%s' % (self.key, self.secret))) headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) return headers class KubernetesPod(object): def __init__(self, name, containers, namespace): """ A Kubernetes pod """ self.name = name self.containers = containers self.namespace = namespace class KubernetesContainerDriver(ContainerDriver): type = Provider.KUBERNETES name = 'Kubernetes' website = 'http://kubernetes.io' connectionCls = KubernetesConnection supports_clusters = True def __init__(self, key=None, secret=None, secure=False, host='localhost', port=4243): """ :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Some providers only support HTTPS, and it is on by default. :type secure: ``bool`` :param host: Override hostname used for connections. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :return: ``None`` """ super(KubernetesContainerDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port) if host is not None: if host.startswith('https://'): secure = True # strip the prefix prefixes = ['http://', 'https://'] for prefix in prefixes: if host.startswith(prefix): host = host.strip(prefix) self.connection.host = host self.connection.port = port self.connection.secure = secure self.connection.key = key self.connection.secret = secret def list_containers(self, image=None, all=True): """ List the deployed container images :param image: Filter to containers with a certain image :type image: :class:`libcloud.container.base.ContainerImage` :param all: Show all container (including stopped ones) :type all: ``bool`` :rtype: ``list`` of :class:`libcloud.container.base.Container` """ try: result = self.connection.request( ROOT_URL + "v1/pods").object except Exception as exc: errno = getattr(exc, 'errno', None) if errno == 111: raise KubernetesException( errno, 'Make sure kube host is accessible' 'and the API port is correct') raise pods = [self._to_pod(value) for value in result['items']] containers = [] for pod in pods: containers.extend(pod.containers) return containers def get_container(self, id): """ Get a container by ID :param id: The ID of the container to get :type id: ``str`` :rtype: :class:`libcloud.container.base.Container` """ containers = self.list_containers() match = [container for container in containers if container.id == id] return match[0] def list_clusters(self): """ Get a list of namespaces that pods can be deployed into :param location: The location to search in :type location: :class:`libcloud.container.base.ClusterLocation` :rtype: ``list`` of :class:`libcloud.container.base.ContainerCluster` """ try: result = self.connection.request( ROOT_URL + "v1/namespaces/").object except Exception as exc: errno = getattr(exc, 'errno', None) if errno == 111: raise KubernetesException( errno, 'Make sure kube host is accessible' 'and the API port is correct') raise clusters = [self._to_cluster(value) for value in result['items']] return clusters def get_cluster(self, id): """ Get a cluster by ID :param id: The ID of the cluster to get :type id: ``str`` :rtype: :class:`libcloud.container.base.ContainerCluster` """ result = self.connection.request(ROOT_URL + "v1/namespaces/%s" % id).object return self._to_cluster(result) def destroy_cluster(self, cluster): """ Delete a cluster (namespace) :return: ``True`` if the destroy was successful, otherwise ``False``. :rtype: ``bool`` """ self.connection.request(ROOT_URL + "v1/namespaces/%s" % cluster.id, method='DELETE').object return True def create_cluster(self, name, location=None): """ Create a container cluster (a namespace) :param name: The name of the cluster :type name: ``str`` :param location: The location to create the cluster in :type location: :class:`.ClusterLocation` :rtype: :class:`.ContainerCluster` """ request = { 'metadata': { 'name': name } } result = self.connection.request(ROOT_URL + "v1/namespaces", method='POST', data=json.dumps(request)).object return self._to_cluster(result) def deploy_container(self, name, image, cluster=None, parameters=None, start=True): """ Deploy an installed container image. In kubernetes this deploys a single container Pod. https://cloud.google.com/container-engine/docs/pods/single-container :param name: The name of the new container :type name: ``str`` :param image: The container image to deploy :type image: :class:`.ContainerImage` :param cluster: The cluster to deploy to, None is default :type cluster: :class:`.ContainerCluster` :param parameters: Container Image parameters :type parameters: ``str`` :param start: Start the container on deployment :type start: ``bool`` :rtype: :class:`.Container` """ if cluster is None: namespace = 'default' else: namespace = cluster.id request = { "metadata": { "name": name }, "spec": { "containers": [ { "name": name, "image": image.name } ] } } result = self.connection.request(ROOT_URL + "v1/namespaces/%s/pods" % namespace, method='POST', data=json.dumps(request)).object return self._to_cluster(result) def destroy_container(self, container): """ Destroy a deployed container. Because the containers are single container pods, this will delete the pod. :param container: The container to destroy :type container: :class:`.Container` :rtype: ``bool`` """ return self.ex_destroy_pod(container.extra['namespace'], container.extra['pod']) def ex_list_pods(self): """ List available Pods :rtype: ``list`` of :class:`.KubernetesPod` """ result = self.connection.request(ROOT_URL + "v1/pods").object return [self._to_pod(value) for value in result['items']] def ex_destroy_pod(self, namespace, pod_name): """ Delete a pod and the containers within it. """ self.connection.request( ROOT_URL + "v1/namespaces/%s/pods/%s" % ( namespace, pod_name), method='DELETE').object return True def _to_pod(self, data): """ Convert an API response to a Pod object """ container_statuses = data['status']['containerStatuses'] containers = [] # response contains the status of the containers in a separate field for container in data['spec']['containers']: spec = list(filter(lambda i: i['name'] == container['name'], container_statuses))[0] containers.append( self._to_container(container, spec, data) ) return KubernetesPod( name=data['metadata']['name'], namespace=data['metadata']['namespace'], containers=containers) def _to_container(self, data, container_status, pod_data): """ Convert container in Container instances """ return Container( id=container_status['containerID'], name=data['name'], image=ContainerImage( id=container_status['imageID'], name=data['image'], path=None, version=None, driver=self.connection.driver), ip_addresses=None, state=ContainerState.RUNNING, driver=self.connection.driver, extra={ 'pod': pod_data['metadata']['name'], 'namespace': pod_data['metadata']['namespace'] }) def _to_cluster(self, data): """ Convert namespace to a cluster """ metadata = data['metadata'] status = data['status'] return ContainerCluster( id=metadata['name'], name=metadata['name'], driver=self.connection.driver, extra={'phase': status['phase']}) def ts_to_str(timestamp): """ Return a timestamp as a nicely formated datetime string. """ date = datetime.datetime.fromtimestamp(timestamp) date_string = date.strftime("%d/%m/%Y %H:%M %Z") return date_string apache-libcloud-2.8.0/libcloud/container/drivers/rancher.py0000664000175000017500000006111313535474530023667 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 try: import simplejson as json except Exception: import json from libcloud.utils.py3 import httplib, urlparse from libcloud.utils.py3 import b from libcloud.common.base import JsonResponse, ConnectionUserAndKey from libcloud.container.base import (Container, ContainerDriver, ContainerImage) from libcloud.container.providers import Provider from libcloud.container.types import ContainerState VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] class RancherResponse(JsonResponse): def parse_error(self): parsed = super(RancherResponse, self).parse_error() if 'fieldName' in parsed: return "Field %s is %s: %s - %s" % (parsed['fieldName'], parsed['code'], parsed['message'], parsed['detail']) else: return "%s - %s" % (parsed['message'], parsed['detail']) def success(self): return self.status in VALID_RESPONSE_CODES class RancherException(Exception): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return "%s %s" % (self.code, self.message) def __repr__(self): return "RancherException %s %s" % (self.code, self.message) class RancherConnection(ConnectionUserAndKey): responseCls = RancherResponse timeout = 30 def add_default_headers(self, headers): """ Add parameters that are necessary for every request If user and password are specified, include a base http auth header """ headers['Content-Type'] = 'application/json' headers['Accept'] = 'application/json' if self.key and self.user_id: user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8')) return headers class RancherContainerDriver(ContainerDriver): """ Driver for Rancher by Rancher Labs. This driver is capable of interacting with the Version 1 API of Rancher. It currently does NOT support the Version 2 API. Example: >>> from libcloud.container.providers import get_driver >>> from libcloud.container.types import Provider >>> driver = get_driver(Provider.RANCHER) >>> connection = driver(key="ACCESS_KEY_HERE", secret="SECRET_KEY_HERE", host="172.30.0.100", port=8080) >>> image = ContainerImage("hastebin", "hastebin", "rlister/hastebin", "latest", driver=None) >>> newcontainer = connection.deploy_container("myawesomepastebin", image, environment={"STORAGE_TYPE": "file"}) :ivar baseuri: The URL base path to the API. :type baseuri: ``str`` """ type = Provider.RANCHER name = 'Rancher' website = 'http://rancher.com' connectionCls = RancherConnection # Holding off on cluster support for now. # Only Environment API interaction enabled. supports_clusters = False # As in the /v1/ version = '1' def __init__(self, key, secret, secure=True, host='localhost', port=443): """ Creates a new Rancher Container driver. :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. :type secure: ``bool`` :param host: Override hostname used for connections. This can also be a full URL string, including scheme, port, and base path. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :return: A newly initialized driver instance. """ # Parse the Given Host if '://' not in host and not host.startswith("//"): host = '//' + host parsed = urlparse.urlparse(host) super(RancherContainerDriver, self).__init__( key=key, secret=secret, secure=False if parsed.scheme == 'http' else secure, host=parsed.hostname, port=parsed.port if parsed.port else port ) self.baseuri = parsed.path if parsed.path else "/v%s" % self.version def ex_list_stacks(self): """ List all Rancher Stacks http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/ :rtype: ``list`` of ``dict`` """ result = self.connection.request( "%s/environments" % self.baseuri).object return result['data'] def ex_deploy_stack(self, name, description=None, docker_compose=None, environment=None, external_id=None, rancher_compose=None, start=True): """ Deploy a new stack. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#create :param name: The desired name of the stack. (required) :type name: ``str`` :param description: A desired description for the stack. :type description: ``str`` :param docker_compose: The Docker Compose configuration to use. :type docker_compose: ``str`` :param environment: Environment K/V specific to this stack. :type environment: ``dict`` :param external_id: The externalId of the stack. :type external_id: ``str`` :param rancher_compose: The Rancher Compose configuration for this env. :type rancher_compose: ``str`` :param start: Whether to start this stack on creation. :type start: ``bool`` :return: The newly created stack. :rtype: ``dict`` """ payload = { "description": description, "dockerCompose": docker_compose, "environment": environment, "externalId": external_id, "name": name, "rancherCompose": rancher_compose, "startOnCreate": start } data = json.dumps(dict((k, v) for (k, v) in payload.items() if v is not None)) result = self.connection.request('%s/environments' % self.baseuri, data=data, method='POST').object return result def ex_get_stack(self, env_id): """ Get a stack by ID :param env_id: The stack to be obtained. :type env_id: ``str`` :rtype: ``dict`` """ result = self.connection.request("%s/environments/%s" % (self.baseuri, env_id)).object return result def ex_search_stacks(self, search_params): """ Search for stacks matching certain filters i.e. ``{ "name": "awesomestack"}`` :param search_params: A collection of search parameters to use. :type search_params: ``dict`` :rtype: ``list`` """ search_list = [] for f, v in search_params.items(): search_list.append(f + '=' + v) search_items = '&'.join(search_list) result = self.connection.request("%s/environments?%s" % ( self.baseuri, search_items)).object return result['data'] def ex_destroy_stack(self, env_id): """ Destroy a stack by ID http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#delete :param env_id: The stack to be destroyed. :type env_id: ``str`` :return: True if destroy was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request('%s/environments/%s' % ( self.baseuri, env_id), method='DELETE') return result.status in VALID_RESPONSE_CODES def ex_activate_stack(self, env_id): """ Activate Services for a stack. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#activateservices :param env_id: The stack to activate services for. :type env_id: ``str`` :return: True if activate was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request( '%s/environments/%s?action=activateservices' % ( self.baseuri, env_id), method='POST' ) return result.status in VALID_RESPONSE_CODES def ex_deactivate_stack(self, env_id): """ Deactivate Services for a stack. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#deactivateservices :param env_id: The stack to deactivate services for. :type env_id: ``str`` :return: True if deactivate was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request( '%s/environments/%s?action=deactivateservices' % ( self.baseuri, env_id), method='POST' ) return result.status in VALID_RESPONSE_CODES def ex_list_services(self): """ List all Rancher Services http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/ :rtype: ``list`` of ``dict`` """ result = self.connection.request("%s/services" % self.baseuri).object return result['data'] def ex_deploy_service(self, name, image, environment_id, start=True, assign_service_ip_address=None, service_description=None, external_id=None, metadata=None, retain_ip=None, scale=None, scale_policy=None, secondary_launch_configs=None, selector_container=None, selector_link=None, vip=None, **launch_conf): """ Deploy a Rancher Service under a stack. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#create *Any further configuration passed applies to the ``launchConfig``* :param name: The desired name of the service. (required) :type name: ``str`` :param image: The Image object to deploy. (required) :type image: :class:`libcloud.container.base.ContainerImage` :param environment_id: The stack ID this service is tied to. (required) :type environment_id: ``str`` :param start: Whether to start the service on creation. :type start: ``bool`` :param assign_service_ip_address: The IP address to assign the service. :type assign_service_ip_address: ``bool`` :param service_description: The service description. :type service_description: ``str`` :param external_id: The externalId for this service. :type external_id: ``str`` :param metadata: K/V Metadata for this service. :type metadata: ``dict`` :param retain_ip: Whether this service should retain its IP. :type retain_ip: ``bool`` :param scale: The scale of containers in this service. :type scale: ``int`` :param scale_policy: The scaling policy for this service. :type scale_policy: ``dict`` :param secondary_launch_configs: Secondary container launch configs. :type secondary_launch_configs: ``list`` :param selector_container: The selectorContainer for this service. :type selector_container: ``str`` :param selector_link: The selectorLink for this service. :type selector_link: ``type`` :param vip: The VIP to assign to this service. :type vip: ``str`` :return: The newly created service. :rtype: ``dict`` """ launch_conf['imageUuid'] = self._degen_image(image), service_payload = { "assignServiceIpAddress": assign_service_ip_address, "description": service_description, "environmentId": environment_id, "externalId": external_id, "launchConfig": launch_conf, "metadata": metadata, "name": name, "retainIp": retain_ip, "scale": scale, "scalePolicy": scale_policy, "secondary_launch_configs": secondary_launch_configs, "selectorContainer": selector_container, "selectorLink": selector_link, "startOnCreate": start, "vip": vip } data = json.dumps(dict((k, v) for (k, v) in service_payload.items() if v is not None)) result = self.connection.request('%s/services' % self.baseuri, data=data, method='POST').object return result def ex_get_service(self, service_id): """ Get a service by ID :param service_id: The service_id to be obtained. :type service_id: ``str`` :rtype: ``dict`` """ result = self.connection.request("%s/services/%s" % (self.baseuri, service_id)).object return result def ex_search_services(self, search_params): """ Search for services matching certain filters i.e. ``{ "name": "awesomesause", "environmentId": "1e2"}`` :param search_params: A collection of search parameters to use. :type search_params: ``dict`` :rtype: ``list`` """ search_list = [] for f, v in search_params.items(): search_list.append(f + '=' + v) search_items = '&'.join(search_list) result = self.connection.request("%s/services?%s" % ( self.baseuri, search_items)).object return result['data'] def ex_destroy_service(self, service_id): """ Destroy a service by ID http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#delete :param service_id: The service to be destroyed. :type service_id: ``str`` :return: True if destroy was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request('%s/services/%s' % (self.baseuri, service_id), method='DELETE') return result.status in VALID_RESPONSE_CODES def ex_activate_service(self, service_id): """ Activate a service. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#activate :param service_id: The service to activate services for. :type service_id: ``str`` :return: True if activate was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request('%s/services/%s?action=activate' % (self.baseuri, service_id), method='POST') return result.status in VALID_RESPONSE_CODES def ex_deactivate_service(self, service_id): """ Deactivate a service. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#deactivate :param service_id: The service to deactivate services for. :type service_id: ``str`` :return: True if deactivate was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request('%s/services/%s?action=deactivate' % (self.baseuri, service_id), method='POST') return result.status in VALID_RESPONSE_CODES def list_containers(self): """ List the deployed containers. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/container/ :rtype: ``list`` of :class:`libcloud.container.base.Container` """ result = self.connection.request("%s/containers" % self.baseuri).object containers = [self._to_container(value) for value in result['data']] return containers def deploy_container(self, name, image, parameters=None, start=True, **config): """ Deploy a new container. http://docs.rancher.com/rancher/v1.2/en/api/api-resources/container/#create **The following is the Image format used for ``ContainerImage``** *For a ``imageuuid``*: - ``docker:://:`` *The following applies*: - ``id`` = ```` - ``name`` = ```` - ``path`` = ``://`` - ``version`` = ```` *Any extra configuration can also be passed i.e. "environment"* :param name: The desired name of the container. (required) :type name: ``str`` :param image: The Image object to deploy. (required) :type image: :class:`libcloud.container.base.ContainerImage` :param parameters: Container Image parameters (unused) :type parameters: ``str`` :param start: Whether to start the container on creation(startOnCreate) :type start: ``bool`` :rtype: :class:`Container` """ payload = { "name": name, "imageUuid": self._degen_image(image), "startOnCreate": start, } config.update(payload) data = json.dumps(config) result = self.connection.request('%s/containers' % self.baseuri, data=data, method='POST').object return self._to_container(result) def get_container(self, con_id): """ Get a container by ID :param con_id: The ID of the container to get :type con_id: ``str`` :rtype: :class:`libcloud.container.base.Container` """ result = self.connection.request("%s/containers/%s" % (self.baseuri, con_id)).object return self._to_container(result) def start_container(self, container): """ Start a container :param container: The container to be started :type container: :class:`libcloud.container.base.Container` :return: The container refreshed with current data :rtype: :class:`libcloud.container.base.Container` """ result = self.connection.request('%s/containers/%s?action=start' % (self.baseuri, container.id), method='POST').object return self._to_container(result) def stop_container(self, container): """ Stop a container :param container: The container to be stopped :type container: :class:`libcloud.container.base.Container` :return: The container refreshed with current data :rtype: :class:`libcloud.container.base.Container` """ result = self.connection.request('%s/containers/%s?action=stop' % (self.baseuri, container.id), method='POST').object return self._to_container(result) def ex_search_containers(self, search_params): """ Search for containers matching certain filters i.e. ``{ "imageUuid": "docker:mysql", "state": "running"}`` :param search_params: A collection of search parameters to use. :type search_params: ``dict`` :rtype: ``list`` """ search_list = [] for f, v in search_params.items(): search_list.append(f + '=' + v) search_items = '&'.join(search_list) result = self.connection.request("%s/containers?%s" % ( self.baseuri, search_items)).object return result['data'] def destroy_container(self, container): """ Remove a container :param container: The container to be destroyed :type container: :class:`libcloud.container.base.Container` :return: True if the destroy was successful, False otherwise. :rtype: ``bool`` """ result = self.connection.request('%s/containers/%s' % (self.baseuri, container.id), method='DELETE').object return self._to_container(result) def _gen_image(self, imageuuid): """ This function converts a valid Rancher ``imageUuid`` string to a valid image object. Only supports docker based images hence `docker:` must prefix!! Please see the deploy_container() for details on the format. :param imageuuid: A valid Rancher image string i.e. ``docker:rlister/hastebin:8.0`` :type imageuuid: ``str`` :return: Converted ContainerImage object. :rtype: :class:`libcloud.container.base.ContainerImage` """ # Obtain just the name(:version) for parsing if '/' not in imageuuid: # String looks like `docker:mysql:8.0` image_name_version = imageuuid.partition(':')[2] else: # String looks like `docker:oracle/mysql:8.0` image_name_version = imageuuid.rpartition("/")[2] # Parse based on ':' if ':' in image_name_version: version = image_name_version.partition(":")[2] id = image_name_version.partition(":")[0] name = id else: version = 'latest' id = image_name_version name = id # Get our path based on if there was a version if version != 'latest': path = imageuuid.partition(':')[2].rpartition(':')[0] else: path = imageuuid.partition(':')[2] return ContainerImage( id=id, name=name, path=path, version=version, driver=self.connection.driver, extra={ "imageUuid": imageuuid } ) def _degen_image(self, image): """ Take in an image object to break down into an ``imageUuid`` :param image: :return: """ # Only supporting docker atm image_type = "docker" if image.version is not None: return image_type + ':' + image.path + ':' + image.version else: return image_type + ':' + image.path def _to_container(self, data): """ Convert container in proper Container instance object ** Updating is NOT supported!! :param data: API data about container i.e. result.object :return: Proper Container object: see http://libcloud.readthedocs.io/en/latest/container/api.html """ rancher_state = data['state'] # A Removed container is purged after x amt of time. # Both of these render the container dead (can't be started later) terminate_condition = ["removed", "purged"] if 'running' in rancher_state: state = ContainerState.RUNNING elif 'stopped' in rancher_state: state = ContainerState.STOPPED elif 'restarting' in rancher_state: state = ContainerState.REBOOTING elif 'error' in rancher_state: state = ContainerState.ERROR elif any(x in rancher_state for x in terminate_condition): state = ContainerState.TERMINATED elif data['transitioning'] == 'yes': # Best we can do for current actions state = ContainerState.PENDING else: state = ContainerState.UNKNOWN # Everything contained in the json response is dumped in extra extra = data return Container( id=data['id'], name=data['name'], image=self._gen_image(data['imageUuid']), ip_addresses=[data['primaryIpAddress']], state=state, driver=self.connection.driver, extra=extra) apache-libcloud-2.8.0/libcloud/container/providers.py0000664000175000017500000000352413535474530022606 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.container.types import Provider from libcloud.common.providers import get_driver as _get_provider_driver from libcloud.common.providers import set_driver as _set_provider_driver DRIVERS = { Provider.DUMMY: ('libcloud.container.drivers.dummy', 'DummyContainerDriver'), Provider.DOCKER: ('libcloud.container.drivers.docker', 'DockerContainerDriver'), Provider.JOYENT: ('libcloud.container.drivers.joyent', 'JoyentContainerDriver'), Provider.ECS: ('libcloud.container.drivers.ecs', 'ElasticContainerDriver'), Provider.KUBERNETES: ('libcloud.container.drivers.kubernetes', 'KubernetesContainerDriver'), Provider.RANCHER: ('libcloud.container.drivers.rancher', 'RancherContainerDriver'), Provider.GKE: ('libcloud.container.drivers.gke', 'GKEContainerDriver') } def get_driver(provider): return _get_provider_driver(drivers=DRIVERS, provider=provider) def set_driver(provider, module, klass): return _set_provider_driver(drivers=DRIVERS, provider=provider, module=module, klass=klass) apache-libcloud-2.8.0/libcloud/container/types.py0000664000175000017500000000533413535474530021736 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'Provider', 'ContainerState' ] class Type(object): @classmethod def tostring(cls, value): """Return the string representation of the state object attribute :param str value: the state object to turn into string :return: the uppercase string that represents the state object :rtype: str """ return value.upper() @classmethod def fromstring(cls, value): """Return the state object attribute that matches the string :param str value: the string to look up :return: the state object attribute that matches the string :rtype: str """ return getattr(cls, value.upper(), None) class Provider(object): """ Defines for each of the supported providers Non-Dummy drivers are sorted in alphabetical order. Please preserve this ordering when adding new drivers. """ DUMMY = 'dummy' DOCKER = 'docker' ECS = 'ecs' GKE = 'GKE' JOYENT = 'joyent' KUBERNETES = 'kubernetes' RANCHER = 'rancher' class ContainerState(Type): """ Standard states for a container :cvar RUNNING: Container is running. :cvar REBOOTING: Container is rebooting. :cvar TERMINATED: Container is terminated. This container can't be started later on. :cvar STOPPED: Container is stopped. This container can be started later on. :cvar PENDING: Container is pending. :cvar SUSPENDED: Container is suspended. :cvar ERROR: Container is an error state. Usually no operations can be performed on the container once it ends up in the error state. :cvar PAUSED: Container is paused. :cvar UNKNOWN: Container state is unknown. """ RUNNING = 'running' REBOOTING = 'rebooting' TERMINATED = 'terminated' PENDING = 'pending' UNKNOWN = 'unknown' STOPPED = 'stopped' SUSPENDED = 'suspended' ERROR = 'error' PAUSED = 'paused' apache-libcloud-2.8.0/libcloud/container/utils/0000775000175000017500000000000013600223624021340 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/container/utils/__init__.py0000664000175000017500000000000013535474530023452 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/container/utils/docker.py0000664000175000017500000001431413535474530023177 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement from base64 import b64encode from libcloud.common.base import Connection, JsonResponse from libcloud.container.base import ContainerImage __all__ = [ 'RegistryClient', 'HubClient' ] class DockerHubConnection(Connection): responseCls = JsonResponse def __init__(self, host, username=None, password=None, secure=True, port=None, url=None, timeout=None, proxy_url=None, backoff=None, retry_delay=None): super(DockerHubConnection, self).__init__(secure=secure, host=host, port=port, url=url, timeout=timeout, proxy_url=proxy_url, backoff=backoff, retry_delay=retry_delay) self.username = username self.password = password def add_default_headers(self, headers): headers['Content-Type'] = 'application/json' if self.username is not None: authstr = 'Basic ' + str( b64encode( ('%s:%s' % (self.username, self.password)) .encode('latin1')) .strip() ) headers['Authorization'] = authstr return headers class RegistryClient(object): """ A client for the Docker v2 registry API """ connectionCls = DockerHubConnection def __init__(self, host, username=None, password=None, **kwargs): """ Construct a Docker registry client :param host: Your registry endpoint, e.g. 'registry.hub.docker.com' :type host: ``str`` :param username: (optional) Your registry account username :type username: ``str`` :param password: (optional) Your registry account password :type password: ``str`` """ self.connection = self.connectionCls(host, username, password, **kwargs) def list_images(self, repository_name, namespace='library', max_count=100): """ List the tags (versions) in a repository :param repository_name: The name of the repository e.g. 'ubuntu' :type repository_name: ``str`` :param namespace: (optional) The docker namespace :type namespace: ``str`` :param max_count: The maximum number of records to return :type max_count: ``int`` :return: A list of images :rtype: ``list`` of :class:`libcloud.container.base.ContainerImage` """ path = '/v2/repositories/%s/%s/tags/?page=1&page_size=%s' \ % (namespace, repository_name, max_count) response = self.connection.request(path) images = [] for image in response.object['results']: images.append(self._to_image(repository_name, image)) return images def get_repository(self, repository_name, namespace='library'): """ Get the information about a specific repository :param repository_name: The name of the repository e.g. 'ubuntu' :type repository_name: ``str`` :param namespace: (optional) The docker namespace :type namespace: ``str`` :return: The details of the repository :rtype: ``object`` """ path = '/v2/repositories/%s/%s/' % (namespace, repository_name) response = self.connection.request(path) return response.object def get_image(self, repository_name, tag='latest', namespace='library'): """ Get an image from a repository with a specific tag :param repository_name: The name of the repository, e.g. ubuntu :type repository_name: ``str`` :param tag: (optional) The image tag (defaults to latest) :type tag: ``str`` :param namespace: (optional) The docker namespace :type namespace: ``str`` :return: A container image :rtype: :class:`libcloud.container.base.ContainerImage` """ path = '/v2/repositories/%s/%s/tags/%s/' \ % (namespace, repository_name, tag) response = self.connection.request(path) return self._to_image(repository_name, response.object) def _to_image(self, repository_name, obj): path = '%s/%s:%s' % (self.connection.host, repository_name, obj['name']) return ContainerImage( id=obj['id'], path=path, name=path, version=obj['name'], extra={ 'full_size': obj['full_size'] }, driver=None ) class HubClient(RegistryClient): """ A client for the Docker Hub API The hub is based on the v2 registry API """ host = 'registry.hub.docker.com' def __init__(self, username=None, password=None, **kwargs): """ Construct a Docker hub client :param username: (optional) Your Hub account username :type username: ``str`` :param password: (optional) Your hub account password :type password: ``str`` """ super(HubClient, self).__init__(self.host, username, password, **kwargs) apache-libcloud-2.8.0/libcloud/data/0000775000175000017500000000000013600223624017127 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/data/pricing.json0000664000175000017500000016502713600217315021470 0ustar kamikami00000000000000{ "compute": { "bluebox": { "1gb": 0.15, "2gb": 0.25, "4gb": 0.35, "8gb": 0.45 }, "cloudsigma_lvs": { "high-cpu-extra-large": 0.0, "high-cpu-medium": 0.0, "high-memory-double-extra-large": 0.0, "high-memory-extra-large": 0.0, "micro-high-cpu": 0.0, "micro-regular": 0.0, "standard-extra-large": 0.0, "standard-large": 0.0, "standard-small": 0.0 }, "cloudsigma_zrh": { "high-cpu-extra-large": 0.78, "high-cpu-medium": 0.211, "high-memory-double-extra-large": 1.383, "high-memory-extra-large": 0.642, "micro-high-cpu": 0.381, "micro-regular": 0.0548, "standard-extra-large": 0.762, "standard-large": 0.381, "standard-small": 0.0796 }, "ec2_ap_northeast": { "c1.medium": 0.158, "c1.xlarge": 0.632, "c3.large": 0.128, "c3.xlarge": 0.255, "c3.2xlarge": 0.511, "c3.4xlarge": 1.021, "c3.8xlarge": 2.043, "c4.large": 0.114, "c4.xlarge": 0.227, "c4.2xlarge": 0.454, "c4.4xlarge": 0.907, "c4.8xlarge": 1.815, "c5.large": 0.096, "c5.xlarge": 0.192, "c5.2xlarge": 0.384, "c5.4xlarge": 0.768, "c5.9xlarge": 1.728, "c5.18xlarge": 3.456, "cc2.8xlarge": 2.349, "cr1.8xlarge": 4.105, "d2.xlarge": 0.844, "d2.2xlarge": 1.688, "d2.4xlarge": 3.376, "d2.8xlarge": 6.752, "g2.2xlarge": 0.898, "g2.8xlarge": 3.592, "g3.4xlarge": 1.58, "g3.8xlarge": 3.16, "g3.16xlarge": 6.32, "hs1.8xlarge": 5.4, "i2.xlarge": 1.001, "i2.2xlarge": 2.001, "i2.4xlarge": 4.002, "i2.8xlarge": 8.004, "i3.large": 0.183, "i3.xlarge": 0.366, "i3.metal": 5.856, "i3.2xlarge": 0.732, "i3.4xlarge": 1.464, "i3.8xlarge": 2.928, "i3.16xlarge": 5.856, "m1.small": 0.061, "m1.medium": 0.122, "m1.large": 0.243, "m1.xlarge": 0.486, "m2.xlarge": 0.287, "m2.2xlarge": 0.575, "m2.4xlarge": 1.15, "m3.medium": 0.096, "m3.large": 0.193, "m3.xlarge": 0.385, "m3.2xlarge": 0.77, "m4.large": 0.123, "m4.xlarge": 0.246, "m4.2xlarge": 0.492, "m4.4xlarge": 0.984, "m4.10xlarge": 2.46, "m4.16xlarge": 3.936, "m5.large": 0.118, "m5.xlarge": 0.236, "m5.2xlarge": 0.472, "m5.4xlarge": 0.944, "m5.12xlarge": 2.832, "m5.24xlarge": 5.664, "p2.xlarge": 1.465, "p2.8xlarge": 11.72, "p2.16xlarge": 23.44, "p3.2xlarge": 4.981, "p3.8xlarge": 19.924, "p3.16xlarge": 39.848, "r3.large": 0.2, "r3.xlarge": 0.399, "r3.2xlarge": 0.798, "r3.4xlarge": 1.596, "r3.8xlarge": 3.192, "r4.large": 0.16, "r4.xlarge": 0.32, "r4.2xlarge": 0.64, "r4.4xlarge": 1.28, "r4.8xlarge": 2.56, "r4.16xlarge": 5.12, "t1.micro": 0.026, "t2.micro": 0.0144, "t2.small": 0.0288, "t2.medium": 0.0576, "t2.large": 0.1152, "t2.xlarge": 0.2304, "t2.nano": 0.0072, "t2.2xlarge": 0.4608, "x1.16xlarge": 9.671, "x1.32xlarge": 19.341, "x1e.xlarge": 1.209, "x1e.2xlarge": 2.418, "x1e.4xlarge": 4.836, "x1e.8xlarge": 9.672, "x1e.16xlarge": 19.344, "x1e.32xlarge": 38.688 }, "ec2_ap_south_1": { "c4.large": 0.1, "c4.xlarge": 0.2, "c4.2xlarge": 0.4, "c4.4xlarge": 0.8, "c4.8xlarge": 1.6, "c5.large": 0.085, "c5.xlarge": 0.17, "c5.2xlarge": 0.34, "c5.4xlarge": 0.68, "c5.9xlarge": 1.53, "c5.18xlarge": 3.06, "d2.xlarge": 0.827, "d2.2xlarge": 1.653, "d2.4xlarge": 3.306, "d2.8xlarge": 6.612, "i2.xlarge": 0.967, "i2.2xlarge": 1.933, "i2.4xlarge": 3.867, "i2.8xlarge": 7.733, "i3.large": 0.177, "i3.xlarge": 0.354, "i3.2xlarge": 0.708, "i3.4xlarge": 1.416, "i3.8xlarge": 2.832, "i3.16xlarge": 5.664, "m4.large": 0.105, "m4.xlarge": 0.21, "m4.2xlarge": 0.42, "m4.4xlarge": 0.84, "m4.10xlarge": 2.1, "m4.16xlarge": 3.36, "m5.large": 0.101, "m5.xlarge": 0.202, "m5.2xlarge": 0.404, "m5.4xlarge": 0.808, "m5.12xlarge": 2.424, "m5.24xlarge": 4.848, "p2.xlarge": 1.718, "p2.8xlarge": 13.744, "p2.16xlarge": 27.488, "r3.large": 0.19, "r3.xlarge": 0.379, "r3.2xlarge": 0.758, "r3.4xlarge": 1.516, "r3.8xlarge": 3.032, "r4.large": 0.137, "r4.xlarge": 0.274, "r4.2xlarge": 0.548, "r4.4xlarge": 1.096, "r4.8xlarge": 2.192, "r4.16xlarge": 4.384, "t2.micro": 0.0124, "t2.small": 0.0248, "t2.medium": 0.0496, "t2.large": 0.0992, "t2.xlarge": 0.1984, "t2.nano": 0.0062, "t2.2xlarge": 0.3968, "x1.16xlarge": 9.187, "x1.32xlarge": 18.374 }, "ec2_ap_southeast": { "c1.medium": 0.164, "c1.xlarge": 0.655, "c3.large": 0.132, "c3.xlarge": 0.265, "c3.2xlarge": 0.529, "c3.4xlarge": 1.058, "c3.8xlarge": 2.117, "c4.large": 0.115, "c4.xlarge": 0.231, "c4.2xlarge": 0.462, "c4.4xlarge": 0.924, "c4.8xlarge": 1.848, "c5.large": 0.098, "c5.xlarge": 0.196, "c5.2xlarge": 0.392, "c5.4xlarge": 0.784, "c5.9xlarge": 1.764, "c5.18xlarge": 3.528, "d2.xlarge": 0.87, "d2.2xlarge": 1.74, "d2.4xlarge": 3.48, "d2.8xlarge": 6.96, "g2.2xlarge": 1.0, "g2.8xlarge": 4.0, "g3.4xlarge": 1.67, "g3.8xlarge": 3.34, "g3.16xlarge": 6.68, "hs1.8xlarge": 5.57, "i2.xlarge": 1.018, "i2.2xlarge": 2.035, "i2.4xlarge": 4.07, "i2.8xlarge": 8.14, "i3.large": 0.187, "i3.xlarge": 0.374, "i3.2xlarge": 0.748, "i3.4xlarge": 1.496, "i3.8xlarge": 2.992, "i3.16xlarge": 5.984, "m1.small": 0.058, "m1.medium": 0.117, "m1.large": 0.233, "m1.xlarge": 0.467, "m2.xlarge": 0.296, "m2.2xlarge": 0.592, "m2.4xlarge": 1.183, "m3.medium": 0.098, "m3.large": 0.196, "m3.xlarge": 0.392, "m3.2xlarge": 0.784, "m4.large": 0.125, "m4.xlarge": 0.25, "m4.2xlarge": 0.5, "m4.4xlarge": 1.0, "m4.10xlarge": 2.5, "m4.16xlarge": 4.0, "m5.large": 0.12, "m5.xlarge": 0.24, "m5.2xlarge": 0.48, "m5.4xlarge": 0.96, "m5.12xlarge": 2.88, "m5.24xlarge": 5.76, "p2.xlarge": 1.718, "p2.8xlarge": 13.744, "p2.16xlarge": 27.488, "r3.large": 0.2, "r3.xlarge": 0.399, "r3.2xlarge": 0.798, "r3.4xlarge": 1.596, "r3.8xlarge": 3.192, "r4.large": 0.16, "r4.xlarge": 0.32, "r4.2xlarge": 0.64, "r4.4xlarge": 1.28, "r4.8xlarge": 2.56, "r4.16xlarge": 5.12, "t1.micro": 0.02, "t2.micro": 0.0146, "t2.small": 0.0292, "t2.medium": 0.0584, "t2.large": 0.1168, "t2.xlarge": 0.2336, "t2.nano": 0.0073, "t2.2xlarge": 0.4672, "x1.16xlarge": 9.671, "x1.32xlarge": 19.341 }, "ec2_ap_southeast_2": { "c1.medium": 0.164, "c1.xlarge": 0.655, "c3.large": 0.132, "c3.xlarge": 0.265, "c3.2xlarge": 0.529, "c3.4xlarge": 1.058, "c3.8xlarge": 2.117, "c4.large": 0.13, "c4.xlarge": 0.261, "c4.2xlarge": 0.522, "c4.4xlarge": 1.042, "c4.8xlarge": 2.085, "c5.large": 0.111, "c5.xlarge": 0.222, "c5.2xlarge": 0.444, "c5.4xlarge": 0.888, "c5.9xlarge": 1.998, "c5.18xlarge": 3.996, "d2.xlarge": 0.87, "d2.2xlarge": 1.74, "d2.4xlarge": 3.48, "d2.8xlarge": 6.96, "g2.2xlarge": 0.898, "g2.8xlarge": 3.592, "g3.4xlarge": 1.754, "g3.8xlarge": 3.508, "g3.16xlarge": 7.016, "hs1.8xlarge": 5.57, "i2.xlarge": 1.018, "i2.2xlarge": 2.035, "i2.4xlarge": 4.07, "i2.8xlarge": 8.14, "i3.large": 0.187, "i3.xlarge": 0.374, "i3.metal": 5.984, "i3.2xlarge": 0.748, "i3.4xlarge": 1.496, "i3.8xlarge": 2.992, "i3.16xlarge": 5.984, "m1.small": 0.058, "m1.medium": 0.117, "m1.large": 0.233, "m1.xlarge": 0.467, "m2.xlarge": 0.296, "m2.2xlarge": 0.592, "m2.4xlarge": 1.183, "m3.medium": 0.093, "m3.large": 0.186, "m3.xlarge": 0.372, "m3.2xlarge": 0.745, "m4.large": 0.125, "m4.xlarge": 0.25, "m4.2xlarge": 0.5, "m4.4xlarge": 1.0, "m4.10xlarge": 2.5, "m4.16xlarge": 4.0, "m5.large": 0.12, "m5.xlarge": 0.24, "m5.2xlarge": 0.48, "m5.4xlarge": 0.96, "m5.12xlarge": 2.88, "m5.24xlarge": 5.76, "p2.xlarge": 1.542, "p2.8xlarge": 12.336, "p2.16xlarge": 24.672, "r3.large": 0.2, "r3.xlarge": 0.399, "r3.2xlarge": 0.798, "r3.4xlarge": 1.596, "r3.8xlarge": 3.192, "r4.large": 0.16, "r4.xlarge": 0.319, "r4.2xlarge": 0.638, "r4.4xlarge": 1.277, "r4.8xlarge": 2.554, "r4.16xlarge": 5.107, "t1.micro": 0.02, "t2.micro": 0.0146, "t2.small": 0.0292, "t2.medium": 0.0584, "t2.large": 0.1168, "t2.xlarge": 0.2336, "t2.nano": 0.0073, "t2.2xlarge": 0.4672, "x1.16xlarge": 9.671, "x1.32xlarge": 19.341, "x1e.xlarge": 1.209, "x1e.2xlarge": 2.418, "x1e.4xlarge": 4.836, "x1e.8xlarge": 9.672, "x1e.16xlarge": 19.344, "x1e.32xlarge": 38.688 }, "ec2_ca_central": { "c4.large": 0.11, "c4.xlarge": 0.218, "c4.2xlarge": 0.438, "c4.4xlarge": 0.876, "c4.8xlarge": 1.75, "d2.xlarge": 0.759, "d2.2xlarge": 1.518, "d2.4xlarge": 3.036, "d2.8xlarge": 6.072, "i3.large": 0.172, "i3.xlarge": 0.344, "i3.2xlarge": 0.688, "i3.4xlarge": 1.376, "i3.8xlarge": 2.752, "i3.16xlarge": 5.504, "m4.large": 0.111, "m4.xlarge": 0.222, "m4.2xlarge": 0.444, "m4.4xlarge": 0.888, "m4.10xlarge": 2.22, "m4.16xlarge": 3.552, "r4.large": 0.146, "r4.xlarge": 0.292, "r4.2xlarge": 0.584, "r4.4xlarge": 1.168, "r4.8xlarge": 2.336, "r4.16xlarge": 4.672, "t2.micro": 0.013, "t2.small": 0.026, "t2.medium": 0.052, "t2.large": 0.103, "t2.xlarge": 0.206, "t2.nano": 0.0065, "t2.2xlarge": 0.412, "x1.16xlarge": 7.336, "x1.32xlarge": 14.672 }, "ec2_ca_central_1": { "c4.large": 0.11, "c4.xlarge": 0.218, "c4.2xlarge": 0.438, "c4.4xlarge": 0.876, "c4.8xlarge": 1.75, "c5.large": 0.093, "c5.xlarge": 0.186, "c5.2xlarge": 0.372, "c5.4xlarge": 0.744, "c5.9xlarge": 1.674, "c5.18xlarge": 3.348, "c5d.large": 0.106, "c5d.xlarge": 0.212, "c5d.2xlarge": 0.424, "c5d.4xlarge": 0.848, "c5d.9xlarge": 1.908, "c5d.18xlarge": 3.816, "d2.xlarge": 0.759, "d2.2xlarge": 1.518, "d2.4xlarge": 3.036, "d2.8xlarge": 6.072, "i3.large": 0.172, "i3.xlarge": 0.344, "i3.2xlarge": 0.688, "i3.4xlarge": 1.376, "i3.8xlarge": 2.752, "i3.16xlarge": 5.504, "m4.large": 0.111, "m4.xlarge": 0.222, "m4.2xlarge": 0.444, "m4.4xlarge": 0.888, "m4.10xlarge": 2.22, "m4.16xlarge": 3.552, "m5.large": 0.107, "m5.xlarge": 0.214, "m5.2xlarge": 0.428, "m5.4xlarge": 0.856, "m5.12xlarge": 2.568, "m5.24xlarge": 5.136, "m5d.large": 0.126, "m5d.xlarge": 0.252, "m5d.2xlarge": 0.504, "m5d.4xlarge": 1.008, "m5d.12xlarge": 3.024, "m5d.24xlarge": 6.048, "r4.large": 0.146, "r4.xlarge": 0.292, "r4.2xlarge": 0.584, "r4.4xlarge": 1.168, "r4.8xlarge": 2.336, "r4.16xlarge": 4.672, "t2.micro": 0.0128, "t2.small": 0.0256, "t2.medium": 0.0512, "t2.large": 0.1024, "t2.xlarge": 0.2048, "t2.nano": 0.0064, "t2.2xlarge": 0.4096, "x1.16xlarge": 7.336, "x1.32xlarge": 14.672 }, "ec2_eu_central": { "c3.large": 0.129, "c3.xlarge": 0.258, "c3.2xlarge": 0.516, "c3.4xlarge": 1.032, "c3.8xlarge": 2.064, "c4.large": 0.114, "c4.xlarge": 0.227, "c4.2xlarge": 0.454, "c4.4xlarge": 0.909, "c4.8xlarge": 1.817, "c5.large": 0.097, "c5.xlarge": 0.194, "c5.2xlarge": 0.388, "c5.4xlarge": 0.776, "c5.9xlarge": 1.746, "c5.18xlarge": 3.492, "d2.xlarge": 0.794, "d2.2xlarge": 1.588, "d2.4xlarge": 3.176, "d2.8xlarge": 6.352, "g2.2xlarge": 0.772, "g2.8xlarge": 3.088, "g3.4xlarge": 1.425, "g3.8xlarge": 2.85, "g3.16xlarge": 5.7, "i2.xlarge": 1.013, "i2.2xlarge": 2.026, "i2.4xlarge": 4.051, "i2.8xlarge": 8.102, "i3.large": 0.186, "i3.xlarge": 0.372, "i3.metal": 5.952, "i3.2xlarge": 0.744, "i3.4xlarge": 1.488, "i3.8xlarge": 2.976, "i3.16xlarge": 5.952, "m3.medium": 0.079, "m3.large": 0.158, "m3.xlarge": 0.315, "m3.2xlarge": 0.632, "m4.large": 0.12, "m4.xlarge": 0.24, "m4.2xlarge": 0.48, "m4.4xlarge": 0.96, "m4.10xlarge": 2.4, "m4.16xlarge": 3.84, "m5.large": 0.115, "m5.xlarge": 0.23, "m5.2xlarge": 0.46, "m5.4xlarge": 0.92, "m5.12xlarge": 2.76, "m5.24xlarge": 5.52, "p2.xlarge": 1.326, "p2.8xlarge": 10.608, "p2.16xlarge": 21.216, "r3.large": 0.2, "r3.xlarge": 0.4, "r3.2xlarge": 0.8, "r3.4xlarge": 1.6, "r3.8xlarge": 3.201, "r4.large": 0.16, "r4.xlarge": 0.32, "r4.2xlarge": 0.64, "r4.4xlarge": 1.28, "r4.8xlarge": 2.561, "r4.16xlarge": 5.122, "t2.micro": 0.0134, "t2.small": 0.0268, "t2.medium": 0.0536, "t2.large": 0.1072, "t2.xlarge": 0.2144, "t2.nano": 0.0067, "t2.2xlarge": 0.4288, "x1.16xlarge": 9.337, "x1.32xlarge": 18.674, "x1e.xlarge": 1.167, "x1e.2xlarge": 2.334, "x1e.4xlarge": 4.668, "x1e.8xlarge": 9.336, "x1e.16xlarge": 18.672, "x1e.32xlarge": 37.344 }, "ec2_eu_west": { "c1.medium": 0.148, "c1.xlarge": 0.592, "c3.large": 0.12, "c3.xlarge": 0.239, "c3.2xlarge": 0.478, "c3.4xlarge": 0.956, "c3.8xlarge": 1.912, "c4.large": 0.113, "c4.xlarge": 0.226, "c4.2xlarge": 0.453, "c4.4xlarge": 0.905, "c4.8xlarge": 1.811, "c5.large": 0.096, "c5.xlarge": 0.192, "c5.2xlarge": 0.384, "c5.4xlarge": 0.768, "c5.9xlarge": 1.728, "c5.18xlarge": 3.456, "c5d.large": 0.109, "c5d.xlarge": 0.218, "c5d.2xlarge": 0.436, "c5d.4xlarge": 0.872, "c5d.9xlarge": 1.962, "c5d.18xlarge": 3.924, "cc2.8xlarge": 2.25, "cr1.8xlarge": 3.75, "d2.xlarge": 0.735, "d2.2xlarge": 1.47, "d2.4xlarge": 2.94, "d2.8xlarge": 5.88, "f1.2xlarge": 1.815, "f1.16xlarge": 14.52, "g2.2xlarge": 0.702, "g2.8xlarge": 2.808, "g3.4xlarge": 1.21, "g3.8xlarge": 2.42, "g3.16xlarge": 4.84, "h1.2xlarge": 0.519, "h1.4xlarge": 1.038, "h1.8xlarge": 2.076, "h1.16xlarge": 4.152, "hs1.8xlarge": 4.9, "i2.xlarge": 0.938, "i2.2xlarge": 1.876, "i2.4xlarge": 3.751, "i2.8xlarge": 7.502, "i3.large": 0.172, "i3.xlarge": 0.344, "i3.metal": 5.504, "i3.2xlarge": 0.688, "i3.4xlarge": 1.376, "i3.8xlarge": 2.752, "i3.16xlarge": 5.504, "m1.small": 0.047, "m1.medium": 0.095, "m1.large": 0.19, "m1.xlarge": 0.379, "m2.xlarge": 0.275, "m2.2xlarge": 0.55, "m2.4xlarge": 1.1, "m3.medium": 0.073, "m3.large": 0.146, "m3.xlarge": 0.293, "m3.2xlarge": 0.585, "m4.large": 0.111, "m4.xlarge": 0.222, "m4.2xlarge": 0.444, "m4.4xlarge": 0.888, "m4.10xlarge": 2.22, "m4.16xlarge": 3.552, "m5.large": 0.107, "m5.xlarge": 0.214, "m5.2xlarge": 0.428, "m5.4xlarge": 0.856, "m5.12xlarge": 2.568, "m5.24xlarge": 5.136, "m5d.large": 0.126, "m5d.xlarge": 0.252, "m5d.2xlarge": 0.504, "m5d.4xlarge": 1.008, "m5d.12xlarge": 3.024, "m5d.24xlarge": 6.048, "p2.xlarge": 0.972, "p2.8xlarge": 7.776, "p2.16xlarge": 15.552, "p3.2xlarge": 3.305, "p3.8xlarge": 13.22, "p3.16xlarge": 26.44, "r3.large": 0.185, "r3.xlarge": 0.371, "r3.2xlarge": 0.741, "r3.4xlarge": 1.482, "r3.8xlarge": 2.964, "r4.large": 0.148, "r4.xlarge": 0.296, "r4.2xlarge": 0.593, "r4.4xlarge": 1.186, "r4.8xlarge": 2.371, "r4.16xlarge": 4.742, "t1.micro": 0.02, "t2.micro": 0.0126, "t2.small": 0.025, "t2.medium": 0.05, "t2.large": 0.1008, "t2.xlarge": 0.2016, "t2.nano": 0.0063, "t2.2xlarge": 0.4032, "x1.16xlarge": 8.003, "x1.32xlarge": 16.006, "x1e.xlarge": 1.0, "x1e.2xlarge": 2.0, "x1e.4xlarge": 4.0, "x1e.8xlarge": 8.0, "x1e.16xlarge": 16.0, "x1e.32xlarge": 32.0 }, "ec2_eu_west_2": { "c4.large": 0.119, "c4.xlarge": 0.237, "c4.2xlarge": 0.476, "c4.4xlarge": 0.95, "c4.8xlarge": 1.902, "d2.xlarge": 0.772, "d2.2xlarge": 1.544, "d2.4xlarge": 3.087, "d2.8xlarge": 6.174, "i3.large": 0.181, "i3.xlarge": 0.362, "i3.2xlarge": 0.724, "i3.4xlarge": 1.448, "i3.8xlarge": 2.896, "i3.16xlarge": 5.792, "m4.large": 0.125, "m4.xlarge": 0.25, "m4.2xlarge": 0.499, "m4.4xlarge": 0.998, "m4.10xlarge": 2.496, "m4.16xlarge": 3.993, "r4.large": 0.156, "r4.xlarge": 0.312, "r4.2xlarge": 0.624, "r4.4xlarge": 1.248, "r4.8xlarge": 2.496, "r4.16xlarge": 4.992, "t2.micro": 0.014, "t2.small": 0.026, "t2.medium": 0.052, "t2.large": 0.106, "t2.xlarge": 0.212, "t2.nano": 0.0066, "t2.2xlarge": 0.424, "x1.16xlarge": 8.403, "x1.32xlarge": 16.806 }, "ec2_eu_west_3": { "c5.large": 0.101, "c5.xlarge": 0.202, "c5.2xlarge": 0.404, "c5.4xlarge": 0.808, "c5.9xlarge": 1.818, "c5.18xlarge": 3.636, "d2.xlarge": 0.772, "d2.2xlarge": 1.544, "d2.4xlarge": 3.088, "d2.8xlarge": 6.176, "i3.large": 0.181, "i3.xlarge": 0.362, "i3.2xlarge": 0.724, "i3.4xlarge": 1.448, "i3.8xlarge": 2.896, "i3.16xlarge": 5.792, "m5.large": 0.112, "m5.xlarge": 0.224, "m5.2xlarge": 0.448, "m5.4xlarge": 0.896, "m5.12xlarge": 2.688, "m5.24xlarge": 5.376, "r4.large": 0.156, "r4.xlarge": 0.312, "r4.2xlarge": 0.624, "r4.4xlarge": 1.248, "r4.8xlarge": 2.496, "r4.16xlarge": 4.992, "t2.micro": 0.0132, "t2.small": 0.0264, "t2.medium": 0.0528, "t2.large": 0.1056, "t2.xlarge": 0.2112, "t2.nano": 0.0066, "t2.2xlarge": 0.4224, "x1.16xlarge": 8.403, "x1.32xlarge": 16.806 }, "ec2_eu_west_london": { "c4.large": 0.119, "c4.xlarge": 0.237, "c4.2xlarge": 0.476, "c4.4xlarge": 0.95, "c4.8xlarge": 1.902, "c5.large": 0.101, "c5.xlarge": 0.202, "c5.2xlarge": 0.404, "c5.4xlarge": 0.808, "c5.9xlarge": 1.818, "c5.18xlarge": 3.636, "d2.xlarge": 0.772, "d2.2xlarge": 1.544, "d2.4xlarge": 3.087, "d2.8xlarge": 6.174, "i3.large": 0.181, "i3.xlarge": 0.362, "i3.metal": 5.792, "i3.2xlarge": 0.724, "i3.4xlarge": 1.448, "i3.8xlarge": 2.896, "i3.16xlarge": 5.792, "m4.large": 0.116, "m4.xlarge": 0.232, "m4.2xlarge": 0.464, "m4.4xlarge": 0.928, "m4.10xlarge": 2.32, "m4.16xlarge": 3.712, "m5.large": 0.111, "m5.xlarge": 0.222, "m5.2xlarge": 0.444, "m5.4xlarge": 0.888, "m5.12xlarge": 2.664, "m5.24xlarge": 5.328, "r4.large": 0.156, "r4.xlarge": 0.312, "r4.2xlarge": 0.624, "r4.4xlarge": 1.248, "r4.8xlarge": 2.496, "r4.16xlarge": 4.992, "t2.micro": 0.0132, "t2.small": 0.026, "t2.medium": 0.052, "t2.large": 0.1056, "t2.xlarge": 0.2112, "t2.nano": 0.0066, "t2.2xlarge": 0.4224, "x1.16xlarge": 8.403, "x1.32xlarge": 16.806 }, "ec2_sa_east": { "c1.medium": 0.179, "c1.xlarge": 0.718, "c3.large": 0.163, "c3.xlarge": 0.325, "c3.2xlarge": 0.65, "c3.4xlarge": 1.3, "c3.8xlarge": 2.6, "c4.large": 0.155, "c4.xlarge": 0.309, "c4.2xlarge": 0.618, "c4.4xlarge": 1.235, "c4.8xlarge": 2.47, "c5.large": 0.131, "c5.xlarge": 0.262, "c5.2xlarge": 0.524, "c5.4xlarge": 1.048, "c5.9xlarge": 2.358, "c5.18xlarge": 4.716, "i3.large": 0.286, "i3.xlarge": 0.572, "i3.2xlarge": 1.144, "i3.4xlarge": 2.288, "i3.8xlarge": 4.576, "i3.16xlarge": 9.152, "m1.small": 0.058, "m1.medium": 0.117, "m1.large": 0.233, "m1.xlarge": 0.467, "m2.xlarge": 0.323, "m2.2xlarge": 0.645, "m2.4xlarge": 1.291, "m3.medium": 0.095, "m3.large": 0.19, "m3.xlarge": 0.381, "m3.2xlarge": 0.761, "m4.large": 0.159, "m4.xlarge": 0.318, "m4.2xlarge": 0.636, "m4.4xlarge": 1.272, "m4.10xlarge": 3.18, "m4.16xlarge": 5.088, "m5.large": 0.153, "m5.xlarge": 0.306, "m5.2xlarge": 0.612, "m5.4xlarge": 1.224, "m5.12xlarge": 3.672, "m5.24xlarge": 7.344, "r3.large": 0.35, "r3.xlarge": 0.7, "r3.2xlarge": 1.399, "r3.4xlarge": 2.799, "r3.8xlarge": 5.597, "r4.large": 0.28, "r4.xlarge": 0.56, "r4.2xlarge": 1.12, "r4.4xlarge": 2.24, "r4.8xlarge": 4.48, "r4.16xlarge": 8.96, "t1.micro": 0.027, "t2.micro": 0.0186, "t2.small": 0.0372, "t2.medium": 0.0744, "t2.large": 0.1488, "t2.xlarge": 0.2976, "t2.nano": 0.0093, "t2.2xlarge": 0.5952, "x1.16xlarge": 13.005, "x1.32xlarge": 26.01 }, "ec2_us_east": { "c1.medium": 0.13, "c1.xlarge": 0.52, "c3.large": 0.105, "c3.xlarge": 0.21, "c3.2xlarge": 0.42, "c3.4xlarge": 0.84, "c3.8xlarge": 1.68, "c4.large": 0.1, "c4.xlarge": 0.199, "c4.2xlarge": 0.398, "c4.4xlarge": 0.796, "c4.8xlarge": 1.591, "c5.large": 0.085, "c5.xlarge": 0.17, "c5.2xlarge": 0.34, "c5.4xlarge": 0.68, "c5.9xlarge": 1.53, "c5.18xlarge": 3.06, "c5d.large": 0.096, "c5d.xlarge": 0.192, "c5d.2xlarge": 0.384, "c5d.4xlarge": 0.768, "c5d.9xlarge": 1.728, "c5d.18xlarge": 3.456, "cc2.8xlarge": 2.0, "cr1.8xlarge": 3.5, "d2.xlarge": 0.69, "d2.2xlarge": 1.38, "d2.4xlarge": 2.76, "d2.8xlarge": 5.52, "f1.2xlarge": 1.65, "f1.16xlarge": 13.2, "g2.2xlarge": 0.65, "g2.8xlarge": 2.6, "g3.4xlarge": 1.14, "g3.8xlarge": 2.28, "g3.16xlarge": 4.56, "h1.2xlarge": 0.468, "h1.4xlarge": 0.936, "h1.8xlarge": 1.872, "h1.16xlarge": 3.744, "hs1.8xlarge": 4.6, "i2.xlarge": 0.853, "i2.2xlarge": 1.705, "i2.4xlarge": 3.41, "i2.8xlarge": 6.82, "i3.large": 0.156, "i3.xlarge": 0.312, "i3.metal": 4.992, "i3.2xlarge": 0.624, "i3.4xlarge": 1.248, "i3.8xlarge": 2.496, "i3.16xlarge": 4.992, "m1.small": 0.044, "m1.medium": 0.087, "m1.large": 0.175, "m1.xlarge": 0.35, "m2.xlarge": 0.245, "m2.2xlarge": 0.49, "m2.4xlarge": 0.98, "m3.medium": 0.067, "m3.large": 0.133, "m3.xlarge": 0.266, "m3.2xlarge": 0.532, "m4.large": 0.1, "m4.xlarge": 0.2, "m4.2xlarge": 0.4, "m4.4xlarge": 0.8, "m4.10xlarge": 2.0, "m4.16xlarge": 3.2, "m5.large": 0.096, "m5.xlarge": 0.192, "m5.2xlarge": 0.384, "m5.4xlarge": 0.768, "m5.12xlarge": 2.304, "m5.24xlarge": 4.608, "m5d.large": 0.113, "m5d.xlarge": 0.226, "m5d.2xlarge": 0.452, "m5d.4xlarge": 0.904, "m5d.12xlarge": 2.712, "m5d.24xlarge": 5.424, "p2.xlarge": 0.9, "p2.8xlarge": 7.2, "p2.16xlarge": 14.4, "p3.2xlarge": 3.06, "p3.8xlarge": 12.24, "p3.16xlarge": 24.48, "r3.large": 0.166, "r3.xlarge": 0.333, "r3.2xlarge": 0.665, "r3.4xlarge": 1.33, "r3.8xlarge": 2.66, "r4.large": 0.133, "r4.xlarge": 0.266, "r4.2xlarge": 0.532, "r4.4xlarge": 1.064, "r4.8xlarge": 2.128, "r4.16xlarge": 4.256, "t1.micro": 0.02, "t2.micro": 0.0116, "t2.small": 0.023, "t2.medium": 0.0464, "t2.large": 0.0928, "t2.xlarge": 0.1856, "t2.nano": 0.0058, "t2.2xlarge": 0.3712, "x1.16xlarge": 6.669, "x1.32xlarge": 13.338, "x1e.xlarge": 0.834, "x1e.2xlarge": 1.668, "x1e.4xlarge": 3.336, "x1e.8xlarge": 6.672, "x1e.16xlarge": 13.344, "x1e.32xlarge": 26.688 }, "ec2_us_east_ohio": { "c4.large": 0.1, "c4.xlarge": 0.199, "c4.2xlarge": 0.398, "c4.4xlarge": 0.796, "c4.8xlarge": 1.591, "c5.large": 0.085, "c5.xlarge": 0.17, "c5.2xlarge": 0.34, "c5.4xlarge": 0.68, "c5.9xlarge": 1.53, "c5.18xlarge": 3.06, "c5d.large": 0.096, "c5d.xlarge": 0.192, "c5d.2xlarge": 0.384, "c5d.4xlarge": 0.768, "c5d.9xlarge": 1.728, "c5d.18xlarge": 3.456, "d2.xlarge": 0.69, "d2.2xlarge": 1.38, "d2.4xlarge": 2.76, "d2.8xlarge": 5.52, "g3.4xlarge": 1.14, "g3.8xlarge": 2.28, "g3.16xlarge": 4.56, "h1.2xlarge": 0.468, "h1.4xlarge": 0.936, "h1.8xlarge": 1.872, "h1.16xlarge": 3.744, "i2.xlarge": 0.853, "i2.2xlarge": 1.705, "i2.4xlarge": 3.41, "i2.8xlarge": 6.82, "i3.large": 0.156, "i3.xlarge": 0.312, "i3.metal": 4.992, "i3.2xlarge": 0.624, "i3.4xlarge": 1.248, "i3.8xlarge": 2.496, "i3.16xlarge": 4.992, "m4.large": 0.1, "m4.xlarge": 0.2, "m4.2xlarge": 0.4, "m4.4xlarge": 0.8, "m4.10xlarge": 2.0, "m4.16xlarge": 3.2, "m5.large": 0.096, "m5.xlarge": 0.192, "m5.2xlarge": 0.384, "m5.4xlarge": 0.768, "m5.12xlarge": 2.304, "m5.24xlarge": 4.608, "m5d.large": 0.113, "m5d.xlarge": 0.226, "m5d.2xlarge": 0.452, "m5d.4xlarge": 0.904, "m5d.12xlarge": 2.712, "m5d.24xlarge": 5.424, "p2.xlarge": 0.9, "p2.8xlarge": 7.2, "p2.16xlarge": 14.4, "p3.2xlarge": 3.06, "p3.8xlarge": 12.24, "p3.16xlarge": 24.48, "r3.large": 0.166, "r3.xlarge": 0.333, "r3.2xlarge": 0.665, "r3.4xlarge": 1.33, "r3.8xlarge": 2.66, "r4.large": 0.133, "r4.xlarge": 0.266, "r4.2xlarge": 0.532, "r4.4xlarge": 1.064, "r4.8xlarge": 2.128, "r4.16xlarge": 4.256, "t2.micro": 0.0116, "t2.small": 0.023, "t2.medium": 0.0464, "t2.large": 0.0928, "t2.xlarge": 0.1856, "t2.nano": 0.0058, "t2.2xlarge": 0.3712, "x1.16xlarge": 6.669, "x1.32xlarge": 13.338 }, "ec2_us_govwest": { "c1.medium": 0.157, "c1.xlarge": 0.628, "c3.large": 0.126, "c3.xlarge": 0.252, "c3.2xlarge": 0.504, "c3.4xlarge": 1.008, "c3.8xlarge": 2.016, "c4.large": 0.12, "c4.xlarge": 0.239, "c4.2xlarge": 0.479, "c4.4xlarge": 0.958, "c4.8xlarge": 1.915, "c5.large": 0.102, "c5.xlarge": 0.204, "c5.2xlarge": 0.408, "c5.4xlarge": 0.816, "c5.9xlarge": 1.836, "c5.18xlarge": 3.672, "cc2.8xlarge": 2.25, "d2.xlarge": 0.828, "d2.2xlarge": 1.656, "d2.4xlarge": 3.312, "d2.8xlarge": 6.624, "f1.2xlarge": 1.98, "f1.16xlarge": 15.84, "g3.4xlarge": 1.32, "g3.8xlarge": 2.64, "g3.16xlarge": 5.28, "hs1.8xlarge": 5.52, "i2.xlarge": 1.023, "i2.2xlarge": 2.046, "i2.4xlarge": 4.092, "i2.8xlarge": 8.184, "i3.large": 0.188, "i3.xlarge": 0.376, "i3.metal": 6.016, "i3.2xlarge": 0.752, "i3.4xlarge": 1.504, "i3.8xlarge": 3.008, "i3.16xlarge": 6.016, "m1.small": 0.053, "m1.medium": 0.106, "m1.large": 0.211, "m1.xlarge": 0.423, "m2.xlarge": 0.293, "m2.2xlarge": 0.586, "m2.4xlarge": 1.171, "m3.medium": 0.084, "m3.large": 0.168, "m3.xlarge": 0.336, "m3.2xlarge": 0.672, "m4.large": 0.126, "m4.xlarge": 0.252, "m4.2xlarge": 0.504, "m4.4xlarge": 1.008, "m4.10xlarge": 2.52, "m4.16xlarge": 4.032, "m5.large": 0.121, "m5.xlarge": 0.242, "m5.2xlarge": 0.484, "m5.4xlarge": 0.968, "m5.12xlarge": 2.904, "m5.24xlarge": 5.808, "p2.xlarge": 1.08, "p2.8xlarge": 8.64, "p2.16xlarge": 17.28, "p3.2xlarge": 3.672, "p3.8xlarge": 14.688, "p3.16xlarge": 29.376, "r3.large": 0.2, "r3.xlarge": 0.399, "r3.2xlarge": 0.798, "r3.4xlarge": 1.596, "r3.8xlarge": 3.192, "r4.large": 0.16, "r4.xlarge": 0.319, "r4.2xlarge": 0.638, "r4.4xlarge": 1.277, "r4.8xlarge": 2.554, "r4.16xlarge": 5.107, "t1.micro": 0.024, "t2.micro": 0.0136, "t2.small": 0.0272, "t2.medium": 0.0544, "t2.large": 0.1088, "t2.xlarge": 0.2176, "t2.nano": 0.0068, "t2.2xlarge": 0.4352, "x1.16xlarge": 8.003, "x1.32xlarge": 16.006 }, "ec2_us_west": { "c1.medium": 0.148, "c1.xlarge": 0.592, "c3.large": 0.12, "c3.xlarge": 0.239, "c3.2xlarge": 0.478, "c3.4xlarge": 0.956, "c3.8xlarge": 1.912, "c4.large": 0.124, "c4.xlarge": 0.249, "c4.2xlarge": 0.498, "c4.4xlarge": 0.997, "c4.8xlarge": 1.993, "c5.large": 0.106, "c5.xlarge": 0.212, "c5.2xlarge": 0.424, "c5.4xlarge": 0.848, "c5.9xlarge": 1.908, "c5.18xlarge": 3.816, "d2.xlarge": 0.781, "d2.2xlarge": 1.563, "d2.4xlarge": 3.125, "d2.8xlarge": 6.25, "g2.2xlarge": 0.702, "g2.8xlarge": 2.808, "g3.4xlarge": 1.534, "g3.8xlarge": 3.068, "g3.16xlarge": 6.136, "i2.xlarge": 0.938, "i2.2xlarge": 1.876, "i2.4xlarge": 3.751, "i2.8xlarge": 7.502, "i3.large": 0.172, "i3.xlarge": 0.344, "i3.2xlarge": 0.688, "i3.4xlarge": 1.376, "i3.8xlarge": 2.752, "i3.16xlarge": 5.504, "m1.small": 0.047, "m1.medium": 0.095, "m1.large": 0.19, "m1.xlarge": 0.379, "m2.xlarge": 0.275, "m2.2xlarge": 0.55, "m2.4xlarge": 1.1, "m3.medium": 0.077, "m3.large": 0.154, "m3.xlarge": 0.308, "m3.2xlarge": 0.616, "m4.large": 0.117, "m4.xlarge": 0.234, "m4.2xlarge": 0.468, "m4.4xlarge": 0.936, "m4.10xlarge": 2.34, "m4.16xlarge": 3.744, "m5.large": 0.112, "m5.xlarge": 0.224, "m5.2xlarge": 0.448, "m5.4xlarge": 0.896, "m5.12xlarge": 2.688, "m5.24xlarge": 5.376, "r3.large": 0.185, "r3.xlarge": 0.371, "r3.2xlarge": 0.741, "r3.4xlarge": 1.482, "r3.8xlarge": 2.964, "r4.large": 0.148, "r4.xlarge": 0.296, "r4.2xlarge": 0.593, "r4.4xlarge": 1.186, "r4.8xlarge": 2.371, "r4.16xlarge": 4.742, "t1.micro": 0.025, "t2.micro": 0.0138, "t2.small": 0.0276, "t2.medium": 0.0552, "t2.large": 0.1104, "t2.xlarge": 0.2208, "t2.nano": 0.0069, "t2.2xlarge": 0.4416 }, "ec2_us_west_oregon": { "c1.medium": 0.13, "c1.xlarge": 0.52, "c3.large": 0.105, "c3.xlarge": 0.21, "c3.2xlarge": 0.42, "c3.4xlarge": 0.84, "c3.8xlarge": 1.68, "c4.large": 0.1, "c4.xlarge": 0.199, "c4.2xlarge": 0.398, "c4.4xlarge": 0.796, "c4.8xlarge": 1.591, "c5.large": 0.085, "c5.xlarge": 0.17, "c5.2xlarge": 0.34, "c5.4xlarge": 0.68, "c5.9xlarge": 1.53, "c5.18xlarge": 3.06, "c5d.large": 0.096, "c5d.xlarge": 0.192, "c5d.2xlarge": 0.384, "c5d.4xlarge": 0.768, "c5d.9xlarge": 1.728, "c5d.18xlarge": 3.456, "cc2.8xlarge": 2.0, "cr1.8xlarge": 3.5, "d2.xlarge": 0.69, "d2.2xlarge": 1.38, "d2.4xlarge": 2.76, "d2.8xlarge": 5.52, "f1.2xlarge": 1.65, "f1.16xlarge": 13.2, "g2.2xlarge": 0.65, "g2.8xlarge": 2.6, "g3.4xlarge": 1.14, "g3.8xlarge": 2.28, "g3.16xlarge": 4.56, "h1.2xlarge": 0.468, "h1.4xlarge": 0.936, "h1.8xlarge": 1.872, "h1.16xlarge": 3.744, "hs1.8xlarge": 4.6, "i2.xlarge": 0.853, "i2.2xlarge": 1.705, "i2.4xlarge": 3.41, "i2.8xlarge": 6.82, "i3.large": 0.156, "i3.xlarge": 0.312, "i3.metal": 4.992, "i3.2xlarge": 0.624, "i3.4xlarge": 1.248, "i3.8xlarge": 2.496, "i3.16xlarge": 4.992, "m1.small": 0.044, "m1.medium": 0.087, "m1.large": 0.175, "m1.xlarge": 0.35, "m2.xlarge": 0.245, "m2.2xlarge": 0.49, "m2.4xlarge": 0.98, "m3.medium": 0.067, "m3.large": 0.133, "m3.xlarge": 0.266, "m3.2xlarge": 0.532, "m4.large": 0.1, "m4.xlarge": 0.2, "m4.2xlarge": 0.4, "m4.4xlarge": 0.8, "m4.10xlarge": 2.0, "m4.16xlarge": 3.2, "m5.large": 0.096, "m5.xlarge": 0.192, "m5.2xlarge": 0.384, "m5.4xlarge": 0.768, "m5.12xlarge": 2.304, "m5.24xlarge": 4.608, "m5d.large": 0.113, "m5d.xlarge": 0.226, "m5d.2xlarge": 0.452, "m5d.4xlarge": 0.904, "m5d.12xlarge": 2.712, "m5d.24xlarge": 5.424, "p2.xlarge": 0.9, "p2.8xlarge": 7.2, "p2.16xlarge": 14.4, "p3.2xlarge": 3.06, "p3.8xlarge": 12.24, "p3.16xlarge": 24.48, "r3.large": 0.166, "r3.xlarge": 0.333, "r3.2xlarge": 0.665, "r3.4xlarge": 1.33, "r3.8xlarge": 2.66, "r4.large": 0.133, "r4.xlarge": 0.266, "r4.2xlarge": 0.532, "r4.4xlarge": 1.064, "r4.8xlarge": 2.128, "r4.16xlarge": 4.256, "t1.micro": 0.02, "t2.micro": 0.0116, "t2.small": 0.023, "t2.medium": 0.0464, "t2.large": 0.0928, "t2.xlarge": 0.1856, "t2.nano": 0.0058, "t2.2xlarge": 0.3712, "x1.16xlarge": 6.669, "x1.32xlarge": 13.338, "x1e.xlarge": 0.834, "x1e.2xlarge": 1.668, "x1e.4xlarge": 3.336, "x1e.8xlarge": 6.672, "x1e.16xlarge": 13.344, "x1e.32xlarge": 26.688 }, "elastichosts": { "small": 0.1, "medium": 0.223, "large": 0.378, "extra-large": 0.579, "high-cpu-extra-large": 0.77, "high-cpu-medium": 0.18 }, "gandi": { "small": 0.02, "medium": 0.03, "large": 0.06, "x-large": 0.12, "1": 0.02 }, "gogrid": { "1GB": 0.19, "2GB": 0.38, "4GB": 0.76, "8GB": 1.52, "16GB": 3.04, "24GB": 4.56, "512MB": 0.095 }, "google_asia": { "f1-micro": 0.009, "f1-micro-preemptible": 0.005, "g1-small": 0.03, "g1-small-preemptible": 0.01, "n1-highcpu-2": 0.084, "n1-highcpu-2-preemptible": 0.022, "n1-highcpu-4": 0.168, "n1-highcpu-4-preemptible": 0.044, "n1-highcpu-8": 0.336, "n1-highcpu-8-preemptible": 0.088, "n1-highcpu-16": 0.672, "n1-highcpu-16-preemptible": 0.176, "n1-highcpu-32": 1.344, "n1-highcpu-32-preemptible": 0.352, "n1-highmem-2": 0.139, "n1-highmem-2-preemptible": 0.0385, "n1-highmem-4": 0.278, "n1-highmem-4-preemptible": 0.077, "n1-highmem-8": 0.556, "n1-highmem-8-preemptible": 0.154, "n1-highmem-16": 1.112, "n1-highmem-16-preemptible": 0.308, "n1-highmem-32": 2.224, "n1-highmem-32-preemptible": 0.616, "n1-standard-1": 0.055, "n1-standard-1-preemptible": 0.0165, "n1-standard-2": 0.11, "n1-standard-2-preemptible": 0.033, "n1-standard-4": 0.22, "n1-standard-4-preemptible": 0.066, "n1-standard-8": 0.44, "n1-standard-8-preemptible": 0.132, "n1-standard-16": 0.88, "n1-standard-16-preemptible": 0.264, "n1-standard-32": 1.76, "n1-standard-32-preemptible": 0.528 }, "google_europe": { "f1-micro": 0.009, "f1-micro-preemptible": 0.005, "g1-small": 0.03, "g1-small-preemptible": 0.01, "n1-highcpu-2": 0.084, "n1-highcpu-2-preemptible": 0.022, "n1-highcpu-4": 0.168, "n1-highcpu-4-preemptible": 0.044, "n1-highcpu-8": 0.336, "n1-highcpu-8-preemptible": 0.088, "n1-highcpu-16": 0.672, "n1-highcpu-16-preemptible": 0.176, "n1-highcpu-32": 1.344, "n1-highcpu-32-preemptible": 0.352, "n1-highmem-2": 0.139, "n1-highmem-2-preemptible": 0.0385, "n1-highmem-4": 0.278, "n1-highmem-4-preemptible": 0.077, "n1-highmem-8": 0.556, "n1-highmem-8-preemptible": 0.154, "n1-highmem-16": 1.112, "n1-highmem-16-preemptible": 0.308, "n1-highmem-32": 2.224, "n1-highmem-32-preemptible": 0.616, "n1-standard-1": 0.055, "n1-standard-1-preemptible": 0.0165, "n1-standard-2": 0.11, "n1-standard-2-preemptible": 0.033, "n1-standard-4": 0.22, "n1-standard-4-preemptible": 0.066, "n1-standard-8": 0.44, "n1-standard-8-preemptible": 0.132, "n1-standard-16": 0.88, "n1-standard-16-preemptible": 0.264, "n1-standard-32": 1.76, "n1-standard-32-preemptible": 0.528 }, "google_us": { "f1-micro": 0.008, "f1-micro-preemptible": 0.005, "g1-small": 0.027, "g1-small-preemptible": 0.01, "n1-highcpu-2": 0.076, "n1-highcpu-2-preemptible": 0.02, "n1-highcpu-4": 0.152, "n1-highcpu-4-preemptible": 0.04, "n1-highcpu-8": 0.304, "n1-highcpu-8-preemptible": 0.08, "n1-highcpu-16": 0.608, "n1-highcpu-16-preemptible": 0.16, "n1-highcpu-32": 1.216, "n1-highcpu-32-preemptible": 0.32, "n1-highmem-2": 0.126, "n1-highmem-2-preemptible": 0.035, "n1-highmem-4": 0.252, "n1-highmem-4-preemptible": 0.07, "n1-highmem-8": 0.504, "n1-highmem-8-preemptible": 0.14, "n1-highmem-16": 1.008, "n1-highmem-16-preemptible": 0.28, "n1-highmem-32": 2.016, "n1-highmem-32-preemptible": 0.56, "n1-standard-1": 0.05, "n1-standard-1-preemptible": 0.015, "n1-standard-2": 0.1, "n1-standard-2-preemptible": 0.03, "n1-standard-4": 0.2, "n1-standard-4-preemptible": 0.06, "n1-standard-8": 0.4, "n1-standard-8-preemptible": 0.12, "n1-standard-16": 0.8, "n1-standard-16-preemptible": 0.24, "n1-standard-32": 1.6, "n1-standard-32-preemptible": 0.48 }, "nephoscale": { "1": 0.6, "3": 0.063, "5": 0.031, "7": 0.125, "9": 0.188, "11": 0.35, "27": 0.0, "46": 0.1, "48": 0.15, "50": 0.28, "52": 0.48, "54": 0.938, "56": 0.75 }, "nimbus": { "m1.small": 0.0, "m1.large": 0.0, "m1.xlarge": 0.0 }, "osc_inc_eu_west_1": { "c1.medium": "0.230", "c1.xlarge": "0.900", "cc1.4xlarge": "1.300", "cc2.8xlarge": "2.400", "cr1.8xlarge": "3.500", "m1.small": "0.090", "m1.medium": "0.120", "m1.large": "0.360", "m1.xlarge": "0.730", "m2.xlarge": "0.410", "m2.2xlarge": "0.820", "m2.4xlarge": "1.640", "m3.xlarge": "0.780", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.250", "nv1.large": "5.490", "nv1.xlarge": "5.610", "os1.8xlarge": "4.310", "t1.micro": "0.040" }, "osc_inc_eu_west_2": { "c1.medium": "0.230", "c1.xlarge": "0.900", "cc1.4xlarge": "1.300", "cc2.8xlarge": "2.400", "cr1.8xlarge": "3.500", "m1.small": "0.090", "m1.medium": "0.120", "m1.large": "0.360", "m1.xlarge": "0.730", "m2.xlarge": "0.410", "m2.2xlarge": "0.820", "m2.4xlarge": "1.640", "m3.xlarge": "0.780", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.250", "nv1.large": "5.490", "nv1.xlarge": "5.610", "os1.8xlarge": "4.310", "t1.micro": "0.040" }, "osc_inc_eu_west_3": { "c1.medium": "0.230", "c1.xlarge": "0.900", "cc1.4xlarge": "1.300", "cc2.8xlarge": "2.400", "cr1.8xlarge": "3.500", "m1.small": "0.090", "m1.medium": "0.120", "m1.large": "0.360", "m1.xlarge": "0.730", "m2.xlarge": "0.410", "m2.2xlarge": "0.820", "m2.4xlarge": "1.640", "m3.xlarge": "0.780", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.250", "nv1.large": "5.490", "nv1.xlarge": "5.610", "os1.8xlarge": "4.310", "t1.micro": "0.040" }, "osc_inc_us_east_1": { "c1.medium": "0.150", "c1.xlarge": "0.580", "cc1.4xlarge": "1.610", "cc2.8xlarge": "2.400", "cr1.8xlarge": "3.500", "m1.small": "0.060", "m1.medium": "0.180", "m1.large": "0.240", "m1.xlarge": "0.730", "m2.xlarge": "0.410", "m2.2xlarge": "1.020", "m2.4xlarge": "2.040", "m3.xlarge": "0.500", "m3.2xlarge": "1.560", "nv1.small": "5.190", "nv1.medium": "5.250", "nv1.large": "5.490", "nv1.xlarge": "5.610", "os1.8xlarge": "6.400", "t1.micro": "0.020" }, "osc_inc_us_east_2": { "c1.medium": "0.150", "c1.xlarge": "0.580", "cc1.4xlarge": "1.610", "cc2.8xlarge": "2.400", "cr1.8xlarge": "3.500", "m1.small": "0.060", "m1.medium": "0.180", "m1.large": "0.240", "m1.xlarge": "0.730", "m2.xlarge": "0.410", "m2.2xlarge": "1.020", "m2.4xlarge": "2.040", "m3.xlarge": "0.500", "m3.2xlarge": "1.560", "nv1.small": "5.190", "nv1.medium": "5.250", "nv1.large": "5.490", "nv1.xlarge": "5.610", "os1.8xlarge": "6.400", "t1.micro": "0.020" }, "osc_sas_eu_west_1": { "c1.medium": "0.230", "c1.xlarge": "0.900", "cc1.4xlarge": "1.460", "cc2.8xlarge": "2.700", "cr1.8xlarge": "3.750", "m1.small": "0.090", "m1.medium": "0.130", "m1.large": "0.360", "m1.xlarge": "0.730", "m2.xlarge": "0.460", "m2.2xlarge": "0.920", "m2.4xlarge": "1.840", "m3.xlarge": "0.780", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.310", "nv1.large": "5.490", "nv1.xlarge": "5.860", "os1.8xlarge": "6.400", "t1.micro": "0.040" }, "osc_sas_eu_west_2": { "c1.medium": "0.230", "c1.xlarge": "0.900", "cc1.4xlarge": "1.460", "cc2.8xlarge": "2.700", "cr1.8xlarge": "3.750", "m1.small": "0.090", "m1.medium": "0.130", "m1.large": "0.360", "m1.xlarge": "0.730", "m2.xlarge": "0.460", "m2.2xlarge": "0.920", "m2.4xlarge": "1.840", "m3.xlarge": "0.780", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.310", "nv1.large": "5.490", "nv1.xlarge": "5.860", "os1.8xlarge": "6.400", "t1.micro": "0.040" }, "osc_sas_eu_west_3": { "c1.medium": "0.230", "c1.xlarge": "0.900", "cc1.4xlarge": "1.460", "cc2.8xlarge": "2.700", "cr1.8xlarge": "3.750", "m1.small": "0.090", "m1.medium": "0.130", "m1.large": "0.360", "m1.xlarge": "0.730", "m2.xlarge": "0.460", "m2.2xlarge": "0.920", "m2.4xlarge": "1.840", "m3.xlarge": "0.780", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.310", "nv1.large": "5.490", "nv1.xlarge": "5.860", "os1.8xlarge": "6.400", "t1.micro": "0.040" }, "osc_sas_us_east_1": { "c1.medium": "0.170", "c1.xlarge": "0.660", "cc1.4xlarge": "1.610", "cc2.8xlarge": "2.700", "cr1.8xlarge": "3.750", "m1.small": "0.070", "m1.medium": "0.180", "m1.large": "0.260", "m1.xlarge": "0.730", "m2.xlarge": "0.460", "m2.2xlarge": "1.020", "m2.4xlarge": "2.040", "m3.xlarge": "0.550", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.310", "nv1.large": "5.490", "nv1.xlarge": "5.860", "os1.8xlarge": "6.400", "t1.micro": "0.020" }, "osc_sas_us_east_2": { "c1.medium": "0.170", "c1.xlarge": "0.660", "cc1.4xlarge": "1.610", "cc2.8xlarge": "2.700", "cr1.8xlarge": "3.750", "m1.small": "0.070", "m1.medium": "0.180", "m1.large": "0.260", "m1.xlarge": "0.730", "m2.xlarge": "0.460", "m2.2xlarge": "1.020", "m2.4xlarge": "2.040", "m3.xlarge": "0.550", "m3.2xlarge": "1.560", "nv1.small": "5.220", "nv1.medium": "5.310", "nv1.large": "5.490", "nv1.xlarge": "5.860", "os1.8xlarge": "6.400", "t1.micro": "0.020" }, "packet": { "Type S": 1.5, "Type 0": 0.05, "Type 1": 0.4, "Type 2": 1.25, "Type 2A": 0.5, "Type 3": 1.75 }, "rackspace": { "performance1-1": 0.04, "performance1-2": 0.08, "performance1-4": 0.16, "performance1-8": 0.32, "performance2-15": 0.68, "performance2-30": 1.36, "performance2-60": 2.72, "performance2-90": 4.08, "performance2-120": 5.44, "1": 0.015, "2": 0.03, "3": 0.06, "4": 0.12, "5": 0.24, "6": 0.48, "7": 0.96, "8": 1.8 }, "rackspacenovalon": { "performance1-1": 0.04, "performance1-2": 0.08, "performance1-4": 0.16, "performance1-8": 0.32, "performance2-15": 0.68, "performance2-30": 1.36, "performance2-60": 2.72, "performance2-90": 4.08, "performance2-120": 5.44, "2": 0.032, "3": 0.064, "4": 0.129, "5": 0.258, "6": 0.516, "7": 0.967, "8": 1.612 }, "rackspacenovasyd": { "performance1-1": 0.04, "performance1-2": 0.08, "performance1-4": 0.16, "performance1-8": 0.32, "performance2-15": 0.68, "performance2-30": 1.36, "performance2-60": 2.72, "performance2-90": 4.08, "performance2-120": 5.44, "2": 0.026, "3": 0.072, "4": 0.144, "5": 0.288, "6": 0.576, "7": 1.08, "8": 1.44 }, "rackspacenovaus": { "performance1-1": 0.04, "performance1-2": 0.08, "performance1-4": 0.16, "performance1-8": 0.32, "performance2-15": 0.68, "performance2-30": 1.36, "performance2-60": 2.72, "performance2-90": 4.08, "performance2-120": 5.44, "2": 0.022, "3": 0.06, "4": 0.12, "5": 0.24, "6": 0.48, "7": 0.96, "8": 1.2 }, "serverlove": { "small": 0.161, "medium": 0.404, "large": 0.534, "extra-large": 0.615, "high-cpu-extra-large": 0.776, "high-cpu-medium": 0.291 }, "skalicloud": { "small": 0.136, "medium": 0.301, "large": 0.505, "extra-large": 0.654, "high-cpu-extra-large": 0.936, "high-cpu-medium": 0.249 }, "softlayer": { "0": 0.023, "1": 0.024, "2": 0.024, "3": 0.026, "4": 0.045, "5": 0.045, "6": 0.045, "7": 0.09, "8": 0.09, "9": 0.09, "10": 0.09, "11": 0.205, "12": 0.205 }, "vps_net": { "1": 0.416 } }, "storage": {}, "updated": 1573685574 }apache-libcloud-2.8.0/libcloud/dns/0000775000175000017500000000000013600223624017002 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/dns/__init__.py0000664000175000017500000000000013535474530021114 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/dns/base.py0000664000175000017500000003522013535474530020303 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import datetime from libcloud import __version__ from libcloud.common.base import ConnectionUserAndKey, BaseDriver from libcloud.dns.types import RecordType __all__ = [ 'Zone', 'Record', 'DNSDriver' ] class Zone(object): """ DNS zone. """ def __init__(self, id, domain, type, ttl, driver, extra=None): """ :param id: Zone id. :type id: ``str`` :param domain: The name of the domain. :type domain: ``str`` :param type: Zone type (master, slave). :type type: ``str`` :param ttl: Default TTL for records in this zone (in seconds). :type ttl: ``int`` :param driver: DNSDriver instance. :type driver: :class:`DNSDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.domain = domain self.type = type self.ttl = ttl or None self.driver = driver self.extra = extra or {} def list_records(self): return self.driver.list_records(zone=self) def create_record(self, name, type, data, extra=None): return self.driver.create_record(name=name, zone=self, type=type, data=data, extra=extra) def update(self, domain=None, type=None, ttl=None, extra=None): return self.driver.update_zone(zone=self, domain=domain, type=type, ttl=ttl, extra=extra) def delete(self): return self.driver.delete_zone(zone=self) def export_to_bind_format(self): return self.driver.export_zone_to_bind_format(zone=self) def export_to_bind_zone_file(self, file_path): self.driver.export_zone_to_bind_zone_file(zone=self, file_path=file_path) def __repr__(self): return ('' % (self.domain, self.ttl, self.driver.name)) class Record(object): """ Zone record / resource. """ def __init__(self, id, name, type, data, zone, driver, ttl=None, extra=None): """ :param id: Record id :type id: ``str`` :param name: Hostname or FQDN. :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param zone: Zone instance. :type zone: :class:`Zone` :param driver: DNSDriver instance. :type driver: :class:`DNSDriver` :param ttl: Record TTL. :type ttl: ``int`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.name = name self.type = type self.data = data self.zone = zone self.driver = driver self.ttl = ttl self.extra = extra or {} def update(self, name=None, type=None, data=None, extra=None): return self.driver.update_record(record=self, name=name, type=type, data=data, extra=extra) def delete(self): return self.driver.delete_record(record=self) def _get_numeric_id(self): record_id = self.id if record_id.isdigit(): record_id = int(record_id) return record_id def __repr__(self): zone = self.zone.domain if self.zone.domain else self.zone.id return ('' % (zone, self.name, self.type, self.data, self.driver.name, self.ttl)) class DNSDriver(BaseDriver): """ A base DNSDriver class to derive from This class is always subclassed by a specific driver. """ connectionCls = ConnectionUserAndKey name = None website = None # Map libcloud record type enum to provider record type name RECORD_TYPE_MAP = {} def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs): """ :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Some providers only support HTTPS, and it is on by default. :type secure: ``bool`` :param host: Override hostname used for connections. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :return: ``None`` """ super(DNSDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def list_record_types(self): """ Return a list of RecordType objects supported by the provider. :return: ``list`` of :class:`RecordType` """ return list(self.RECORD_TYPE_MAP.keys()) def iterate_zones(self): """ Return a generator to iterate over available zones. :rtype: ``generator`` of :class:`Zone` """ raise NotImplementedError( 'iterate_zones not implemented for this driver') def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ return list(self.iterate_zones()) def iterate_records(self, zone): """ Return a generator to iterate over records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :rtype: ``generator`` of :class:`Record` """ raise NotImplementedError( 'iterate_records not implemented for this driver') def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ return list(self.iterate_records(zone)) def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ raise NotImplementedError( 'get_zone not implemented for this driver') def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ raise NotImplementedError( 'get_record not implemented for this driver') def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (master / slave). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Zone` """ raise NotImplementedError( 'create_zone not implemented for this driver') def update_zone(self, zone, domain, type='master', ttl=None, extra=None): """ Update an existing zone. :param zone: Zone to update. :type zone: :class:`Zone` :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (master / slave). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Zone` """ raise NotImplementedError( 'update_zone not implemented for this driver') def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ raise NotImplementedError( 'create_record not implemented for this driver') def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` """ raise NotImplementedError( 'update_record not implemented for this driver') def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ raise NotImplementedError( 'delete_zone not implemented for this driver') def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ raise NotImplementedError( 'delete_record not implemented for this driver') def export_zone_to_bind_format(self, zone): """ Export Zone object to the BIND compatible format. :param zone: Zone to export. :type zone: :class:`Zone` :return: Zone data in BIND compatible format. :rtype: ``str`` """ if zone.type != 'master': raise ValueError('You can only generate BIND out for master zones') lines = [] # For consistent output, records are sorted based on the id records = zone.list_records() records = sorted(records, key=Record._get_numeric_id) date = datetime.datetime.now().strftime('%Y-%m-%d %H:%m:%S') values = {'version': __version__, 'date': date} lines.append('; Generated by Libcloud v%(version)s on %(date)s' % values) lines.append('$ORIGIN %(domain)s.' % {'domain': zone.domain}) lines.append('$TTL %(domain_ttl)s\n' % {'domain_ttl': zone.ttl}) for record in records: line = self._get_bind_record_line(record=record) lines.append(line) output = '\n'.join(lines) return output def export_zone_to_bind_zone_file(self, zone, file_path): """ Export Zone object to the BIND compatible format and write result to a file. :param zone: Zone to export. :type zone: :class:`Zone` :param file_path: File path where the output will be saved. :type file_path: ``str`` """ result = self.export_zone_to_bind_format(zone=zone) with open(file_path, 'w') as fp: fp.write(result) def _get_bind_record_line(self, record): """ Generate BIND record line for the provided record. :param record: Record to generate the line for. :type record: :class:`Record` :return: Bind compatible record line. :rtype: ``str`` """ parts = [] if record.name: name = '%(name)s.%(domain)s' % {'name': record.name, 'domain': record.zone.domain} else: name = record.zone.domain name += '.' ttl = record.extra['ttl'] if 'ttl' in record.extra else record.zone.ttl ttl = str(ttl) data = record.data if record.type in [RecordType.CNAME, RecordType.DNAME, RecordType.MX, RecordType.PTR, RecordType.SRV]: # Make sure trailing dot is present if data[len(data) - 1] != '.': data += '.' if record.type in [RecordType.TXT, RecordType.SPF] and ' ' in data: # Escape the quotes data = data.replace('"', '\\"') # Quote the string data = '"%s"' % (data) if record.type in [RecordType.MX, RecordType.SRV]: priority = str(record.extra['priority']) parts = [name, ttl, 'IN', record.type, priority, data] else: parts = [name, ttl, 'IN', record.type, data] line = '\t'.join(parts) return line def _string_to_record_type(self, string): """ Return a string representation of a DNS record type to a libcloud RecordType ENUM. :rtype: ``str`` """ string = string.upper() record_type = getattr(RecordType, string) return record_type apache-libcloud-2.8.0/libcloud/dns/drivers/0000775000175000017500000000000013600223624020460 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/dns/drivers/__init__.py0000664000175000017500000000000013535474530022572 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/dns/drivers/auroradns.py0000664000175000017500000005324513535474530023054 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ AuroraDNS DNS Driver """ import base64 import json import hmac import datetime from hashlib import sha256 from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.common.types import InvalidCredsError, ProviderError from libcloud.common.types import LibcloudError from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import RecordType, ZoneDoesNotExistError from libcloud.dns.types import ZoneAlreadyExistsError, RecordDoesNotExistError API_HOST = 'api.auroradns.eu' # Default TTL required by libcloud, but doesn't do anything in AuroraDNS DEFAULT_ZONE_TTL = 3600 DEFAULT_ZONE_TYPE = 'master' VALID_RECORD_PARAMS_EXTRA = ['ttl', 'prio', 'health_check_id', 'disabled'] class AuroraDNSHealthCheckType(object): """ Healthcheck type. """ HTTP = 'HTTP' HTTPS = 'HTTPS' TCP = 'TCP' class HealthCheckError(LibcloudError): error_type = 'HealthCheckError' def __init__(self, value, driver, health_check_id): self.health_check_id = health_check_id super(HealthCheckError, self).__init__(value=value, driver=driver) def __str__(self): return self.__repr__() def __repr__(self): return ('<%s in %s, health_check_id=%s, value=%s>' % (self.error_type, repr(self.driver), self.health_check_id, self.value)) class HealthCheckDoesNotExistError(HealthCheckError): error_type = 'HealthCheckDoesNotExistError' class AuroraDNSHealthCheck(object): """ AuroraDNS Healthcheck resource. """ def __init__(self, id, type, hostname, ipaddress, port, interval, path, threshold, health, enabled, zone, driver, extra=None): """ :param id: Healthcheck id :type id: ``str`` :param hostname: Hostname or FQDN of the target :type hostname: ``str`` :param ipaddress: IPv4 or IPv6 address of the target :type ipaddress: ``str`` :param port: The port on the target to monitor :type port: ``int`` :param interval: The interval of the health check :type interval: ``int`` :param path: The path to monitor on the target :type path: ``str`` :param threshold: The threshold of before marking a check as failed :type threshold: ``int`` :param health: The current health of the health check :type health: ``bool`` :param enabled: If the health check is currently enabled :type enabled: ``bool`` :param zone: Zone instance. :type zone: :class:`Zone` :param driver: DNSDriver instance. :type driver: :class:`DNSDriver` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` """ self.id = str(id) if id else None self.type = type self.hostname = hostname self.ipaddress = ipaddress self.port = int(port) if port else None self.interval = int(interval) self.path = path self.threshold = int(threshold) self.health = bool(health) self.enabled = bool(enabled) self.zone = zone self.driver = driver self.extra = extra or {} def update(self, type=None, hostname=None, ipaddress=None, port=None, interval=None, path=None, threshold=None, enabled=None, extra=None): return self.driver.ex_update_healthcheck(healthcheck=self, type=type, hostname=hostname, ipaddress=ipaddress, port=port, path=path, interval=interval, threshold=threshold, enabled=enabled, extra=extra) def delete(self): return self.driver.ex_delete_healthcheck(healthcheck=self) def __repr__(self): return ('' % (self.zone.id, self.id, self.type, self.hostname, self.ipaddress, self.port, self.interval, self.health, self.driver.name)) class AuroraDNSResponse(JsonResponse): def success(self): return self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def parse_error(self): status = int(self.status) error = {'driver': self, 'value': ''} if status == httplib.UNAUTHORIZED: error['value'] = 'Authentication failed' raise InvalidCredsError(**error) elif status == httplib.FORBIDDEN: error['value'] = 'Authorization failed' error['http_status'] = status raise ProviderError(**error) elif status == httplib.NOT_FOUND: context = self.connection.context if context['resource'] == 'zone': error['zone_id'] = context['id'] raise ZoneDoesNotExistError(**error) elif context['resource'] == 'record': error['record_id'] = context['id'] raise RecordDoesNotExistError(**error) elif context['resource'] == 'healthcheck': error['health_check_id'] = context['id'] raise HealthCheckDoesNotExistError(**error) elif status == httplib.CONFLICT: context = self.connection.context if context['resource'] == 'zone': error['zone_id'] = context['id'] raise ZoneAlreadyExistsError(**error) elif status == httplib.BAD_REQUEST: context = self.connection.context body = self.parse_body() raise ProviderError(value=body['errormsg'], http_code=status, driver=self) class AuroraDNSConnection(ConnectionUserAndKey): host = API_HOST responseCls = AuroraDNSResponse def calculate_auth_signature(self, secret_key, method, url, timestamp): b64_hmac = base64.b64encode( hmac.new(b(secret_key), b(method) + b(url) + b(timestamp), digestmod=sha256).digest() ) return b64_hmac.decode('utf-8') def gen_auth_header(self, api_key, secret_key, method, url, timestamp): signature = self.calculate_auth_signature(secret_key, method, url, timestamp) auth_b64 = base64.b64encode(b('%s:%s' % (api_key, signature))) return 'AuroraDNSv1 %s' % (auth_b64.decode('utf-8')) def request(self, action, params=None, data='', headers=None, method='GET'): if not headers: headers = {} if not params: params = {} if method in ("POST", "PUT"): headers = {'Content-Type': 'application/json; charset=UTF-8'} t = datetime.datetime.utcnow() timestamp = t.strftime('%Y%m%dT%H%M%SZ') headers['X-AuroraDNS-Date'] = timestamp headers['Authorization'] = self.gen_auth_header(self.user_id, self.key, method, action, timestamp) return super(AuroraDNSConnection, self).request(action=action, params=params, data=data, method=method, headers=headers) class AuroraDNSDriver(DNSDriver): name = 'AuroraDNS' website = 'https://www.pcextreme.nl/en/aurora/dns' connectionCls = AuroraDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.SOA: 'SOA', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', RecordType.DS: 'DS', RecordType.PTR: 'PTR', RecordType.SSHFP: 'SSHFP', RecordType.TLSA: 'TLSA' } HEALTHCHECK_TYPE_MAP = { AuroraDNSHealthCheckType.HTTP: 'HTTP', AuroraDNSHealthCheckType.HTTPS: 'HTTPS', AuroraDNSHealthCheckType.TCP: 'TCP' } def iterate_zones(self): res = self.connection.request('/zones') for zone in res.parse_body(): yield self.__res_to_zone(zone) def iterate_records(self, zone): self.connection.set_context({'resource': 'zone', 'id': zone.id}) res = self.connection.request('/zones/%s/records' % zone.id) for record in res.parse_body(): yield self.__res_to_record(zone, record) def get_zone(self, zone_id): self.connection.set_context({'resource': 'zone', 'id': zone_id}) res = self.connection.request('/zones/%s' % zone_id) zone = res.parse_body() return self.__res_to_zone(zone) def get_record(self, zone_id, record_id): self.connection.set_context({'resource': 'record', 'id': record_id}) res = self.connection.request('/zones/%s/records/%s' % (zone_id, record_id)) record = res.parse_body() zone = self.get_zone(zone_id) return self.__res_to_record(zone, record) def create_zone(self, domain, type='master', ttl=None, extra=None): self.connection.set_context({'resource': 'zone', 'id': domain}) res = self.connection.request('/zones', method='POST', data=json.dumps({'name': domain})) zone = res.parse_body() return self.__res_to_zone(zone) def create_record(self, name, zone, type, data, extra=None): if name is None: name = "" rdata = { 'name': name, 'type': self.RECORD_TYPE_MAP[type], 'content': data } rdata = self.__merge_extra_data(rdata, extra) if 'ttl' not in rdata: rdata['ttl'] = DEFAULT_ZONE_TTL self.connection.set_context({'resource': 'zone', 'id': zone.id}) res = self.connection.request('/zones/%s/records' % zone.id, method='POST', data=json.dumps(rdata)) record = res.parse_body() return self.__res_to_record(zone, record) def delete_zone(self, zone): self.connection.set_context({'resource': 'zone', 'id': zone.id}) self.connection.request('/zones/%s' % zone.id, method='DELETE') return True def delete_record(self, record): self.connection.set_context({'resource': 'record', 'id': record.id}) self.connection.request('/zones/%s/records/%s' % (record.zone.id, record.id), method='DELETE') return True def list_record_types(self): types = [] for record_type in self.RECORD_TYPE_MAP.keys(): types.append(record_type) return types def update_record(self, record, name, type, data, extra=None): rdata = {} if name is not None: rdata['name'] = name if type is not None: rdata['type'] = self.RECORD_TYPE_MAP[type] if data is not None: rdata['content'] = data rdata = self.__merge_extra_data(rdata, extra) self.connection.set_context({'resource': 'record', 'id': record.id}) self.connection.request('/zones/%s/records/%s' % (record.zone.id, record.id), method='PUT', data=json.dumps(rdata)) return self.get_record(record.zone.id, record.id) def ex_list_healthchecks(self, zone): """ List all Health Checks in a zone. :param zone: Zone to list health checks for. :type zone: :class:`Zone` :return: ``list`` of :class:`AuroraDNSHealthCheck` """ healthchecks = [] self.connection.set_context({'resource': 'zone', 'id': zone.id}) res = self.connection.request('/zones/%s/health_checks' % zone.id) for healthcheck in res.parse_body(): healthchecks.append(self.__res_to_healthcheck(zone, healthcheck)) return healthchecks def ex_get_healthcheck(self, zone, health_check_id): """ Get a single Health Check from a zone :param zone: Zone in which the health check is :type zone: :class:`Zone` :param health_check_id: ID of the required health check :type health_check_id: ``str`` :return: :class:`AuroraDNSHealthCheck` """ self.connection.set_context({'resource': 'healthcheck', 'id': health_check_id}) res = self.connection.request('/zones/%s/health_checks/%s' % (zone.id, health_check_id)) check = res.parse_body() return self.__res_to_healthcheck(zone, check) def ex_create_healthcheck(self, zone, type, hostname, port, path, interval, threshold, ipaddress=None, enabled=True, extra=None): """ Create a new Health Check in a zone :param zone: Zone in which the health check should be created :type zone: :class:`Zone` :param type: The type of health check to be created :type type: :class:`AuroraDNSHealthCheckType` :param hostname: The hostname of the target to monitor :type hostname: ``str`` :param port: The port of the target to monitor. E.g. 80 for HTTP :type port: ``int`` :param path: The path of the target to monitor. Only used by HTTP at this moment. Usually this is simple /. :type path: ``str`` :param interval: The interval of checks. 10, 30 or 60 seconds. :type interval: ``int`` :param threshold: The threshold of failures before the healthcheck is marked as failed. :type threshold: ``int`` :param ipaddress: (optional) The IP Address of the target to monitor. You can pass a empty string if this is not required. :type ipaddress: ``str`` :param enabled: (optional) If this healthcheck is enabled to run :type enabled: ``bool`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :return: :class:`AuroraDNSHealthCheck` """ cdata = { 'type': self.HEALTHCHECK_TYPE_MAP[type], 'hostname': hostname, 'ipaddress': ipaddress, 'port': int(port), 'interval': int(interval), 'path': path, 'threshold': int(threshold), 'enabled': enabled } self.connection.set_context({'resource': 'zone', 'id': zone.id}) res = self.connection.request('/zones/%s/health_checks' % zone.id, method='POST', data=json.dumps(cdata)) healthcheck = res.parse_body() return self.__res_to_healthcheck(zone, healthcheck) def ex_update_healthcheck(self, healthcheck, type=None, hostname=None, ipaddress=None, port=None, path=None, interval=None, threshold=None, enabled=None, extra=None): """ Update an existing Health Check :param zone: The healthcheck which has to be updated :type zone: :class:`AuroraDNSHealthCheck` :param type: (optional) The type of health check to be created :type type: :class:`AuroraDNSHealthCheckType` :param hostname: (optional) The hostname of the target to monitor :type hostname: ``str`` :param ipaddress: (optional) The IP Address of the target to monitor. You can pass a empty string if this is not required. :type ipaddress: ``str`` :param port: (optional) The port of the target to monitor. E.g. 80 for HTTP :type port: ``int`` :param path: (optional) The path of the target to monitor. Only used by HTTP at this moment. Usually just '/'. :type path: ``str`` :param interval: (optional) The interval of checks. 10, 30 or 60 seconds. :type interval: ``int`` :param threshold: (optional) The threshold of failures before the healthcheck is marked as failed. :type threshold: ``int`` :param enabled: (optional) If this healthcheck is enabled to run :type enabled: ``bool`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :return: :class:`AuroraDNSHealthCheck` """ cdata = {} if type is not None: cdata['type'] = self.HEALTHCHECK_TYPE_MAP[type] if hostname is not None: cdata['hostname'] = hostname if ipaddress is not None: if len(ipaddress) == 0: cdata['ipaddress'] = None else: cdata['ipaddress'] = ipaddress if port is not None: cdata['port'] = int(port) if path is not None: cdata['path'] = path if interval is not None: cdata['interval'] = int(interval) if threshold is not None: cdata['threshold'] = threshold if enabled is not None: cdata['enabled'] = bool(enabled) self.connection.set_context({'resource': 'healthcheck', 'id': healthcheck.id}) self.connection.request('/zones/%s/health_checks/%s' % (healthcheck.zone.id, healthcheck.id), method='PUT', data=json.dumps(cdata)) return self.ex_get_healthcheck(healthcheck.zone, healthcheck.id) def ex_delete_healthcheck(self, healthcheck): """ Remove an existing Health Check :param zone: The healthcheck which has to be removed :type zone: :class:`AuroraDNSHealthCheck` """ self.connection.set_context({'resource': 'healthcheck', 'id': healthcheck.id}) self.connection.request('/zones/%s/health_checks/%s' % (healthcheck.zone.id, healthcheck.id), method='DELETE') return True def __res_to_record(self, zone, record): if len(record['name']) == 0: name = None else: name = record['name'] extra = {} extra['created'] = record['created'] extra['modified'] = record['modified'] extra['disabled'] = record['disabled'] extra['ttl'] = record['ttl'] extra['priority'] = record['prio'] return Record(id=record['id'], name=name, type=record['type'], data=record['content'], zone=zone, driver=self.connection.driver, ttl=record['ttl'], extra=extra) def __res_to_zone(self, zone): return Zone(id=zone['id'], domain=zone['name'], type=DEFAULT_ZONE_TYPE, ttl=DEFAULT_ZONE_TTL, driver=self.connection.driver, extra={'created': zone['created'], 'servers': zone['servers'], 'account_id': zone['account_id'], 'cluster_id': zone['cluster_id']}) def __res_to_healthcheck(self, zone, healthcheck): return AuroraDNSHealthCheck(id=healthcheck['id'], type=healthcheck['type'], hostname=healthcheck['hostname'], ipaddress=healthcheck['ipaddress'], health=healthcheck['health'], threshold=healthcheck['threshold'], path=healthcheck['path'], interval=healthcheck['interval'], port=healthcheck['port'], enabled=healthcheck['enabled'], zone=zone, driver=self.connection.driver) def __merge_extra_data(self, rdata, extra): if extra is not None: for param in VALID_RECORD_PARAMS_EXTRA: if param in extra: rdata[param] = extra[param] return rdata apache-libcloud-2.8.0/libcloud/dns/drivers/buddyns.py0000664000175000017500000001112613570310635022510 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ BuddyNS DNS Driver """ try: import simplejson as json except ImportError: import json from libcloud.dns.types import Provider, ZoneDoesNotExistError,\ ZoneAlreadyExistsError from libcloud.dns.base import DNSDriver, Zone from libcloud.common.buddyns import BuddyNSConnection, BuddyNSResponse,\ BuddyNSException __all__ = [ 'BuddyNSDNSDriver' ] class BuddyNSDNSResponse(BuddyNSResponse): pass class BuddyNSDNSConnection(BuddyNSConnection): responseCls = BuddyNSDNSResponse class BuddyNSDNSDriver(DNSDriver): name = 'BuddyNS DNS' website = 'https://www.buddyns.com' type = Provider.BUDDYNS connectionCls = BuddyNSDNSConnection def list_zones(self): action = '/api/v2/zone/' response = self.connection.request(action=action, method='GET') zones = self._to_zones(items=response.parse_body()) return zones def get_zone(self, zone_id): """ :param zone_id: Zone domain name (e.g. example.com) :return: :class:`Zone` """ action = '/api/v2/zone/%s' % zone_id try: response = self.connection.request(action=action, method='GET') except BuddyNSException as e: if e.message == 'Not found': raise ZoneDoesNotExistError(value=e.message, driver=self, zone_id=zone_id) else: raise e zone = self._to_zone(response.parse_body()) return zone def create_zone(self, domain, type='master', ttl=None, extra=None): """ :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (This is not really used. See API docs for extra parameters) :type type: ``str`` :param ttl: TTL for new records (This is used through the extra param) :type ttl: ``int`` :param extra: Extra attributes that are specific to the driver such as ttl. :type extra: ``dict`` :rtype: :class:`Zone` Do not forget to pass the master in extra, extra = {'master':'65.55.37.62'} for example. """ action = '/api/v2/zone/' data = {'name': domain} if extra is not None: data.update(extra) post_data = json.dumps(data) try: response = self.connection.request(action=action, method='POST', data=post_data) except BuddyNSException as e: if e.message == 'Invalid zone submitted for addition.': raise ZoneAlreadyExistsError(value=e.message, driver=self, zone_id=domain) else: raise e zone = self._to_zone(response.parse_body()) return zone def delete_zone(self, zone): """ :param zone: Zone to be deleted. :type zone: :class:`Zone` :return: Boolean """ action = '/api/v2/zone/%s' % zone.domain try: self.connection.request(action=action, method='DELETE') except BuddyNSException as e: if e.message == 'Not found': raise ZoneDoesNotExistError(value=e.message, driver=self, zone_id=zone.id) else: raise e return True def _to_zone(self, item): common_keys = ['name', ] extra = {} for key in item: if key not in common_keys: extra[key] = item.get(key) zone = Zone(domain=item['name'], id=item['name'], type=None, extra=extra, ttl=None, driver=self) return zone def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones apache-libcloud-2.8.0/libcloud/dns/drivers/cloudflare.py0000664000175000017500000003432513570310635023166 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'CloudFlareDNSDriver' ] import itertools import json from libcloud.common.base import JsonResponse, ConnectionUserAndKey from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import RecordAlreadyExistsError, ZoneAlreadyExistsError from libcloud.dns.types import RecordDoesNotExistError, ZoneDoesNotExistError from libcloud.utils.misc import merge_valid_keys, reverse_dict API_HOST = 'api.cloudflare.com' API_BASE = '/client/v4' CLOUDFLARE_TO_LIBCLOUD_ZONE_TYPE = { 'full': 'master', 'partial': 'slave', } LIBCLOUD_TO_CLOUDFLARE_ZONE_TYPE = reverse_dict( CLOUDFLARE_TO_LIBCLOUD_ZONE_TYPE) ZONE_EXTRA_ATTRIBUTES = { 'development_mode', 'original_name_servers', 'original_registrar', 'original_dnshost', 'created_on', 'modified_on', 'activated_on', 'owner', 'account', 'permissions', 'plan', 'plan_pending', 'status', 'paused', 'name_servers', } ZONE_UPDATE_ATTRIBUTES = { 'paused', 'vanity_name_servers', 'plan', } ZONE_CREATE_ATTRIBUTES = { 'jump_start', } RECORD_EXTRA_ATTRIBUTES = { 'proxiable', 'proxied', 'locked', 'created_on', 'modified_on', 'data', } RECORD_CREATE_ATTRIBUTES = { 'ttl', 'priority', 'proxied', } RECORD_UPDATE_ATTRIBUTES = { 'ttl', 'proxied', } class CloudFlareDNSResponse(JsonResponse): exceptions = { 9103: (InvalidCredsError, []), 1001: (ZoneDoesNotExistError, ['zone_id']), 1061: (ZoneAlreadyExistsError, ['zone_id']), 1002: (RecordDoesNotExistError, ['record_id']), 81053: (RecordAlreadyExistsError, ['record_id']), } def success(self): body = self.parse_body() is_success = body.get('success', False) return is_success def parse_error(self): body = self.parse_body() errors = body.get('errors', []) for error in errors: try: exception_class, context = self.exceptions[error['code']] except KeyError: exception_class, context = LibcloudError, [] kwargs = { 'value': '{}: {}'.format(error['code'], error['message']), 'driver': self.connection.driver, } merge_valid_keys(kwargs, context, self.connection.context) raise exception_class(**kwargs) class CloudFlareDNSConnection(ConnectionUserAndKey): host = API_HOST secure = True responseCls = CloudFlareDNSResponse def add_default_headers(self, headers): headers['Content-Type'] = 'application/json' headers['X-Auth-Email'] = self.user_id headers['X-Auth-Key'] = self.key return headers def encode_data(self, data): return json.dumps(data) class CloudFlareDNSDriver(DNSDriver): type = Provider.CLOUDFLARE name = 'CloudFlare DNS' website = 'https://www.cloudflare.com' connectionCls = CloudFlareDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.TXT: 'TXT', RecordType.SPF: 'SPF', RecordType.NS: 'NS', RecordType.SRV: 'SRV', RecordType.URL: 'LOC' } ZONES_PAGE_SIZE = 50 RECORDS_PAGE_SIZE = 100 MEMBERSHIPS_PAGE_SIZE = 50 def iterate_zones(self): def _iterate_zones(params): url = '{}/zones'.format(API_BASE) response = self.connection.request(url, params=params) items = response.object['result'] zones = [self._to_zone(item) for item in items] return response, zones return self._paginate(_iterate_zones, self.ZONES_PAGE_SIZE) def iterate_records(self, zone): def _iterate_records(params): url = '{}/zones/{}/dns_records'.format(API_BASE, zone.id) self.connection.set_context({'zone_id': zone.id}) response = self.connection.request(url, params=params) items = response.object['result'] records = [self._to_record(zone, item) for item in items] return response, records return self._paginate(_iterate_records, self.RECORDS_PAGE_SIZE) def get_zone(self, zone_id): url = '{}/zones/{}'.format(API_BASE, zone_id) self.connection.set_context({'zone_id': zone_id}) response = self.connection.request(url) item = response.object['result'] zone = self._to_zone(item) return zone def create_zone(self, domain, type='master', ttl=None, extra=None): """ @inherits: :class:`DNSDriver.create_zone` Note that for users who have more than one account membership, the id of the account in which to create the zone must be specified via the ``extra`` key ``account``. Note that for ``extra`` zone properties, only the ones specified in ``ZONE_CREATE_ATTRIBUTES`` can be set at creation time. Additionally, setting the ``ttl` property is not supported. """ extra = extra or {} account = extra.get('account') if account is None: memberships = self.ex_get_user_account_memberships() memberships = list(itertools.islice(memberships, 2)) if len(memberships) != 1: raise ValueError('must specify account for zone') account = memberships[0]['account']['id'] url = '{}/zones'.format(API_BASE) body = { 'name': domain, 'account': { 'id': account }, 'type': LIBCLOUD_TO_CLOUDFLARE_ZONE_TYPE[type] } merge_valid_keys(body, ZONE_CREATE_ATTRIBUTES, extra) response = self.connection.request(url, data=body, method='POST') item = response.object['result'] zone = self._to_zone(item) return zone def update_zone(self, zone, domain, type='master', ttl=None, extra=None): """ @inherits: :class:`DNSDriver.update_zone` Note that the ``zone``, ``type`` and ``ttl`` properties can't be updated. The only updatable properties are the ``extra`` zone properties specified in ``ZONE_UPDATE_ATTRIBUTES``. Only one property may be updated at a time. Any non-updatable properties are ignored. """ body = merge_valid_keys({}, ZONE_UPDATE_ATTRIBUTES, extra) if len(body) != 1: return zone url = '{}/zones/{}'.format(API_BASE, zone.id) self.connection.set_context({'zone_id': zone.id}) response = self.connection.request(url, data=body, method='PATCH') item = response.object['result'] zone = self._to_zone(item) return zone def delete_zone(self, zone): url = '{}/zones/{}'.format(API_BASE, zone.id) self.connection.set_context({'zone_id': zone.id}) response = self.connection.request(url, method='DELETE') item = response.object.get('result', {}).get('id') is_deleted = item == zone.id return is_deleted def get_record(self, zone_id, record_id): zone = self.get_zone(zone_id) url = '{}/zones/{}/dns_records/{}'.format(API_BASE, zone.id, record_id) self.connection.set_context({'record_id': record_id}) response = self.connection.request(url) item = response.object['result'] record = self._to_record(zone, item) return record def create_record(self, name, zone, type, data, extra=None): """ @inherits: :class:`DNSDriver.create_record` Note that for ``extra`` record properties, only the ones specified in ``RECORD_CREATE_ATTRIBUTES`` can be set at creation time. Any non-settable properties are ignored. """ url = '{}/zones/{}/dns_records'.format(API_BASE, zone.id) body = { 'type': type, 'name': name, 'content': data, } merge_valid_keys(body, RECORD_CREATE_ATTRIBUTES, extra) self.connection.set_context({'zone_id': zone.id}) response = self.connection.request(url, data=body, method='POST') item = response.object['result'] record = self._to_record(zone, item) return record def update_record(self, record, name=None, type=None, data=None, extra=None): """ @inherits: :class:`DNSDriver.update_record` Note that for ``extra`` record properties, only the ones specified in ``RECORD_UPDATE_ATTRIBUTES`` can be updated. Any non-updatable properties are ignored. """ url = '{}/zones/{}/dns_records/{}'.format(API_BASE, record.zone.id, record.id) body = { 'type': record.type if type is None else type, 'name': record.name if name is None else name, 'content': record.data if data is None else data, 'extra': record.extra or {}, } merge_valid_keys(body['extra'], RECORD_UPDATE_ATTRIBUTES, extra) self.connection.set_context({'record_id': record.id}) response = self.connection.request(url, data=body, method='PUT') item = response.object['result'] record = self._to_record(record.zone, item) return record def delete_record(self, record): url = '{}/zones/{}/dns_records/{}'.format(API_BASE, record.zone.id, record.id) self.connection.set_context({'record_id': record.id}) response = self.connection.request(url, method='DELETE') item = response.object.get('result', {}).get('id') is_deleted = item == record.id return is_deleted def ex_get_user_account_memberships(self): def _ex_get_user_account_memberships(params): url = '{}/memberships'.format(API_BASE) response = self.connection.request(url, params=params) return response, response.object['result'] return self._paginate(_ex_get_user_account_memberships, self.MEMBERSHIPS_PAGE_SIZE) def ex_get_zone_stats(self, zone, interval=30): raise NotImplementedError('not yet implemented in v4 driver') def ex_zone_check(self, zones): raise NotImplementedError('not yet implemented in v4 driver') def ex_get_ip_threat_score(self, ip): raise NotImplementedError('not yet implemented in v4 driver') def ex_get_zone_settings(self, zone): raise NotImplementedError('not yet implemented in v4 driver') def ex_set_zone_security_level(self, zone, level): raise NotImplementedError('not yet implemented in v4 driver') def ex_set_zone_cache_level(self, zone, level): raise NotImplementedError('not yet implemented in v4 driver') def ex_enable_development_mode(self, zone): raise NotImplementedError('not yet implemented in v4 driver') def ex_disable_development_mode(self, zone): raise NotImplementedError('not yet implemented in v4 driver') def ex_purge_cached_files(self, zone): raise NotImplementedError('not yet implemented in v4 driver') def ex_purge_cached_file(self, zone, url): raise NotImplementedError('not yet implemented in v4 driver') def ex_whitelist_ip(self, zone, ip): raise NotImplementedError('not yet implemented in v4 driver') def ex_blacklist_ip(self, zone, ip): raise NotImplementedError('not yet implemented in v4 driver') def ex_unlist_ip(self, zone, ip): raise NotImplementedError('not yet implemented in v4 driver') def ex_enable_ipv6_support(self, zone): raise NotImplementedError('not yet implemented in v4 driver') def ex_disable_ipv6_support(self, zone): raise NotImplementedError('not yet implemented in v4 driver') def _to_zone(self, item): return Zone( id=item['id'], domain=item['name'], type=CLOUDFLARE_TO_LIBCLOUD_ZONE_TYPE[item['type']], ttl=None, driver=self, extra={key: item.get(key) for key in ZONE_EXTRA_ATTRIBUTES}, ) def _to_record(self, zone, item): name = item['name'] name = name.replace('.' + item['zone_name'], '') name = name.replace(item['zone_name'], '') name = name or None ttl = item.get('ttl') if ttl is not None: ttl = int(ttl) return Record( id=item['id'], name=name, type=item['type'], data=item['content'], zone=zone, driver=self, ttl=ttl, extra={key: item.get(key) for key in RECORD_EXTRA_ATTRIBUTES}, ) def _paginate(self, get_page, page_size): for page in itertools.count(start=1): params = {'page': page, 'per_page': page_size} response, items = get_page(params) for item in items: yield item if self._is_last_page(response): break if len(items) < page_size: break def _is_last_page(self, response): try: result_info = response.object['result_info'] last_page = result_info['total_pages'] current_page = result_info['page'] except KeyError: return False return current_page == last_page apache-libcloud-2.8.0/libcloud/dns/drivers/digitalocean.py0000664000175000017500000002430013535474530023467 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Digital Ocean DNS Driver """ __all__ = [ 'DigitalOceanDNSDriver' ] from libcloud.utils.py3 import httplib from libcloud.common.digitalocean import DigitalOcean_v2_BaseDriver from libcloud.common.digitalocean import DigitalOcean_v2_Connection from libcloud.dns.types import Provider, RecordType from libcloud.dns.base import DNSDriver, Zone, Record class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver): connectionCls = DigitalOcean_v2_Connection type = Provider.DIGITAL_OCEAN name = "DigitalOcean" website = 'https://www.digitalocean.com' RECORD_TYPE_MAP = { RecordType.NS: 'NS', RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.TXT: 'TXT', RecordType.SRV: 'SRV', } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ data = self._paginated_request('/v2/domains', 'domains') return list(map(self._to_zone, data)) def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ data = self._paginated_request('/v2/domains/%s/records' % (zone.id), 'domain_records') # TODO: Not use list comprehension to add zone to record for proper data map # functionality? This passes a reference to zone for each data currently # to _to_record which returns a Record. map() does not take keywords return list(map(self._to_record, data, [zone for z in data])) def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ data = self.connection.request('/v2/domains/%s' % (zone_id)).object['domain'] return self._to_zone(data) def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ data = self.connection.request('/v2/domains/%s/records/%s' % (zone_id, record_id)).object['domain_record'] # TODO: Any way of not using get_zone which polls the API again # without breaking the DNSDriver.get_record parameters? return self._to_record(data, self.get_zone(zone_id)) def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (master / slave) (does nothing). :type type: ``str`` :param ttl: TTL for new records. (does nothing) :type ttl: ``int`` :param extra: Extra attributes (to set ip). (optional) Note: This can be used to set the default A record with {"ip" : "IP.AD.DR.ESS"} otherwise 127.0.0.1 is used :type extra: ``dict`` :rtype: :class:`Zone` """ params = {'name': domain} try: params['ip_address'] = extra['ip'] except Exception: params['ip_address'] = '127.0.0.1' res = self.connection.request('/v2/domains', params=params, method='POST') return Zone(id=res.object['domain']['name'], domain=res.object['domain']['name'], type='master', ttl=1800, driver=self, extra={}) def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes for MX and SRV. (Depends on record) {"priority" : 0, "port" : 443, "weight" : 100} :type extra: ``dict`` :rtype: :class:`Record` """ params = { "type": self.RECORD_TYPE_MAP[type], "name": name, "data": data } if extra: try: params['priority'] = extra['priority'] except KeyError: params['priority'] = 'null' try: params['port'] = extra['port'] except KeyError: params['port'] = 'null' try: params['weight'] = extra['weight'] except KeyError: params['weight'] = 'null' if 'ttl' in extra: params['ttl'] = extra['ttl'] res = self.connection.request('/v2/domains/%s/records' % zone.id, params=params, method='POST') return Record(id=res.object['domain_record']['id'], name=res.object['domain_record']['name'], type=type, data=data, zone=zone, ttl=res.object['domain_record'].get('ttl', None), driver=self, extra=extra) def update_record(self, record, name=None, type=None, data=None, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). (Ignored) Note: The value is pulled from the record being updated :type name: ``str`` :param type: DNS record type (A, AAAA, ...). (Ignored) Note: Updating records does not support changing type so this value is ignored :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` """ params = { "type": record.type, "name": record.name, "data": data } if data is None: params['data'] = record.data if extra: try: params['priority'] = extra['priority'] except KeyError: params['priority'] = 'null' try: params['port'] = extra['port'] except KeyError: params['port'] = 'null' try: params['weight'] = extra['weight'] except KeyError: params['weight'] = 'null' if 'ttl' in extra: params['ttl'] = extra['ttl'] res = self.connection.request('/v2/domains/%s/records/%s' % (record.zone.id, record.id), params=params, method='PUT') return Record(id=res.object['domain_record']['id'], name=res.object['domain_record']['name'], type=record.type, data=data, zone=record.zone, ttl=res.object['domain_record'].get('ttl', None), driver=self, extra=extra) def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ params = {} res = self.connection.request('/v2/domains/%s' % zone.id, params=params, method='DELETE') return res.status == httplib.NO_CONTENT def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ params = {} res = self.connection.request('/v2/domains/%s/records/%s' % ( record.zone.id, record.id), params=params, method='DELETE') return res.status == httplib.NO_CONTENT def _to_record(self, data, zone=None): extra = {'port': data['port'], 'priority': data['priority'], 'weight': data['weight']} return Record(id=data['id'], name=data['name'], type=self._string_to_record_type(data['type']), data=data['data'], zone=zone, ttl=data.get('ttl', None), driver=self, extra=extra) def _to_zone(self, data): extra = {'zone_file': data['zone_file']} return Zone(id=data['name'], domain=data['name'], type='master', ttl=data['ttl'], driver=self, extra=extra) apache-libcloud-2.8.0/libcloud/dns/drivers/dnsimple.py0000664000175000017500000002300213535474530022655 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ DNSimple DNS Driver """ __all__ = [ 'DNSimpleDNSDriver' ] try: import simplejson as json except ImportError: import json from libcloud.common.dnsimple import DNSimpleDNSConnection from libcloud.dns.types import Provider, RecordType from libcloud.dns.base import DNSDriver, Zone, Record DEFAULT_ZONE_TTL = 3600 class DNSimpleDNSDriver(DNSDriver): type = Provider.DNSIMPLE name = 'DNSimple' website = 'https://dnsimple.com/' connectionCls = DNSimpleDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.ALIAS: 'ALIAS', RecordType.CNAME: 'CNAME', RecordType.HINFO: 'HINFO', RecordType.MX: 'MX', RecordType.NAPTR: 'NAPTR', RecordType.NS: 'NS', 'POOL': 'POOL', RecordType.SOA: 'SOA', RecordType.SPF: 'SPF', RecordType.SRV: 'SRV', RecordType.SSHFP: 'SSHFP', RecordType.TXT: 'TXT', RecordType.URL: 'URL' } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ response = self.connection.request('/v1/domains') zones = self._to_zones(response.object) return zones def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ response = self.connection.request('/v1/domains/%s/records' % zone.id) records = self._to_records(response.object, zone) return records def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ response = self.connection.request('/v1/domains/%s' % zone_id) zone = self._to_zone(response.object) return zone def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ response = self.connection.request('/v1/domains/%s/records/%s' % (zone_id, record_id)) record = self._to_record(response.object, zone_id=zone_id) return record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (All zones are master by design). :type type: ``str`` :param ttl: TTL for new records. (This is not really used) :type ttl: ``int`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Zone` For more info, please see: http://developer.dnsimple.com/v1/domains/ """ r_json = {'name': domain} if extra is not None: r_json.update(extra) r_data = json.dumps({'domain': r_json}) response = self.connection.request( '/v1/domains', method='POST', data=r_data) zone = self._to_zone(response.object) return zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ r_json = {'name': name, 'record_type': type, 'content': data} if extra is not None: r_json.update(extra) r_data = json.dumps({'record': r_json}) response = self.connection.request('/v1/domains/%s/records' % zone.id, method='POST', data=r_data) record = self._to_record(response.object, zone=zone) return record def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` """ zone = record.zone r_json = {'name': name, 'content': data} if extra is not None: r_json.update(extra) r_data = json.dumps({'record': r_json}) response = self.connection.request('/v1/domains/%s/records/%s' % (zone.id, record.id), method='PUT', data=r_data) record = self._to_record(response.object, zone=zone) return record def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ self.connection.request('/v1/domains/%s' % zone.id, method='DELETE') return True def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ zone_id = record.zone.id self.connection.request('/v1/domains/%s/records/%s' % (zone_id, record.id), method='DELETE') return True def _to_zones(self, data): zones = [] for zone in data: _zone = self._to_zone(zone) zones.append(_zone) return zones def _to_zone(self, data): domain = data.get('domain') id = domain.get('id') name = domain.get('name') extra = {'registrant_id': domain.get('registrant_id'), 'user_id': domain.get('user_id'), 'unicode_name': domain.get('unicode_name'), 'token': domain.get('token'), 'state': domain.get('state'), 'language': domain.get('language'), 'lockable': domain.get('lockable'), 'auto_renew': domain.get('auto_renew'), 'whois_protected': domain.get('whois_protected'), 'record_count': domain.get('record_count'), 'service_count': domain.get('service_count'), 'expires_on': domain.get('expires_on'), 'created_at': domain.get('created_at'), 'updated_at': domain.get('updated_at')} # All zones are primary by design type = 'master' return Zone(id=id, domain=name, type=type, ttl=DEFAULT_ZONE_TTL, driver=self, extra=extra) def _to_records(self, data, zone): records = [] for item in data: record = self._to_record(item, zone=zone) records.append(record) return records def _to_record(self, data, zone_id=None, zone=None): if not zone: # We need zone_id or zone zone = self.get_zone(zone_id) record = data.get('record') id = record.get('id') name = record.get('name') type = record.get('record_type') data = record.get('content') extra = {'ttl': record.get('ttl'), 'created_at': record.get('created_at'), 'updated_at': record.get('updated_at'), 'domain_id': record.get('domain_id'), 'priority': record.get('prio')} return Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=record.get('ttl', None), extra=extra) apache-libcloud-2.8.0/libcloud/dns/drivers/dnspod.py0000664000175000017500000002671413570310635022340 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.dns.types import Provider, ZoneDoesNotExistError, \ ZoneAlreadyExistsError, RecordDoesNotExistError, RecordAlreadyExistsError from libcloud.dns.base import DNSDriver, Zone, Record, RecordType from libcloud.common.dnspod import DNSPodConnection, DNSPodResponse, \ DNSPodException from libcloud.utils.py3 import urlencode __all__ = [ 'DNSPodDNSDriver' ] ZONE_ALREADY_EXISTS_ERROR_MSGS = ['Domain is exists', 'Domain already exists as ' 'an alias of another domain'] ZONE_DOES_NOT_EXIST_ERROR_MSGS = ['Domain not under you or your user', 'Domain id invalid'] RECORD_DOES_NOT_EXIST_ERRORS_MSGS = ['Record id invalid'] class DNSPodDNSResponse(DNSPodResponse): pass class DNSPodDNSConnection(DNSPodConnection): responseCls = DNSPodDNSResponse class DNSPodDNSDriver(DNSDriver): name = 'DNSPod' website = 'https://dnspod.com' type = Provider.DNSPOD connectionCls = DNSPodDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SOA: 'SOA', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT' } def _make_request(self, action, method, data=None): data = data or {} if not data.get('user_token'): data['user_token'] = self.key if not data.get('format'): data['format'] = 'json' data = urlencode(data) r = self.connection.request(action=action, method=method, data=data) return r def list_zones(self): action = '/Domain.List' try: response = self._make_request(action=action, method='POST') except DNSPodException as e: if e.message == 'No domains': return [] zones = self._to_zones(items=response.object['domains']) return zones def delete_zone(self, zone): """ :param zone: Zone to be deleted. :type zone: :class:`Zone` :return: Boolean """ action = '/Domain.Remove' data = {'domain_id': zone.id} try: self._make_request(action=action, method='POST', data=data) except DNSPodException as e: if e.message in ZONE_DOES_NOT_EXIST_ERROR_MSGS: raise ZoneDoesNotExistError(value=e.message, driver=self, zone_id=zone.id) else: raise e return True def get_zone(self, zone_id): """ :param zone_id: Zone domain name (e.g. example.com) :return: :class:`Zone` """ action = '/Domain.Info' data = {'domain_id': zone_id} try: response = self._make_request(action=action, method='POST', data=data) except DNSPodException as e: if e.message in ZONE_DOES_NOT_EXIST_ERROR_MSGS: raise ZoneDoesNotExistError(value=e.message, driver=self, zone_id=zone_id) else: raise e zone = self._to_zone(response.object['domain']) return zone def create_zone(self, domain, type='master', ttl=None, extra=None): """ :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (This is not really used. See API docs for extra parameters) :type type: ``str`` :param ttl: TTL for new records (This is used through the extra param) :type ttl: ``int`` :param extra: Extra attributes that are specific to the driver such as ttl. :type extra: ``dict`` :rtype: :class:`Zone` """ action = '/Domain.Create' data = {'domain': domain} if extra is not None: data.update(extra) try: response = self._make_request(action=action, method='POST', data=data) except DNSPodException as e: if e.message in ZONE_ALREADY_EXISTS_ERROR_MSGS: raise ZoneAlreadyExistsError(value=e.message, driver=self, zone_id=domain) else: raise e zone = self._to_zone(response.object['domain']) return zone def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '/Record.List' data = {'domain_id': zone.id} try: response = self._make_request(action=action, data=data, method='POST') except DNSPodException as e: if e.message in ZONE_DOES_NOT_EXIST_ERROR_MSGS: raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone.id) else: raise e records = self._to_records(response.object['records'], zone=zone) return records def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ action = '/Record.Remove' data = {'domain_id': record.zone.id, 'record_id': record.id} try: self._make_request(action=action, method='POST', data=data) except DNSPodException as e: if e.message in RECORD_DOES_NOT_EXIST_ERRORS_MSGS: raise RecordDoesNotExistError(record_id=record.id, driver=self, value='') elif e.message in ZONE_DOES_NOT_EXIST_ERROR_MSGS: raise ZoneDoesNotExistError(zone_id=record.zone.id, driver=self, value='') else: raise e return True def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ zone = self.get_zone(zone_id=zone_id) action = '/Record.Info' data = {'domain_id': zone_id, 'record_id': record_id} try: response = self._make_request(action=action, method='POST', data=data) except DNSPodException as e: if e.message in RECORD_DOES_NOT_EXIST_ERRORS_MSGS: raise RecordDoesNotExistError(record_id=record_id, driver=self, value='') elif e.message in ZONE_DOES_NOT_EXIST_ERROR_MSGS: raise ZoneDoesNotExistError(zone_id=zone_id, driver=self, value='') else: raise e record = self._to_record(response.object['record'], zone=zone) return record def create_record(self, name, zone, type, data, extra=None): """ Create a record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone which the records will be created for. :type zone: :class:`Zone` :param type: DNS record type ( 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT'). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes ('prio', 'ttl'). :type extra: ``dict`` :rtype: :class:`Record` """ action = '/Record.Create' data = {'sub_domain': name, 'value': data, 'record_type': type, 'domain_id': zone.id} # ttl is optional # pass it through extra like this: extra={'ttl':ttl} # record_line is a required parameter # pass it through extra like this: extra={'record_line':'default'} # when creating MX records you need to pass mx through extra # mx ranges from 1 to 20 # extra = {'ttl': '13', 'record_line': default, 'mx': 1} if extra is not None: data.update(extra) try: response = self._make_request(action=action, method='POST', data=data) except DNSPodException as e: if e.message == ('Record impacted, same record exists ' 'or CNAME/URL impacted'): raise RecordAlreadyExistsError(record_id='', driver=self, value=name) raise e record_id = response.object['record'].get('id') record = self.get_record(zone_id=zone.id, record_id=record_id) return record def _to_zone(self, item): common_attr = ['name', 'id', 'ttl'] extra = {} for key in item.keys(): if key not in common_attr: extra[key] = item.get(key) zone = Zone(domain=item.get('name') or item.get('domain'), id=item.get('id'), type=None, extra=extra, ttl=item.get('ttl'), driver=self) return zone def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone): common_attr = ['id', 'value', 'name', 'type'] extra = {} for key in item: if key not in common_attr: extra[key] = item.get(key) record = Record(id=item.get('id'), name=item.get('name') or item.get('sub_domain'), type=item.get('type') or item.get('record_type'), data=item.get('value'), zone=zone, driver=self, extra=extra) return record def _to_records(self, items, zone): records = [] for item in items: records.append(self._to_record(item, zone)) return records apache-libcloud-2.8.0/libcloud/dns/drivers/dummy.py0000664000175000017500000001715513535474530022211 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import RecordType from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError from libcloud.dns.types import RecordDoesNotExistError from libcloud.dns.types import RecordAlreadyExistsError class DummyDNSDriver(DNSDriver): """ Dummy DNS driver. >>> from libcloud.dns.drivers.dummy import DummyDNSDriver >>> driver = DummyDNSDriver('key', 'secret') >>> driver.name 'Dummy DNS Provider' """ name = 'Dummy DNS Provider' website = 'http://example.com' def __init__(self, api_key, api_secret): """ :param api_key: API key or username to used (required) :type api_key: ``str`` :param api_secret: Secret password to be used (required) :type api_secret: ``str`` :rtype: ``None`` """ self._zones = {} def list_record_types(self): """ >>> driver = DummyDNSDriver('key', 'secret') >>> driver.list_record_types() ['A'] @inherits: :class:`DNSDriver.list_record_types` """ return [RecordType.A] def list_zones(self): """ >>> driver = DummyDNSDriver('key', 'secret') >>> driver.list_zones() [] @inherits: :class:`DNSDriver.list_zones` """ return [zone['zone'] for zone in list(self._zones.values())] def list_records(self, zone): """ >>> driver = DummyDNSDriver('key', 'secret') >>> zone = driver.create_zone(domain='apache.org', type='master', ... ttl=100) >>> list(zone.list_records()) [] >>> record = driver.create_record(name='libcloud', zone=zone, ... type=RecordType.A, data='127.0.0.1') >>> list(zone.list_records()) #doctest: +ELLIPSIS [] """ return self._zones[zone.id]['records'].values() def get_zone(self, zone_id): """ >>> driver = DummyDNSDriver('key', 'secret') >>> driver.get_zone(zone_id='foobar') ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ZoneDoesNotExistError: @inherits: :class:`DNSDriver.get_zone` """ if zone_id not in self._zones: raise ZoneDoesNotExistError(driver=self, value=None, zone_id=zone_id) return self._zones[zone_id]['zone'] def get_record(self, zone_id, record_id): """ >>> driver = DummyDNSDriver('key', 'secret') >>> driver.get_record(zone_id='doesnotexist', record_id='exists') ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ZoneDoesNotExistError: @inherits: :class:`DNSDriver.get_record` """ self.get_zone(zone_id=zone_id) zone_records = self._zones[zone_id]['records'] if record_id not in zone_records: raise RecordDoesNotExistError(record_id=record_id, value=None, driver=self) return zone_records[record_id] def create_zone(self, domain, type='master', ttl=None, extra=None): """ >>> driver = DummyDNSDriver('key', 'secret') >>> zone = driver.create_zone(domain='apache.org', type='master', ... ttl=100) >>> zone >>> zone = driver.create_zone(domain='apache.org', type='master', ... ttl=100) ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ZoneAlreadyExistsError: @inherits: :class:`DNSDriver.create_zone` """ id = 'id-%s' % (domain) if id in self._zones: raise ZoneAlreadyExistsError(zone_id=id, value=None, driver=self) zone = Zone(id=id, domain=domain, type=type, ttl=ttl, extra={}, driver=self) self._zones[id] = {'zone': zone, 'records': {}} return zone def create_record(self, name, zone, type, data, extra=None): """ >>> driver = DummyDNSDriver('key', 'secret') >>> zone = driver.create_zone(domain='apache.org', type='master', ... ttl=100) >>> record = driver.create_record(name='libcloud', zone=zone, ... type=RecordType.A, data='127.0.0.1') >>> record #doctest: +ELLIPSIS >>> record = driver.create_record(name='libcloud', zone=zone, ... type=RecordType.A, data='127.0.0.1') ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): RecordAlreadyExistsError: @inherits: :class:`DNSDriver.create_record` """ id = 'id-%s' % (name) zone = self.get_zone(zone_id=zone.id) if id in self._zones[zone.id]['records']: raise RecordAlreadyExistsError(record_id=id, value=None, driver=self) record = Record(id=id, name=name, type=type, data=data, extra=extra, zone=zone, driver=self) self._zones[zone.id]['records'][id] = record return record def delete_zone(self, zone): """ >>> driver = DummyDNSDriver('key', 'secret') >>> zone = driver.create_zone(domain='apache.org', type='master', ... ttl=100) >>> driver.delete_zone(zone) True >>> driver.delete_zone(zone) #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ZoneDoesNotExistError: @inherits: :class:`DNSDriver.delete_zone` """ self.get_zone(zone_id=zone.id) del self._zones[zone.id] return True def delete_record(self, record): """ >>> driver = DummyDNSDriver('key', 'secret') >>> zone = driver.create_zone(domain='apache.org', type='master', ... ttl=100) >>> record = driver.create_record(name='libcloud', zone=zone, ... type=RecordType.A, data='127.0.0.1') >>> driver.delete_record(record) True >>> driver.delete_record(record) #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): RecordDoesNotExistError: @inherits: :class:`DNSDriver.delete_record` """ self.get_record(zone_id=record.zone.id, record_id=record.id) del self._zones[record.zone.id]['records'][record.id] return True if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/dns/drivers/durabledns.py0000664000175000017500000006314013570310635023166 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ DurableDNS Driver """ from libcloud.utils.py3 import httplib from libcloud.utils.py3 import ensure_string from libcloud.dns.types import Provider, RecordType from libcloud.dns.base import Record, Zone from libcloud.dns.base import DNSDriver from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError from libcloud.dns.types import RecordDoesNotExistError from xml.etree.ElementTree import tostring from libcloud.common.durabledns import DurableConnection, DurableResponse from libcloud.common.durabledns import DurableDNSException from libcloud.common.durabledns import _schema_builder as api_schema_builder from libcloud.common.durabledns import SCHEMA_BUILDER_MAP __all__ = [ 'ZONE_EXTRA_PARAMS_DEFAULT_VALUES', 'RECORD_EXTRA_PARAMS_DEFAULT_VALUES', 'DEFAULT_TTL', 'DurableDNSResponse', 'DurableDNSConnection', 'DurableDNSDriver' ] # This will be the default values for each extra attributes when are not # specified in the 'extra' parameter ZONE_EXTRA_PARAMS_DEFAULT_VALUES = { 'ns': 'ns1.durabledns.com.', 'mbox': 'support.durabledns.com', 'refresh': '28800', 'retry': 7200, 'expire': 604800, 'minimum': 82000, 'xfer': '', 'update_acl': '' } RECORD_EXTRA_PARAMS_DEFAULT_VALUES = {'aux': 0, 'ttl': 3600} DEFAULT_TTL = 3600 class DurableDNSResponse(DurableResponse): pass class DurableDNSConnection(DurableConnection): responseCls = DurableDNSResponse class DurableDNSDriver(DNSDriver): type = Provider.DURABLEDNS name = 'DurableDNS' website = 'https://durabledns.com' connectionCls = DurableDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.HINFO: 'HINFO', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.RP: 'RP', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT' } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ schema_params = SCHEMA_BUILDER_MAP.get('list_zones') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret} urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: child.text = str(params.get(key)) req_data = tostring(schema) action = '/services/dns/listZones.php' params = {} headers = {"SOAPAction": "urn:listZoneswsdl#listZones"} response = self.connection.request(action=action, params=params, data=req_data, method="POST", headers=headers) # listZones method doens't return full data in zones as getZone # method does. zones = [] for data in response.objects: zone = self.get_zone(data.get('id')) zones.append(zone) return zones def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ schema_params = SCHEMA_BUILDER_MAP.get('list_records') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': zone.id} urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: child.text = str(params.get(key)) req_data = tostring(schema) action = '/services/dns/listRecords.php?' params = {} headers = {"SOAPAction": "urn:listRecordswsdl#listRecords"} try: response = self.connection.request(action=action, params=params, data=req_data, method="POST", headers=headers) except DurableDNSException as e: if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e # listRecords method doens't return full data in records as getRecord # method does. records = [] for data in response.objects: record = self.get_record(zone.id, data.get('id')) records.append(record) return records def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ schema_params = SCHEMA_BUILDER_MAP.get('get_zone') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': zone_id} urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: child.text = str(params.get(key)) req_data = tostring(schema) action = '/services/dns/getZone.php?' params = {} headers = {"SOAPAction": "urn:getZonewsdl#getZone"} try: response = self.connection.request(action=action, params=params, data=req_data, method="POST", headers=headers) except DurableDNSException as e: if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=zone_id, driver=self, value=e.message) raise e zones = self._to_zones(response.objects) return zones[0] def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ schema_params = SCHEMA_BUILDER_MAP.get('get_record') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': zone_id, 'recordid': record_id} urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: child.text = str(params.get(key)) req_data = tostring(schema) action = '/services/dns/getRecord.php?' params = {} headers = {"SOAPAction": "urn:getRecordwsdl#getRecord"} try: response = self.connection.request(action=action, params=params, data=req_data, method="POST", headers=headers) except DurableDNSException as e: if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=zone_id, driver=self, value=e.message) if 'Record does not exist' in e.message: raise RecordDoesNotExistError(record_id=record_id, driver=self, value=e.message) raise e zone = self.get_zone(zone_id) record = self._to_record(response.objects[0], zone) return record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Name of zone, followed by a dot (.) (e.g. example.com.) :type domain: ``str`` :param type: Zone type (Only master available). (optional) :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes ('mbox', 'ns', 'minimum', 'refresh', 'expire', 'update_acl', 'xfer'). (optional) :type extra: ``dict`` :rtype: :class:`Zone` """ if extra is None: extra = ZONE_EXTRA_PARAMS_DEFAULT_VALUES else: extra_fields = ZONE_EXTRA_PARAMS_DEFAULT_VALUES.keys() missing = set(extra_fields).difference(set(extra.keys())) for field in missing: extra[field] = ZONE_EXTRA_PARAMS_DEFAULT_VALUES.get(field) schema_params = SCHEMA_BUILDER_MAP.get('create_zone') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': domain, 'ttl': ttl or DEFAULT_TTL} params.update(extra) urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: if isinstance(params.get(key), int): child.text = "%d" else: child.text = "%s" # We can't insert values directly in child.text because API raises # and exception for values that need to be integers. And tostring # method from ElementTree can't handle int values. skel = ensure_string(tostring(schema)) # Deal with PY3 req_data = skel % (self.key, self.secret, domain, extra.get('ns'), extra.get('mbox'), extra.get('refresh'), extra.get('retry'), extra.get('expire'), extra.get('minimum'), ttl or DEFAULT_TTL, extra.get('xfer'), extra.get('update_acl')) action = '/services/dns/createZone.php?' params = {} headers = {"SOAPAction": "urn:createZonewsdl#createZone"} try: self.connection.request(action=action, params=params, data=req_data, method="POST", headers=headers) except DurableDNSException as e: if 'Zone Already Exist' in e.message: raise ZoneAlreadyExistsError(zone_id=domain, driver=self, value=e.message) raise e zone = self.get_zone(domain) return zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (e.g. 'aux', 'ttl'). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ if extra is None: extra = RECORD_EXTRA_PARAMS_DEFAULT_VALUES else: if 'aux' not in extra: extra['aux'] = RECORD_EXTRA_PARAMS_DEFAULT_VALUES.get('aux') if 'ttl' not in extra: extra['ttl'] = RECORD_EXTRA_PARAMS_DEFAULT_VALUES.get('ttl') extra['ddns_enabled'] = 'N' schema_params = SCHEMA_BUILDER_MAP.get('create_record') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': zone.id, 'name': name, 'type': type, 'data': data} params.update(extra) urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: if isinstance(params.get(key), int): child.text = "%d" else: child.text = "%s" # We can't insert values directly in child.text because API raises # and exception for values that need to be integers. And tostring # method from ElementTree can't handle int values. skel = ensure_string(tostring(schema)) # Deal with PY3 req_data = skel % (self.key, self.secret, zone.id, name, type, data, extra.get('aux'), extra.get('ttl'), extra.get('ddns_enabled')) action = '/services/dns/createRecord.php?' headers = {"SOAPAction": "urn:createRecordwsdl#createRecord"} try: response = self.connection.request(action=action, data=req_data, method="POST", headers=headers) objects = response.objects except DurableDNSException as e: # In DurableDNS is possible to create records with same data. # Their ID's will be different but the API does not implement # the RecordAlreadyExist exception. Only ZoneDoesNotExist will # be handled. if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e record_item = objects[0] record_item['name'] = name record_item['type'] = type record_item['data'] = data record_item['ttl'] = extra.get('ttl') record_item['aux'] = extra.get('aux') record = self._to_record(record_item, zone) return record def update_zone(self, zone, domain, type='master', ttl=None, extra=None): """ Update an existing zone. :param zone: Zone to update. :type zone: :class:`Zone` :param domain: Name of zone, followed by a dot (.) (e.g. example.com.) :type domain: ``str`` :param type: Zone type (master / slave). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes ('ns', 'mbox', 'refresh', 'retry', 'expire', 'minimum', 'xfer', 'update_acl'). (optional) :type extra: ``dict`` :rtype: :class:`Zone` """ if ttl is None: ttl = zone.ttl if extra is None: extra = zone.extra else: extra_fields = ZONE_EXTRA_PARAMS_DEFAULT_VALUES.keys() missing = set(extra_fields).difference(set(extra.keys())) for field in missing: extra[field] = zone.extra.get(field) schema_params = SCHEMA_BUILDER_MAP.get('update_zone') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': domain, 'ttl': ttl} params.update(extra) urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: if isinstance(params.get(key), int): child.text = "%d" else: child.text = "%s" # We can't insert values directly in child.text because API raises # and exception for values that need to be integers. And tostring # method from ElementTree can't handle int values. skel = ensure_string(tostring(schema)) # Deal with PY3 req_data = skel % (self.key, self.secret, domain, extra['ns'], extra['mbox'], extra['refresh'], extra['retry'], extra['expire'], extra['minimum'], ttl, extra['xfer'], extra['update_acl']) action = '/services/dns/updateZone.php?' headers = {"SOAPAction": "urn:updateZonewsdl#updateZone"} try: self.connection.request(action=action, data=req_data, method="POST", headers=headers) except DurableDNSException as e: if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e # After update the zone, serial number change. In order to have it # updated, we need to get again the zone data. zone = self.get_zone(zone.id) return zone def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` """ zone = record.zone if extra is None: extra = record.extra else: extra_fields = ['aux', 'ttl'] missing = set(extra_fields).difference(set(extra.keys())) for field in missing: extra[field] = record.extra.get(field) extra['ddns_enabled'] = 'N' schema_params = SCHEMA_BUILDER_MAP.get('update_record') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': zone.id, 'id': record.id, 'name': name, 'data': data} params.update(extra) urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: if isinstance(params.get(key), int): child.text = "%d" else: child.text = "%s" # We can't insert values directly in child.text because API raises # and exception for values that need to be integers. And tostring # method from ElementTree can't handle int values. skel = ensure_string(tostring(schema)) # Deal with PY3 req_data = skel % (self.key, self.secret, zone.id, record.id, name, extra.get('aux'), data, extra.get('ttl'), extra.get('ddns_enabled')) action = '/services/dns/updateRecord.php?' headers = {"SOAPAction": "urn:updateRecordwsdl#updateRecord"} try: self.connection.request(action=action, data=req_data, method="POST", headers=headers) except DurableDNSException as e: if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e record_item = {} record_item['id'] = record.id record_item['name'] = name record_item['type'] = type record_item['data'] = data record_item['ttl'] = extra.get('ttl') record_item['aux'] = extra.get('aux') record = self._to_record(record_item, zone) return record def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ schema_params = SCHEMA_BUILDER_MAP.get('delete_zone') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': zone.id} urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: child.text = str(params.get(key)) req_data = tostring(schema) action = '/services/dns/deleteZone.php?' headers = {"SOAPAction": "urn:deleteZonewsdl#deleteZone"} try: response = self.connection.request(action=action, data=req_data, method="POST", headers=headers) except DurableDNSException as e: if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e return response.status in [httplib.OK] def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ schema_params = SCHEMA_BUILDER_MAP.get('delete_record') attributes = schema_params.get('attributes') schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes) params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': record.zone.id, 'id': record.id} urn = list(schema)[0] for child in urn: key = child.tag.split(':')[2] if key in attributes: child.text = str(params.get(key)) req_data = tostring(schema) action = '/services/dns/deleteRecord.php?' headers = {"SOAPAction": "urn:deleteRecordwsdl#deleteRecord"} try: response = self.connection.request(action=action, data=req_data, headers=headers, method="POST") except DurableDNSException as e: if 'Record does not exists' in e.message: raise RecordDoesNotExistError(record_id=record.id, driver=self, value=e.message) if 'Zone does not exist' in e.message: raise ZoneDoesNotExistError(zone_id=record.zone.id, driver=self, value=e.message) raise e return response.status in [httplib.OK] def _to_zone(self, item): extra = item.get('extra') # DurableDNS does not return information about zone type. This will be # set as master by default. zone = Zone(id=item.get('id'), type='master', domain=item.get('id'), ttl=item.get('ttl'), driver=self, extra=extra) return zone def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone=None): extra = {'aux': int(item.get('aux')), 'ttl': int(item.get('ttl'))} record = Record(id=item.get('id'), type=item.get('type'), zone=zone, name=item.get('name'), data=item.get('data'), driver=self, ttl=item.get('ttl', None), extra=extra) return record def _to_records(self, items, zone=None): records = [] for item in items: records.append(self._to_record(item, zone)) return records apache-libcloud-2.8.0/libcloud/dns/drivers/gandi.py0000664000175000017500000002174013535474530022133 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement __all__ = [ 'GandiDNSDriver' ] from libcloud.common.gandi import BaseGandiDriver, GandiConnection from libcloud.common.gandi import GandiResponse from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import RecordError from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record TTL_MIN = 30 TTL_MAX = 2592000 # 30 days class NewZoneVersion(object): """ Changes to a zone in the Gandi DNS service need to be wrapped in a new version object. The changes are made to the new version, then that version is made active. In effect, this is a transaction. Any calls made inside this context manager will be applied to a new version id. If your changes are successful (and only if they are successful) they are activated. """ def __init__(self, driver, zone): self.driver = driver self.connection = driver.connection self.zone = zone def __enter__(self): zid = int(self.zone.id) self.connection.set_context({'zone_id': self.zone.id}) vid = self.connection.request('domain.zone.version.new', zid).object self.vid = vid return vid def __exit__(self, type, value, traceback): if not traceback: zid = int(self.zone.id) con = self.connection con.set_context({'zone_id': self.zone.id}) con.request('domain.zone.version.set', zid, self.vid).object class GandiDNSResponse(GandiResponse): exceptions = { 581042: ZoneDoesNotExistError, } class GandiDNSConnection(GandiConnection): responseCls = GandiDNSResponse class GandiDNSDriver(BaseGandiDriver, DNSDriver): """ API reference can be found at: http://doc.rpc.gandi.net/domain/reference.html """ type = Provider.GANDI name = 'Gandi DNS' website = 'http://www.gandi.net/domain' connectionCls = GandiDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.LOC: 'LOC', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.SPF: 'SPF', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', RecordType.WKS: 'WKS', } def _to_zone(self, zone): return Zone( id=str(zone['id']), domain=zone['name'], type='master', ttl=0, driver=self, extra={} ) def _to_zones(self, zones): ret = [] for z in zones: ret.append(self._to_zone(z)) return ret def list_zones(self): zones = self.connection.request('domain.zone.list') return self._to_zones(zones.object) def get_zone(self, zone_id): zid = int(zone_id) self.connection.set_context({'zone_id': zone_id}) zone = self.connection.request('domain.zone.info', zid) return self._to_zone(zone.object) def create_zone(self, domain, type='master', ttl=None, extra=None): params = { 'name': domain, } info = self.connection.request('domain.zone.create', params) return self._to_zone(info.object) def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): zid = int(zone.id) params = {'name': domain} self.connection.set_context({'zone_id': zone.id}) zone = self.connection.request('domain.zone.update', zid, params) return self._to_zone(zone.object) def delete_zone(self, zone): zid = int(zone.id) self.connection.set_context({'zone_id': zone.id}) res = self.connection.request('domain.zone.delete', zid) return res.object def _to_record(self, record, zone): extra = {'ttl': int(record['ttl'])} value = record['value'] if record['type'] == 'MX': # Record is in the following form: # # e.g. 15 aspmx.l.google.com split = record['value'].split(' ') extra['priority'] = int(split[0]) value = split[1] return Record( id='%s:%s' % (record['type'], record['name']), name=record['name'], type=self._string_to_record_type(record['type']), data=value, zone=zone, driver=self, ttl=record['ttl'], extra=extra) def _to_records(self, records, zone): retval = [] for r in records: retval.append(self._to_record(r, zone)) return retval def list_records(self, zone): zid = int(zone.id) self.connection.set_context({'zone_id': zone.id}) records = self.connection.request('domain.zone.record.list', zid, 0) return self._to_records(records.object, zone) def get_record(self, zone_id, record_id): zid = int(zone_id) record_type, name = record_id.split(':', 1) filter_opts = { 'name': name, 'type': record_type } self.connection.set_context({'zone_id': zone_id}) records = self.connection.request('domain.zone.record.list', zid, 0, filter_opts).object if len(records) == 0: raise RecordDoesNotExistError(value='', driver=self, record_id=record_id) return self._to_record(records[0], self.get_zone(zone_id)) def _validate_record(self, record_id, name, record_type, data, extra): if len(data) > 1024: raise RecordError('Record data must be <= 1024 characters', driver=self, record_id=record_id) if extra and 'ttl' in extra: if extra['ttl'] < TTL_MIN: raise RecordError('TTL must be at least 30 seconds', driver=self, record_id=record_id) if extra['ttl'] > TTL_MAX: raise RecordError('TTL must not excdeed 30 days', driver=self, record_id=record_id) def create_record(self, name, zone, type, data, extra=None): self._validate_record(None, name, type, data, extra) zid = int(zone.id) create = { 'name': name, 'type': self.RECORD_TYPE_MAP[type], 'value': data } if 'ttl' in extra: create['ttl'] = extra['ttl'] with NewZoneVersion(self, zone) as vid: con = self.connection con.set_context({'zone_id': zone.id}) rec = con.request('domain.zone.record.add', zid, vid, create).object return self._to_record(rec, zone) def update_record(self, record, name, type, data, extra): self._validate_record(record.id, name, type, data, extra) filter_opts = { 'name': record.name, 'type': self.RECORD_TYPE_MAP[record.type] } update = { 'name': name, 'type': self.RECORD_TYPE_MAP[type], 'value': data } if 'ttl' in extra: update['ttl'] = extra['ttl'] zid = int(record.zone.id) with NewZoneVersion(self, record.zone) as vid: con = self.connection con.set_context({'zone_id': record.zone.id}) con.request('domain.zone.record.delete', zid, vid, filter_opts) res = con.request('domain.zone.record.add', zid, vid, update).object return self._to_record(res, record.zone) def delete_record(self, record): zid = int(record.zone.id) filter_opts = { 'name': record.name, 'type': self.RECORD_TYPE_MAP[record.type] } with NewZoneVersion(self, record.zone) as vid: con = self.connection con.set_context({'zone_id': record.zone.id}) count = con.request('domain.zone.record.delete', zid, vid, filter_opts).object if count == 1: return True raise RecordDoesNotExistError(value='No such record', driver=self, record_id=record.id) apache-libcloud-2.8.0/libcloud/dns/drivers/gandi_live.py0000664000175000017500000004346113570310635023150 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import copy from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import RecordError from libcloud.dns.types import ZoneDoesNotExistError, \ RecordDoesNotExistError, ZoneAlreadyExistsError, RecordAlreadyExistsError from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.common.gandi_live import ResourceNotFoundError, \ ResourceConflictError, GandiLiveResponse, GandiLiveConnection, \ BaseGandiLiveDriver __all__ = [ 'GandiLiveDNSDriver', ] TTL_MIN = 300 TTL_MAX = 2592000 # 30 days API_BASE = '/api/v5' class GandiLiveDNSResponse(GandiLiveResponse): pass class GandiLiveDNSConnection(GandiLiveConnection): responseCls = GandiLiveDNSResponse class GandiLiveDNSDriver(BaseGandiLiveDriver, DNSDriver): """ API reference can be found at: https://doc.livedns.gandi.net/ Please note that the Libcloud paradigm of one zone per domain does not match exactly with Gandi LiveDNS. For Gandi, a "zone" can apply to multiple domains. This driver behaves as if the domain is a zone, but be warned that modifying a domain means modifying the zone. Iif you have a zone associated with mutiple domains, all of those domains will be modified as well. """ type = Provider.GANDI name = 'Gandi LiveDNS' website = 'http://www.gandi.net/domain' connectionCls = GandiLiveDNSConnection # also supports CAA, CDS RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.ALIAS: 'ALIAS', RecordType.CNAME: 'CNAME', RecordType.DNAME: 'DNAME', RecordType.DS: 'DS', RecordType.KEY: 'KEY', RecordType.LOC: 'LOC', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SPF: 'SPF', RecordType.SRV: 'SRV', RecordType.SSHFP: 'SSHFP', RecordType.TLSA: 'TLSA', RecordType.TXT: 'TXT', RecordType.WKS: 'WKS', } def list_zones(self): zones = self.connection.request(action='%s/domains' % API_BASE, method='GET') return self._to_zones(zones.object) def get_zone(self, zone_id): action = '%s/domains/%s' % (API_BASE, zone_id) try: zone = self.connection.request(action=action, method='GET') except ResourceNotFoundError: raise ZoneDoesNotExistError(value='', driver=self.connection.driver, zone_id=zone_id) return self._to_zone(zone.object) """ :param extra: (optional) Extra attribute ('name'); if not provided, name is based on domain. :return: :class:`Zone` with attribute zone_uuid set in extra ``dict`` """ def create_zone(self, domain, type='master', ttl=None, extra=None): if extra and 'name' in extra: zone_name = extra['name'] else: zone_name = '%s zone' % domain zone_data = { 'name': zone_name, } try: new_zone = self.connection.request(action='%s/zones' % API_BASE, method='POST', data=zone_data) except ResourceConflictError: raise ZoneAlreadyExistsError(value='', driver=self.connection.driver, zone_id=zone_name) new_zone_uuid = new_zone.headers['location'].split('/')[-1] self.ex_switch_domain_gandi_zone(domain, new_zone_uuid) return self._to_zone({'fqdn': domain, 'zone_uuid': new_zone_uuid}) def list_records(self, zone): action = '%s/domains/%s/records' % (API_BASE, zone.id) records = self.connection.request(action=action, method='GET') return self._to_records(records.object, zone) """ :return: :class:`Record` with the extra ``dict`` containing attribute other_values ``list`` of ``str`` for other values; the first value is returned through Record.data. """ def get_record(self, zone_id, record_id): record_type, name = record_id.split(':', 1) action = '%s/domains/%s/records/%s/%s' % (API_BASE, zone_id, name, record_type) try: record = self.connection.request(action=action, method='GET') except ResourceNotFoundError: raise RecordDoesNotExistError(value='', driver=self.connection.driver, record_id=record_id) return self._to_record(record.object, self.get_zone(zone_id))[0] def create_record(self, name, zone, type, data, extra=None): self._validate_record(None, name, type, data, extra) action = '%s/domains/%s/records' % (API_BASE, zone.id) if type == 'MX': data = '%s %s' % (extra['priority'], data) record_data = { 'rrset_name': name, 'rrset_type': self.RECORD_TYPE_MAP[type], 'rrset_values': [data], } if extra is not None and 'ttl' in extra: record_data['rrset_ttl'] = extra['ttl'] try: self.connection.request(action=action, method='POST', data=record_data) except ResourceConflictError: raise RecordAlreadyExistsError(value='', driver=self.connection.driver, record_id='%s:%s' % ( self.RECORD_TYPE_MAP[type], name)) return self._to_record_sub(record_data, zone, data) """ Ignores name and type, not allowed in an update call to the service. The Gandi service requires all values for a record when doing an update. Not providing all values during an update means the service will interpret it as replacing all values with the one data value. The easiest way to accomplish this is to make sure the value of a get_record is used as the value of the record parameter. This method will change the value when only one exists. When more than one exists, it will combine the data parameter value with the extra dict values contained in the list extra['_other_records']. This method should only be used to make single value updates. To change the number of values in the value set or to change several at once, delete and recreate, potentially using ex_create_multi_value_record. """ def update_record(self, record, name, type, data, extra): self._validate_record(record.id, record.name, record.type, data, extra) action = '%s/domains/%s/records/%s/%s' % ( API_BASE, record.zone.id, record.name, self.RECORD_TYPE_MAP[record.type] ) multiple_value_record = record.extra.get('_multi_value', False) other_records = record.extra.get('_other_records', []) if record.type == RecordType.MX: data = '%s %s' % (extra['priority'], data) if multiple_value_record and len(other_records) > 0: rvalue = [data] for other_record in other_records: if record.type == RecordType.MX: rvalue.append('%s %s' % (other_record['extra']['priority'], other_record['data'])) else: rvalue.append(other_record['data']) else: rvalue = [data] record_data = { 'rrset_values': rvalue } if extra is not None and 'ttl' in extra: record_data['rrset_ttl'] = extra['ttl'] try: self.connection.request(action=action, method='PUT', data=record_data) except ResourceNotFoundError: raise RecordDoesNotExistError(value='', driver=self.connection.driver, record_id=record.id) record_data['rrset_name'] = record.name record_data['rrset_type'] = self.RECORD_TYPE_MAP[record.type] return self._to_record(record_data, record.zone)[0] """ The Gandi service considers all values for a name-type combination to be one record. Deleting that name-type record means deleting all values for it. """ def delete_record(self, record): action = '%s/domains/%s/records/%s/%s' % ( API_BASE, record.zone.id, record.name, self.RECORD_TYPE_MAP[record.type] ) try: self.connection.request(action=action, method='DELETE') except ResourceNotFoundError: raise RecordDoesNotExistError(value='', driver=self.connection.driver, record_id=record.id) # Originally checked for success here, but it should never reach # this point with anything other than HTTP 200 return True def export_zone_to_bind_format(self, zone): action = '%s/domains/%s/records' % (API_BASE, zone.id) headers = { 'Accept': 'text/plain' } resp = self.connection.request(action=action, method='GET', headers=headers, raw=True) return resp.body # There is nothing you can update about a domain; you can update zones' # names and which zone a domain is associated with, but the domain itself # is basically immutable. Instead, some ex_ methods for dealing with # Gandi zones. """ Update the name of a Gandi zone. Note that a Gandi zone is not the same as a Libcloud zone. A Gandi zone is a separate object type from a Gandi domain; a Gandi zone can be reused by multiple Gandi domains, and the actual records are associated with the zone directly. This is mostly masked in this driver to make it look like records are associated with domains. If you need to step out of that masking, use these extension methods. :param zone_uuid: Identifier for the Gandi zone. :type zone_uuid: ``str`` :param name: New name for the Gandi zone. :type name: ``str`` :return: ``bool`` """ def ex_update_gandi_zone_name(self, zone_uuid, name): action = '%s/zones/%s' % (API_BASE, zone_uuid) data = { 'name': name, } self.connection.request(action=action, method='PATCH', data=data) return True # There is no concept of deleting domains in this API, not even to # disassociate a domain from a zone. You can delete a zone, though. """ Delete a Gandi zone. This may raise a ResourceConflictError if you try to delete a zone that has domains still using it. :param zone_uuid: Identifier for the Gandi zone :type zone_uuid: ``str`` :return: ``bool`` """ def ex_delete_gandi_zone(self, zone_uuid): self.connection.request(action='%s/zones/%s' % (API_BASE, zone_uuid), method='DELETE') return True """ Change the Gandi zone a domain is asociated with. :param domain: Domain name to switch zones. :type domain: ``str`` :param zone_uuid: Identifier for the new Gandi zone to switch to. :type zone_uuid: ``str`` :return: ``bool`` """ def ex_switch_domain_gandi_zone(self, domain, zone_uuid): domain_data = { 'zone_uuid': zone_uuid, } self.connection.request(action='%s/domains/%s' % (API_BASE, domain), method='PATCH', data=domain_data) return True """ Create a new record with multiple values. :param data: Record values (depends on the record type) :type data: ``list`` (of ``str``) :return: ``list`` of :class:`Record`s """ def ex_create_multi_value_record(self, name, zone, type, data, extra=None): self._validate_record(None, name, type, data, extra) action = '%s/domains/%s/records' % (API_BASE, zone.id) record_data = { 'rrset_name': name, 'rrset_type': self.RECORD_TYPE_MAP[type], 'rrset_values': data, } if extra is not None and 'ttl' in extra: record_data['rrset_ttl'] = extra['ttl'] try: self.connection.request(action=action, method='POST', data=record_data) except ResourceConflictError: raise RecordAlreadyExistsError(value='', driver=self.connection.driver, record_id='%s:%s' % ( self.RECORD_TYPE_MAP[type], name)) return self._to_record(record_data, zone) def _to_record(self, data, zone): records = [] rrset_values = data['rrset_values'] multiple_value_record = len(rrset_values) > 1 for index, rrset_value in enumerate(rrset_values): record = self._to_record_sub(data, zone, rrset_value) record.extra['_multi_value'] = multiple_value_record if multiple_value_record: record.extra['_other_records'] = [] records.append(record) if multiple_value_record: for index in range(0, len(records)): record = records[index] for other_index, other_record in enumerate(records): if index == other_index: continue extra = copy.deepcopy(other_record.extra) extra.pop('_multi_value') extra.pop('_other_records') item = { 'name': other_record.name, 'data': other_record.data, 'type': other_record.type, 'extra': extra } record.extra['_other_records'].append(item) return records def _to_record_sub(self, data, zone, value): extra = { 'ttl': int(data['rrset_ttl']), } if data['rrset_type'] == 'MX': priority, value = value.split() extra['priority'] = priority return Record( id='%s:%s' % (data['rrset_type'], data['rrset_name']), name=data['rrset_name'], type=self._string_to_record_type(data['rrset_type']), data=value, zone=zone, driver=self, ttl=data['rrset_ttl'], extra=extra) def _to_records(self, data, zone): records = [] for r in data: records += self._to_record(r, zone) return records def _to_zone(self, zone): extra = {} if 'zone_uuid' in zone: extra = { 'zone_uuid': zone['zone_uuid'] } return Zone( id=str(zone['fqdn']), domain=zone['fqdn'], type='master', ttl=0, driver=self, extra=extra, ) def _to_zones(self, zones): ret = [] for z in zones: ret.append(self._to_zone(z)) return ret def _validate_record(self, record_id, name, record_type, data, extra): if len(data) > 1024: raise RecordError('Record data must be <= 1024 characters', driver=self, record_id=record_id) if type == 'MX' or type == RecordType.MX: if extra is None or 'priority' not in extra: raise RecordError('MX record must have a priority', driver=self, record_id=record_id) if extra is not None and '_other_records' in extra: for other_value in extra.get('_other_records', []): if len(other_value['data']) > 1024: raise RecordError('Record data must be <= 1024 characters', driver=self, record_id=record_id) if type == 'MX' or type == RecordType.MX: if (other_value['extra'] is None or 'priority' not in other_value['extra']): raise RecordError('MX record must have a priority', driver=self, record_id=record_id) if extra is not None and 'ttl' in extra: if extra['ttl'] < TTL_MIN: raise RecordError('TTL must be at least 300 seconds', driver=self, record_id=record_id) if extra['ttl'] > TTL_MAX: raise RecordError('TTL must not exceed 30 days', driver=self, record_id=record_id) apache-libcloud-2.8.0/libcloud/dns/drivers/godaddy.py0000664000175000017500000003715413535474530022472 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'GoDaddyDNSDriver' ] try: import simplejson as json except Exception: import json from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.common.types import LibcloudError from libcloud.utils.py3 import httplib from libcloud.dns.types import Provider, RecordType, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record API_HOST = 'api.godaddy.com' VALID_RECORD_EXTRA_PARAMS = ['prio', 'ttl'] class GoDaddyDNSException(LibcloudError): def __init__(self, code, message): self.code = code self.message = message self.args = (code, message) def __str__(self): return self.__repr__() def __repr__(self): return ('' % (self.code, self.message)) class GoDaddyDNSResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED, httplib.NO_CONTENT] def parse_body(self): if not self.body: return None # json.loads doesn't like the regex expressions used in godaddy schema self.body = self.body.replace('\\.', '\\\\.') data = json.loads(self.body) return data def parse_error(self): data = self.parse_body() raise GoDaddyDNSException(code=data['code'], message=data['message']) def success(self): return self.status in self.valid_response_codes class GoDaddyDNSConnection(ConnectionKey): responseCls = GoDaddyDNSResponse host = API_HOST allow_insecure = False def __init__(self, key, secret, secure=True, shopper_id=None, host=None, port=None, url=None, timeout=None, proxy_url=None, backoff=None, retry_delay=None): super(GoDaddyDNSConnection, self).__init__( key, secure=secure, host=host, port=port, url=url, timeout=timeout, proxy_url=proxy_url, backoff=backoff, retry_delay=retry_delay) self.key = key self.secret = secret self.shopper_id = shopper_id def add_default_headers(self, headers): if self.shopper_id is not None: headers['X-Shopper-Id'] = self.shopper_id headers['Content-type'] = 'application/json' headers['Authorization'] = "sso-key %s:%s" % \ (self.key, self.secret) return headers class GoDaddyDNSDriver(DNSDriver): """ A driver for GoDaddy DNS. This is for customers of GoDaddy who wish to purchase, update existing domains and manage records for DNS zones owned by GoDaddy NS servers. """ type = Provider.GODADDY name = 'GoDaddy DNS' website = 'https://www.godaddy.com/' connectionCls = GoDaddyDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'SPF', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', } def __init__(self, shopper_id, key, secret, secure=True, host=None, port=None): """ Instantiate a new `GoDaddyDNSDriver` :param shopper_id: Your customer ID or shopper ID with GoDaddy :type shopper_id: ``str`` :param key: Your access key from developer.godaddy.com :type key: ``str`` :param secret: Your access key secret :type secret: ``str`` """ self.shopper_id = shopper_id super(GoDaddyDNSDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, shopper_id=str(shopper_id)) def list_zones(self): """ Return a list of zones (purchased domains) :return: ``list`` of :class:`Zone` """ result = self.connection.request( '/v1/domains/').object zones = self._to_zones(result) return zones def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ result = self.connection.request( '/v1/domains/%s/records' % (zone.domain)).object records = self._to_records(items=result, zone=zone) return records def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ new_record = self._format_record(name, type, data, extra) self.connection.request( '/v1/domains/%s/records' % (zone.domain), method='PATCH', data=json.dumps([new_record])) id = self._get_id_of_record(name, type) return Record( id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=new_record['ttl'], extra=extra) def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` """ new_record = self._format_record(name, type, data, extra) self.connection.request( '/v1/domains/%s/records/%s/%s' % (record.zone.domain, record.type, record.name), method='PUT', data=json.dumps([new_record])) id = self._get_id_of_record(name, type) return Record( id=id, name=name, type=type, data=data, zone=record.zone, driver=self, ttl=new_record['ttl'], extra=extra) def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ parts = record_id.split(':') result = self.connection.request( '/v1/domains/%s/records/%s/%s' % ( zone_id, parts[1], parts[0])).object if len(result) == 0: raise RecordDoesNotExistError(record_id, driver=self, record_id=record_id) return self._to_record(result[0], self.get_zone(zone_id)) def get_zone(self, zone_id): """ Get a zone (by domain) :param zone_id: The domain, not the ID :type zone_id: ``str`` :rtype: :class:`Zone` """ result = self.connection.request( '/v1/domains/%s/' % zone_id).object zone = self._to_zone(result) return zone def delete_zone(self, zone): """ Delete a zone. Note: This will CANCEL a purchased domain :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ self.connection.request( '/v1/domains/%s' % (zone.domain), method='DELETE') # no error means ok return True def ex_check_availability(self, domain, for_transfer=False): """ Check the availability of the domain :param domain: the domain name e.g. wazzlewobbleflooble.com :type domain: ``str`` :param for_transfer: Check if domain is available for transfer :type for_transfer: ``bool`` :rtype: `list` of :class:`GoDaddyAvailability` """ result = self.connection.request( '/v1/domains/available', method='GET', params={ 'domain': domain, 'forTransfer': str(for_transfer) } ).object return GoDaddyAvailability( domain=result['domain'], available=result['available'], price=result['price'], currency=result['currency'], period=result['period'] ) def ex_list_tlds(self): """ List available TLDs for sale :rtype: ``list`` of :class:`GoDaddyTLD` """ result = self.connection.request( '/v1/domains/tlds', method='GET' ).object return self._to_tlds(result) def ex_get_purchase_schema(self, tld): """ Get the schema that needs completing to purchase a new domain Use this in conjunction with ex_purchase_domain :param tld: The top level domain e.g com, eu, uk :type tld: ``str`` :rtype: `dict` the JSON Schema """ result = self.connection.request( '/v1/domains/purchase/schema/%s' % tld, method='GET' ).object return result def ex_get_agreements(self, tld, privacy=True): """ Get the legal agreements for a tld Use this in conjunction with ex_purchase_domain :param tld: The top level domain e.g com, eu, uk :type tld: ``str`` :rtype: `dict` the JSON Schema """ result = self.connection.request( '/v1/domains/agreements', params={ 'tlds': tld, 'privacy': str(privacy) }, method='GET' ).object agreements = [] for item in result: agreements.append( GoDaddyLegalAgreement( agreement_key=item['agreementKey'], title=item['title'], url=item['url'], content=item['content'])) return agreements def ex_purchase_domain(self, purchase_request): """ Purchase a domain with GoDaddy :param purchase_request: The completed document from ex_get_purchase_schema :type purchase_request: ``dict`` :rtype: :class:`GoDaddyDomainPurchaseResponse` Your order """ result = self.connection.request( '/v1/domains/purchase', data=purchase_request, method='POST' ).object return GoDaddyDomainPurchaseResponse( order_id=result['orderId'], item_count=result['itemCount'], total=result['total'], currency=result['currency'] ) def _format_record(self, name, type, data, extra): if extra is None: extra = {} new_record = {} if type == RecordType.SRV: new_record = { 'type': type, 'name': name, 'data': data, 'priority': 1, 'ttl': extra.get('ttl', 5), 'service': extra.get('service', ''), 'protocol': extra.get('protocol', ''), 'port': extra.get('port', ''), 'weight': extra.get('weight', '1') } else: new_record = { 'type': type, 'name': name, 'data': data, 'ttl': extra.get('ttl', 5) } if type == RecordType.MX: new_record['priority'] = 1 return new_record def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_zone(self, item): extra = {"expires": item['expires']} zone = Zone(id=item['domainId'], domain=item['domain'], type='master', ttl=None, driver=self, extra=extra) return zone def _to_records(self, items, zone=None): records = [] for item in items: records.append(self._to_record(item=item, zone=zone)) return records def _to_record(self, item, zone=None): ttl = item['ttl'] type = self._string_to_record_type(item['type']) name = item['name'] id = self._get_id_of_record(name, type) record = Record(id=id, name=name, type=type, data=item['data'], zone=zone, driver=self, ttl=ttl) return record def _to_tlds(self, items): tlds = [] for item in items: tlds.append(self._to_tld(item)) return tlds def _to_tld(self, item): return GoDaddyTLD( name=item['name'], tld_type=item['type'] ) def _get_id_of_record(self, name, type): return '%s:%s' % (name, type) def _ex_connection_class_kwargs(self): return {'shopper_id': self.shopper_id} class GoDaddyAvailability(object): def __init__(self, domain, available, price, currency, period): self.domain = domain self.available = bool(available) # currency comes in micro-units, convert to dollars. self.price = float(price) / 1000000 self.currency = currency self.period = int(period) class GoDaddyTLD(object): def __init__(self, name, tld_type): self.name = name self.type = tld_type class GoDaddyDomainPurchaseResponse(object): def __init__(self, order_id, item_count, total, currency): self.order_id = order_id self.item_count = item_count self.total = total self.current = currency class GoDaddyLegalAgreement(object): def __init__(self, agreement_key, title, url, content): self.agreement_key = agreement_key self.title = title self.url = url self.content = content apache-libcloud-2.8.0/libcloud/dns/drivers/google.py0000664000175000017500000003046113535474530022325 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'GoogleDNSDriver' ] # API docs: https://cloud.google.com/dns/api/v1 API_VERSION = 'v1' import re from libcloud.common.google import GoogleResponse, GoogleBaseConnection from libcloud.common.google import ResourceNotFoundError from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record class GoogleDNSResponse(GoogleResponse): pass class GoogleDNSConnection(GoogleBaseConnection): host = "www.googleapis.com" responseCls = GoogleDNSResponse def __init__(self, user_id, key, secure, auth_type=None, credential_file=None, project=None, **kwargs): super(GoogleDNSConnection, self).\ __init__(user_id, key, secure=secure, auth_type=auth_type, credential_file=credential_file, **kwargs) self.request_path = '/dns/%s/projects/%s' % (API_VERSION, project) class GoogleDNSDriver(DNSDriver): type = Provider.GOOGLE name = 'Google DNS' connectionCls = GoogleDNSConnection website = 'https://cloud.google.com/' RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SOA: 'SOA', RecordType.SPF: 'SPF', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', } def __init__(self, user_id, key, project=None, auth_type=None, scopes=None, **kwargs): self.auth_type = auth_type self.project = project self.scopes = scopes if not self.project: raise ValueError('Project name must be specified using ' '"project" keyword.') super(GoogleDNSDriver, self).__init__(user_id, key, **kwargs) def iterate_zones(self): """ Return a generator to iterate over available zones. :rtype: ``generator`` of :class:`Zone` """ return self._get_more('zones') def iterate_records(self, zone): """ Return a generator to iterate over records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :rtype: ``generator`` of :class:`Record` """ return self._get_more('records', zone=zone) def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ request = '/managedZones/%s' % (zone_id) try: response = self.connection.request(request, method='GET').object except ResourceNotFoundError: raise ZoneDoesNotExistError(value='', driver=self.connection.driver, zone_id=zone_id) return self._to_zone(response) def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ (record_type, record_name) = record_id.split(':', 1) params = { 'name': record_name, 'type': record_type, } request = '/managedZones/%s/rrsets' % (zone_id) try: response = self.connection.request(request, method='GET', params=params).object except ResourceNotFoundError: raise ZoneDoesNotExistError(value='', driver=self.connection.driver, zone_id=zone_id) if len(response['rrsets']) > 0: zone = self.get_zone(zone_id) return self._to_record(response['rrsets'][0], zone) raise RecordDoesNotExistError(value='', driver=self.connection.driver, record_id=record_id) def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com.) with a \'.\' at the end. :type domain: ``str`` :param type: Zone type (master is the only one supported). :type type: ``str`` :param ttl: TTL for new records. (unused) :type ttl: ``int`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Zone` """ name = None description = '' if extra: description = extra.get('description') name = extra.get('name') if name is None: name = self._cleanup_domain(domain) data = { 'dnsName': domain, 'name': name, 'description': description, } request = '/managedZones' response = self.connection.request(request, method='POST', data=data).object return self._to_zone(response) def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name fully qualified, with a \'.\' at the end. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes. (optional) :type extra: ``dict`` :rtype: :class:`Record` """ ttl = data.get('ttl', 0) rrdatas = data.get('rrdatas', []) data = { 'additions': [ { 'name': name, 'type': type, 'ttl': int(ttl), 'rrdatas': rrdatas, } ] } request = '/managedZones/%s/changes' % (zone.id) response = self.connection.request(request, method='POST', data=data).object return self._to_record(response['additions'][0], zone) def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ request = '/managedZones/%s' % (zone.id) response = self.connection.request(request, method='DELETE') return response.success() def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ data = { 'deletions': [ { 'name': record.name, 'type': record.type, 'rrdatas': record.data['rrdatas'], 'ttl': record.data['ttl'] } ] } request = '/managedZones/%s/changes' % (record.zone.id) response = self.connection.request(request, method='POST', data=data) return response.success() def ex_bulk_record_changes(self, zone, records): """ Bulk add and delete records. :param zone: Zone where the requested record changes are done. :type zone: :class:`Zone` :param records: Dictionary of additions list or deletions list, or both of resourceRecordSets. For example: {'additions': [{'rrdatas': ['127.0.0.1'], 'kind': 'dns#resourceRecordSet', 'type': 'A', 'name': 'www.example.com.', 'ttl': '300'}], 'deletions': [{'rrdatas': ['127.0.0.1'], 'kind': 'dns#resourceRecordSet', 'type': 'A', 'name': 'www2.example.com.', 'ttl': '300'}]} :type records: ``dict`` :return: A dictionary of Record additions and deletions. :rtype: ``dict`` of additions and deletions of :class:`Record` """ request = '/managedZones/%s/changes' % (zone.id) response = self.connection.request(request, method='POST', data=records).object response = response or {} response_data = { 'additions': self._to_records(response.get('additions', []), zone), 'deletions': self._to_records(response.get('deletions', []), zone), } return response_data def _get_more(self, rtype, **kwargs): last_key = None exhausted = False while not exhausted: items, last_key, exhausted = self._get_data(rtype, last_key, **kwargs) for item in items: yield item def _get_data(self, rtype, last_key, **kwargs): params = {} if last_key: params['pageToken'] = last_key if rtype == 'zones': request = '/managedZones' transform_func = self._to_zones r_key = 'managedZones' elif rtype == 'records': zone = kwargs['zone'] request = '/managedZones/%s/rrsets' % (zone.id) transform_func = self._to_records r_key = 'rrsets' response = self.connection.request(request, method='GET', params=params,) if response.success(): nextpage = response.object.get('nextPageToken', None) items = transform_func(response.object.get(r_key), **kwargs) exhausted = False if nextpage is not None else True return items, nextpage, exhausted else: return [], None, True def _ex_connection_class_kwargs(self): return {'auth_type': self.auth_type, 'project': self.project, 'scopes': self.scopes} def _to_zones(self, response): zones = [] for r in response: zones.append(self._to_zone(r)) return zones def _to_zone(self, r): extra = {} if 'description' in r: extra['description'] = r.get('description') extra['creationTime'] = r.get('creationTime') extra['nameServers'] = r.get('nameServers') extra['id'] = r.get('id') return Zone(id=r['name'], domain=r['dnsName'], type='master', ttl=0, driver=self, extra=extra) def _to_records(self, response, zone): records = [] for r in response: records.append(self._to_record(r, zone)) return records def _to_record(self, r, zone): record_id = '%s:%s' % (r['type'], r['name']) return Record(id=record_id, name=r['name'], type=r['type'], data=r, zone=zone, driver=self, ttl=r.get('ttl', None), extra={}) def _cleanup_domain(self, domain): # name can only contain lower case alphanumeric characters and hyphens domain = re.sub(r'[^a-zA-Z0-9-]', '-', domain) if domain[-1] == '-': domain = domain[:-1] return domain apache-libcloud-2.8.0/libcloud/dns/drivers/hostvirtual.py0000664000175000017500000002223313570310635023425 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'HostVirtualDNSDriver' ] try: import simplejson as json except Exception: import json from libcloud.utils.py3 import httplib from libcloud.utils.misc import merge_valid_keys, get_new_obj from libcloud.common.hostvirtual import HostVirtualResponse from libcloud.common.hostvirtual import HostVirtualConnection from libcloud.compute.drivers.hostvirtual import API_ROOT from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record VALID_RECORD_EXTRA_PARAMS = ['prio', 'ttl'] class HostVirtualDNSResponse(HostVirtualResponse): def parse_error(self): context = self.connection.context status = int(self.status) if status == httplib.NOT_FOUND: if context['resource'] == 'zone': raise ZoneDoesNotExistError( value=self.parse_body()['error']['message'], driver=self, zone_id=context['id']) elif context['resource'] == 'record': raise RecordDoesNotExistError( value=self.parse_body()['error']['message'], driver=self, record_id=context['id']) super(HostVirtualDNSResponse, self).parse_error() return self.body class HostVirtualDNSConnection(HostVirtualConnection): responseCls = HostVirtualDNSResponse class HostVirtualDNSDriver(DNSDriver): type = Provider.HOSTVIRTUAL name = 'Host Virtual DNS' website = 'https://www.hostvirtual.com/' connectionCls = HostVirtualDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'SPF', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', } def __init__(self, key, secure=True, host=None, port=None): super(HostVirtualDNSDriver, self).__init__(key=key, secure=secure, host=host, port=port) def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_zone(self, item): extra = {} if 'records' in item: extra['records'] = item['records'] if item['type'] == 'NATIVE': item['type'] = 'master' zone = Zone(id=item['id'], domain=item['name'], type=item['type'], ttl=item['ttl'], driver=self, extra=extra) return zone def _to_records(self, items, zone=None): records = [] for item in items: records.append(self._to_record(item=item, zone=zone)) return records def _to_record(self, item, zone=None): extra = {'ttl': item['ttl']} type = self._string_to_record_type(item['type']) name = item['name'][:-len(zone.domain) - 1] record = Record(id=item['id'], name=name, type=type, data=item['content'], zone=zone, driver=self, ttl=item['ttl'], extra=extra) return record def list_zones(self): result = self.connection.request( API_ROOT + '/dns/zones/').object zones = self._to_zones(result) return zones def list_records(self, zone): params = {'id': zone.id} self.connection.set_context({'resource': 'zone', 'id': zone.id}) try: result = self.connection.request( API_ROOT + '/dns/records/', params=params).object except ZoneDoesNotExistError as e: if 'Not Found: No Records Found' in e.value: return [] raise e records = self._to_records(items=result, zone=zone) return records def get_zone(self, zone_id): params = {'id': zone_id} self.connection.set_context({'resource': 'zone', 'id': zone_id}) result = self.connection.request( API_ROOT + '/dns/zone/', params=params).object if 'id' not in result: raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone_id) zone = self._to_zone(result) return zone def get_record(self, zone_id, record_id): zone = self.get_zone(zone_id=zone_id) params = {'id': record_id} self.connection.set_context({'resource': 'record', 'id': record_id}) result = self.connection.request( API_ROOT + '/dns/record/', params=params).object if 'id' not in result: raise RecordDoesNotExistError(value='', driver=self, record_id=record_id) record = self._to_record(item=result, zone=zone) return record def delete_zone(self, zone): params = {'id': zone.id} self.connection.set_context({'resource': 'zone', 'id': zone.id}) result = self.connection.request( API_ROOT + '/dns/zone/', params=params, method='DELETE').object return bool(result) def delete_record(self, record): params = {'id': record.id} self.connection.set_context({'resource': 'record', 'id': record.id}) result = self.connection.request( API_ROOT + '/dns/record/', params=params, method='DELETE').object return bool(result) def create_zone(self, domain, type='NATIVE', ttl=None, extra=None): if type == 'master': type = 'NATIVE' elif type == 'slave': type = 'SLAVE' params = {'name': domain, 'type': type, 'ttl': ttl} result = self.connection.request( API_ROOT + '/dns/zone/', data=json.dumps(params), method='POST').object extra = { 'soa': result['soa'], 'ns': result['ns'] } zone = Zone(id=result['id'], domain=domain, type=type, ttl=ttl, extra=extra, driver=self) return zone def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): params = {'id': zone.id} if domain: params['name'] = domain if type: params['type'] = type self.connection.set_context({'resource': 'zone', 'id': zone.id}) self.connection.request(API_ROOT + '/dns/zone/', data=json.dumps(params), method='PUT').object updated_zone = get_new_obj( obj=zone, klass=Zone, attributes={ 'domain': domain, 'type': type, 'ttl': ttl, 'extra': extra }) return updated_zone def create_record(self, name, zone, type, data, extra=None): params = { 'name': name, 'type': self.RECORD_TYPE_MAP[type], 'domain_id': zone.id, 'content': data } merged = merge_valid_keys( params=params, valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra ) self.connection.set_context({'resource': 'zone', 'id': zone.id}) result = self.connection.request( API_ROOT + '/dns/record/', data=json.dumps(params), method='POST').object record = Record(id=result['id'], name=name, type=type, data=data, extra=merged, zone=zone, ttl=merged.get('ttl', None), driver=self) return record def update_record(self, record, name=None, type=None, data=None, extra=None): params = { 'domain_id': record.zone.id, 'record_id': record.id } if name: params['name'] = name if data: params['content'] = data if type is not None: params['type'] = self.RECORD_TYPE_MAP[type] merged = merge_valid_keys( params=params, valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra ) self.connection.set_context({'resource': 'record', 'id': record.id}) self.connection.request(API_ROOT + '/dns/record/', data=json.dumps(params), method='PUT').object updated_record = get_new_obj( obj=record, klass=Record, attributes={ 'name': name, 'data': data, 'type': type, 'extra': merged }) return updated_record apache-libcloud-2.8.0/libcloud/dns/drivers/linode.py0000664000175000017500000002415713535474530022330 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'LinodeDNSDriver' ] from libcloud.utils.misc import merge_valid_keys, get_new_obj from libcloud.common.linode import (API_ROOT, LinodeException, LinodeConnection, LinodeResponse) from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record VALID_ZONE_EXTRA_PARAMS = ['SOA_Email', 'Refresh_sec', 'Retry_sec', 'Expire_sec', 'status', 'master_ips'] VALID_RECORD_EXTRA_PARAMS = ['Priority', 'Weight', 'Port', 'Protocol', 'TTL_sec'] class LinodeDNSResponse(LinodeResponse): def _make_excp(self, error): result = super(LinodeDNSResponse, self)._make_excp(error) if isinstance(result, LinodeException) and result.code == 5: context = self.connection.context if context['resource'] == 'zone': result = ZoneDoesNotExistError(value='', driver=self.connection.driver, zone_id=context['id']) elif context['resource'] == 'record': result = RecordDoesNotExistError(value='', driver=self.connection.driver, record_id=context['id']) return result class LinodeDNSConnection(LinodeConnection): responseCls = LinodeDNSResponse class LinodeDNSDriver(DNSDriver): type = Provider.LINODE name = 'Linode DNS' website = 'http://www.linode.com/' connectionCls = LinodeDNSConnection RECORD_TYPE_MAP = { RecordType.NS: 'NS', RecordType.MX: 'MX', RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.TXT: 'TXT', RecordType.SRV: 'SRV', } def list_zones(self): params = {'api_action': 'domain.list'} data = self.connection.request(API_ROOT, params=params).objects[0] zones = self._to_zones(data) return zones def list_records(self, zone): params = {'api_action': 'domain.resource.list', 'DOMAINID': zone.id} self.connection.set_context(context={'resource': 'zone', 'id': zone.id}) data = self.connection.request(API_ROOT, params=params).objects[0] records = self._to_records(items=data, zone=zone) return records def get_zone(self, zone_id): params = {'api_action': 'domain.list', 'DomainID': zone_id} self.connection.set_context(context={'resource': 'zone', 'id': zone_id}) data = self.connection.request(API_ROOT, params=params).objects[0] zones = self._to_zones(data) if len(zones) != 1: raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone_id) return zones[0] def get_record(self, zone_id, record_id): zone = self.get_zone(zone_id=zone_id) params = {'api_action': 'domain.resource.list', 'DomainID': zone_id, 'ResourceID': record_id} self.connection.set_context(context={'resource': 'record', 'id': record_id}) data = self.connection.request(API_ROOT, params=params).objects[0] records = self._to_records(items=data, zone=zone) if len(records) != 1: raise RecordDoesNotExistError(value='', driver=self, record_id=record_id) return records[0] def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. API docs: http://www.linode.com/api/dns/domain.create """ params = {'api_action': 'domain.create', 'Type': type, 'Domain': domain} if ttl: params['TTL_sec'] = ttl merged = merge_valid_keys(params=params, valid_keys=VALID_ZONE_EXTRA_PARAMS, extra=extra) data = self.connection.request(API_ROOT, params=params).objects[0] zone = Zone(id=data['DomainID'], domain=domain, type=type, ttl=ttl, extra=merged, driver=self) return zone def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): """ Update an existing zone. API docs: http://www.linode.com/api/dns/domain.update """ params = {'api_action': 'domain.update', 'DomainID': zone.id} if type: params['Type'] = type if domain: params['Domain'] = domain if ttl: params['TTL_sec'] = ttl merged = merge_valid_keys(params=params, valid_keys=VALID_ZONE_EXTRA_PARAMS, extra=extra) self.connection.request(API_ROOT, params=params).objects[0] updated_zone = get_new_obj(obj=zone, klass=Zone, attributes={'domain': domain, 'type': type, 'ttl': ttl, 'extra': merged}) return updated_zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. API docs: http://www.linode.com/api/dns/domain.resource.create """ params = {'api_action': 'domain.resource.create', 'DomainID': zone.id, 'Name': name, 'Target': data, 'Type': self.RECORD_TYPE_MAP[type]} merged = merge_valid_keys(params=params, valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra) result = self.connection.request(API_ROOT, params=params).objects[0] record = Record(id=result['ResourceID'], name=name, type=type, data=data, extra=merged, zone=zone, driver=self, ttl=merged.get('TTL_sec', None)) return record def update_record(self, record, name=None, type=None, data=None, extra=None): """ Update an existing record. API docs: http://www.linode.com/api/dns/domain.resource.update """ params = {'api_action': 'domain.resource.update', 'ResourceID': record.id, 'DomainID': record.zone.id} if name: params['Name'] = name if data: params['Target'] = data if type is not None: params['Type'] = self.RECORD_TYPE_MAP[type] merged = merge_valid_keys(params=params, valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra) self.connection.request(API_ROOT, params=params).objects[0] updated_record = get_new_obj(obj=record, klass=Record, attributes={'name': name, 'data': data, 'type': type, 'extra': merged}) return updated_record def delete_zone(self, zone): params = {'api_action': 'domain.delete', 'DomainID': zone.id} self.connection.set_context(context={'resource': 'zone', 'id': zone.id}) data = self.connection.request(API_ROOT, params=params).objects[0] return 'DomainID' in data def delete_record(self, record): params = {'api_action': 'domain.resource.delete', 'DomainID': record.zone.id, 'ResourceID': record.id} self.connection.set_context(context={'resource': 'record', 'id': record.id}) data = self.connection.request(API_ROOT, params=params).objects[0] return 'ResourceID' in data def _to_zones(self, items): """ Convert a list of items to the Zone objects. """ zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_zone(self, item): """ Build an Zone object from the item dictionary. """ extra = {'SOA_Email': item['SOA_EMAIL'], 'status': item['STATUS'], 'description': item['DESCRIPTION']} zone = Zone(id=item['DOMAINID'], domain=item['DOMAIN'], type=item['TYPE'], ttl=item['TTL_SEC'], driver=self, extra=extra) return zone def _to_records(self, items, zone=None): """ Convert a list of items to the Record objects. """ records = [] for item in items: records.append(self._to_record(item=item, zone=zone)) return records def _to_record(self, item, zone=None): """ Build a Record object from the item dictionary. """ extra = {'protocol': item['PROTOCOL'], 'ttl_sec': item['TTL_SEC'], 'port': item['PORT'], 'weight': item['WEIGHT'], 'priority': item['PRIORITY']} type = self._string_to_record_type(item['TYPE']) record = Record(id=item['RESOURCEID'], name=item['NAME'], type=type, data=item['TARGET'], zone=zone, driver=self, ttl=item['TTL_SEC'], extra=extra) return record apache-libcloud-2.8.0/libcloud/dns/drivers/liquidweb.py0000664000175000017500000003115313570310635023027 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Liquid Web DNS Driver """ try: import simplejson as json except ImportError: import json from libcloud.common.liquidweb import LiquidWebResponse, LiquidWebConnection from libcloud.common.liquidweb import APIException from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError from libcloud.dns.types import RecordDoesNotExistError from libcloud.dns.types import RecordAlreadyExistsError __all__ = [ 'LiquidWebDNSDriver' ] class LiquidWebDNSResponse(LiquidWebResponse): pass class LiquidWebDNSConnection(LiquidWebConnection): responseCls = LiquidWebDNSResponse class LiquidWebDNSDriver(DNSDriver): type = Provider.LIQUIDWEB name = 'Liquidweb DNS' website = 'https://www.liquidweb.com' connectionCls = LiquidWebDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SOA: 'SOA', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT' } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ action = '/v1/Network/DNS/Zone/list' response = self.connection.request(action=action, method='POST') zones = self._to_zones(response.objects[0]) return zones def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '/v1/Network/DNS/Record/list' data = json.dumps({'params': {'zone_id': zone.id}}) response = self.connection.request(action=action, method='POST', data=data) records = self._to_records(response.objects[0], zone=zone) return records def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ action = '/v1/Network/DNS/Zone/details' data = json.dumps({'params': {'id': zone_id}}) try: response = self.connection.request(action=action, method='POST', data=data) except APIException as e: if e.error_class == 'LW::Exception::RecordNotFound': raise ZoneDoesNotExistError(zone_id=zone_id, value=e.value, driver=self) else: raise e zone = self._to_zone(response.objects[0]) return zone def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ zone = self.get_zone(zone_id=zone_id) action = '/v1/Network/DNS/Record/details' data = json.dumps({'params': {'id': record_id}}) try: response = self.connection.request(action=action, method='POST', data=data) except APIException as e: if e.error_class == 'LW::Exception::RecordNotFound': raise RecordDoesNotExistError(record_id=record_id, driver=self, value=e.value) else: raise e record = self._to_record(response.objects[0], zone=zone) return record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (This is not really used. See API docs for extra parameters). :type type: ``str`` :param ttl: TTL for new records. (This is not really used) :type ttl: ``int`` :param extra: Extra attributes (driver specific). ('region_support', 'zone_data') :type extra: ``dict`` :rtype: :class:`Zone` For more info, please see: https://www.liquidweb.com/storm/api/docs/v1/Network/DNS/Zone.html """ action = '/v1/Network/DNS/Zone/create' data = {'params': {'name': domain}} if extra is not None: data['params'].update(extra) try: data = json.dumps(data) response = self.connection.request(action=action, method='POST', data=data) except APIException as e: if e.error_class == 'LW::Exception::DuplicateRecord': raise ZoneAlreadyExistsError(zone_id=domain, value=e.value, driver=self) else: raise e zone = self._to_zone(response.objects[0]) return zone def create_record(self, name, zone, type, data, extra=None): """ Create a record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone which the records will be created for. :type zone: :class:`Zone` :param type: DNS record type ( 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT'). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes ('prio', 'ttl'). :type extra: ``dict`` :rtype: :class:`Record` """ action = '/v1/Network/DNS/Record/create' to_post = {'params': {'name': name, 'rdata': data, 'type': type, 'zone': zone.domain, 'zone_id': zone.id } } if extra is not None: to_post['params'].update(extra) data = json.dumps(to_post) try: response = self.connection.request(action=action, method='POST', data=data) except APIException as e: if e.error_class == 'LW::Exception::DuplicateRecord': raise RecordAlreadyExistsError(record_id=name, value=e.value, driver=self) else: raise e record = self._to_record(response.objects[0], zone=zone) return record def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type ( 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT'). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes ('name', 'rdata', 'prio', 'ttl'). :type extra: ``dict`` :rtype: :class:`Record` """ zone = record.zone action = '/v1/Network/DNS/Record/update' to_post = {'params': {'id': int(record.id), 'name': name, 'rdata': data}} if extra is not None: to_post['params'].update(extra) j_data = json.dumps(to_post) try: response = self.connection.request(action=action, method='PUT', data=j_data) except APIException as e: if e.error_class == 'LW::Exception::RecordNotFound': raise RecordDoesNotExistError(record_id=record.id, driver=self, value=e.value) else: raise e record = self._to_record(response.objects[0], zone=zone) return record def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ action = '/v1/Network/DNS/Zone/delete' data = json.dumps({'params': {'id': zone.id}}) try: response = self.connection.request(action=action, method='POST', data=data) except APIException as e: if e.error_class == 'LW::Exception::RecordNotFound': raise ZoneDoesNotExistError(zone_id=zone.id, value=e.value, driver=self) else: raise e return zone.domain in response.objects def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ action = '/v1/Network/DNS/Record/delete' data = json.dumps({'params': {'id': record.id}}) try: response = self.connection.request(action=action, method='POST', data=data) except APIException as e: if e.error_class == 'LW::Exception::RecordNotFound': raise RecordDoesNotExistError(record_id=record.id, driver=self, value=e.value) else: raise e return record.id in response.objects def _to_zone(self, item): common_attr = ['id', 'name', 'type'] extra = {} for key in item: if key not in common_attr: extra[key] = item.get(key) zone = Zone(domain=item['name'], id=item['id'], type=item['type'], ttl=None, driver=self, extra=extra) return zone def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone): common_attr = ['id', 'rdata', 'name', 'type'] extra = {} for key in item: if key not in common_attr: extra[key] = item.get(key) record = Record(id=item['id'], name=item['name'], type=item['type'], data=item['rdata'], zone=zone, driver=self, extra=extra) return record def _to_records(self, items, zone): records = [] for item in items: records.append(self._to_record(item, zone)) return records apache-libcloud-2.8.0/libcloud/dns/drivers/luadns.py0000664000175000017500000002260513570310635022332 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. try: import simplejson as json except ImportError: import json from libcloud.common.luadns import LuadnsResponse, LuadnsConnection from libcloud.common.luadns import LuadnsException from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError from libcloud.dns.types import RecordDoesNotExistError __all__ = [ 'LuadnsDNSDriver' ] class LuadnsDNSResponse(LuadnsResponse): pass class LuadnsDNSConnection(LuadnsConnection): responseCls = LuadnsDNSResponse class LuadnsDNSDriver(DNSDriver): type = Provider.LUADNS name = 'Luadns' website = 'https://www.luadns.com' connectionCls = LuadnsDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SOA: 'SOA', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT' } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ action = '/v1/zones' response = self.connection.request(action=action, method='GET') zones = self._to_zones(response.parse_body()) return zones def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ action = '/v1/zones/%s' % zone_id try: response = self.connection.request(action=action) except LuadnsException as e: if e.message in ['Zone not found.', 'Resource not found.']: raise ZoneDoesNotExistError(zone_id=zone_id, value='', driver=self) else: raise e zone = self._to_zone(response.parse_body()) return zone def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ action = '/v1/zones/%s' % zone.id try: response = self.connection.request(action=action, method='DELETE') except LuadnsException as e: if e.message in ['Resource not found.', 'Zone not found.']: raise ZoneDoesNotExistError(zone_id=zone.id, value='', driver=self) else: raise e return response.status == 200 def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (This is not really used. See API docs for extra parameters). :type type: ``str`` :param ttl: TTL for new records. (This is not really used) :type ttl: ``int`` :param extra: Extra attributes (driver specific). ('region_support', 'zone_data') :type extra: ``dict`` :rtype: :class:`Zone` """ action = '/v1/zones' data = json.dumps({'name': domain}) try: response = self.connection.request(action=action, method='POST', data=data) except LuadnsException as e: if e.message == "Zone '%s' is taken already." % domain: raise ZoneAlreadyExistsError(zone_id=domain, value='', driver=self) else: raise e zone = self._to_zone(response.parse_body()) return zone def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '/v1/zones/%s/records' % zone.id response = self.connection.request(action=action) records = self._to_records(response.parse_body(), zone=zone) return records def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ zone = self.get_zone(zone_id=zone_id) action = '/v1/zones/%s/records/%s' % (zone_id, record_id) try: response = self.connection.request(action=action) except LuadnsException as e: if e.message == 'Record not found.': raise RecordDoesNotExistError(record_id=record_id, driver=self, value='') else: raise e record = self._to_record(response.parse_body(), zone=zone) return record def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ action = '/v1/zones/%s/records/%s' % (record.zone.id, record.id) try: response = self.connection.request(action=action, method='DELETE') except LuadnsException as e: if e.message == 'Record not found.': raise RecordDoesNotExistError(record_id=record.id, driver=self, value='') else: raise e return response.status == 200 def create_record(self, name, zone, type, data, extra=None): """ Create a record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone which the records will be created for. :type zone: :class:`Zone` :param type: DNS record type ( 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT'). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes ('prio', 'ttl'). :type extra: ``dict`` :rtype: :class:`Record` """ action = '/v1/zones/%s/records' % zone.id to_post = {'name': name, 'content': data, 'type': type, 'zone_id': int(zone.id)} # ttl is required to create a record for luadns # pass it through extra like this: extra={'ttl':ttl} if extra is not None: to_post.update(extra) data = json.dumps(to_post) try: response = self.connection.request(action=action, method='POST', data=data) except LuadnsException as e: raise e record = self._to_record(response.parse_body(), zone=zone) return record def _to_zone(self, item): common_attr = ['id', 'name'] extra = {} for key in item: if key not in common_attr: extra[key] = item.get(key) zone = Zone(domain=item['name'], id=item['id'], type=None, ttl=None, driver=self, extra=extra) return zone def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone): common_attr = ['id', 'content', 'name', 'type'] extra = {} for key in item: if key not in common_attr: extra[key] = item.get(key) record = Record(id=item['id'], name=item['name'], type=item['type'], data=item['content'], zone=zone, driver=self, extra=extra) return record def _to_records(self, items, zone): records = [] for item in items: records.append(self._to_record(item, zone)) return records apache-libcloud-2.8.0/libcloud/dns/drivers/nfsn.py0000664000175000017500000001577313570310635022020 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ NFSN DNS Driver """ import re from libcloud.common.exceptions import BaseHTTPError from libcloud.common.nfsn import NFSNConnection from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.types import RecordAlreadyExistsError from libcloud.dns.types import Provider, RecordType from libcloud.utils.py3 import httplib __all__ = [ 'NFSNDNSDriver', ] # The NFSN API does not return any internal "ID" strings for any DNS records. # This means that we must set all returned Record objects' id properties to # None. It also means that we cannot implement libcloud APIs that rely on # record_id, such as get_record(). Instead, the NFSN-specific # ex_get_records_by() method will return the desired Record objects. # # Additionally, the NFSN API does not provide ways to create, delete, or list # all zones, so create_zone(), delete_zone(), and list_zones() are not # implemented. class NFSNDNSDriver(DNSDriver): type = Provider.NFSN name = 'NFSN DNS' website = 'https://www.nearlyfreespeech.net' connectionCls = NFSNConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', RecordType.PTR: 'PTR', } def list_records(self, zone): """ Return a list of all records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ # Just use ex_get_records_by() with no name or type filters. return self.ex_get_records_by(zone) def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: name of the required zone, for example "example.com". :type zone_id: ``str`` :rtype: :class:`Zone` :raises: ZoneDoesNotExistError: If no zone could be found. """ # We will check if there is a serial property for this zone. If so, # then the zone exists. try: self.connection.request(action='/dns/%s/serial' % zone_id) except BaseHTTPError as e: if e.code == httplib.NOT_FOUND: raise ZoneDoesNotExistError(zone_id=None, driver=self, value=e.message) raise e return Zone(id=None, domain=zone_id, type='master', ttl=3600, driver=self) def ex_get_records_by(self, zone, name=None, type=None): """ Return a list of records for the provided zone, filtered by name and/or type. :param zone: Zone to list records for. :type zone: :class:`Zone` :param zone: Zone where the requested records are found. :type zone: :class:`Zone` :param name: name of the records, for example "www". (optional) :type name: ``str`` :param type: DNS record type (A, MX, TXT). (optional) :type type: :class:`RecordType` :return: ``list`` of :class:`Record` """ payload = {} if name is not None: payload['name'] = name if type is not None: payload['type'] = type action = '/dns/%s/listRRs' % zone.domain response = self.connection.request(action=action, data=payload, method='POST') return self._to_records(response, zone) def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, MX, TXT). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific, e.g. 'ttl'). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ action = '/dns/%s/addRR' % zone.domain payload = {'name': name, 'data': data, 'type': type} if extra is not None and extra.get('ttl', None) is not None: payload['ttl'] = extra['ttl'] try: self.connection.request(action=action, data=payload, method='POST') except BaseHTTPError as e: exists_re = re.compile(r'That RR already exists on the domain') if e.code == httplib.BAD_REQUEST and \ re.search(exists_re, e.message) is not None: value = '"%s" already exists in %s' % (name, zone.domain) raise RecordAlreadyExistsError(value=value, driver=self, record_id=None) raise e return self.ex_get_records_by(zone=zone, name=name, type=type)[0] def delete_record(self, record): """ Use this method to delete a record. :param record: record to delete :type record: `Record` :rtype: Bool """ action = '/dns/%s/removeRR' % record.zone.domain payload = {'name': record.name, 'data': record.data, 'type': record.type} try: self.connection.request(action=action, data=payload, method='POST') except BaseHTTPError as e: if e.code == httplib.NOT_FOUND: raise RecordDoesNotExistError(value=e.message, driver=self, record_id=None) raise e return True def _to_record(self, item, zone): ttl = int(item['ttl']) return Record(id=None, name=item['name'], data=item['data'], type=item['type'], zone=zone, driver=self, ttl=ttl) def _to_records(self, items, zone): records = [] for item in items.object: records.append(self._to_record(item, zone)) return records apache-libcloud-2.8.0/libcloud/dns/drivers/nsone.py0000664000175000017500000002744113570310635022171 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. try: import simplejson as json except ImportError: import json from libcloud.dns.types import Provider, ZoneDoesNotExistError, \ ZoneAlreadyExistsError, RecordDoesNotExistError, RecordAlreadyExistsError from libcloud.utils.py3 import httplib from libcloud.dns.base import DNSDriver, Zone, Record, RecordType from libcloud.common.nsone import NsOneConnection, NsOneResponse, \ NsOneException __all__ = [ 'NsOneDNSDriver' ] class NsOneDNSResponse(NsOneResponse): pass class NsOneDNSConnection(NsOneConnection): responseCls = NsOneDNSResponse class NsOneDNSDriver(DNSDriver): name = 'NS1 DNS' website = 'https://ns1.com' type = Provider.NSONE connectionCls = NsOneDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SOA: 'SOA', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT' } def list_zones(self): action = '/v1/zones' response = self.connection.request(action=action, method='GET') zones = self._to_zones(items=response.parse_body()) return zones def get_zone(self, zone_id): """ :param zone_id: Zone domain name (e.g. example.com) :return: :class:`Zone` """ action = '/v1/zones/%s' % zone_id try: response = self.connection.request(action=action, method='GET') except NsOneException as e: if e.message == 'zone not found': raise ZoneDoesNotExistError(value=e.message, driver=self, zone_id=zone_id) else: raise e zone = self._to_zone(response.objects[0]) return zone def create_zone(self, domain, type='master', ttl=None, extra=None): """ :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (This is not really used. See API docs for extra parameters) :type type: ``str`` :param ttl: TTL for new records (This is used through the extra param) :type ttl: ``int`` :param extra: Extra attributes that are specific to the driver such as ttl. :type extra: ``dict`` :rtype: :class:`Zone` """ action = '/v1/zones/%s' % domain raw_data = {'zone': domain} if extra is not None: raw_data.update(extra) post_data = json.dumps(raw_data) try: response = self.connection.request(action=action, method='PUT', data=post_data) except NsOneException as e: if e.message == 'zone already exists': raise ZoneAlreadyExistsError(value=e.message, driver=self, zone_id=domain) else: raise e zone = self._to_zone(response.objects[0]) return zone def delete_zone(self, zone): """ :param zone: Zone to be deleted. :type zone: :class:`Zone` :return: Boolean """ action = '/v1/zones/%s' % zone.domain """zones_list = self.list_zones() if not self.ex_zone_exists(zone_id=zone.id, zones_list=zones_list): raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone.id) """ try: response = self.connection.request(action=action, method='DELETE') except NsOneException as e: if e.message == 'zone not found': raise ZoneDoesNotExistError(value=e.message, driver=self, zone_id=zone.id) else: raise e return response.status == httplib.OK def list_records(self, zone): """ :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '/v1/zones/%s' % zone.domain try: response = self.connection.request(action=action, method='GET') except NsOneException as e: if e.message == 'zone not found': raise ZoneDoesNotExistError(value=e.message, driver=self, zone_id=zone.id) else: raise e records = self._to_records(items=response.parse_body()['records'], zone=zone) return records def get_record(self, zone_id, record_id): """ :param zone_id: The id of the zone where to search for the record (e.g. example.com) :type zone_id: ``str`` :param record_id: The type of record to search for (e.g. A, AAA, MX etc) :return: :class:`Record` """ action = '/v1/zones/%s/%s/%s' % (zone_id, zone_id, record_id) try: response = self.connection.request(action=action, method='GET') except NsOneException as e: if e.message == 'record not found': raise RecordDoesNotExistError(value=e.message, driver=self, record_id=record_id) else: raise e zone = self.get_zone(zone_id=zone_id) record = self._to_record(item=response.parse_body(), zone=zone) return record def delete_record(self, record): """ :param record: Record to delete. :type record: :class:`Record` :return: Boolean """ action = '/v1/zones/%s/%s/%s' % (record.zone.domain, record.name, record.type) try: response = self.connection.request(action=action, method='DELETE') except NsOneException as e: if e.message == 'record not found': raise RecordDoesNotExistError(value=e.message, driver=self, record_id=record.id) else: raise e return response.status == httplib.OK def create_record(self, name, zone, type, data, extra=None): """ :param name: Name of the record to create (e.g. foo). :type name: ``str`` :param zone: Zone where the record should be created. :type zone: :class:`Zone` :param type: Type of record (e.g. A, MX etc) :type type: ``str`` :param data: Data of the record (e.g. 127.0.0.1 for the A record) :type data: ``str`` :param extra: Extra data needed to create different types of records :type extra: ``dict`` :return: :class:`Record` """ action = '/v1/zones/%s/%s/%s' % (zone.domain, '%s.%s' % (name, zone.domain), type) raw_data = { "answers": [ { "answer": [ data ], } ], "type": type, "domain": '%s.%s' % (name, zone.domain), "zone": zone.domain } if extra is not None and extra.get('answers'): raw_data['answers'] = extra.get('answers') post_data = json.dumps(raw_data) try: response = self.connection.request(action=action, method='PUT', data=post_data) except NsOneException as e: if e.message == 'record already exists': raise RecordAlreadyExistsError(value=e.message, driver=self, record_id='') else: raise e record = self._to_record(item=response.parse_body(), zone=zone) return record def update_record(self, record, name, type, data, extra=None): """ :param record: Record to update :type record: :class:`Record` :param name: Name of the record to update (e.g. foo). :type name: ``str`` :param type: Type of record (e.g. A, MX etc) :type type: ``str`` :param data: Data of the record (e.g. 127.0.0.1 for the A record) :type data: ``str`` :param extra: Extra data needed to create different types of records :type extra: ``dict`` :return: :class:`Record` """ zone = record.zone action = '/v1/zones/%s/%s/%s' % (zone.domain, '%s.%s' % (name, zone.domain), type) raw_data = { "answers": [ { "answer": [ data ], } ] } if extra is not None and extra.get('answers'): raw_data['answers'] = extra.get('answers') post_data = json.dumps(raw_data) try: response = self.connection.request(action=action, data=post_data, method='POST') except NsOneException as e: if e.message == 'record does not exist': raise RecordDoesNotExistError(value=e.message, driver=self, record_id=record.id) else: raise e record = self._to_record(item=response.parse_body(), zone=zone) return record def ex_zone_exists(self, zone_id, zones_list): """ Function to check if a `Zone` object exists. :param zone_id: ID of the `Zone` object. :type zone_id: ``str`` :param zones_list: A list containing `Zone` objects. :type zones_list: ``list``. :rtype: Returns `True` or `False`. """ zone_ids = [] for zone in zones_list: zone_ids.append(zone.id) return zone_id in zone_ids def _to_zone(self, item): common_attr = ['zone', 'id', 'type'] extra = {} for key in item.keys(): if key not in common_attr: extra[key] = item.get(key) zone = Zone(domain=item['zone'], id=item['id'], type=item.get('type'), extra=extra, ttl=extra.get('ttl'), driver=self) return zone def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone): common_attr = ['id', 'short_answers', 'answers', 'domain', 'type'] extra = {} for key in item.keys(): if key not in common_attr: extra[key] = item.get(key) if item.get('answers') is not None: data = item.get('answers')[0]['answer'] else: data = item.get('short_answers') record = Record(id=item['id'], name=item['domain'], type=item['type'], data=data, zone=zone, driver=self, extra=extra) return record def _to_records(self, items, zone): records = [] for item in items: records.append(self._to_record(item, zone)) return records apache-libcloud-2.8.0/libcloud/dns/drivers/onapp.py0000664000175000017500000002467413535474530022177 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ OnApp DNS Driver """ __all__ = [ 'OnAppDNSDriver' ] import json from libcloud.common.onapp import OnAppConnection from libcloud.dns.types import Provider, RecordType from libcloud.dns.base import DNSDriver, Zone, Record DEFAULT_ZONE_TTL = 1200 class OnAppDNSDriver(DNSDriver): type = Provider.ONAPP name = 'OnApp' website = 'http://onapp.com/' connectionCls = OnAppConnection RECORD_TYPE_MAP = { RecordType.SOA: 'SOA', RecordType.NS: 'NS', RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.TXT: 'TXT', RecordType.SRV: 'SRV', } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ response = self.connection.request('/dns_zones.json') zones = self._to_zones(response.object) return zones def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ response = self.connection.request('/dns_zones/%s.json' % zone_id) zone = self._to_zone(response.object) return zone def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (All zones are master by design). :type type: ``str`` :param ttl: TTL for new records. (This is not really used) :type ttl: ``int`` :param extra: Extra attributes (set auto_populate: 0 if you don't want to auto populate with existing DNS records). (optional) :type extra: ``dict`` :rtype: :class:`Zone` For more info, please see: https://docs.onapp.com/display/52API/Add+DNS+Zone """ dns_zone = {'name': domain} if extra is not None: dns_zone.update(extra) dns_zone_data = json.dumps({'dns_zone': dns_zone}) response = self.connection.request( '/dns_zones.json', method='POST', headers={"Content-type": "application/json"}, data=dns_zone_data) zone = self._to_zone(response.object) return zone def delete_zone(self, zone): """ Delete a zone. Note: This will also delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ self.connection.request( '/dns_zones/%s.json' % zone.id, method='DELETE') return True def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ response = self.connection.request( '/dns_zones/%s/records.json' % zone.id) dns_records = response.object['dns_zone']['records'] records = self._to_records(dns_records, zone) return records def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ response = self.connection.request('/dns_zones/%s/records/%s.json' % (zone_id, record_id)) record = self._to_record(response.object, zone_id=zone_id) return record def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). Used only for A and AAAA record types. :type data: ``str`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Record` For more info, please see: https://docs.onapp.com/display/52API/Add+DNS+Record """ dns_record = self._format_record(name, type, data, extra) dns_record_data = json.dumps({'dns_record': dns_record}) response = self.connection.request( '/dns_zones/%s/records.json' % zone.id, method='POST', headers={"Content-type": "application/json"}, data=dns_record_data) record = self._to_record(response.object, zone=zone) return record def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). Used only for A and AAAA record types. :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` For more info, please see: https://docs.onapp.com/display/52API/Edit+DNS+Records """ zone = record.zone dns_record = self._format_record(name, type, data, extra) dns_record_data = json.dumps({'dns_record': dns_record}) self.connection.request( '/dns_zones/%s/records/%s.json' % (zone.id, record.id), method='PUT', headers={"Content-type": "application/json"}, data=dns_record_data) record = self.get_record(zone.id, record.id) return record def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` For more info, please see: https://docs.onapp.com/display/52API/Delete+DNS+Record """ zone_id = record.zone.id self.connection.request('/dns_zones/%s/records/%s.json' % (zone_id, record.id), method='DELETE') return True # # Helper methods # def _format_record(self, name, type, data, extra): if name == '': name = '@' if extra is None: extra = {} record_type = self.RECORD_TYPE_MAP[type] new_record = { 'name': name, 'ttl': extra.get('ttl', DEFAULT_ZONE_TTL), 'type': record_type } if type == RecordType.MX: additions = { 'priority': extra.get('priority', 1), 'hostname': extra.get('hostname') } elif type == RecordType.SRV: additions = { 'port': extra.get('port'), 'weight': extra.get('weight', 1), 'priority': extra.get('priority', 1), 'hostname': extra.get('hostname') } elif type == RecordType.A: additions = {'ip': data} elif type == RecordType.CNAME: additions = {'hostname': extra.get('hostname')} elif type == RecordType.AAAA: additions = {'ip': data} elif type == RecordType.TXT: additions = {'txt': extra.get('txt')} elif type == RecordType.NS: additions = {'hostname': extra.get('hostname')} new_record.update(additions) return new_record def _to_zones(self, data): zones = [] for zone in data: _zone = self._to_zone(zone) zones.append(_zone) return zones def _to_zone(self, data): dns_zone = data.get('dns_zone') id = dns_zone.get('id') name = dns_zone.get('name') extra = {'user_id': dns_zone.get('user_id'), 'cdn_reference': dns_zone.get('cdn_reference'), 'created_at': dns_zone.get('created_at'), 'updated_at': dns_zone.get('updated_at')} type = 'master' return Zone(id=id, domain=name, type=type, ttl=DEFAULT_ZONE_TTL, driver=self, extra=extra) def _to_records(self, data, zone): records = [] data = data.values() for data_type in data: for item in data_type: record = self._to_record(item, zone=zone) records.append(record) records.sort(key=lambda x: x.id, reverse=False) return records def _to_record(self, data, zone_id=None, zone=None): if not zone: # We need zone_id or zone zone = self.get_zone(zone_id) record = data.get('dns_record') id = record.get('id') name = record.get('name') type = record.get('type') ttl = record.get('ttl', None) return Record(id=id, name=name, type=type, data=record, zone=zone, driver=self, ttl=ttl, extra={}) apache-libcloud-2.8.0/libcloud/dns/drivers/pointdns.py0000664000175000017500000006740513570310635022711 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Point DNS Driver """ __all__ = [ 'PointDNSException', 'Redirect', 'MailRedirect', 'PointDNSDriver' ] try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import httplib from libcloud.common.types import ProviderError from libcloud.common.types import MalformedResponseError from libcloud.common.pointdns import PointDNSConnection from libcloud.common.exceptions import BaseHTTPError from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError from libcloud.dns.types import RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record class PointDNSException(ProviderError): def __init__(self, value, http_code, driver=None): super(PointDNSException, self).__init__(value=value, http_code=http_code, driver=driver) self.args = (http_code, value) class Redirect(object): """ Point DNS redirect. """ def __init__(self, id, name, data, type, driver, zone, iframe=None, query=False): """ :param id: Redirect id. :type id: ``str`` :param name: The FQDN for the record. :type name: ``str`` :param data: The data field. (redirect_to) :type data: ``str`` :param type: The type of redirects 301, 302 or 0 for iframes. :type type: ``str`` :param driver: DNSDriver instance. :type driver: :class:`DNSDriver` :param zone: Zone where redirect belongs. :type zone: :class:`Zone` :param iframe: Title of iframe (optional). :type iframe: ``str`` :param query: boolean Information about including query string when redirecting. (optional). :type query: ``bool`` """ self.id = str(id) if id else None self.name = name self.data = data self.type = str(type) if type else None self.driver = driver self.zone = zone self.iframe = iframe self.query = query def update(self, data, name=None, type=None, iframe=None, query=None): return self.driver.ex_update_redirect(redirect=self, name=name, data=data, type=type, iframe=iframe, query=query) def delete(self): return self.driver.ex_delete_redirect(redirect=self) def __repr__(self): return ('' % (self.name, self.data, self.type)) class MailRedirect(object): """ Point DNS mail redirect. """ def __init__(self, id, source, destination, zone, driver): """ :param id: MailRedirect id. :type id: ``str`` :param source: The source address of mail redirect. :type source: ``str`` :param destination: The destination address of mail redirect. :type destination: ``str`` :param zone: Zone where mail redirect belongs. :type zone: :class:`Zone` :param driver: DNSDriver instance. :type driver: :class:`DNSDriver` """ self.id = str(id) if id else None self.source = source self.destination = destination self.zone = zone self.driver = driver def update(self, destination, source=None): return self.driver.ex_update_mail_redirect(mail_r=self, destination=destination, source=None) def delete(self): return self.driver.ex_delete_mail_redirect(mail_r=self) def __repr__(self): return ('' % (self.source, self.destination, self.zone.id)) class PointDNSDriver(DNSDriver): type = Provider.POINTDNS name = 'Point DNS' website = 'https://pointhq.com/' connectionCls = PointDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.ALIAS: 'ALIAS', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SRV: 'SRV', RecordType.SSHFP: 'SSHFP', RecordType.TXT: 'TXT' } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ response = self.connection.request('/zones') zones = self._to_zones(response.object) return zones def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ response = self.connection.request('/zones/%s/records' % zone.id) records = self._to_records(response.object, zone) return records def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ try: response = self.connection.request('/zones/%s' % zone_id) except MalformedResponseError as e: if e.body == 'Not found': raise ZoneDoesNotExistError(driver=self, value="The zone doesn't exists", zone_id=zone_id) raise e zone = self._to_zone(response.object) return zone def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ try: response = self.connection.request('/zones/%s/records/%s' % (zone_id, record_id)) except MalformedResponseError as e: if e.body == 'Not found': raise RecordDoesNotExistError(value="Record doesn't exists", driver=self, record_id=record_id) raise e record = self._to_record(response.object, zone_id=zone_id) return record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (All zones are master by design). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Zone` """ r_json = {'name': domain} if ttl is not None: r_json['ttl'] = ttl if extra is not None: r_json.update(extra) r_data = json.dumps({'zone': r_json}) try: response = self.connection.request('/zones', method='POST', data=r_data) except BaseHTTPError as e: raise PointDNSException(value=e.message, http_code=e.code, driver=self) zone = self._to_zone(response.object) return zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ r_json = {'name': name, 'data': data, 'record_type': type} if extra is not None: r_json.update(extra) r_data = json.dumps({'zone_record': r_json}) try: response = self.connection.request('/zones/%s/records' % zone.id, method='POST', data=r_data) except BaseHTTPError as e: raise PointDNSException(value=e.message, http_code=e.code, driver=self) record = self._to_record(response.object, zone=zone) return record def update_zone(self, zone, domain, type='master', ttl=None, extra=None): """ Update an existing zone. :param zone: Zone to update. :type zone: :class:`Zone` :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (All zones are master by design). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes (group, user-id). (optional) :type extra: ``dict`` :rtype: :class:`Zone` """ r_json = {'name': domain} if extra is not None: r_json.update(extra) r_data = json.dumps({'zone': r_json}) try: response = self.connection.request('/zones/%s' % zone.id, method='PUT', data=r_data) except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise ZoneDoesNotExistError(value="Zone doesn't exists", driver=self, zone_id=zone.id) raise PointDNSException(value=e.message, http_code=e.code, driver=self) zone = self._to_zone(response.object) return zone def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` """ zone = record.zone r_json = {'name': name, 'data': data, 'record_type': type} if extra is not None: r_json.update(extra) r_data = json.dumps({'zone_record': r_json}) try: response = self.connection.request('/zones/%s/records/%s' % (zone.id, record.id), method='PUT', data=r_data) except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise RecordDoesNotExistError(value="Record doesn't exists", driver=self, record_id=record.id) raise PointDNSException(value=e.message, http_code=e.code, driver=self) record = self._to_record(response.object, zone=zone) return record def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ try: self.connection.request('/zones/%s' % zone.id, method='DELETE') except MalformedResponseError as e: if e.body == 'Not found': raise ZoneDoesNotExistError(driver=self, value="The zone doesn't exists", zone_id=zone.id) raise e return True def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ zone_id = record.zone.id record_id = record.id try: self.connection.request('/zones/%s/records/%s' % (zone_id, record_id), method='DELETE') except MalformedResponseError as e: if e.body == 'Not found': raise RecordDoesNotExistError(value="Record doesn't exists", driver=self, record_id=record_id) raise e return True def ex_list_redirects(self, zone): """ :param zone: Zone to list redirects for. :type zone: :class:`Zone` :rtype: ``list`` of :class:`Record` """ response = self.connection.request('/zones/%s/redirects' % zone.id) redirects = self._to_redirects(response.object, zone) return redirects def ex_list_mail_redirects(self, zone): """ :param zone: Zone to list redirects for. :type zone: :class:`Zone` :rtype: ``list`` of :class:`MailRedirect` """ response = self.connection.request('/zones/%s/mail_redirects' % zone.id) mail_redirects = self._to_mail_redirects(response.object, zone) return mail_redirects def ex_create_redirect(self, redirect_to, name, type, zone, iframe=None, query=None): """ :param redirect_to: The data field. (redirect_to) :type redirect_to: ``str`` :param name: The FQDN for the record. :type name: ``str`` :param type: The type of redirects 301, 302 or 0 for iframes. :type type: ``str`` :param zone: Zone to list redirects for. :type zone: :class:`Zone` :param iframe: Title of iframe (optional). :type iframe: ``str`` :param query: boolean Information about including query string when redirecting. (optional). :type query: ``bool`` :rtype: :class:`Record` """ r_json = {'name': name, 'redirect_to': redirect_to} if type is not None: r_json['redirect_type'] = type if iframe is not None: r_json['iframe_title'] = iframe if query is not None: r_json['redirect_query_string'] = query r_data = json.dumps({'zone_redirect': r_json}) try: response = self.connection.request('/zones/%s/redirects' % zone.id, method='POST', data=r_data) except (BaseHTTPError, MalformedResponseError) as e: raise PointDNSException(value=e.message, http_code=e.code, driver=self) redirect = self._to_redirect(response.object, zone=zone) return redirect def ex_create_mail_redirect(self, destination, source, zone): """ :param destination: The destination address of mail redirect. :type destination: ``str`` :param source: The source address of mail redirect. :type source: ``str`` :param zone: Zone to list redirects for. :type zone: :class:`Zone` :rtype: ``list`` of :class:`MailRedirect` """ r_json = {'destination_address': destination, 'source_address': source} r_data = json.dumps({'zone_mail_redirect': r_json}) try: response = self.connection.request('/zones/%s/mail_redirects' % zone.id, method='POST', data=r_data) except (BaseHTTPError, MalformedResponseError) as e: raise PointDNSException(value=e.message, http_code=e.code, driver=self) mail_redirect = self._to_mail_redirect(response.object, zone=zone) return mail_redirect def ex_get_redirect(self, zone_id, redirect_id): """ :param zone: Zone to list redirects for. :type zone: :class:`Zone` :param redirect_id: Redirect id. :type redirect_id: ``str`` :rtype: ``list`` of :class:`Redirect` """ try: response = self.connection.request('/zones/%s/redirects/%s' % (zone_id, redirect_id)) except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise PointDNSException(value='Couldn\'t found redirect', http_code=httplib.NOT_FOUND, driver=self) raise PointDNSException(value=e.message, http_code=e.code, driver=self) redirect = self._to_redirect(response.object, zone_id=zone_id) return redirect def ex_get_mail_redirects(self, zone_id, mail_r_id): """ :param zone: Zone to list redirects for. :type zone: :class:`Zone` :param mail_r_id: Mail redirect id. :type mail_r_id: ``str`` :rtype: ``list`` of :class:`MailRedirect` """ try: response = self.connection.request('/zones/%s/mail_redirects/%s' % (zone_id, mail_r_id)) except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise PointDNSException(value='Couldn\'t found mail redirect', http_code=httplib.NOT_FOUND, driver=self) raise PointDNSException(value=e.message, http_code=e.code, driver=self) mail_redirect = self._to_mail_redirect(response.object, zone_id=zone_id) return mail_redirect def ex_update_redirect(self, redirect, redirect_to=None, name=None, type=None, iframe=None, query=None): """ :param redirect: Record to update :type id: :class:`Redirect` :param redirect_to: The data field. (optional). :type redirect_to: ``str`` :param name: The FQDN for the record. :type name: ``str`` :param type: The type of redirects 301, 302 or 0 for iframes. (optional). :type type: ``str`` :param iframe: Title of iframe (optional). :type iframe: ``str`` :param query: boolean Information about including query string when redirecting. (optional). :type query: ``bool`` :rtype: ``list`` of :class:`Redirect` """ zone_id = redirect.zone.id r_json = {} if redirect_to is not None: r_json['redirect_to'] = redirect_to if name is not None: r_json['name'] = name if type is not None: r_json['record_type'] = type if iframe is not None: r_json['iframe_title'] = iframe if query is not None: r_json['redirect_query_string'] = query r_data = json.dumps({'zone_redirect': r_json}) try: response = self.connection.request('/zones/%s/redirects/%s' % (zone_id, redirect.id), method='PUT', data=r_data) except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise PointDNSException(value='Couldn\'t found redirect', http_code=httplib.NOT_FOUND, driver=self) raise PointDNSException(value=e.message, http_code=e.code, driver=self) redirect = self._to_redirect(response.object, zone=redirect.zone) return redirect def ex_update_mail_redirect(self, mail_r, destination, source=None): """ :param mail_r: Mail redirect to update :type mail_r: :class:`MailRedirect` :param destination: The destination address of mail redirect. :type destination: ``str`` :param source: The source address of mail redirect. (optional) :type source: ``str`` :rtype: ``list`` of :class:`MailRedirect` """ zone_id = mail_r.zone.id r_json = {'destination_address': destination} if source is not None: r_json['source_address'] = source r_data = json.dumps({'zone_redirect': r_json}) try: response = self.connection.request('/zones/%s/mail_redirects/%s' % (zone_id, mail_r.id), method='PUT', data=r_data) except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise PointDNSException(value='Couldn\'t found mail redirect', http_code=httplib.NOT_FOUND, driver=self) raise PointDNSException(value=e.message, http_code=e.code, driver=self) mail_redirect = self._to_mail_redirect(response.object, zone=mail_r.zone) return mail_redirect def ex_delete_redirect(self, redirect): """ :param mail_r: Redirect to delete :type mail_r: :class:`Redirect` :rtype: ``bool`` """ zone_id = redirect.zone.id redirect_id = redirect.id try: self.connection.request('/zones/%s/redirects/%s' % (zone_id, redirect_id), method='DELETE') except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise PointDNSException(value='Couldn\'t found redirect', http_code=httplib.NOT_FOUND, driver=self) raise PointDNSException(value=e.message, http_code=e.code, driver=self) return True def ex_delete_mail_redirect(self, mail_r): """ :param mail_r: Mail redirect to update :type mail_r: :class:`MailRedirect` :rtype: ``bool`` """ zone_id = mail_r.zone.id mail_r_id = mail_r.id try: self.connection.request('/zones/%s/mail_redirects/%s' % (zone_id, mail_r_id), method='DELETE') except (BaseHTTPError, MalformedResponseError) as e: if isinstance(e, MalformedResponseError) and e.body == 'Not found': raise PointDNSException(value='Couldn\'t found mail redirect', http_code=httplib.NOT_FOUND, driver=self) raise PointDNSException(value=e.message, http_code=e.code, driver=self) return True def _to_zones(self, data): zones = [] for zone in data: _zone = self._to_zone(zone) zones.append(_zone) return zones def _to_zone(self, data): zone = data.get('zone') id = zone.get('id') name = zone.get('name') ttl = zone.get('ttl') extra = {'group': zone.get('group'), 'user-id': zone.get('user-id')} # All zones are a primary ones by design, so they # assume that are the master source of info about the # zone, which is the case when domain DNS records # points to PointDNS nameservers. type = 'master' return Zone(id=id, domain=name, type=type, ttl=ttl, driver=self, extra=extra) def _to_records(self, data, zone): records = [] for item in data: record = self._to_record(item, zone=zone) records.append(record) return records def _to_record(self, data, zone_id=None, zone=None): if not zone: # We need zone_id or zone zone = self.get_zone(zone_id) record = data.get('zone_record') id = record.get('id') name = record.get('name') type = record.get('record_type') data = record.get('data') extra = {'ttl': record.get('ttl'), 'zone_id': record.get('zone_id'), 'aux': record.get('aux')} return Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=record.get('ttl', None), extra=extra) def _to_redirects(self, data, zone): redirects = [] for item in data: redirect = self._to_redirect(item, zone=zone) redirects.append(redirect) return redirects def _to_redirect(self, data, zone_id=None, zone=None): if not zone: # We need zone_id or zone zone = self.get_zone(zone_id) record = data.get('zone_redirect') id = record.get('id') name = record.get('name') redirect_to = record.get('redirect_to') type = record.get('redirect_type') iframe = record.get('iframe_title') query = record.get('redirect_query_string') return Redirect(id, name, redirect_to, type, self, zone, iframe=iframe, query=query) def _to_mail_redirects(self, data, zone): mail_redirects = [] for item in data: mail_redirect = self._to_mail_redirect(item, zone=zone) mail_redirects.append(mail_redirect) return mail_redirects def _to_mail_redirect(self, data, zone_id=None, zone=None): if not zone: # We need zone_id or zone zone = self.get_zone(zone_id) record = data.get('zone_mail_redirect') id = record.get('id') destination = record.get('destination_address') source = record.get('source_address') return MailRedirect(id, source, destination, zone, self) apache-libcloud-2.8.0/libcloud/dns/drivers/powerdns.py0000664000175000017500000004630613570310635022711 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ PowerDNS Driver """ import json from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.common.exceptions import BaseHTTPError from libcloud.common.types import InvalidCredsError, MalformedResponseError from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError from libcloud.dns.types import Provider, RecordType from libcloud.utils.py3 import httplib __all__ = [ 'PowerDNSDriver', ] class PowerDNSResponse(JsonResponse): def success(self): i = int(self.status) return 200 <= i <= 299 def parse_error(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError('Invalid provider credentials') try: body = self.parse_body() except MalformedResponseError as e: body = '%s: %s' % (e.value, e.body) try: errors = [body['error']] except TypeError: # parse_body() gave us a simple string, not a dict. return '%s (HTTP Code: %d)' % (body, self.status) try: errors.append(body['errors']) except KeyError: # The PowerDNS API does not return the "errors" list all the time. pass return '%s (HTTP Code: %d)' % (' '.join(errors), self.status) class PowerDNSConnection(ConnectionKey): responseCls = PowerDNSResponse def add_default_headers(self, headers): headers['X-API-Key'] = self.key return headers class PowerDNSDriver(DNSDriver): type = Provider.POWERDNS name = 'PowerDNS' website = 'https://www.powerdns.com/' connectionCls = PowerDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.AFSDB: 'AFSDB', RecordType.CERT: 'CERT', RecordType.CNAME: 'CNAME', RecordType.DNSKEY: 'DNSKEY', RecordType.DS: 'DS', RecordType.HINFO: 'HINFO', RecordType.KEY: 'KEY', RecordType.LOC: 'LOC', RecordType.MX: 'MX', RecordType.NAPTR: 'NAPTR', RecordType.NS: 'NS', RecordType.NSEC: 'NSEC', RecordType.OPENPGPKEY: 'OPENPGPKEY', RecordType.PTR: 'PTR', RecordType.RP: 'RP', RecordType.RRSIG: 'RRSIG', RecordType.SOA: 'SOA', RecordType.SPF: 'SPF', RecordType.SSHFP: 'SSHFP', RecordType.SRV: 'SRV', RecordType.TLSA: 'TLSA', RecordType.TXT: 'TXT', } def __init__(self, key, secret=None, secure=False, host=None, port=None, api_version='experimental', **kwargs): """ PowerDNS Driver defaulting to using PowerDNS 3.x API (ie "experimental"). :param key: API key or username to used (required) :type key: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Off by default for PowerDNS. :type secure: ``bool`` :param host: Hostname used for connections. :type host: ``str`` :param port: Port used for connections. :type port: ``int`` :param api_version: Specifies the API version to use. ``experimental`` and ``v1`` are the only valid options. Defaults to using ``experimental`` (optional) :type api_version: ``str`` :return: ``None`` """ # libcloud doesn't really have a concept of "servers". We'll just use # localhost for now. self.ex_server = 'localhost' if api_version == 'experimental': # PowerDNS 3.x has no API root prefix. self.api_root = '' elif api_version == 'v1': # PowerDNS 4.x has an '/api/v1' root prefix. self.api_root = '/api/v1' else: raise NotImplementedError('Unsupported API version: %s' % api_version) super(PowerDNSDriver, self).__init__(key=key, secure=secure, host=host, port=port, **kwargs) def create_record(self, name, zone, type, data, extra=None): """ Create a new record. There are two PowerDNS-specific quirks here. Firstly, this method will silently clobber any pre-existing records that might already exist. For example, if PowerDNS already contains a "test.example.com" A record, and you create that record using this function, then the old A record will be replaced with your new one. Secondly, PowerDNS requires that you provide a ttl for all new records. In other words, the "extra" parameter must be ``{'ttl': }`` at a minimum. :param name: FQDN of the new record, for example "www.example.com". :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific, e.g. 'ttl'). Note that PowerDNS *requires* a ttl value for every record. :type extra: ``dict`` :rtype: :class:`Record` """ extra = extra or {} action = '%s/servers/%s/zones/%s' % (self.api_root, self.ex_server, zone.id) if extra is None or extra.get('ttl', None) is None: raise ValueError('PowerDNS requires a ttl value for every record') if self._pdns_version() == 3: record = { 'content': data, 'disabled': False, 'name': name, 'ttl': extra['ttl'], 'type': type, } payload = { 'rrsets': [ { 'name': name, 'type': type, 'changetype': 'REPLACE', 'records': [record] } ] } elif self._pdns_version() == 4: record = { 'content': data, 'disabled': extra.get('disabled', False), 'set-ptr': False, } payload = { 'rrsets': [ { 'name': name, 'type': type, 'changetype': 'REPLACE', 'ttl': extra['ttl'], 'records': [record], } ] } if 'comment' in extra: payload['rrsets'][0]['comments'] = extra['comment'] try: self.connection.request(action=action, data=json.dumps(payload), method='PATCH') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith('Could not find domain'): raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e return Record(id=None, name=name, data=data, type=type, zone=zone, driver=self, ttl=extra['ttl']) def create_zone(self, domain, type=None, ttl=None, extra={}): """ Create a new zone. There are two PowerDNS-specific quirks here. Firstly, the "type" and "ttl" parameters are ignored (no-ops). The "type" parameter is simply not implemented, and PowerDNS does not have an ability to set a zone-wide default TTL. (TTLs must be set per-record.) Secondly, PowerDNS requires that you provide a list of nameservers for the zone upon creation. In other words, the "extra" parameter must be ``{'nameservers': ['ns1.example.org']}`` at a minimum. :param name: Zone domain name (e.g. example.com) :type name: ``str`` :param domain: Zone type (master / slave). (optional). Note that the PowerDNS driver does nothing with this parameter. :type domain: :class:`Zone` :param ttl: TTL for new records. (optional). Note that the PowerDNS driver does nothing with this parameter. :type ttl: ``int`` :param extra: Extra attributes (driver specific). For example, specify ``extra={'nameservers': ['ns1.example.org']}`` to set a list of nameservers for this new zone. :type extra: ``dict`` :rtype: :class:`Zone` """ action = '%s/servers/%s/zones' % (self.api_root, self.ex_server) if extra is None or extra.get('nameservers', None) is None: msg = 'PowerDNS requires a list of nameservers for every new zone' raise ValueError(msg) payload = {'name': domain, 'kind': 'Native'} payload.update(extra) zone_id = domain + '.' try: self.connection.request(action=action, data=json.dumps(payload), method='POST') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith("Domain '%s' already exists" % domain): raise ZoneAlreadyExistsError(zone_id=zone_id, driver=self, value=e.message) raise e return Zone(id=zone_id, domain=domain, type=None, ttl=None, driver=self, extra=extra) def delete_record(self, record): """ Use this method to delete a record. :param record: record to delete :type record: `Record` :rtype: ``bool`` """ action = '%s/servers/%s/zones/%s' % (self.api_root, self.ex_server, record.zone.id) payload = {'rrsets': [{'name': record.name, 'type': record.type, 'changetype': 'DELETE', }] } try: self.connection.request(action=action, data=json.dumps(payload), method='PATCH') except BaseHTTPError: # I'm not sure if we should raise a ZoneDoesNotExistError here. The # base DNS API only specifies that we should return a bool. So, # let's ignore this code for now. # if e.code == httplib.UNPROCESSABLE_ENTITY and \ # e.message.startswith('Could not find domain'): # raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, # value=e.message) # raise e return False return True def delete_zone(self, zone): """ Use this method to delete a zone. :param zone: zone to delete :type zone: `Zone` :rtype: ``bool`` """ action = '%s/servers/%s/zones/%s' % (self.api_root, self.ex_server, zone.id) try: self.connection.request(action=action, method='DELETE') except BaseHTTPError: # I'm not sure if we should raise a ZoneDoesNotExistError here. The # base DNS API only specifies that we should return a bool. So, # let's ignore this code for now. # if e.code == httplib.UNPROCESSABLE_ENTITY and \ # e.message.startswith('Could not find domain'): # raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, # value=e.message) # raise e return False return True def get_zone(self, zone_id): """ Return a Zone instance. (Note that PowerDNS does not support per-zone TTL defaults, so all Zone objects will have ``ttl=None``.) :param zone_id: name of the required zone with the trailing period, for example "example.com.". :type zone_id: ``str`` :rtype: :class:`Zone` :raises: ZoneDoesNotExistError: If no zone could be found. """ action = '%s/servers/%s/zones/%s' % (self.api_root, self.ex_server, zone_id) try: response = self.connection.request(action=action, method='GET') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY: raise ZoneDoesNotExistError(zone_id=zone_id, driver=self, value=e.message) raise e return self._to_zone(response.object) def list_records(self, zone): """ Return a list of all records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '%s/servers/%s/zones/%s' % (self.api_root, self.ex_server, zone.id) try: response = self.connection.request(action=action, method='GET') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith('Could not find domain'): raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e return self._to_records(response, zone) def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ action = '%s/servers/%s/zones' % (self.api_root, self.ex_server) response = self.connection.request(action=action, method='GET') return self._to_zones(response) def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: FQDN of the new record, for example "www.example.com". :type name: ``str`` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: :class:`Record` """ action = '%s/servers/%s/zones/%s' % (self.api_root, self.ex_server, record.zone.id) if extra is None or extra.get('ttl', None) is None: raise ValueError('PowerDNS requires a ttl value for every record') if self._pdns_version() == 3: updated_record = { 'content': data, 'disabled': False, 'name': name, 'ttl': extra['ttl'], 'type': type, } payload = { 'rrsets': [ { 'name': record.name, 'type': record.type, 'changetype': 'DELETE', }, { 'name': name, 'type': type, 'changetype': 'REPLACE', 'records': [updated_record] } ] } elif self._pdns_version() == 4: disabled = False if "disabled" in extra: disabled = extra['disabled'] updated_record = { 'content': data, 'disabled': disabled, 'set-ptr': False, } payload = { 'rrsets': [{ 'name': name, 'type': type, 'changetype': 'REPLACE', 'ttl': extra['ttl'], 'records': [updated_record], }] } if 'comment' in extra: payload["rrsets"][0]["comments"] = extra['comment'] try: self.connection.request(action=action, data=json.dumps(payload), method='PATCH') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith('Could not find domain'): raise ZoneDoesNotExistError(zone_id=record.zone.id, driver=self, value=e.message) raise e return Record(id=None, name=name, data=data, type=type, zone=record.zone, driver=self, ttl=extra['ttl']) def _to_zone(self, item): extra = {} for e in ['kind', 'dnssec', 'account', 'masters', 'serial', 'notified_serial', 'last_check']: extra[e] = item[e] # XXX: we have to hard-code "ttl" to "None" here because PowerDNS does # not support per-zone ttl defaults. However, I don't know what "type" # should be; probably not None. return Zone(id=item['id'], domain=item['name'], type=None, ttl=None, driver=self, extra=extra) def _to_zones(self, items): zones = [] for item in items.object: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone, record=None): if record is None: data = item['content'] else: data = record['content'] return Record(id=None, name=item['name'], data=data, type=item['type'], zone=zone, driver=self, ttl=item['ttl']) def _to_records(self, items, zone): records = [] if self._pdns_version() == 3: for item in items.object['records']: records.append(self._to_record(item, zone)) elif self._pdns_version() == 4: for item in items.object['rrsets']: for record in item['records']: records.append(self._to_record(item, zone, record)) return records def _pdns_version(self): if self.api_root == '': return 3 elif self.api_root == '/api/v1': return 4 raise ValueError('PowerDNS version has not been declared') apache-libcloud-2.8.0/libcloud/dns/drivers/rackspace.py0000664000175000017500000006002613535474530023005 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import copy from libcloud.utils.py3 import httplib from libcloud.common.openstack import OpenStackDriverMixin from libcloud.common.base import PollingConnection from libcloud.common.exceptions import BaseHTTPError from libcloud.common.types import LibcloudError from libcloud.utils.misc import merge_valid_keys, get_new_obj from libcloud.common.rackspace import AUTH_URL from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection from libcloud.compute.drivers.openstack import OpenStack_1_1_Response from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record __all__ = [ 'RackspaceDNSResponse', 'RackspaceDNSConnection' ] VALID_ZONE_EXTRA_PARAMS = ['email', 'comment', 'ns1'] VALID_RECORD_EXTRA_PARAMS = ['ttl', 'comment', 'priority', 'created', 'updated'] class RackspaceDNSResponse(OpenStack_1_1_Response): """ Rackspace DNS Response class. """ def parse_error(self): status = int(self.status) context = self.connection.context body = self.parse_body() if status == httplib.NOT_FOUND: if context['resource'] == 'zone': raise ZoneDoesNotExistError(value='', driver=self, zone_id=context['id']) elif context['resource'] == 'record': raise RecordDoesNotExistError(value='', driver=self, record_id=context['id']) if body: if 'code' and 'message' in body: err = '%s - %s (%s)' % (body['code'], body['message'], body['details']) return err elif 'validationErrors' in body: errors = [m for m in body['validationErrors']['messages']] err = 'Validation errors: %s' % ', '.join(errors) return err raise LibcloudError('Unexpected status code: %s' % (status)) class RackspaceDNSConnection(OpenStack_1_1_Connection, PollingConnection): """ Rackspace DNS Connection class. """ responseCls = RackspaceDNSResponse XML_NAMESPACE = None poll_interval = 2.5 timeout = 30 auth_url = AUTH_URL _auth_version = '2.0' def __init__(self, *args, **kwargs): self.region = kwargs.pop('region', None) super(RackspaceDNSConnection, self).__init__(*args, **kwargs) def get_poll_request_kwargs(self, response, context, request_kwargs): job_id = response.object['jobId'] kwargs = {'action': '/status/%s' % (job_id), 'params': {'showDetails': True}} return kwargs def has_completed(self, response): status = response.object['status'] if status == 'ERROR': data = response.object['error'] if 'code' and 'message' in data: message = '%s - %s (%s)' % (data['code'], data['message'], data['details']) else: message = data['message'] raise LibcloudError(message, driver=self.driver) return status == 'COMPLETED' def get_endpoint(self): if '2.0' in self._auth_version: ep = self.service_catalog.get_endpoint(name='cloudDNS', service_type='rax:dns', region=None) else: raise LibcloudError("Auth version %s not supported" % (self._auth_version)) public_url = ep.url # This is a nasty hack, but because of how global auth and old accounts # work, there is no way around it. if self.region == 'us': # Old UK account, which only has us endpoint in the catalog public_url = public_url.replace('https://lon.dns.api', 'https://dns.api') if self.region == 'uk': # Old US account, which only has uk endpoint in the catalog public_url = public_url.replace('https://dns.api', 'https://lon.dns.api') return public_url class RackspacePTRRecord(object): def __init__(self, id, ip, domain, driver, extra=None): self.id = str(id) if id else None self.ip = ip self.type = RecordType.PTR self.domain = domain self.driver = driver self.extra = extra or {} def update(self, domain, extra=None): return self.driver.ex_update_ptr_record(record=self, domain=domain, extra=extra) def delete(self): return self.driver.ex_delete_ptr_record(record=self) def __repr__(self): return ('<%s: ip=%s, domain=%s, provider=%s ...>' % (self.__class__.__name__, self.ip, self.domain, self.driver.name)) class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin): name = 'Rackspace DNS' website = 'http://www.rackspace.com/' type = Provider.RACKSPACE connectionCls = RackspaceDNSConnection def __init__(self, key, secret=None, secure=True, host=None, port=None, region='us', **kwargs): valid_regions = self.list_regions() if region not in valid_regions: raise ValueError('Invalid region: %s' % (region)) OpenStackDriverMixin.__init__(self, **kwargs) super(RackspaceDNSDriver, self).__init__(key=key, secret=secret, host=host, port=port, region=region) RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', } @classmethod def list_regions(cls): return ['us', 'uk'] def iterate_zones(self): offset = 0 limit = 100 while True: params = { 'limit': limit, 'offset': offset, } response = self.connection.request( action='/domains', params=params).object zones_list = response['domains'] for item in zones_list: yield self._to_zone(item) if _rackspace_result_has_more(response, len(zones_list), limit): offset += limit else: break def iterate_records(self, zone): self.connection.set_context({'resource': 'zone', 'id': zone.id}) offset = 0 limit = 100 while True: params = { 'showRecord': True, 'limit': limit, 'offset': offset, } response = self.connection.request( action='/domains/%s' % (zone.id), params=params).object records_list = response['recordsList'] records = records_list['records'] for item in records: record = self._to_record(data=item, zone=zone) yield record if _rackspace_result_has_more(records_list, len(records), limit): offset += limit else: break def get_zone(self, zone_id): self.connection.set_context({'resource': 'zone', 'id': zone_id}) response = self.connection.request(action='/domains/%s' % (zone_id)) zone = self._to_zone(data=response.object) return zone def get_record(self, zone_id, record_id): zone = self.get_zone(zone_id=zone_id) self.connection.set_context({'resource': 'record', 'id': record_id}) response = self.connection.request(action='/domains/%s/records/%s' % (zone_id, record_id)).object record = self._to_record(data=response, zone=zone) return record def create_zone(self, domain, type='master', ttl=None, extra=None): extra = extra if extra else {} # Email address is required if 'email' not in extra: raise ValueError('"email" key must be present in extra dictionary') payload = {'name': domain, 'emailAddress': extra['email'], 'recordsList': {'records': []}} if ttl: payload['ttl'] = ttl if 'comment' in extra: payload['comment'] = extra['comment'] data = {'domains': [payload]} response = self.connection.async_request(action='/domains', method='POST', data=data) zone = self._to_zone(data=response.object['response']['domains'][0]) return zone def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): # Only ttl, comment and email address can be changed extra = extra if extra else {} if domain: raise LibcloudError('Domain cannot be changed', driver=self) data = {} if ttl: data['ttl'] = int(ttl) if 'email' in extra: data['emailAddress'] = extra['email'] if 'comment' in extra: data['comment'] = extra['comment'] type = type if type else zone.type ttl = ttl if ttl else zone.ttl self.connection.set_context({'resource': 'zone', 'id': zone.id}) self.connection.async_request(action='/domains/%s' % (zone.id), method='PUT', data=data) merged = merge_valid_keys(params=copy.deepcopy(zone.extra), valid_keys=VALID_ZONE_EXTRA_PARAMS, extra=extra) updated_zone = get_new_obj(obj=zone, klass=Zone, attributes={'type': type, 'ttl': ttl, 'extra': merged}) return updated_zone def create_record(self, name, zone, type, data, extra=None): # Name must be a FQDN - e.g. if domain is "foo.com" then a record # name is "bar.foo.com" extra = extra if extra else {} name = self._to_full_record_name(domain=zone.domain, name=name) data = {'name': name, 'type': self.RECORD_TYPE_MAP[type], 'data': data} if 'ttl' in extra: data['ttl'] = int(extra['ttl']) if 'priority' in extra: data['priority'] = int(extra['priority']) payload = {'records': [data]} self.connection.set_context({'resource': 'zone', 'id': zone.id}) response = self.connection.async_request(action='/domains/%s/records' % (zone.id), data=payload, method='POST').object record = self._to_record(data=response['response']['records'][0], zone=zone) return record def update_record(self, record, name=None, type=None, data=None, extra=None): # Only data, ttl, and comment attributes can be modified, but name # attribute must always be present. extra = extra if extra else {} name = self._to_full_record_name(domain=record.zone.domain, name=record.name) payload = {'name': name} if data: payload['data'] = data if 'ttl' in extra: payload['ttl'] = extra['ttl'] if 'comment' in extra: payload['comment'] = extra['comment'] type = type if type is not None else record.type data = data if data else record.data self.connection.set_context({'resource': 'record', 'id': record.id}) self.connection.async_request(action='/domains/%s/records/%s' % (record.zone.id, record.id), method='PUT', data=payload) merged = merge_valid_keys(params=copy.deepcopy(record.extra), valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra) updated_record = get_new_obj(obj=record, klass=Record, attributes={'type': type, 'data': data, 'driver': self, 'extra': merged}) return updated_record def delete_zone(self, zone): self.connection.set_context({'resource': 'zone', 'id': zone.id}) self.connection.async_request(action='/domains/%s' % (zone.id), method='DELETE') return True def delete_record(self, record): self.connection.set_context({'resource': 'record', 'id': record.id}) self.connection.async_request(action='/domains/%s/records/%s' % (record.zone.id, record.id), method='DELETE') return True def ex_iterate_ptr_records(self, device): """ Return a generator to iterate over existing PTR Records. The ``device`` should be an instance of one of these: :class:`libcloud.compute.base.Node` :class:`libcloud.loadbalancer.base.LoadBalancer` And it needs to have the following ``extra`` fields set: service_name - the service catalog name for the device uri - the URI pointing to the GET endpoint for the device Those are automatically set for you if you got the device from the Rackspace driver for that service. For example: server = rs_compute.ex_get_node_details(id) ptr_iter = rs_dns.ex_list_ptr_records(server) loadbalancer = rs_lbs.get_balancer(id) ptr_iter = rs_dns.ex_list_ptr_records(loadbalancer) Note: the Rackspace DNS API docs indicate that the device 'href' is optional, but testing does not bear this out. It throws a 400 Bad Request error if you do not pass in the 'href' from the server or loadbalancer. So ``device`` is required. :param device: the device that owns the IP :rtype: ``generator`` of :class:`RackspacePTRRecord` """ _check_ptr_extra_fields(device) params = {'href': device.extra['uri']} service_name = device.extra['service_name'] # without a valid context, the 404 on empty list will blow up # in the error-handling code self.connection.set_context({'resource': 'ptr_records'}) try: response = self.connection.request( action='/rdns/%s' % (service_name), params=params).object records = response['records'] link = dict(rel=service_name, **params) for item in records: record = self._to_ptr_record(data=item, link=link) yield record except BaseHTTPError as exc: # 404 just means empty list if exc.code == 404: return raise def ex_get_ptr_record(self, service_name, record_id): """ Get a specific PTR record by id. :param service_name: the service catalog name of the linked device(s) i.e. cloudLoadBalancers or cloudServersOpenStack :param record_id: the id (i.e. PTR-12345) of the PTR record :rtype: instance of :class:`RackspacePTRRecord` """ self.connection.set_context({'resource': 'record', 'id': record_id}) response = self.connection.request( action='/rdns/%s/%s' % (service_name, record_id)).object item = next(iter(response['recordsList']['records'])) return self._to_ptr_record(data=item, link=response['link']) def ex_create_ptr_record(self, device, ip, domain, extra=None): """ Create a PTR record for a specific IP on a specific device. The ``device`` should be an instance of one of these: :class:`libcloud.compute.base.Node` :class:`libcloud.loadbalancer.base.LoadBalancer` And it needs to have the following ``extra`` fields set: service_name - the service catalog name for the device uri - the URI pointing to the GET endpoint for the device Those are automatically set for you if you got the device from the Rackspace driver for that service. For example: server = rs_compute.ex_get_node_details(id) rs_dns.create_ptr_record(server, ip, domain) loadbalancer = rs_lbs.get_balancer(id) rs_dns.create_ptr_record(loadbalancer, ip, domain) :param device: the device that owns the IP :param ip: the IP for which you want to set reverse DNS :param domain: the fqdn you want that IP to represent :param extra: a ``dict`` with optional extra values: ttl - the time-to-live of the PTR record :rtype: instance of :class:`RackspacePTRRecord` """ _check_ptr_extra_fields(device) if extra is None: extra = {} # the RDNS API reverse the name and data fields for PTRs # the record name *should* be the ip and the data the fqdn data = { "name": domain, "type": RecordType.PTR, "data": ip } if 'ttl' in extra: data['ttl'] = extra['ttl'] payload = { "recordsList": { "records": [data] }, "link": { "content": "", "href": device.extra['uri'], "rel": device.extra['service_name'], } } response = self.connection.async_request( action='/rdns', method='POST', data=payload).object item = next(iter(response['response']['records'])) return self._to_ptr_record(data=item, link=payload['link']) def ex_update_ptr_record(self, record, domain=None, extra=None): """ Update a PTR record for a specific IP on a specific device. If you need to change the domain or ttl, use this API to update the record by deleting the old one and creating a new one. :param record: the original :class:`RackspacePTRRecord` :param domain: the fqdn you want that IP to represent :param extra: a ``dict`` with optional extra values: ttl - the time-to-live of the PTR record :rtype: instance of :class:`RackspacePTRRecord` """ if domain is not None and domain == record.domain: domain = None if extra is not None: extra = dict(extra) for key in extra: if key in record.extra and record.extra[key] == extra[key]: del extra[key] if domain is None and not extra: # nothing to do, it already matches return record _check_ptr_extra_fields(record) ip = record.ip self.ex_delete_ptr_record(record) # records have the same metadata in 'extra' as the original device # so you can pass the original record object in instead return self.ex_create_ptr_record(record, ip, domain, extra=extra) def ex_delete_ptr_record(self, record): """ Delete an existing PTR Record :param record: the original :class:`RackspacePTRRecord` :rtype: ``bool`` """ _check_ptr_extra_fields(record) self.connection.set_context({'resource': 'record', 'id': record.id}) self.connection.async_request( action='/rdns/%s' % (record.extra['service_name']), method='DELETE', params={'href': record.extra['uri'], 'ip': record.ip}, ) return True def _to_zone(self, data): id = data['id'] domain = data['name'] type = 'master' ttl = data.get('ttl', 0) extra = {} if 'emailAddress' in data: extra['email'] = data['emailAddress'] if 'comment' in data: extra['comment'] = data['comment'] zone = Zone(id=str(id), domain=domain, type=type, ttl=int(ttl), driver=self, extra=extra) return zone def _to_record(self, data, zone): id = data['id'] fqdn = data['name'] name = self._to_partial_record_name(domain=zone.domain, name=fqdn) type = self._string_to_record_type(data['type']) record_data = data['data'] extra = {'fqdn': fqdn} for key in VALID_RECORD_EXTRA_PARAMS: if key in data: extra[key] = data[key] record = Record(id=str(id), name=name, type=type, data=record_data, zone=zone, driver=self, ttl=extra.get('ttl', None), extra=extra) return record def _to_ptr_record(self, data, link): id = data['id'] ip = data['data'] domain = data['name'] extra = {'uri': link['href'], 'service_name': link['rel']} for key in VALID_RECORD_EXTRA_PARAMS: if key in data: extra[key] = data[key] record = RackspacePTRRecord(id=str(id), ip=ip, domain=domain, driver=self, extra=extra) return record def _to_full_record_name(self, domain, name): """ Build a FQDN from a domain and record name. :param domain: Domain name. :type domain: ``str`` :param name: Record name. :type name: ``str`` """ if name: name = '%s.%s' % (name, domain) else: name = domain return name def _to_partial_record_name(self, domain, name): """ Remove domain portion from the record name. :param domain: Domain name. :type domain: ``str`` :param name: Full record name (fqdn). :type name: ``str`` """ if name == domain: # Map "root" record names to None to be consistent with other # drivers return None # Strip domain portion name = name.replace('.%s' % (domain), '') return name def _ex_connection_class_kwargs(self): kwargs = self.openstack_connection_kwargs() kwargs['region'] = self.region return kwargs def _rackspace_result_has_more(response, result_length, limit): # If rackspace returns less than the limit, then we've reached the end of # the result set. if result_length < limit: return False # Paginated results return links to the previous and next sets of data, but # 'next' only exists when there is more to get. for item in response.get('links', ()): if item['rel'] == 'next': return True return False def _check_ptr_extra_fields(device_or_record): if not (hasattr(device_or_record, 'extra') and isinstance(device_or_record.extra, dict) and device_or_record.extra.get('uri') is not None and device_or_record.extra.get('service_name') is not None): raise LibcloudError("Can't create PTR Record for %s because it " "doesn't have a 'uri' and 'service_name' in " "'extra'" % device_or_record) apache-libcloud-2.8.0/libcloud/dns/drivers/rcodezero.py0000664000175000017500000004470613570310635023046 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ RcodeZero DNS Driver """ import json import hashlib import re from libcloud.common.base import ConnectionKey, JsonResponse from libcloud.common.exceptions import BaseHTTPError from libcloud.common.types import InvalidCredsError, MalformedResponseError from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError from libcloud.dns.types import Provider, RecordType from libcloud.utils.py3 import httplib API_HOST = 'my.rcodezero.at' __all__ = [ 'RcodeZeroDNSDriver', ] class RcodeZeroResponse(JsonResponse): def success(self): i = int(self.status) return 200 <= i <= 299 def parse_error(self): if self.status == httplib.UNAUTHORIZED: raise InvalidCredsError( 'Invalid API key. Check https://my.rcodezero.at/enableapi') errors = [] try: body = self.parse_body() except MalformedResponseError as e: body = '%s: %s' % (e.value, e.body) try: errors = [body['message']] except TypeError: return '%s (HTTP Code: %d)' % (body, self.status) except KeyError: pass return '%s (HTTP Code: %d)' % (' '.join(errors), self.status) class RcodeZeroConnection(ConnectionKey): responseCls = RcodeZeroResponse host = API_HOST def add_default_headers(self, headers): headers['Authorization'] = 'Bearer ' + self.key headers['Accept'] = 'application/json' return headers class RcodeZeroDNSDriver(DNSDriver): type = Provider.RCODEZERO name = 'RcodeZero DNS' website = 'https://www.rcodezero.at/' connectionCls = RcodeZeroConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.AFSDB: 'AFSDB', RecordType.ALIAS: 'ALIAS', RecordType.CERT: 'CERT', RecordType.CNAME: 'CNAME', RecordType.DNAME: 'DNAME', RecordType.DNSKEY: 'DNSKEY', RecordType.DS: 'DS', RecordType.HINFO: 'HINFO', RecordType.KEY: 'KEY', RecordType.LOC: 'LOC', RecordType.MX: 'MX', RecordType.NAPTR: 'NAPTR', RecordType.NS: 'NS', RecordType.NSEC: 'NSEC', RecordType.OPENPGPKEY: 'OPENPGPKEY', RecordType.PTR: 'PTR', RecordType.RP: 'RP', RecordType.RRSIG: 'RRSIG', RecordType.SOA: 'SOA', RecordType.SPF: 'SPF', RecordType.SRV: 'SRV', RecordType.SSHFP: 'SSHFP', RecordType.SRV: 'SRV', RecordType.TLSA: 'TLSA', RecordType.TXT: 'TXT', } def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version='v1', **kwargs): """ :param key: API token to be used (required) :type key: ``str`` :param secret: Password to be used, ignored by RcodeZero :type key: ``str`` :param secure: Whether to use HTTPS (default) or HTTP. :type secure: ``bool`` :param host: Hostname used for connections. :type host: ``str`` :param port: Port used for connections. :type port: ``int`` :param api_version: Specifies the API version to use. ``v1`` is currently the only valid option (and default) :type api_version: ``str`` :return: ``None`` """ if api_version == 'v1': self.api_root = '/api/v1' else: raise NotImplementedError('Unsupported API version: %s' % api_version) super(RcodeZeroDNSDriver, self).__init__(key=key, secure=secure, host=host, port=port, **kwargs) def create_record(self, name, zone, type, data, extra=None): """ Create a new record in a given, existing zone. :param name: name of the new record without the domain name, for example "www". :type name: ``str`` :param zone: Zone in which the requested record is created. :type zone: :class:`Zone` :param type: DNS resource record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depending on the record type). :type data: ``str`` :param extra: Extra attributes: 'ttl', 'disabled' :type extra: ``dict`` :rtype: :class:`Record` """ action = '%s/zones/%s/rrsets' % (self.api_root, zone.id) payload = self._to_patchrequest( zone.id, None, name, type, data, extra, 'add') try: self.connection.request(action=action, data=json.dumps(payload), method='PATCH') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith('Could not find domain'): raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e if extra is not None and extra.get('ttl', None) is not None: ttl = extra['ttl'] else: ttl = None return Record(id=None, name=name, data=data, type=type, zone=zone, ttl=ttl, driver=self) def create_zone(self, domain, type='master', ttl=None, extra={}): """ Create a new zone. :param name: Zone domain name (e.g. example.com) :type name: ``str`` :param domain: Zone type ('master' / 'slave'). (required). :type domain: :class:`Zone` :param ttl: TTL for new records. (optional). Ignored by RcodeZero. RcodeZero uses record specific TTLs. :type ttl: ``int`` :param extra: Extra attributes: 'masters' (for type=slave): ``extra={'masters': ['193.0.2.2','2001:db8::2']}`` sets the Master nameservers for a type=slave zone. :type extra: ``dict`` :rtype: :class:`Zone` """ action = '%s/zones' % (self.api_root) if type.lower() == 'slave' and (extra is None or extra.get('masters', None) is None): msg = 'Master IPs required for slave zones' raise ValueError(msg) payload = {'domain': domain.lower(), 'type': type.lower()} payload.update(extra) zone_id = domain + '.' try: self.connection.request(action=action, data=json.dumps(payload), method='POST') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.find("Zone '%s' already configured for your account" % domain): raise ZoneAlreadyExistsError(zone_id=zone_id, driver=self, value=e.message) raise e return Zone(id=zone_id, domain=domain, type=type.lower(), ttl=None, driver=self, extra=extra) def update_zone(self, zone, domain, type=None, ttl=None, extra=None): """ Update an existing zone. :param zone: Zone to update. :type zone: :class:`Zone` :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type ('master' / 'slave'). :type type: ``str`` :param ttl: not supported. RcodeZero uses RRSet-specific TTLs :type ttl: ``int`` :param extra: Extra attributes: 'masters' (for type=slave) ``extra={'masters': ['193.0.2.2','2001:db8::2']}`` sets the Master nameserver addresses for a type=slave zone :type extra: ``dict`` :rtype: :class:`Zone` """ action = '%s/zones/%s' % (self.api_root, domain) if type is None: type = zone.type if type.lower() == 'slave' and (extra is None or extra.get('masters', None) is None): msg = 'Master IPs required for slave zones' raise ValueError(msg) payload = {'domain': domain.lower(), 'type': type.lower()} if extra is not None: payload.update(extra) try: self.connection.request(action=action, data=json.dumps(payload), method='PUT') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith("Domain '%s' update failed" % domain): raise ZoneAlreadyExistsError(zone_id=zone.id, driver=self, value=e.message) raise e return Zone(id=zone.id, domain=domain, type=type, ttl=None, driver=self, extra=extra) def delete_record(self, record): """ Delete a record in a given zone. :param record: record to delete (record object) :type record: `Record` :rtype: ``bool`` """ action = '%s/zones/%s/rrsets' % (self.api_root, record.zone.id) payload = self._to_patchrequest( record.zone.id, None, record.name, record.type, record.data, record.extra, 'delete') try: self.connection.request(action=action, data=json.dumps(payload), method='PATCH') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith('Could not find domain'): raise ZoneDoesNotExistError(zone_id=record.zone.id, driver=self, value=e.message) raise e return True def delete_zone(self, zone): """ Delete a zone and all its records. :param zone: zone to delete :type zone: `Zone` :rtype: ``bool`` """ action = '%s/zones/%s' % (self.api_root, zone.id) try: self.connection.request(action=action, method='DELETE') except BaseHTTPError: return False return True def get_zone(self, zone_id): """ Get a Zone object. :param zone_id: name of the zone, for example "example.com". :type zone_id: ``str`` :rtype: :class:`Zone` :raises: ZoneDoesNotExistError: if zone could not be found. """ action = '%s/zones/%s' % (self.api_root, zone_id) try: response = self.connection.request(action=action, method='GET') except BaseHTTPError as e: if e.code == httplib.NOT_FOUND: raise ZoneDoesNotExistError(zone_id=zone_id, driver=self, value=e.message) raise e return self._to_zone(response.object) def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ records = self.list_records(Zone(id=zone_id, domain=zone_id, type=None, ttl=None, driver=self, extra=None)) foundrecords = list(filter(lambda x: x.id == record_id, records)) if len(foundrecords) > 0: return(foundrecords[0]) else: return(None) def list_records(self, zone): """ Return a list of all record objects for the given zone. :param zone: Zone object to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '%s/zones/%s/rrsets?page_size=-1' % (self.api_root, zone.id) try: response = self.connection.request(action=action, method='GET') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith('Could not find domain'): raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e return self._to_records(response.object['data'], zone) def list_zones(self): """ Return a list of zone objects for this account. :return: ``list`` of :class:`Zone` """ action = '%s/zones?page_size=-1' % (self.api_root) response = self.connection.request(action=action, method='GET') return self._to_zones(response.object['data']) def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record object to update. :type record: :class:`Record` :param name: name of the new record, for example "www". :type name: ``str`` :param type: DNS resource record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depending on the record type). :type data: ``str`` :param extra: Extra attributes: 'ttl','disabled' (optional) :type extra: ``dict`` :rtype: :class:`Record` """ action = '%s/zones/%s/rrsets' % (self.api_root, record.zone.id) payload = self._to_patchrequest( record.zone.id, record, name, type, data, record.extra, 'update') try: self.connection.request(action=action, data=json.dumps(payload), method='PATCH') except BaseHTTPError as e: if e.code == httplib.UNPROCESSABLE_ENTITY and \ e.message.startswith('Could not find domain'): raise ZoneDoesNotExistError(zone_id=record.zone.id, driver=self, value=e.message) raise e if not (extra is None or extra.get('ttl', None) is None): ttl = extra['ttl'] else: ttl = record.ttl return Record(id=hashlib.md5(str(name + ' ' + data).encode('utf-8')).hexdigest(), name=name, data=data, type=type, zone=record.zone, driver=self, ttl=ttl, extra=extra) def _to_zone(self, item): extra = {} for e in ['dnssec_status', 'dnssec_status_detail', 'dnssec_ksk_status', 'dnssec_ksk_status_detail', 'dnssec_ds', 'dnssec_dnskey', 'dnssec_safe_to_unsign', 'dnssec', 'masters', 'serial', 'created', 'last_check']: if e in item: extra[e] = item[e] return Zone(id=item['domain'], domain=item['domain'], type=item['type'].lower(), ttl=None, driver=self, extra=extra) def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_records(self, items, zone): records = [] for item in items: for record in item['records']: extra = {} extra['disabled'] = record['disabled'] # strip domain and trailing dot from recordname recordname = re.sub('.' + zone.id + '$', '', item['name'][:-1]) records.append( Record(id=hashlib.md5(str(recordname + ' ' + record['content']). encode('utf-8')).hexdigest(), name=recordname, data=record['content'], type=item['type'], zone=zone, driver=self, ttl=item['ttl'], extra=extra)) return records # rcodezero supports only rrset, so we must create rrsets from the given # record def _to_patchrequest(self, zone, record, name, type, data, extra, action): rrset = {} cur_records = self.list_records( Zone(id=zone, domain=None, type=None, ttl=None, driver=self)) if name != '': rrset['name'] = name + '.' + zone + '.' else: rrset['name'] = zone + '.' rrset['type'] = type rrset['changetype'] = action rrset['records'] = [] if not (extra is None or extra.get('ttl', None) is None): rrset['ttl'] = extra['ttl'] content = {} if not action == 'delete': content['content'] = data if not (extra is None or extra.get('disabled', None) is None): content['disabled'] = extra['disabled'] rrset['records'].append(content) id = hashlib.md5(str(name + ' ' + data).encode('utf-8')).hexdigest() # check if rrset contains more than one record. if yes we need to create an # update request for r in cur_records: if action == 'update' and r.id == record.id: # do not include records which should be updated in the update # request continue if name == r.name and r.id != id: # we have other records with the same name so make an update # request rrset['changetype'] = 'update' content = {} content['content'] = r.data if not (r.extra is None or r.extra.get('disabled', None) is None): content['disabled'] = r.extra['disabled'] rrset['records'].append(content) request = list() request.append(rrset) return request apache-libcloud-2.8.0/libcloud/dns/drivers/route53.py0000664000175000017500000005135113535474530022360 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'Route53DNSDriver' ] import base64 import hmac import datetime import uuid import copy from libcloud.utils.py3 import httplib from hashlib import sha1 from libcloud.utils.py3 import ET from libcloud.utils.py3 import b, urlencode from libcloud.utils.xml import findtext, findall, fixxpath from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.common.types import LibcloudError from libcloud.common.aws import AWSGenericResponse, AWSTokenConnection from libcloud.common.base import ConnectionUserAndKey API_VERSION = '2012-02-29' API_HOST = 'route53.amazonaws.com' API_ROOT = '/%s/' % (API_VERSION) NAMESPACE = 'https://%s/doc%s' % (API_HOST, API_ROOT) class InvalidChangeBatch(LibcloudError): pass class Route53DNSResponse(AWSGenericResponse): """ Amazon Route53 response class. """ namespace = NAMESPACE xpath = 'Error' exceptions = { 'NoSuchHostedZone': ZoneDoesNotExistError, 'InvalidChangeBatch': InvalidChangeBatch, } class BaseRoute53Connection(ConnectionUserAndKey): host = API_HOST responseCls = Route53DNSResponse def pre_connect_hook(self, params, headers): time_string = datetime.datetime.utcnow() \ .strftime('%a, %d %b %Y %H:%M:%S GMT') headers['Date'] = time_string tmp = [] signature = self._get_aws_auth_b64(self.key, time_string) auth = {'AWSAccessKeyId': self.user_id, 'Signature': signature, 'Algorithm': 'HmacSHA1'} for k, v in auth.items(): tmp.append('%s=%s' % (k, v)) headers['X-Amzn-Authorization'] = 'AWS3-HTTPS ' + ','.join(tmp) return params, headers def _get_aws_auth_b64(self, secret_key, time_string): b64_hmac = base64.b64encode( hmac.new(b(secret_key), b(time_string), digestmod=sha1).digest() ) return b64_hmac.decode('utf-8') class Route53Connection(AWSTokenConnection, BaseRoute53Connection): pass class Route53DNSDriver(DNSDriver): type = Provider.ROUTE53 name = 'Route53 DNS' website = 'http://aws.amazon.com/route53/' connectionCls = Route53Connection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.SOA: 'SOA', RecordType.SPF: 'SPF', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', } def __init__(self, *args, **kwargs): self.token = kwargs.pop('token', None) super(Route53DNSDriver, self).__init__(*args, **kwargs) def iterate_zones(self): return self._get_more('zones') def iterate_records(self, zone): return self._get_more('records', zone=zone) def get_zone(self, zone_id): self.connection.set_context({'zone_id': zone_id}) uri = API_ROOT + 'hostedzone/' + zone_id data = self.connection.request(uri).object elem = findall(element=data, xpath='HostedZone', namespace=NAMESPACE)[0] return self._to_zone(elem) def get_record(self, zone_id, record_id): zone = self.get_zone(zone_id=zone_id) record_type, name = record_id.split(':', 1) if name: full_name = ".".join((name, zone.domain)) else: full_name = zone.domain self.connection.set_context({'zone_id': zone_id}) params = urlencode({ 'name': full_name, 'type': record_type, 'maxitems': '1' }) uri = API_ROOT + 'hostedzone/' + zone_id + '/rrset?' + params data = self.connection.request(uri).object record = self._to_records(data=data, zone=zone)[0] # A cute aspect of the /rrset filters is that they are more pagination # hints than filters!! # So will return a result even if its not what you asked for. record_type_num = self._string_to_record_type(record_type) if record.name != name or record.type != record_type_num: raise RecordDoesNotExistError(value='', driver=self, record_id=record_id) return record def create_zone(self, domain, type='master', ttl=None, extra=None): zone = ET.Element('CreateHostedZoneRequest', {'xmlns': NAMESPACE}) ET.SubElement(zone, 'Name').text = domain ET.SubElement(zone, 'CallerReference').text = str(uuid.uuid4()) if extra and 'Comment' in extra: hzg = ET.SubElement(zone, 'HostedZoneConfig') ET.SubElement(hzg, 'Comment').text = extra['Comment'] uri = API_ROOT + 'hostedzone' data = ET.tostring(zone) rsp = self.connection.request(uri, method='POST', data=data).object elem = findall(element=rsp, xpath='HostedZone', namespace=NAMESPACE)[0] return self._to_zone(elem=elem) def delete_zone(self, zone, ex_delete_records=False): self.connection.set_context({'zone_id': zone.id}) if ex_delete_records: self.ex_delete_all_records(zone=zone) uri = API_ROOT + 'hostedzone/%s' % (zone.id) response = self.connection.request(uri, method='DELETE') return response.status in [httplib.OK] def create_record(self, name, zone, type, data, extra=None): if type in (RecordType.TXT, RecordType.SPF): data = self._quote_data(data) extra = extra or {} batch = [('CREATE', name, type, data, extra)] self._post_changeset(zone, batch) id = ':'.join((self.RECORD_TYPE_MAP[type], name)) return Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=extra.get('ttl', None), extra=extra) def update_record(self, record, name=None, type=None, data=None, extra=None): name = name or record.name type = type or record.type extra = extra or record.extra if not extra: extra = record.extra # Multiple value records need to be handled specially - we need to # pass values for other records as well multiple_value_record = record.extra.get('_multi_value', False) other_records = record.extra.get('_other_records', []) if multiple_value_record and other_records: self._update_multi_value_record(record=record, name=name, type=type, data=data, extra=extra) else: self._update_single_value_record(record=record, name=name, type=type, data=data, extra=extra) id = ':'.join((self.RECORD_TYPE_MAP[type], name)) return Record(id=id, name=name, type=type, data=data, zone=record.zone, driver=self, ttl=extra.get('ttl', None), extra=extra) def delete_record(self, record): try: r = record batch = [('DELETE', r.name, r.type, r.data, r.extra)] self._post_changeset(record.zone, batch) except InvalidChangeBatch: raise RecordDoesNotExistError(value='', driver=self, record_id=r.id) return True def ex_create_multi_value_record(self, name, zone, type, data, extra=None): """ Create a record with multiple values with a single call. :return: A list of created records. :rtype: ``list`` of :class:`libcloud.dns.base.Record` """ extra = extra or {} attrs = {'xmlns': NAMESPACE} changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs) batch = ET.SubElement(changeset, 'ChangeBatch') changes = ET.SubElement(batch, 'Changes') change = ET.SubElement(changes, 'Change') ET.SubElement(change, 'Action').text = 'CREATE' rrs = ET.SubElement(change, 'ResourceRecordSet') ET.SubElement(rrs, 'Name').text = name + '.' + zone.domain ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type] ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0')) rrecs = ET.SubElement(rrs, 'ResourceRecords') # Value is provided as a multi line string values = [value.strip() for value in data.split('\n') if value.strip()] for value in values: rrec = ET.SubElement(rrecs, 'ResourceRecord') ET.SubElement(rrec, 'Value').text = value uri = API_ROOT + 'hostedzone/' + zone.id + '/rrset' data = ET.tostring(changeset) self.connection.set_context({'zone_id': zone.id}) self.connection.request(uri, method='POST', data=data) id = ':'.join((self.RECORD_TYPE_MAP[type], name)) records = [] for value in values: record = Record(id=id, name=name, type=type, data=value, zone=zone, driver=self, ttl=extra.get('ttl', None), extra=extra) records.append(record) return records def ex_delete_all_records(self, zone): """ Remove all the records for the provided zone. :param zone: Zone to delete records for. :type zone: :class:`Zone` """ deletions = [] for r in zone.list_records(): if r.type in (RecordType.NS, RecordType.SOA): continue deletions.append(('DELETE', r.name, r.type, r.data, r.extra)) if deletions: self._post_changeset(zone, deletions) def _update_single_value_record(self, record, name=None, type=None, data=None, extra=None): batch = [ ('DELETE', record.name, record.type, record.data, record.extra), ('CREATE', name, type, data, extra) ] return self._post_changeset(record.zone, batch) def _update_multi_value_record(self, record, name=None, type=None, data=None, extra=None): other_records = record.extra.get('_other_records', []) attrs = {'xmlns': NAMESPACE} changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs) batch = ET.SubElement(changeset, 'ChangeBatch') changes = ET.SubElement(batch, 'Changes') # Delete existing records change = ET.SubElement(changes, 'Change') ET.SubElement(change, 'Action').text = 'DELETE' rrs = ET.SubElement(change, 'ResourceRecordSet') if record.name: record_name = record.name + '.' + record.zone.domain else: record_name = record.zone.domain ET.SubElement(rrs, 'Name').text = record_name ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[record.type] ET.SubElement(rrs, 'TTL').text = str(record.extra.get('ttl', '0')) rrecs = ET.SubElement(rrs, 'ResourceRecords') rrec = ET.SubElement(rrecs, 'ResourceRecord') ET.SubElement(rrec, 'Value').text = record.data for other_record in other_records: rrec = ET.SubElement(rrecs, 'ResourceRecord') ET.SubElement(rrec, 'Value').text = other_record['data'] # Re-create new (updated) records. Since we are updating a multi value # record, only a single record is updated and others are left as is. change = ET.SubElement(changes, 'Change') ET.SubElement(change, 'Action').text = 'CREATE' rrs = ET.SubElement(change, 'ResourceRecordSet') if name: record_name = name + '.' + record.zone.domain else: record_name = record.zone.domain ET.SubElement(rrs, 'Name').text = record_name ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type] ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0')) rrecs = ET.SubElement(rrs, 'ResourceRecords') rrec = ET.SubElement(rrecs, 'ResourceRecord') ET.SubElement(rrec, 'Value').text = data for other_record in other_records: rrec = ET.SubElement(rrecs, 'ResourceRecord') ET.SubElement(rrec, 'Value').text = other_record['data'] uri = API_ROOT + 'hostedzone/' + record.zone.id + '/rrset' data = ET.tostring(changeset) self.connection.set_context({'zone_id': record.zone.id}) response = self.connection.request(uri, method='POST', data=data) return response.status == httplib.OK def _post_changeset(self, zone, changes_list): attrs = {'xmlns': NAMESPACE} changeset = ET.Element('ChangeResourceRecordSetsRequest', attrs) batch = ET.SubElement(changeset, 'ChangeBatch') changes = ET.SubElement(batch, 'Changes') for action, name, type_, data, extra in changes_list: change = ET.SubElement(changes, 'Change') ET.SubElement(change, 'Action').text = action rrs = ET.SubElement(change, 'ResourceRecordSet') if name: record_name = name + '.' + zone.domain else: record_name = zone.domain ET.SubElement(rrs, 'Name').text = record_name ET.SubElement(rrs, 'Type').text = self.RECORD_TYPE_MAP[type_] ET.SubElement(rrs, 'TTL').text = str(extra.get('ttl', '0')) rrecs = ET.SubElement(rrs, 'ResourceRecords') rrec = ET.SubElement(rrecs, 'ResourceRecord') if 'priority' in extra: data = '%s %s' % (extra['priority'], data) ET.SubElement(rrec, 'Value').text = data uri = API_ROOT + 'hostedzone/' + zone.id + '/rrset' data = ET.tostring(changeset) self.connection.set_context({'zone_id': zone.id}) response = self.connection.request(uri, method='POST', data=data) return response.status == httplib.OK def _to_zones(self, data): zones = [] for element in data.findall(fixxpath(xpath='HostedZones/HostedZone', namespace=NAMESPACE)): zones.append(self._to_zone(element)) return zones def _to_zone(self, elem): name = findtext(element=elem, xpath='Name', namespace=NAMESPACE) id = findtext(element=elem, xpath='Id', namespace=NAMESPACE).replace('/hostedzone/', '') comment = findtext(element=elem, xpath='Config/Comment', namespace=NAMESPACE) resource_record_count = int(findtext(element=elem, xpath='ResourceRecordSetCount', namespace=NAMESPACE)) extra = {'Comment': comment, 'ResourceRecordSetCount': resource_record_count} zone = Zone(id=id, domain=name, type='master', ttl=0, driver=self, extra=extra) return zone def _to_records(self, data, zone): records = [] elems = data.findall( fixxpath(xpath='ResourceRecordSets/ResourceRecordSet', namespace=NAMESPACE)) for elem in elems: record_set = elem.findall(fixxpath( xpath='ResourceRecords/ResourceRecord', namespace=NAMESPACE)) record_count = len(record_set) multiple_value_record = (record_count > 1) record_set_records = [] for index, record in enumerate(record_set): # Need to special handling for records with multiple values for # update to work correctly record = self._to_record(elem=elem, zone=zone, index=index) record.extra['_multi_value'] = multiple_value_record if multiple_value_record: record.extra['_other_records'] = [] record_set_records.append(record) # Store reference to other records so update works correctly if multiple_value_record: for index in range(0, len(record_set_records)): record = record_set_records[index] for other_index, other_record in \ enumerate(record_set_records): if index == other_index: # Skip current record continue extra = copy.deepcopy(other_record.extra) extra.pop('_multi_value') extra.pop('_other_records') item = {'name': other_record.name, 'data': other_record.data, 'type': other_record.type, 'extra': extra} record.extra['_other_records'].append(item) records.extend(record_set_records) return records def _to_record(self, elem, zone, index=0): name = findtext(element=elem, xpath='Name', namespace=NAMESPACE) name = name[:-len(zone.domain) - 1] type = self._string_to_record_type(findtext(element=elem, xpath='Type', namespace=NAMESPACE)) ttl = findtext(element=elem, xpath='TTL', namespace=NAMESPACE) if ttl is not None: ttl = int(ttl) value_elem = elem.findall( fixxpath(xpath='ResourceRecords/ResourceRecord', namespace=NAMESPACE))[index] data = findtext(element=(value_elem), xpath='Value', namespace=NAMESPACE) extra = {'ttl': ttl} if type == 'MX': split = data.split() priority, data = split extra['priority'] = int(priority) elif type == 'SRV': split = data.split() priority, weight, port, data = split extra['priority'] = int(priority) extra['weight'] = int(weight) extra['port'] = int(port) id = ':'.join((self.RECORD_TYPE_MAP[type], name)) record = Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=extra.get('ttl', None), extra=extra) return record def _get_more(self, rtype, **kwargs): exhausted = False last_key = None while not exhausted: items, last_key, exhausted = self._get_data(rtype, last_key, **kwargs) for item in items: yield item def _get_data(self, rtype, last_key, **kwargs): params = {} if last_key: params['name'] = last_key path = API_ROOT + 'hostedzone' if rtype == 'zones': response = self.connection.request(path, params=params) transform_func = self._to_zones elif rtype == 'records': zone = kwargs['zone'] path += '/%s/rrset' % (zone.id) self.connection.set_context({'zone_id': zone.id}) response = self.connection.request(path, params=params) transform_func = self._to_records if response.status == httplib.OK: is_truncated = findtext(element=response.object, xpath='IsTruncated', namespace=NAMESPACE) exhausted = is_truncated != 'true' last_key = findtext(element=response.object, xpath='NextRecordName', namespace=NAMESPACE) items = transform_func(data=response.object, **kwargs) return items, last_key, exhausted else: return [], None, True def _ex_connection_class_kwargs(self): kwargs = super(Route53DNSDriver, self)._ex_connection_class_kwargs() kwargs['token'] = self.token return kwargs def _quote_data(self, data): if data[0] == '"' and data[-1] == '"': return data return '"{0}"'.format(data.replace('"', '\"')) apache-libcloud-2.8.0/libcloud/dns/drivers/softlayer.py0000664000175000017500000001647013535474530023065 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # pylint: disable=unexpected-keyword-arg __all__ = [ 'SoftLayerDNSDriver' ] from libcloud.common.softlayer import SoftLayerConnection from libcloud.common.softlayer import SoftLayerObjectDoesntExist from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record VALID_RECORD_EXTRA_PARAMS = ['priority', 'ttl'] class SoftLayerDNSDriver(DNSDriver): type = Provider.SOFTLAYER name = 'Softlayer DNS' website = 'https://www.softlayer.com' connectionCls = SoftLayerConnection RECORD_TYPE_MAP = { RecordType.A: 'a', RecordType.AAAA: 'aaaa', RecordType.CNAME: 'cname', RecordType.MX: 'mx', RecordType.NS: 'ns', RecordType.PTR: 'ptr', RecordType.SOA: 'soa', RecordType.SPF: 'spf', RecordType.SRV: 'srv', RecordType.TXT: 'txt', } def create_zone(self, domain, ttl=None, extra=None): self.connection.set_context({'resource': 'zone', 'id': domain}) data = { 'name': domain, 'resourceRecords': [] } response = self.connection.request( 'SoftLayer_Dns_Domain', 'createObject', data ).object zone = Zone(id=response['id'], domain=domain, type='master', ttl=3600, driver=self) return zone def get_zone(self, zone_id): self.connection.set_context({'resource': 'zone', 'id': zone_id}) try: response = self.connection.request( 'SoftLayer_Dns_Domain', 'getObject', id=zone_id ).object except SoftLayerObjectDoesntExist: raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone_id) return self._to_zone(response) def delete_zone(self, zone): self.connection.set_context({'resource': 'zone', 'id': zone.id}) try: self.connection.request( 'SoftLayer_Dns_Domain', 'deleteObject', id=zone.id ).object except SoftLayerObjectDoesntExist: raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone.id) else: return True def iterate_zones(self): zones_list = self.connection.request( 'SoftLayer_Dns_Domain', 'getByDomainName', '.' ).object for item in zones_list: yield self._to_zone(item) def iterate_records(self, zone): self.connection.set_context({'resource': 'zone', 'id': zone.id}) records_list = self.connection.request( 'SoftLayer_Dns_Domain', 'getResourceRecords', id=zone.id ).object for item in records_list: yield self._to_record(item, zone=zone) def get_record(self, zone_id, record_id): try: record = self.connection.request( 'SoftLayer_Dns_Domain_ResourceRecord', 'getObject', id=record_id ).object return self._to_record(record, zone=self.get_zone(zone_id)) except SoftLayerObjectDoesntExist: raise RecordDoesNotExistError(value='', driver=self, record_id=record_id) def delete_record(self, record): try: self.connection.request( 'SoftLayer_Dns_Domain_ResourceRecord', 'deleteObject', id=record.id ).object except SoftLayerObjectDoesntExist: raise RecordDoesNotExistError(value='', driver=self, record_id=record.id) else: return True def create_record(self, name, zone, type, data, extra=None): params = { 'domainId': zone.id, 'type': self.RECORD_TYPE_MAP[type], 'host': name, 'data': data } if extra: if extra.get('ttl'): params['ttl'] = extra['ttl'] if extra.get('refresh'): params['refresh'] = extra['refresh'] if extra.get('retry'): params['retry'] = extra['retry'] if extra.get('expire'): params['expire'] = extra['expire'] if extra.get('priority'): params['mxPriority'] = extra['priority'] response = self.connection.request( 'SoftLayer_Dns_Domain_ResourceRecord', 'createObject', params ).object return self._to_record(response, zone=zone) def update_record( self, record, name=None, type=None, data=None, extra=None): params = {} if type: params['type'] = self.RECORD_TYPE_MAP[type] if name: params['host'] = name if data: params['data'] = data if extra: if extra.get('ttl'): params['ttl'] = extra['ttl'] if extra.get('refresh'): params['refresh'] = extra['refresh'] if extra.get('retry'): params['retry'] = extra['retry'] if extra.get('expire'): params['expire'] = extra['expire'] if extra.get('priority'): params['mxPriority'] = extra['priority'] response = self.connection.request( 'SoftLayer_Dns_Domain_ResourceRecord', 'editObject', params, id=record.id, ).object if response: changed_record = self.connection.request( 'SoftLayer_Dns_Domain_ResourceRecord', 'getObject', id=record.id, ).object return self._to_record(changed_record, zone=record.zone) else: return False def _to_zone(self, item): ttl = item.get('ttl', 3600) zone = Zone(id=item['id'], domain=item['name'], type='master', ttl=ttl, driver=self) return zone def _to_record(self, item, zone=None): extra = { 'ttl': item['ttl'], 'expire': item['expire'], 'mxPriority': item['mxPriority'], 'refresh': item['refresh'], 'retry': item['retry'], } record = Record( id=item['id'], name=item['host'], type=self._string_to_record_type(item['type']), data=item['data'], zone=zone, driver=self, ttl=item['ttl'], extra=extra ) return record apache-libcloud-2.8.0/libcloud/dns/drivers/vultr.py0000664000175000017500000002732113535474530022226 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Vultr DNS Driver """ from libcloud.utils.py3 import urlencode from libcloud.common.vultr import VultrConnection, VultrResponse from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.types import ZoneAlreadyExistsError, RecordAlreadyExistsError from libcloud.dns.types import Provider, RecordType __all__ = [ 'ZoneRequiredException', 'VultrDNSResponse', 'VultrDNSConnection', 'VultrDNSDriver', ] class ZoneRequiredException(Exception): pass class VultrDNSResponse(VultrResponse): pass class VultrDNSConnection(VultrConnection): responseCls = VultrDNSResponse class VultrDNSDriver(DNSDriver): type = Provider.VULTR name = 'Vultr DNS' website = 'http://www.vultr.com/' connectionCls = VultrDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.TXT: 'TXT', RecordType.CNAME: 'CNAME', RecordType.MX: 'MX', RecordType.NS: 'NS', RecordType.SRV: 'SRV', } def list_zones(self): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '/v1/dns/list' params = {'api_key': self.key} response = self.connection.request(action=action, params=params) zones = self._to_zones(response.objects[0]) return zones def list_records(self, zone): """ Returns a list of records for the provided zone. :param zone: zone to list records for :type zone: `Zone` :rtype: list of :class: `Record` """ if not isinstance(zone, Zone): raise ZoneRequiredException('zone should be of type Zone') zones = self.list_zones() if not self.ex_zone_exists(zone.domain, zones): raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone.domain) action = '/v1/dns/records' params = {'domain': zone.domain} response = self.connection.request(action=action, params=params) records = self._to_records(response.objects[0], zone=zone) return records def get_zone(self, zone_id): """ Returns a `Zone` instance. :param zone_id: name of the zone user wants to get. :type zone_id: ``str`` :rtype: :class:`Zone` """ ret_zone = None action = '/v1/dns/list' params = {'api_key': self.key} response = self.connection.request(action=action, params=params) zones = self._to_zones(response.objects[0]) if not self.ex_zone_exists(zone_id, zones): raise ZoneDoesNotExistError(value=None, zone_id=zone_id, driver=self) for zone in zones: if zone_id == zone.domain: ret_zone = zone return ret_zone def get_record(self, zone_id, record_id): """ Returns a Record instance. :param zone_id: name of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class: `Record` """ ret_record = None zone = self.get_zone(zone_id=zone_id) records = self.list_records(zone=zone) if not self.ex_record_exists(record_id, records): raise RecordDoesNotExistError(value='', driver=self, record_id=record_id) for record in records: if record_id == record.id: ret_record = record return ret_record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Returns a `Zone` object. :param domain: Zone domain name, (e.g. example.com). :type domain: ``str`` :param type: Zone type (master / slave). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: (optional) Extra attributes (driver specific). (e.g. {'serverip':'127.0.0.1'}) """ extra = extra or {} if extra and extra.get('serverip'): serverip = extra['serverip'] params = {'api_key': self.key} data = urlencode({'domain': domain, 'serverip': serverip}) action = '/v1/dns/create_domain' zones = self.list_zones() if self.ex_zone_exists(domain, zones): raise ZoneAlreadyExistsError(value='', driver=self, zone_id=domain) self.connection.request(params=params, action=action, data=data, method='POST') zone = Zone(id=domain, domain=domain, type=type, ttl=ttl, driver=self, extra=extra) return zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, AAAA, ...). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ extra = extra or {} ret_record = None old_records_list = self.list_records(zone=zone) # check if record already exists # if exists raise RecordAlreadyExistsError for record in old_records_list: if record.name == name and record.data == data: raise RecordAlreadyExistsError(value='', driver=self, record_id=record.id) MX = self.RECORD_TYPE_MAP.get('MX') SRV = self.RECORD_TYPE_MAP.get('SRV') if extra and extra.get('priority'): priority = int(extra['priority']) post_data = {'domain': zone.domain, 'name': name, 'type': self.RECORD_TYPE_MAP.get(type), 'data': data} if type == MX or type == SRV: post_data['priority'] = priority encoded_data = urlencode(post_data) params = {'api_key': self.key} action = '/v1/dns/create_record' self.connection.request(action=action, params=params, data=encoded_data, method='POST') updated_zone_records = zone.list_records() for record in updated_zone_records: if record.name == name and record.data == data: ret_record = record return ret_record def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ action = '/v1/dns/delete_domain' params = {'api_key': self.key} data = urlencode({'domain': zone.domain}) zones = self.list_zones() if not self.ex_zone_exists(zone.domain, zones): raise ZoneDoesNotExistError(value='', driver=self, zone_id=zone.domain) response = self.connection.request(params=params, action=action, data=data, method='POST') return response.status == 200 def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ action = '/v1/dns/delete_record' params = {'api_key': self.key} data = urlencode({'RECORDID': record.id, 'domain': record.zone.domain}) zone_records = self.list_records(record.zone) if not self.ex_record_exists(record.id, zone_records): raise RecordDoesNotExistError(value='', driver=self, record_id=record.id) response = self.connection.request(action=action, params=params, data=data, method='POST') return response.status == 200 def ex_zone_exists(self, zone_id, zones_list): """ Function to check if a `Zone` object exists. :param zone_id: Name of the `Zone` object. :type zone_id: ``str`` :param zones_list: A list containing `Zone` objects :type zones_list: ``list`` :rtype: Returns `True` or `False` """ zone_ids = [] for zone in zones_list: zone_ids.append(zone.domain) return zone_id in zone_ids def ex_record_exists(self, record_id, records_list): """ :param record_id: Name of the `Record` object. :type record_id: ``str`` :param records_list: A list containing `Record` objects :type records_list: ``list`` :rtype: ``bool`` """ record_ids = [] for record in records_list: record_ids.append(record.id) return record_id in record_ids def _to_zone(self, item): """ Build an object `Zone` from the item dictionary :param item: item to build the zone from :type item: `dictionary` :rtype: :instance: `Zone` """ type = 'master' extra = {'date_created': item['date_created']} zone = Zone(id=item['domain'], domain=item['domain'], driver=self, type=type, ttl=None, extra=extra) return zone def _to_zones(self, items): """ Returns a list of `Zone` objects. :param: items: a list that contains dictionary objects to be passed to the _to_zone function. :type items: ``list`` """ zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone): extra = {} if item.get('priority'): extra['priority'] = item['priority'] type = self._string_to_record_type(item['type']) record = Record(id=item['RECORDID'], name=item['name'], type=type, data=item['data'], zone=zone, driver=self, extra=extra) return record def _to_records(self, items, zone): records = [] for item in items: records.append(self._to_record(item, zone=zone)) return records apache-libcloud-2.8.0/libcloud/dns/drivers/worldwidedns.py0000664000175000017500000004477613535474530023574 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ World Wide DNS Driver """ __all__ = [ 'WorldWideDNSDriver' ] import re from libcloud.common.types import LibcloudError from libcloud.common.worldwidedns import WorldWideDNSConnection from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError from libcloud.dns.types import RecordError from libcloud.dns.types import RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record MAX_RECORD_ENTRIES = 40 # Maximum record entries for zone class WorldWideDNSError(LibcloudError): def __repr__(self): return ("") class WorldWideDNSDriver(DNSDriver): type = Provider.WORLDWIDEDNS name = 'World Wide DNS' website = 'https://www.worldwidedns.net/' connectionCls = WorldWideDNSConnection RECORD_TYPE_MAP = { RecordType.MX: 'MX', RecordType.CNAME: 'CNAME', RecordType.A: 'A', RecordType.NS: 'NS', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', } def __init__(self, key, secret=None, reseller_id=None, secure=True, host=None, port=None, **kwargs): """ :param key: API key or username to used (required) :type key: ``str`` :param secret: Secret password to be used (required) :type secret: ``str`` :param reseller_id: Reseller ID for reseller accounts :type reseller_id: ``str`` :param secure: Whether to use HTTPS or HTTP. Note: Some providers only support HTTPS, and it is on by default. :type secure: ``bool`` :param host: Override hostname used for connections. :type host: ``str`` :param port: Override port used for connections. :type port: ``int`` :return: ``None`` """ super(WorldWideDNSDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) self.reseller_id = reseller_id def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` For more info, please see: https://www.worldwidedns.net/dns_api_protocol_list.asp or https://www.worldwidedns.net/dns_api_protocol_list_reseller.asp """ action = '/api_dns_list.asp' if self.reseller_id is not None: action = '/api_dns_list_reseller.asp' zones = self.connection.request(action) if len(zones.body) == 0: return [] else: return self._to_zones(zones.body) def iterate_records(self, zone): """ Return a generator to iterate over records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :rtype: ``generator`` of :class:`Record` """ records = self._to_records(zone) for record in records: yield record def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ zones = self.list_zones() zone = [zone for zone in zones if zone.id == zone_id] if len(zone) == 0: raise ZoneDoesNotExistError(driver=self, value="The zone doesn't exists", zone_id=zone_id) return zone[0] def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID number of the required record. :type record_id: ``str`` :rtype: :class:`Record` """ zone = self.get_zone(zone_id) try: if int(record_id) not in range(1, MAX_RECORD_ENTRIES + 1): raise RecordDoesNotExistError(value="Record doesn't exists", driver=zone.driver, record_id=record_id) except ValueError: raise WorldWideDNSError( value="Record id should be a string number", driver=self) subdomain = zone.extra.get('S%s' % record_id) type = zone.extra.get('T%s' % record_id) data = zone.extra.get('D%s' % record_id) record = self._to_record(record_id, subdomain, type, data, zone) return record def update_zone(self, zone, domain, type='master', ttl=None, extra=None, ex_raw=False): """ Update an existing zone. :param zone: Zone to update. :type zone: :class:`Zone` :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (master / slave). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes (driver specific) (optional). Values not specified such as *SECURE*, *IP*, *FOLDER*, *HOSTMASTER*, *REFRESH*, *RETRY* and *EXPIRE* will be kept as already is. The same will be for *S(1 to 40)*, *T(1 to 40)* and *D(1 to 40)* if not in raw mode and for *ZONENS* and *ZONEDATA* if it is. :type extra: ``dict`` :param ex_raw: Mode we use to do the update using zone file or not. :type ex_raw: ``bool`` :rtype: :class:`Zone` For more info, please see https://www.worldwidedns.net/dns_api_protocol_list_domain.asp or https://www.worldwidedns.net/dns_api_protocol_list_domain_raw.asp or https://www.worldwidedns.net/dns_api_protocol_list_domain_reseller.asp or https://www.worldwidedns.net/dns_api_protocol_list_domain_raw_reseller.asp """ if extra is not None: not_specified = [key for key in zone.extra.keys() if key not in extra.keys()] else: not_specified = zone.extra.keys() if ttl is None: ttl = zone.ttl params = {'DOMAIN': domain, 'TTL': ttl} for key in not_specified: params[key] = zone.extra[key] if extra is not None: params.update(extra) if ex_raw: action = '/api_dns_modify_raw.asp' if self.reseller_id is not None: action = '/api_dns_modify_raw_reseller.asp' method = 'POST' else: action = '/api_dns_modify.asp' if self.reseller_id is not None: action = '/api_dns_modify_reseller.asp' method = 'GET' response = self.connection.request(action, params=params, # noqa method=method) zone = self.get_zone(zone.id) return zone def update_record(self, record, name, type, data, extra=None): """ Update an existing record. :param record: Record to update. :type record: :class:`Record` :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param type: DNS record type (MX, CNAME, A, NS, SRV, TXT). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Contains 'entry' Entry position (1 thru 40) :type extra: ``dict`` :rtype: :class:`Record` """ if (extra is None) or ('entry' not in extra): raise WorldWideDNSError(value="You must enter 'entry' parameter", driver=self) record_id = extra.get('entry') if name == '': name = '@' if type not in self.RECORD_TYPE_MAP: raise RecordError(value="Record type is not allowed", driver=record.zone.driver, record_id=name) zone = record.zone extra = {'S%s' % record_id: name, 'T%s' % record_id: type, 'D%s' % record_id: data} zone = self.update_zone(zone, zone.domain, extra=extra) record = self.get_record(zone.id, record_id) return record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param domain: Zone domain name (e.g. example.com) :type domain: ``str`` :param type: Zone type (master / slave). :type type: ``str`` :param ttl: TTL for new records. (optional) :type ttl: ``int`` :param extra: Extra attributes (driver specific). (optional). Possible parameter in here should be *DYN* which values should be 1 for standart and 2 for dynamic. Default is 1. :type extra: ``dict`` :rtype: :class:`Zone` For more info, please see https://www.worldwidedns.net/dns_api_protocol_new_domain.asp or https://www.worldwidedns.net/dns_api_protocol_new_domain_reseller.asp """ if type == 'master': _type = 0 elif type == 'slave': _type = 1 if extra: dyn = extra.get('DYN') or 1 else: dyn = 1 params = {'DOMAIN': domain, 'TYPE': _type} action = '/api_dns_new_domain.asp' if self.reseller_id is not None: params['DYN'] = dyn action = '/api_dns_new_domain_reseller.asp' self.connection.request(action, params=params) zone = self.get_zone(domain) if ttl is not None: zone = self.update_zone(zone, zone.domain, ttl=ttl) return zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. We can create 40 record per domain. If all slots are full, we can replace one of them by choosing a specific entry in ``extra`` argument. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (MX, CNAME, A, NS, SRV, TXT). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Contains 'entry' Entry position (1 thru 40) :type extra: ``dict`` :rtype: :class:`Record` """ if (extra is None) or ('entry' not in extra): # If no entry is specified, we look for an available one. If all # are full, raise error. record_id = self._get_available_record_entry(zone) if not record_id: raise WorldWideDNSError(value="All record entries are full", driver=zone.driver) else: record_id = extra.get('entry') if name == '': name = '@' if type not in self.RECORD_TYPE_MAP: raise RecordError(value="Record type is not allowed", driver=zone.driver, record_id=record_id) extra = {'S%s' % record_id: name, 'T%s' % record_id: type, 'D%s' % record_id: data} zone = self.update_zone(zone, zone.domain, extra=extra) record = self.get_record(zone.id, record_id) return record def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` For more information, please see https://www.worldwidedns.net/dns_api_protocol_delete_domain.asp or https://www.worldwidedns.net/dns_api_protocol_delete_domain_reseller.asp """ params = {'DOMAIN': zone.domain} action = '/api_dns_delete_domain.asp' if self.reseller_id is not None: action = '/api_dns_delete_domain_reseller.asp' response = self.connection.request(action, params=params) return response.success() def delete_record(self, record): """ Delete a record. :param record: Record to delete. :type record: :class:`Record` :rtype: ``bool`` """ zone = record.zone for index in range(MAX_RECORD_ENTRIES): if record.name == zone.extra['S%s' % (index + 1)]: entry = index + 1 break extra = {'S%s' % entry: '', 'T%s' % entry: 'NONE', 'D%s' % entry: ''} self.update_zone(zone, zone.domain, extra=extra) return True def ex_view_zone(self, domain, name_server): """ View zone file from a name server :param domain: Domain name. :type domain: ``str`` :param name_server: Name server to check. (1, 2 or 3) :type name_server: ``int`` :rtype: ``str`` For more info, please see: https://www.worldwidedns.net/dns_api_protocol_viewzone.asp or https://www.worldwidedns.net/dns_api_protocol_viewzone_reseller.asp """ params = {'DOMAIN': domain, 'NS': name_server} action = '/api_dns_viewzone.asp' if self.reseller_id is not None: action = '/api_dns_viewzone_reseller.asp' response = self.connection.request(action, params=params) return response.object def ex_transfer_domain(self, domain, user_id): """ This command will allow you, if you are a reseller, to change the userid on a domain name to another userid in your account ONLY if that new userid is already created. :param domain: Domain name. :type domain: ``str`` :param user_id: The new userid to connect to the domain name. :type user_id: ``str`` :rtype: ``bool`` For more info, please see: https://www.worldwidedns.net/dns_api_protocol_transfer.asp """ if self.reseller_id is None: raise WorldWideDNSError("This is not a reseller account", driver=self) params = {'DOMAIN': domain, 'NEW_ID': user_id} response = self.connection.request('/api_dns_transfer.asp', params=params) return response.success() def _get_available_record_entry(self, zone): """Return an available entry to store a record.""" entries = zone.extra for entry in range(1, MAX_RECORD_ENTRIES + 1): subdomain = entries.get('S%s' % entry) _type = entries.get('T%s' % entry) data = entries.get('D%s' % entry) if not any([subdomain, _type, data]): return entry return None def _to_zones(self, data): domain_list = re.split('\r?\n', data) zones = [] for line in domain_list: zone = self._to_zone(line) zones.append(zone) return zones def _to_zone(self, line): data = line.split('\x1f') name = data[0] if data[1] == "P": type = "master" domain_data = self._get_domain_data(name) resp_lines = re.split('\r?\n', domain_data.body) soa_block = resp_lines[:6] zone_data = resp_lines[6:] extra = {'HOSTMASTER': soa_block[0], 'REFRESH': soa_block[1], 'RETRY': soa_block[2], 'EXPIRE': soa_block[3], 'SECURE': soa_block[5]} ttl = soa_block[4] for line in range(MAX_RECORD_ENTRIES): line_data = zone_data[line].split('\x1f') extra['S%s' % (line + 1)] = line_data[0] _type = line_data[1] extra['T%s' % (line + 1)] = _type if _type != 'NONE' else '' try: extra['D%s' % (line + 1)] = line_data[2] except IndexError: extra['D%s' % (line + 1)] = '' elif data[1] == 'S': type = 'slave' extra = {} ttl = 0 return Zone(id=name, domain=name, type=type, ttl=ttl, driver=self, extra=extra) def _get_domain_data(self, name): params = {'DOMAIN': name} data = self.connection.request('/api_dns_list_domain.asp', params=params) return data def _to_records(self, zone): records = [] for record_id in range(1, MAX_RECORD_ENTRIES + 1): subdomain = zone.extra['S%s' % (record_id)] type = zone.extra['T%s' % (record_id)] data = zone.extra['D%s' % (record_id)] if subdomain and type and data: record = self._to_record( record_id, subdomain, type, data, zone) records.append(record) return records def _to_record(self, _id, subdomain, type, data, zone): return Record(id=_id, name=subdomain, type=type, data=data, zone=zone, driver=zone.driver) apache-libcloud-2.8.0/libcloud/dns/drivers/zerigo.py0000664000175000017500000004353013535474530022351 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'ZerigoDNSDriver' ] import copy import base64 from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.utils.py3 import ET from libcloud.utils.misc import merge_valid_keys, get_new_obj from libcloud.utils.xml import findtext, findall from libcloud.common.base import XmlResponse, ConnectionUserAndKey from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.common.types import MalformedResponseError from libcloud.dns.types import Provider, RecordType from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError from libcloud.dns.base import DNSDriver, Zone, Record API_HOST = 'ns.zerigo.com' API_VERSION = '1.1' API_ROOT = '/api/%s/' % (API_VERSION) VALID_ZONE_EXTRA_PARAMS = ['notes', 'tag-list', 'ns1', 'slave-nameservers'] VALID_RECORD_EXTRA_PARAMS = ['notes', 'ttl', 'priority'] # Number of items per page (maximum limit is 1000) ITEMS_PER_PAGE = 100 class ZerigoError(LibcloudError): def __init__(self, code, errors): self.code = code self.errors = errors or [] def __str__(self): return 'Errors: %s' % (', '.join(self.errors)) def __repr__(self): return ('' % ( self.code, len(self.errors))) class ZerigoDNSResponse(XmlResponse): def success(self): return self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def parse_error(self): status = int(self.status) if status == 401: if not self.body: raise InvalidCredsError(str(self.status) + ': ' + self.error) else: raise InvalidCredsError(self.body) elif status == 404: context = self.connection.context if context['resource'] == 'zone': raise ZoneDoesNotExistError(value='', driver=self, zone_id=context['id']) elif context['resource'] == 'record': raise RecordDoesNotExistError(value='', driver=self, record_id=context['id']) elif status != 503: try: body = ET.XML(self.body) except Exception: raise MalformedResponseError('Failed to parse XML', body=self.body) errors = [] for error in findall(element=body, xpath='error'): errors.append(error.text) raise ZerigoError(code=status, errors=errors) return self.body class ZerigoDNSConnection(ConnectionUserAndKey): host = API_HOST secure = True responseCls = ZerigoDNSResponse def add_default_headers(self, headers): auth_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (auth_b64.decode('utf-8')) return headers def request(self, action, params=None, data='', headers=None, method='GET'): if not headers: headers = {} if not params: params = {} if method in ("POST", "PUT"): headers = {'Content-Type': 'application/xml; charset=UTF-8'} return super(ZerigoDNSConnection, self).request(action=action, params=params, data=data, method=method, headers=headers) class ZerigoDNSDriver(DNSDriver): type = Provider.ZERIGO name = 'Zerigo DNS' website = 'http://www.zerigo.com/' connectionCls = ZerigoDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.AAAA: 'AAAA', RecordType.CNAME: 'CNAME', RecordType.GEO: 'GEO', RecordType.MX: 'MX', RecordType.NAPTR: 'NAPTR', RecordType.NS: 'NS', RecordType.PTR: 'PTR', RecordType.REDIRECT: 'REDIRECT', RecordType.SPF: 'SPF', RecordType.SRV: 'SRV', RecordType.TXT: 'TXT', RecordType.URL: 'URL', } def iterate_zones(self): return self._get_more('zones') def iterate_records(self, zone): return self._get_more('records', zone=zone) def get_zone(self, zone_id): path = API_ROOT + 'zones/%s.xml' % (zone_id) self.connection.set_context({'resource': 'zone', 'id': zone_id}) data = self.connection.request(path).object zone = self._to_zone(elem=data) return zone def get_record(self, zone_id, record_id): zone = self.get_zone(zone_id=zone_id) self.connection.set_context({'resource': 'record', 'id': record_id}) path = API_ROOT + 'hosts/%s.xml' % (record_id) data = self.connection.request(path).object record = self._to_record(elem=data, zone=zone) return record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. Provider API docs: https://www.zerigo.com/docs/apis/dns/1.1/zones/create @inherits: :class:`DNSDriver.create_zone` """ path = API_ROOT + 'zones.xml' zone_elem = self._to_zone_elem(domain=domain, type=type, ttl=ttl, extra=extra) data = self.connection.request(action=path, data=ET.tostring(zone_elem), method='POST').object zone = self._to_zone(elem=data) return zone def update_zone(self, zone, domain=None, type=None, ttl=None, extra=None): """ Update an existing zone. Provider API docs: https://www.zerigo.com/docs/apis/dns/1.1/zones/update @inherits: :class:`DNSDriver.update_zone` """ if domain: raise LibcloudError('Domain cannot be changed', driver=self) path = API_ROOT + 'zones/%s.xml' % (zone.id) zone_elem = self._to_zone_elem(domain=domain, type=type, ttl=ttl, extra=extra) response = self.connection.request(action=path, data=ET.tostring(zone_elem), method='PUT') assert response.status == httplib.OK merged = merge_valid_keys(params=copy.deepcopy(zone.extra), valid_keys=VALID_ZONE_EXTRA_PARAMS, extra=extra) updated_zone = get_new_obj(obj=zone, klass=Zone, attributes={'type': type, 'ttl': ttl, 'extra': merged}) return updated_zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. Provider API docs: https://www.zerigo.com/docs/apis/dns/1.1/hosts/create @inherits: :class:`DNSDriver.create_record` """ path = API_ROOT + 'zones/%s/hosts.xml' % (zone.id) record_elem = self._to_record_elem(name=name, type=type, data=data, extra=extra) response = self.connection.request(action=path, data=ET.tostring(record_elem), method='POST') assert response.status == httplib.CREATED record = self._to_record(elem=response.object, zone=zone) return record def update_record(self, record, name=None, type=None, data=None, extra=None): path = API_ROOT + 'hosts/%s.xml' % (record.id) record_elem = self._to_record_elem(name=name, type=type, data=data, extra=extra) response = self.connection.request(action=path, data=ET.tostring(record_elem), method='PUT') assert response.status == httplib.OK merged = merge_valid_keys(params=copy.deepcopy(record.extra), valid_keys=VALID_RECORD_EXTRA_PARAMS, extra=extra) updated_record = get_new_obj(obj=record, klass=Record, attributes={'type': type, 'data': data, 'extra': merged}) return updated_record def delete_zone(self, zone): path = API_ROOT + 'zones/%s.xml' % (zone.id) self.connection.set_context({'resource': 'zone', 'id': zone.id}) response = self.connection.request(action=path, method='DELETE') return response.status == httplib.OK def delete_record(self, record): path = API_ROOT + 'hosts/%s.xml' % (record.id) self.connection.set_context({'resource': 'record', 'id': record.id}) response = self.connection.request(action=path, method='DELETE') return response.status == httplib.OK def ex_get_zone_by_domain(self, domain): """ Retrieve a zone object by the domain name. :param domain: The domain which should be used :type domain: ``str`` :rtype: :class:`Zone` """ path = API_ROOT + 'zones/%s.xml' % (domain) self.connection.set_context({'resource': 'zone', 'id': domain}) data = self.connection.request(path).object zone = self._to_zone(elem=data) return zone def ex_force_slave_axfr(self, zone): """ Force a zone transfer. :param zone: Zone which should be used. :type zone: :class:`Zone` :rtype: :class:`Zone` """ path = API_ROOT + 'zones/%s/force_slave_axfr.xml' % (zone.id) self.connection.set_context({'resource': 'zone', 'id': zone.id}) response = self.connection.request(path, method='POST') assert response.status == httplib.ACCEPTED return zone def _to_zone_elem(self, domain=None, type=None, ttl=None, extra=None): zone_elem = ET.Element('zone', {}) if domain: domain_elem = ET.SubElement(zone_elem, 'domain') domain_elem.text = domain if type: ns_type_elem = ET.SubElement(zone_elem, 'ns-type') if type == 'master': ns_type_elem.text = 'pri_sec' elif type == 'slave': if not extra or 'ns1' not in extra: raise LibcloudError('ns1 extra attribute is required ' + 'when zone type is slave', driver=self) ns_type_elem.text = 'sec' ns1_elem = ET.SubElement(zone_elem, 'ns1') ns1_elem.text = extra['ns1'] elif type == 'std_master': # TODO: Each driver should provide supported zone types # Slave name servers are elsewhere if not extra or 'slave-nameservers' not in extra: raise LibcloudError('slave-nameservers extra ' + 'attribute is required whenzone ' + 'type is std_master', driver=self) ns_type_elem.text = 'pri' slave_nameservers_elem = ET.SubElement(zone_elem, 'slave-nameservers') slave_nameservers_elem.text = extra['slave-nameservers'] if ttl: default_ttl_elem = ET.SubElement(zone_elem, 'default-ttl') default_ttl_elem.text = str(ttl) if extra and 'tag-list' in extra: tags = extra['tag-list'] tags_elem = ET.SubElement(zone_elem, 'tag-list') tags_elem.text = ' '.join(tags) return zone_elem def _to_record_elem(self, name=None, type=None, data=None, extra=None): record_elem = ET.Element('host', {}) if name: name_elem = ET.SubElement(record_elem, 'hostname') name_elem.text = name if type is not None: type_elem = ET.SubElement(record_elem, 'host-type') type_elem.text = self.RECORD_TYPE_MAP[type] if data: data_elem = ET.SubElement(record_elem, 'data') data_elem.text = data if extra: if 'ttl' in extra: ttl_elem = ET.SubElement(record_elem, 'ttl', {'type': 'integer'}) ttl_elem.text = str(extra['ttl']) if 'priority' in extra: # Only MX and SRV records support priority priority_elem = ET.SubElement(record_elem, 'priority', {'type': 'integer'}) priority_elem.text = str(extra['priority']) if 'notes' in extra: notes_elem = ET.SubElement(record_elem, 'notes') notes_elem.text = extra['notes'] return record_elem def _to_zones(self, elem): zones = [] for item in findall(element=elem, xpath='zone'): zone = self._to_zone(elem=item) zones.append(zone) return zones def _to_zone(self, elem): id = findtext(element=elem, xpath='id') domain = findtext(element=elem, xpath='domain') type = findtext(element=elem, xpath='ns-type') type = 'master' if type.find('pri') == 0 else 'slave' ttl = findtext(element=elem, xpath='default-ttl') hostmaster = findtext(element=elem, xpath='hostmaster') custom_ns = findtext(element=elem, xpath='custom-ns') custom_nameservers = findtext(element=elem, xpath='custom-nameservers') notes = findtext(element=elem, xpath='notes') nx_ttl = findtext(element=elem, xpath='nx-ttl') slave_nameservers = findtext(element=elem, xpath='slave-nameservers') tags = findtext(element=elem, xpath='tag-list') tags = tags.split(' ') if tags else [] extra = {'hostmaster': hostmaster, 'custom-ns': custom_ns, 'custom-nameservers': custom_nameservers, 'notes': notes, 'nx-ttl': nx_ttl, 'slave-nameservers': slave_nameservers, 'tags': tags} zone = Zone(id=str(id), domain=domain, type=type, ttl=int(ttl), driver=self, extra=extra) return zone def _to_records(self, elem, zone): records = [] for item in findall(element=elem, xpath='host'): record = self._to_record(elem=item, zone=zone) records.append(record) return records def _to_record(self, elem, zone): id = findtext(element=elem, xpath='id') name = findtext(element=elem, xpath='hostname') type = findtext(element=elem, xpath='host-type') type = self._string_to_record_type(type) data = findtext(element=elem, xpath='data') notes = findtext(element=elem, xpath='notes', no_text_value=None) state = findtext(element=elem, xpath='state', no_text_value=None) fqdn = findtext(element=elem, xpath='fqdn', no_text_value=None) priority = findtext(element=elem, xpath='priority', no_text_value=None) ttl = findtext(element=elem, xpath='ttl', no_text_value=None) if not name: name = None if ttl: ttl = int(ttl) extra = {'notes': notes, 'state': state, 'fqdn': fqdn, 'priority': priority, 'ttl': ttl} record = Record(id=id, name=name, type=type, data=data, zone=zone, driver=self, ttl=ttl, extra=extra) return record def _get_more(self, rtype, **kwargs): exhausted = False last_key = None while not exhausted: items, last_key, exhausted = self._get_data(rtype, last_key, **kwargs) for item in items: yield item def _get_data(self, rtype, last_key, **kwargs): # Note: last_key in this case really is a "last_page". # TODO: Update base driver and change last_key to something more # generic - e.g. marker params = {} params['per_page'] = ITEMS_PER_PAGE params['page'] = last_key + 1 if last_key else 1 if rtype == 'zones': path = API_ROOT + 'zones.xml' response = self.connection.request(path) transform_func = self._to_zones elif rtype == 'records': zone = kwargs['zone'] path = API_ROOT + 'zones/%s/hosts.xml' % (zone.id) self.connection.set_context({'resource': 'zone', 'id': zone.id}) response = self.connection.request(path, params=params) transform_func = self._to_records exhausted = False result_count = int(response.headers.get('x-query-count', 0)) if (params['page'] * ITEMS_PER_PAGE) >= result_count: exhausted = True if response.status == httplib.OK: items = transform_func(elem=response.object, **kwargs) return items, params['page'], exhausted else: return [], None, True apache-libcloud-2.8.0/libcloud/dns/drivers/zonomi.py0000664000175000017500000002564413570310635022365 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License.You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Zonomi DNS Driver """ from libcloud.common.zonomi import ZonomiConnection, ZonomiResponse from libcloud.common.zonomi import ZonomiException from libcloud.dns.base import DNSDriver, Zone, Record from libcloud.dns.types import ZoneDoesNotExistError, ZoneAlreadyExistsError from libcloud.dns.types import RecordAlreadyExistsError from libcloud.dns.types import RecordDoesNotExistError from libcloud.dns.types import Provider, RecordType __all__ = [ 'ZonomiDNSDriver', ] class ZonomiDNSResponse(ZonomiResponse): pass class ZonomiDNSConnection(ZonomiConnection): responseCls = ZonomiDNSResponse class ZonomiDNSDriver(DNSDriver): type = Provider.ZONOMI name = 'Zonomi DNS' website = 'https://zonomi.com' connectionCls = ZonomiDNSConnection RECORD_TYPE_MAP = { RecordType.A: 'A', RecordType.MX: 'MX', RecordType.TXT: 'TXT' } def list_zones(self): """ Return a list of zones. :return: ``list`` of :class:`Zone` """ action = '/app/dns/dyndns.jsp?' params = {'action': 'QUERYZONES', 'api_key': self.key} response = self.connection.request(action=action, params=params) zones = self._to_zones(response.objects) return zones def list_records(self, zone): """ Return a list of records for the provided zone. :param zone: Zone to list records for. :type zone: :class:`Zone` :return: ``list`` of :class:`Record` """ action = '/app/dns/dyndns.jsp?' params = {'action': 'QUERY', 'name': '**.' + zone.id} try: response = self.connection.request(action=action, params=params) except ZonomiException as e: if e.code == '404': raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e records = self._to_records(response.objects, zone) return records def get_zone(self, zone_id): """ Return a Zone instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :rtype: :class:`Zone` """ zone = None zones = self.list_zones() for z in zones: if z.id == zone_id: zone = z if zone is None: raise ZoneDoesNotExistError(zone_id=zone_id, driver=self, value='') return zone def get_record(self, zone_id, record_id): """ Return a Record instance. :param zone_id: ID of the required zone :type zone_id: ``str`` :param record_id: ID of the required record :type record_id: ``str`` :rtype: :class:`Record` """ record = None zone = self.get_zone(zone_id=zone_id) records = self.list_records(zone=zone) for r in records: if r.id == record_id: record = r if record is None: raise RecordDoesNotExistError(record_id=record_id, driver=self, value='') return record def create_zone(self, domain, type='master', ttl=None, extra=None): """ Create a new zone. :param zone_id: Zone domain name (e.g. example.com) :type zone_id: ``str`` :rtype: :class:`Zone` """ action = '/app/dns/addzone.jsp?' params = {'name': domain} try: self.connection.request(action=action, params=params) except ZonomiException as e: if e.message == 'ERROR: This zone is already in your zone list.': raise ZoneAlreadyExistsError(zone_id=domain, driver=self, value=e.message) raise e zone = Zone(id=domain, domain=domain, type='master', ttl=ttl, driver=self, extra=extra) return zone def create_record(self, name, zone, type, data, extra=None): """ Create a new record. :param name: Record name without the domain name (e.g. www). Note: If you want to create a record for a base domain name, you should specify empty string ('') for this argument. :type name: ``str`` :param zone: Zone where the requested record is created. :type zone: :class:`Zone` :param type: DNS record type (A, MX, TXT). :type type: :class:`RecordType` :param data: Data for the record (depends on the record type). :type data: ``str`` :param extra: Extra attributes (driver specific, e.g. 'prio' or 'ttl'). (optional) :type extra: ``dict`` :rtype: :class:`Record` """ action = '/app/dns/dyndns.jsp?' if name: record_name = name + '.' + zone.domain else: record_name = zone.domain params = {'action': 'SET', 'name': record_name, 'value': data, 'type': type} if type == 'MX' and extra is not None: params['prio'] = extra.get('prio') try: response = self.connection.request(action=action, params=params) except ZonomiException as e: if ('ERROR: No zone found for %s' % record_name) in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e # we determine if an A or MX record already exists # by looking at the response.If the key 'skipped' is present in the # response, it means record already exists. If this is True, # then raise RecordAlreadyExistsError if len(response.objects) != 0 and \ response.objects[0].get('skipped') == 'unchanged': raise RecordAlreadyExistsError(record_id=name, driver=self, value='') if 'DELETED' in response.objects: for el in response.objects[:2]: if el.get('content') == data: response.objects = [el] records = self._to_records(response.objects, zone=zone) return records[0] def delete_zone(self, zone): """ Delete a zone. Note: This will delete all the records belonging to this zone. :param zone: Zone to delete. :type zone: :class:`Zone` :rtype: ``bool`` """ action = '/app/dns/dyndns.jsp?' params = {'action': 'DELETEZONE', 'name': zone.id} try: response = self.connection.request(action=action, params=params) except ZonomiException as e: if e.code == '404': raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) raise e return 'DELETED' in response.objects def delete_record(self, record): """ Use this method to delete a record. :param record: record to delete :type record: `Record` :rtype: Bool """ action = '/app/dns/dyndns.jsp?' params = {'action': 'DELETE', 'name': record.name, 'type': record.type} try: response = self.connection.request(action=action, params=params) except ZonomiException as e: if e.message == 'Record not deleted.': raise RecordDoesNotExistError(record_id=record.id, driver=self, value=e.message) raise e return 'DELETED' in response.objects def ex_convert_to_secondary(self, zone, master): """ Convert existent zone to slave. :param zone: Zone to convert. :type zone: :class:`Zone` :param master: the specified master name server IP address. :type master: ``str`` :rtype: Bool """ action = '/app/dns/converttosecondary.jsp?' params = {'name': zone.domain, 'master': master} try: self.connection.request(action=action, params=params) except ZonomiException as e: if 'ERROR: Could not find' in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) return True def ex_convert_to_master(self, zone): """ Convert existent zone to master. :param zone: Zone to convert. :type zone: :class:`Zone` :rtype: Bool """ action = '/app/dns/converttomaster.jsp?' params = {'name': zone.domain} try: self.connection.request(action=action, params=params) except ZonomiException as e: if 'ERROR: Could not find' in e.message: raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message) return True def _to_zone(self, item): if item['type'] == 'NATIVE': type = 'master' elif item['type'] == 'SLAVE': type = 'slave' zone = Zone(id=item['name'], domain=item['name'], type=type, driver=self, extra={}, ttl=None) return zone def _to_zones(self, items): zones = [] for item in items: zones.append(self._to_zone(item)) return zones def _to_record(self, item, zone): if len(item.get('ttl')) > 0: ttl = item.get('ttl').split(' ')[0] else: ttl = None extra = {'ttl': ttl, 'prio': item.get('prio')} if len(item['name']) > len(zone.domain): full_domain = item['name'] index = full_domain.index('.' + zone.domain) record_name = full_domain[:index] else: record_name = zone.domain record = Record(id=record_name, name=record_name, data=item['content'], type=item['type'], zone=zone, driver=self, ttl=ttl, extra=extra) return record def _to_records(self, items, zone): records = [] for item in items: records.append(self._to_record(item, zone)) return records apache-libcloud-2.8.0/libcloud/dns/providers.py0000664000175000017500000000761313576514553021420 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.dns.types import Provider from libcloud.dns.types import OLD_CONSTANT_TO_NEW_MAPPING from libcloud.common.providers import get_driver as _get_provider_driver from libcloud.common.providers import set_driver as _set_provider_driver __all__ = [ 'DRIVERS', 'get_driver', 'set_driver' ] DRIVERS = { Provider.DUMMY: ('libcloud.dns.drivers.dummy', 'DummyDNSDriver'), Provider.LINODE: ('libcloud.dns.drivers.linode', 'LinodeDNSDriver'), Provider.ZERIGO: ('libcloud.dns.drivers.zerigo', 'ZerigoDNSDriver'), Provider.RACKSPACE: ('libcloud.dns.drivers.rackspace', 'RackspaceDNSDriver'), Provider.HOSTVIRTUAL: ('libcloud.dns.drivers.hostvirtual', 'HostVirtualDNSDriver'), Provider.ROUTE53: ('libcloud.dns.drivers.route53', 'Route53DNSDriver'), Provider.GANDI: ('libcloud.dns.drivers.gandi', 'GandiDNSDriver'), Provider.GANDI_LIVE: ('libcloud.dns.drivers.gandi_live', 'GandiLiveDNSDriver'), Provider.GOOGLE: ('libcloud.dns.drivers.google', 'GoogleDNSDriver'), Provider.SOFTLAYER: ('libcloud.dns.drivers.softlayer', 'SoftLayerDNSDriver'), Provider.DIGITAL_OCEAN: ('libcloud.dns.drivers.digitalocean', 'DigitalOceanDNSDriver'), Provider.WORLDWIDEDNS: ('libcloud.dns.drivers.worldwidedns', 'WorldWideDNSDriver'), Provider.DNSIMPLE: ('libcloud.dns.drivers.dnsimple', 'DNSimpleDNSDriver'), Provider.POINTDNS: ('libcloud.dns.drivers.pointdns', 'PointDNSDriver'), Provider.VULTR: ('libcloud.dns.drivers.vultr', 'VultrDNSDriver'), Provider.LIQUIDWEB: ('libcloud.dns.drivers.liquidweb', 'LiquidWebDNSDriver'), Provider.ZONOMI: ('libcloud.dns.drivers.zonomi', 'ZonomiDNSDriver'), Provider.DURABLEDNS: ('libcloud.dns.drivers.durabledns', 'DurableDNSDriver'), Provider.AURORADNS: ('libcloud.dns.drivers.auroradns', 'AuroraDNSDriver'), Provider.GODADDY: ('libcloud.dns.drivers.godaddy', 'GoDaddyDNSDriver'), Provider.CLOUDFLARE: ('libcloud.dns.drivers.cloudflare', 'CloudFlareDNSDriver'), Provider.NFSN: ('libcloud.dns.drivers.nfsn', 'NFSNDNSDriver'), Provider.NSONE: ('libcloud.dns.drivers.nsone', 'NsOneDNSDriver'), Provider.LUADNS: ('libcloud.dns.drivers.luadns', 'LuadnsDNSDriver'), Provider.BUDDYNS: ('libcloud.dns.drivers.buddyns', 'BuddyNSDNSDriver'), Provider.POWERDNS: ('libcloud.dns.drivers.powerdns', 'PowerDNSDriver'), Provider.ONAPP: ('libcloud.dns.drivers.onapp', 'OnAppDNSDriver'), Provider.RCODEZERO: ('libcloud.dns.drivers.rcodezero', 'RcodeZeroDNSDriver'), # Deprecated Provider.RACKSPACE_US: ('libcloud.dns.drivers.rackspace', 'RackspaceUSDNSDriver'), Provider.RACKSPACE_UK: ('libcloud.dns.drivers.rackspace', 'RackspaceUKDNSDriver') } def get_driver(provider): deprecated_constants = OLD_CONSTANT_TO_NEW_MAPPING return _get_provider_driver(drivers=DRIVERS, provider=provider, deprecated_constants=deprecated_constants) def set_driver(provider, module, klass): return _set_provider_driver(drivers=DRIVERS, provider=provider, module=module, klass=klass) apache-libcloud-2.8.0/libcloud/dns/types.py0000664000175000017500000001000013576514553020527 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.types import LibcloudError __all__ = [ 'Provider', 'RecordType', 'ZoneError', 'ZoneDoesNotExistError', 'ZoneAlreadyExistsError', 'RecordError', 'RecordDoesNotExistError', 'RecordAlreadyExistsError', 'OLD_CONSTANT_TO_NEW_MAPPING' ] class Provider(object): """ Defines for each of the supported providers Non-Dummy drivers are sorted in alphabetical order. Please preserve this ordering when adding new drivers. """ DUMMY = 'dummy' AURORADNS = 'auroradns' BUDDYNS = 'buddyns' CLOUDFLARE = 'cloudflare' DIGITAL_OCEAN = 'digitalocean' DNSIMPLE = 'dnsimple' DURABLEDNS = 'durabledns' GANDI = 'gandi' GANDI_LIVE = 'gandi_live' GODADDY = 'godaddy' GOOGLE = 'google' HOSTVIRTUAL = 'hostvirtual' LINODE = 'linode' LIQUIDWEB = 'liquidweb' LUADNS = 'luadns' NFSN = 'nfsn' NSONE = 'nsone' ONAPP = 'onapp' POINTDNS = 'pointdns' POWERDNS = 'powerdns' RACKSPACE = 'rackspace' RCODEZERO = 'rcodezero' ROUTE53 = 'route53' SOFTLAYER = 'softlayer' VULTR = 'vultr' WORLDWIDEDNS = 'worldwidedns' ZERIGO = 'zerigo' ZONOMI = 'zonomi' DNSPOD = 'dnspod' # Deprecated RACKSPACE_US = 'rackspace_us' RACKSPACE_UK = 'rackspace_uk' OLD_CONSTANT_TO_NEW_MAPPING = { Provider.RACKSPACE_US: Provider.RACKSPACE, Provider.RACKSPACE_UK: Provider.RACKSPACE, } class RecordType(object): """ DNS record type. """ A = 'A' AAAA = 'AAAA' AFSDB = 'A' ALIAS = 'ALIAS' CERT = 'CERT' CNAME = 'CNAME' DNAME = 'DNAME' DNSKEY = 'DNSKEY' DS = 'DS' GEO = 'GEO' HINFO = 'HINFO' KEY = 'KEY' LOC = 'LOC' MX = 'MX' NAPTR = 'NAPTR' NS = 'NS' NSEC = 'NSEC' OPENPGPKEY = 'OPENPGPKEY' PTR = 'PTR' REDIRECT = 'REDIRECT' RP = 'RP' RRSIG = 'RRSIG' SOA = 'SOA' SPF = 'SPF' SRV = 'SRV' SSHFP = 'SSHFP' TLSA = 'TLSA' TXT = 'TXT' URL = 'URL' WKS = 'WKS' class ZoneError(LibcloudError): error_type = 'ZoneError' kwargs = ('zone_id', ) def __init__(self, value, driver, zone_id): self.zone_id = zone_id super(ZoneError, self).__init__(value=value, driver=driver) def __str__(self): return self.__repr__() def __repr__(self): return ('<%s in %s, zone_id=%s, value=%s>' % (self.error_type, repr(self.driver), self.zone_id, self.value)) class ZoneDoesNotExistError(ZoneError): error_type = 'ZoneDoesNotExistError' class ZoneAlreadyExistsError(ZoneError): error_type = 'ZoneAlreadyExistsError' class RecordError(LibcloudError): error_type = 'RecordError' def __init__(self, value, driver, record_id): self.record_id = record_id super(RecordError, self).__init__(value=value, driver=driver) def __str__(self): return self.__repr__() def __repr__(self): return ('<%s in %s, record_id=%s, value=%s>' % (self.error_type, repr(self.driver), self.record_id, self.value)) class RecordDoesNotExistError(RecordError): error_type = 'RecordDoesNotExistError' class RecordAlreadyExistsError(RecordError): error_type = 'RecordAlreadyExistsError' apache-libcloud-2.8.0/libcloud/http.py0000664000175000017500000002441413576514553017574 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Subclass for httplib.HTTPSConnection with optional certificate name verification, depending on libcloud.security settings. """ import os import warnings import requests from requests.adapters import HTTPAdapter from requests.packages.urllib3.poolmanager import PoolManager import libcloud.security from libcloud.utils.py3 import urlparse, PY3 __all__ = [ 'LibcloudBaseConnection', 'LibcloudConnection' ] ALLOW_REDIRECTS = 1 HTTP_PROXY_ENV_VARIABLE_NAME = 'http_proxy' HTTPS_PROXY_ENV_VARIABLE_NAME = 'https_proxy' class SignedHTTPSAdapter(HTTPAdapter): def __init__(self, cert_file, key_file): self.cert_file = cert_file self.key_file = key_file super(SignedHTTPSAdapter, self).__init__() def init_poolmanager(self, connections, maxsize, block=False): self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, cert_file=self.cert_file, key_file=self.key_file) class LibcloudBaseConnection(object): """ Base connection class to inherit from. Note: This class should not be instantiated directly. """ session = None proxy_scheme = None proxy_host = None proxy_port = None proxy_username = None proxy_password = None http_proxy_used = False ca_cert = None def __init__(self): self.session = requests.Session() def set_http_proxy(self, proxy_url): """ Set a HTTP proxy which will be used with this connection. :param proxy_url: Proxy URL (e.g. http://: without authentication and http://:@: for basic auth authentication information. :type proxy_url: ``str`` """ result = self._parse_proxy_url(proxy_url=proxy_url) scheme = result[0] host = result[1] port = result[2] username = result[3] password = result[4] self.proxy_scheme = scheme self.proxy_host = host self.proxy_port = port self.proxy_username = username self.proxy_password = password self.http_proxy_used = True self.session.proxies = { 'http': proxy_url, 'https': proxy_url, } def _parse_proxy_url(self, proxy_url): """ Parse and validate a proxy URL. :param proxy_url: Proxy URL (e.g. http://hostname:3128) :type proxy_url: ``str`` :rtype: ``tuple`` (``scheme``, ``hostname``, ``port``) """ parsed = urlparse.urlparse(proxy_url) if parsed.scheme not in ('http', 'https'): raise ValueError('Only http and https proxies are supported') if not parsed.hostname or not parsed.port: raise ValueError('proxy_url must be in the following format: ' '://:') proxy_scheme = parsed.scheme proxy_host, proxy_port = parsed.hostname, parsed.port netloc = parsed.netloc if '@' in netloc: username_password = netloc.split('@', 1)[0] split = username_password.split(':', 1) if len(split) < 2: raise ValueError('URL is in an invalid format') proxy_username, proxy_password = split[0], split[1] else: proxy_username = None proxy_password = None return (proxy_scheme, proxy_host, proxy_port, proxy_username, proxy_password) def _setup_verify(self): self.verify = libcloud.security.VERIFY_SSL_CERT def _setup_ca_cert(self, **kwargs): # simulating keyword-only argument in Python 2 ca_certs_path = kwargs.get('ca_cert', libcloud.security.CA_CERTS_PATH) if self.verify is False: pass else: if isinstance(ca_certs_path, list): msg = ( 'Providing a list of CA trusts is no longer supported ' 'since libcloud 2.0. Using the first element in the list. ' 'See http://libcloud.readthedocs.io/en/latest/other/' 'changes_in_2_0.html#providing-a-list-of-ca-trusts-is-no-' 'longer-supported') warnings.warn(msg, DeprecationWarning) self.ca_cert = ca_certs_path[0] else: self.ca_cert = ca_certs_path def _setup_signing(self, cert_file=None, key_file=None): """ Setup request signing by mounting a signing adapter to the session """ self.session.mount('https://', SignedHTTPSAdapter(cert_file, key_file)) class LibcloudConnection(LibcloudBaseConnection): timeout = None host = None response = None def __init__(self, host, port, secure=None, **kwargs): scheme = 'https' if secure is not None and secure else 'http' self.host = '{0}://{1}{2}'.format( 'https' if port == 443 else scheme, host, ":{0}".format(port) if port not in (80, 443) else "" ) # Support for HTTP(s) proxy # NOTE: We always only use a single proxy (either HTTP or HTTPS) https_proxy_url_env = os.environ.get(HTTPS_PROXY_ENV_VARIABLE_NAME, None) http_proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, https_proxy_url_env) # Connection argument rgument has precedence over environment variables proxy_url = kwargs.pop('proxy_url', http_proxy_url_env) self._setup_verify() self._setup_ca_cert() LibcloudBaseConnection.__init__(self) if 'cert_file' in kwargs or 'key_file' in kwargs: self._setup_signing(**kwargs) if proxy_url: self.set_http_proxy(proxy_url=proxy_url) self.session.timeout = kwargs.get('timeout', 60) @property def verification(self): """ The option for SSL verification given to underlying requests """ return self.ca_cert if self.ca_cert is not None else self.verify def request(self, method, url, body=None, headers=None, raw=False, stream=False): url = urlparse.urljoin(self.host, url) headers = self._normalize_headers(headers=headers) self.response = self.session.request( method=method.lower(), url=url, data=body, headers=headers, allow_redirects=ALLOW_REDIRECTS, stream=stream, verify=self.verification ) def prepared_request(self, method, url, body=None, headers=None, raw=False, stream=False): headers = self._normalize_headers(headers=headers) req = requests.Request(method, ''.join([self.host, url]), data=body, headers=headers) prepped = self.session.prepare_request(req) prepped.body = body self.response = self.session.send( prepped, stream=stream, verify=self.ca_cert if self.ca_cert is not None else self.verify) def getresponse(self): return self.response def getheaders(self): # urlib decoded response body, libcloud has a bug # and will not check if content is gzipped, so let's # remove headers indicating compressed content. if 'content-encoding' in self.response.headers: del self.response.headers['content-encoding'] return self.response.headers @property def status(self): return self.response.status_code @property def reason(self): return None if self.response.status_code > 400 else self.response.text def connect(self): # pragma: no cover pass def read(self): return self.response.content def close(self): # pragma: no cover # return connection back to pool self.response.close() def _normalize_headers(self, headers): headers = headers or {} # all headers should be strings for key, value in headers.items(): if isinstance(value, (int, float)): headers[key] = str(value) return headers class HttpLibResponseProxy(object): """ Provides a proxy pattern around the :class:`requests.Reponse` object to a :class:`httplib.HTTPResponse` object """ def __init__(self, response): self._response = response def read(self, amt=None): return self._response.text def getheader(self, name, default=None): """ Get the contents of the header name, or default if there is no matching header. """ if name in self._response.headers.keys(): return self._response.headers[name] else: return default def getheaders(self): """ Return a list of (header, value) tuples. """ if PY3: return list(self._response.headers.items()) else: return self._response.headers.items() @property def status(self): return self._response.status_code @property def reason(self): return self._response.reason @property def version(self): # requests doesn't expose this return '11' @property def body(self): # NOTE: We use property to avoid saving whole response body into RAM # See https://github.com/apache/libcloud/pull/1132 for details return self._response.content apache-libcloud-2.8.0/libcloud/loadbalancer/0000775000175000017500000000000013600223624020625 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/loadbalancer/__init__.py0000664000175000017500000000160413535474530022752 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Module for working with Load Balancers """ __all__ = [ 'base', 'providers', 'types', 'drivers' ] apache-libcloud-2.8.0/libcloud/loadbalancer/base.py0000664000175000017500000002465113535474530022134 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.base import ConnectionKey, BaseDriver from libcloud.common.types import LibcloudError __all__ = [ 'Member', 'LoadBalancer', 'Algorithm', 'Driver', 'DEFAULT_ALGORITHM' ] class Member(object): """ Represents a load balancer member. """ def __init__(self, id, ip, port, balancer=None, extra=None): """ :param id: Member ID. :type id: ``str`` :param ip: IP address of this member. :param ip: ``str`` :param port: Port of this member :param port: ``str`` :param balancer: Balancer this member is attached to. (optional) :param balancer: :class:`.LoadBalancer` :param extra: Provider specific attributes. :type extra: ``dict`` """ self.id = str(id) if id else None self.ip = ip self.port = port self.balancer = balancer self.extra = extra or {} def __repr__(self): return ('' % (self.id, self.ip, self.port)) class LoadBalancer(object): """ Provide a common interface for handling Load Balancers. """ def __init__(self, id, name, state, ip, port, driver, extra=None): """ :param id: Load balancer ID. :type id: ``str`` :param name: Load balancer name. :type name: ``str`` :param state: State this loadbalancer is in. :type state: :class:`libcloud.loadbalancer.types.State` :param ip: IP address of this loadbalancer. :type ip: ``str`` :param port: Port of this loadbalancer. :type port: ``int`` :param driver: Driver this loadbalancer belongs to. :type driver: :class:`.Driver` :param extra: Provider specific attributes. (optional) :type extra: ``dict`` """ self.id = str(id) if id else None self.name = name self.state = state self.ip = ip self.port = port self.driver = driver self.extra = extra or {} def attach_compute_node(self, node): return self.driver.balancer_attach_compute_node(balancer=self, node=node) def attach_member(self, member): return self.driver.balancer_attach_member(balancer=self, member=member) def detach_member(self, member): return self.driver.balancer_detach_member(balancer=self, member=member) def list_members(self): return self.driver.balancer_list_members(balancer=self) def destroy(self): return self.driver.destroy_balancer(balancer=self) def __repr__(self): return ('' % (self.id, self.name, self.state, self.ip, self.port)) class Algorithm(object): """ Represents a load balancing algorithm. """ RANDOM = 0 ROUND_ROBIN = 1 LEAST_CONNECTIONS = 2 WEIGHTED_ROUND_ROBIN = 3 WEIGHTED_LEAST_CONNECTIONS = 4 SHORTEST_RESPONSE = 5 PERSISTENT_IP = 6 LEAST_CONNECTIONS_MEMBER = 7 LEAST_CONNECTIONS_NODE = 8 OBSERVED_MEMBER = 9 OBSERVED_NODE = 10 PREDICTIVE_MEMBER = 11 PREDICTIVE_NODE = 12 DEFAULT_ALGORITHM = Algorithm.ROUND_ROBIN class Driver(BaseDriver): """ A base Driver class to derive from This class is always subclassed by a specific driver. """ name = None website = None connectionCls = ConnectionKey _ALGORITHM_TO_VALUE_MAP = {} _VALUE_TO_ALGORITHM_MAP = {} def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs): super(Driver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def list_protocols(self): """ Return a list of supported protocols. :rtype: ``list`` of ``str`` """ raise NotImplementedError( 'list_protocols not implemented for this driver') def list_balancers(self): """ List all loadbalancers :rtype: ``list`` of :class:`LoadBalancer` """ raise NotImplementedError( 'list_balancers not implemented for this driver') def create_balancer(self, name, port, protocol, algorithm, members): """ Create a new load balancer instance :param name: Name of the new load balancer (required) :type name: ``str`` :param port: Port the load balancer should listen on, defaults to 80 :type port: ``str`` :param protocol: Loadbalancer protocol, defaults to http. :type protocol: ``str`` :param members: list of Members to attach to balancer :type members: ``list`` of :class:`Member` :param algorithm: Load balancing algorithm, defaults to ROUND_ROBIN. :type algorithm: :class:`.Algorithm` :rtype: :class:`LoadBalancer` """ raise NotImplementedError( 'create_balancer not implemented for this driver') def destroy_balancer(self, balancer): """ Destroy a load balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :return: ``True`` if the destroy was successful, otherwise ``False``. :rtype: ``bool`` """ raise NotImplementedError( 'destroy_balancer not implemented for this driver') def get_balancer(self, balancer_id): """ Return a :class:`LoadBalancer` object. :param balancer_id: id of a load balancer you want to fetch :type balancer_id: ``str`` :rtype: :class:`LoadBalancer` """ raise NotImplementedError( 'get_balancer not implemented for this driver') def update_balancer(self, balancer, **kwargs): """ Sets the name, algorithm, protocol, or port on a load balancer. :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param name: New load balancer name :type name: ``str`` :param algorithm: New load balancer algorithm :type algorithm: :class:`.Algorithm` :param protocol: New load balancer protocol :type protocol: ``str`` :param port: New load balancer port :type port: ``int`` :rtype: :class:`LoadBalancer` """ raise NotImplementedError( 'update_balancer not implemented for this driver') def balancer_attach_compute_node(self, balancer, node): """ Attach a compute node as a member to the load balancer. :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param node: Node to join to the balancer :type node: :class:`Node` :return: Member after joining the balancer. :rtype: :class:`Member` """ member = Member(id=None, ip=node.public_ips[0], port=balancer.port) return self.balancer_attach_member(balancer, member) def balancer_attach_member(self, balancer, member): """ Attach a member to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member to join to the balancer :type member: :class:`Member` :return: Member after joining the balancer. :rtype: :class:`Member` """ raise NotImplementedError( 'balancer_attach_member not implemented for this driver') def balancer_detach_member(self, balancer, member): """ Detach member from balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member which should be used :type member: :class:`Member` :return: ``True`` if member detach was successful, otherwise ``False``. :rtype: ``bool`` """ raise NotImplementedError( 'balancer_detach_member not implemented for this driver') def balancer_list_members(self, balancer): """ Return list of members attached to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :rtype: ``list`` of :class:`Member` """ raise NotImplementedError( 'balancer_list_members not implemented for this driver') def list_supported_algorithms(self): """ Return algorithms supported by this driver. :rtype: ``list`` of ``str`` """ return list(self._ALGORITHM_TO_VALUE_MAP.keys()) def _value_to_algorithm(self, value): """ Return :class:`.Algorithm` based on the value. :param value: Algorithm name (e.g. http, tcp, ...). :type value: ``str`` :rtype: :class:`.Algorithm` """ try: return self._VALUE_TO_ALGORITHM_MAP[value] except KeyError: raise LibcloudError(value='Invalid value: %s' % (value), driver=self) def _algorithm_to_value(self, algorithm): """ Return string value for the provided algorithm. :param value: Algorithm enum. :type value: :class:`Algorithm` :rtype: ``str`` """ try: return self._ALGORITHM_TO_VALUE_MAP[algorithm] except KeyError: raise LibcloudError(value='Invalid algorithm: %s' % (algorithm), driver=self) apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/0000775000175000017500000000000013600223624022303 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/__init__.py0000664000175000017500000000151013535474530024424 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'rackspace', 'gogrid', 'nttcis' ] apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/alb.py0000664000175000017500000011111013576514553023426 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'ApplicationLBDriver' ] from libcloud.utils.xml import findtext, findall from libcloud.loadbalancer.types import State from libcloud.loadbalancer.base import Driver, LoadBalancer, Member from libcloud.common.aws import AWSGenericResponse, SignedAWSConnection VERSION = '2015-12-01' HOST = 'elasticloadbalancing.%s.amazonaws.com' ROOT = '/%s/' % (VERSION) NS = 'http://elasticloadbalancing.amazonaws.com/doc/%s/' % (VERSION, ) class ALBResponse(AWSGenericResponse): """ Amazon ALB response class. """ namespace = NS exceptions = {} xpath = 'Error' class ALBConnection(SignedAWSConnection): version = VERSION host = HOST responseCls = ALBResponse service_name = 'elasticloadbalancing' class ALBTargetGroup(object): """ AWS ALB target group class http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html """ def __init__(self, target_group_id, name, protocol, port, vpc, driver, health_check_timeout=5, health_check_port="traffic-port", health_check_path="/", health_check_proto="HTTP", health_check_matcher="200", health_check_interval=30, healthy_threshold=5, unhealthy_threshold=2, balancers=[], members=[]): self.id = target_group_id self.name = name self.protocol = protocol self.port = port self.vpc = vpc self.health_check_timeout = health_check_timeout self.health_check_port = health_check_port self.health_check_path = health_check_path self.health_check_proto = health_check_proto self.health_check_matcher = health_check_matcher self.health_check_interval = health_check_interval self.healthy_threshold = healthy_threshold self.unhealthy_threshold = unhealthy_threshold self._balancers = balancers self._balancers_arns = [lb.id for lb in balancers] if balancers else [] self._members = members self._members_ids = [mb.id for mb in members] if members else [] self._driver = driver @property def balancers(self): if not self._balancers and self._balancers_arns: self._balancers = [] for balancer_arn in self._balancers_arns: self._balancers.append( self._driver.get_balancer(balancer_arn) ) return self._balancers @balancers.setter def balancers(self, val): self._balancers = val self._balancers_arns = [lb.id for lb in val] if val else [] @property def members(self): if not self._members: mbrs = self._driver._ex_get_target_group_members(self) self._members = mbrs self._members_ids = [mb.id for mb in mbrs] if mbrs else [] return self._members @members.setter def members(self, val): self._members = val self._members_ids = [mb.id for mb in val] if val else [] class ALBListener(object): """ AWS ALB listener class http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html """ def __init__(self, listener_id, protocol, port, balancer, driver, action="", ssl_policy="", ssl_certificate="", rules=[]): self.id = listener_id self.protocol = protocol self.port = port self.action = action self.ssl_policy = ssl_policy self.ssl_certificate = ssl_certificate self._balancer = balancer self._balancer_arn = balancer.id if balancer else None self._rules = rules self._driver = driver @property def balancer(self): if not self._balancer and self._balancer_arn: self._balancer = self._driver.get_balancer(self._balancer_arn) return self._balancer @balancer.setter def balancer(self, val): self._balancer = val self._balancer_arn = val.id @property def rules(self): if not self._rules: self._rules = self._driver._ex_get_rules_for_listener(self) return self._rules @rules.setter def rules(self, val): self._rules = val class ALBRule(object): """ AWS ALB listener rule class http://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#listener-rules """ def __init__(self, rule_id, is_default, priority, target_group, driver, conditions={}, listener=None): self.id = rule_id self.is_default = is_default self.priority = priority self.conditions = conditions self._listener = listener self._listener_arn = listener.id if listener else None self._target_group = target_group self._target_group_arn = target_group.id if target_group else None self._driver = driver @property def target_group(self): if not self._target_group and self._target_group_arn: self._target_group = self._driver.ex_get_target_group( self._target_group_arn ) return self._target_group @target_group.setter def target_group(self, val): self._target_group = val self._target_group_arn = val.id @property def listener(self): if not self._listener and self._listener_arn: self._listener = self.driver.ex_get_listener(self._listener_arn) return self._listener @listener.setter def listener(self, val): self._listener = val self._listener_arn = val.id class ApplicationLBDriver(Driver): name = 'Amazon Application Load Balancing' website = 'http://aws.amazon.com/elasticloadbalancing/' connectionCls = ALBConnection signature_version = '4' def __init__(self, access_id, secret, region, token=None): self.token = token self.region = region self.region_name = region super(ApplicationLBDriver, self).__init__( access_id, secret, token=token, host=HOST % region, region=region ) def list_protocols(self): """ Return list of protocols supported by driver :rtype: ``list`` of ``strings`` """ return ['http', 'https'] def list_balancers(self): """ List all load balancers :rtype: ``list`` of :class:`LoadBalancer` """ params = {'Action': 'DescribeLoadBalancers'} data = self.connection.request(ROOT, params=params).object return self._to_balancers(data) def get_balancer(self, balancer_id): """ Get a load balancer object by ARN :param balancer_id: ARN of load balancer you wish to fetch. :type balancer_id: ``str`` :rtype: :class:`LoadBalancer` """ params = { 'Action': 'DescribeLoadBalancers', 'LoadBalancerArns.member.1': balancer_id } data = self.connection.request(ROOT, params=params).object return self._to_balancers(data)[0] def create_balancer(self, name, port, protocol, algorithm, members, ex_scheme=None, ex_security_groups=None, ex_subnets=None, ex_tags=None, ex_ssl_cert_arn=None): """ Create a new load balancer instance. AWS ALB balancer creation consists of 5 steps: http://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/Welcome.html create_balancer() is a standard API method so, it's made as a wrapper here to preserve compatibility with other drivers where LB creation is one-step process. It calls respective ALB methods to assemble ready-to-use load balancer. :param name: Name of the new load balancer :type name: ``str`` :param port: Port number to setup load balancer listener :type port: ``int`` :param protocol: Load balancer protocol, should be 'HTTP' or 'HTTPS'. :type protocol: ``str`` :param algorithm: Load balancing algorithm. Ignored for AWS ALB. :type algorithm: :class:`Algorithm` or ``None`` :param members: List of Members to attach to the balancer. If 'port' attribute is set for the memeber - load balancer will send traffic there. Otherwise - load balancer port is used on the memeber's side. 'ip' attribute is ignored. :type members: ``list`` of :class:`Member` :param ex_scheme: Scheme of load balancer. Can be 'internet-facing' or 'internal'. :type ex_scheme: ``str`` :param ex_security_groups: List of load balancer security group ids. :type ex_security_groups: ``list`` of ``str`` :param ex_subnets: List of load balancer subnet ids. :type ex_subnets: ``list`` of ``str`` :param ex_tags: Tags to assign to the load balancer. :type ex_tags: ``dict`` :param ex_ssl_cert_arn: SSL certificate ARN to use when load balancer protocol is 'HTTPS'. :type ex_ssl_cert_arn: ``str`` :return: LoadBalancer object :rtype: :class:`LoadBalancer` """ ex_scheme = ex_scheme or "" ex_security_groups = ex_security_groups or [] ex_subnets = ex_subnets or [] ex_tags = ex_tags or {} ex_ssl_cert_arn = ex_ssl_cert_arn or "" balancer = self.ex_create_balancer(name, scheme=ex_scheme, security_groups=ex_security_groups, subnets=ex_subnets, tags=ex_tags) target_group = self.ex_create_target_group( name + "-tg", port, protocol, balancer.extra.get('vpc'), health_check_proto=protocol ) self.ex_register_targets(target_group, members) listener = self.ex_create_listener(balancer, port, protocol, target_group, ssl_cert_arn=ex_ssl_cert_arn) balancer.extra['listener'] = listener return balancer def ex_create_balancer(self, name, addr_type="ipv4", scheme="internet-facing", security_groups=None, subnets=None, tags=None): """ AWS-specific method to create a new load balancer. Since ALB is a composite object (load balancer, target group, listener etc) - extra methods must be called to assemble ready-to-use balancer. :param name: Name of the new load balancer :type name: ``str`` :param addr_type: Load balancer address type. Can be 'ipv4' or 'ipv6'. :type addr_type: ``str`` :param scheme: Scheme of load balancer. Can be 'internet-facing' or 'internal'. :type scheme: ``str`` :param security_groups: List of load balancer security group ids. :type security_groups: ``list`` of ``str`` :param subnets: List of load balancer subnet ids. :type subnets: ``list`` of ``str`` :param tags: Tags to assign to the load balancer. :type tags: ``dict`` :return: LoadBalancer object :rtype: :class:`LoadBalancer` """ security_groups = security_groups or [] subnets = subnets or [] tags = tags or {} # mandatory params params = { 'Action': 'CreateLoadBalancer', 'Name': name } idx = 0 for subnet in subnets: idx += 1 params['Subnets.member.' + str(idx)] = subnet # optional params params.update( { 'IpAddressType': addr_type, # Valid Values: ipv4 | dualstack 'Scheme': scheme # Valid Values: internet-facing | internal } ) idx = 0 for sg in security_groups: idx += 1 params['SecurityGroups.member.' + str(idx)] = sg idx = 0 for k, v in tags.items(): idx += 1 params['Tags.member.' + str(idx) + '.Key'] = k params['Tags.member.' + str(idx) + '.Value'] = v data = self.connection.request(ROOT, params=params).object xpath = 'CreateLoadBalancerResult/LoadBalancers/member' for el in findall(element=data, xpath=xpath, namespace=NS): balancer = self._to_balancer(el) return balancer def ex_create_target_group(self, name, port, proto, vpc, health_check_interval=30, health_check_path="/", health_check_port="traffic-port", health_check_proto="HTTP", health_check_timeout=5, health_check_matcher="200", healthy_threshold=5, unhealthy_threshold=2): """ Create a target group for AWS ALB load balancer. :param name: Name of target group :type name: ``str`` :param port: The port on which the targets receive traffic. This port is used unless you specify a port override when registering the target. :type port: ``int`` :param proto: The protocol to use for routing traffic to the targets. Can be 'HTTP' or 'HTTPS'. :type proto: ``str`` :param vpc: The identifier of the virtual private cloud (VPC). :type vpc: ``str`` :param health_check_interval: The approximate amount of time, in seconds, between health checks of an individual target. The default is 30 seconds. :type health_check_interval: ``int`` :param health_check_path: The ping path that is the destination on the targets for health checks. The default is / :type health_check_path: ``str`` :param health_check_port: The port the load balancer uses when performing health checks on targets. The default is traffic-port, which indicates the port on which each target receives traffic from the load balancer. :type health_check_port: ``str`` :param health_check_proto: The protocol the load balancer uses when performing health checks on targets. Can be 'HTTP' (default) or 'HTTPS'. :type health_check_proto: ``str`` :param health_check_timeout: The amount of time, in seconds, during which no response from a target means a failed health check. The default is 5s. :type health_check_timeout: ``int`` :param health_check_matcher: The HTTP codes to use when checking for a successful response from a target. Valid values: "200", "200,202", "200-299". :type health_check_matcher: ``str`` :param healthy_threshold: The number of consecutive health checks successes required before considering an unhealthy target healthy. The default is 5 :type healthy_threshold: ``int`` :param unhealthy_threshold: The number of consecutive health check failures required before considering a target unhealthy. The default is 2. :type unhealthy_threshold: ``int`` :return: Target group object. :rtype: :class:`ALBTargetGroup` """ # mandatory params params = { 'Action': 'CreateTargetGroup', 'Name': name, 'Protocol': proto, 'Port': port, 'VpcId': vpc } # optional params params.update( { # Valid Values: Min value of 5. Max value of 300. 'HealthCheckIntervalSeconds': health_check_interval, 'HealthCheckPath': health_check_path, 'HealthCheckPort': health_check_port, # Valid Values: HTTP | HTTPS 'HealthCheckProtocol': health_check_proto, # Valid Range: Min value of 2. Max value of 60. 'HealthCheckTimeoutSeconds': health_check_timeout, # Valid Range: Minimum value of 2. Maximum value of 10. 'HealthyThresholdCount': healthy_threshold, # Valid Range: Minimum value of 2. Maximum value of 10. 'UnhealthyThresholdCount': unhealthy_threshold, # Valid values: "200", "200,202", "200-299" 'Matcher.HttpCode': health_check_matcher } ) data = self.connection.request(ROOT, params=params).object xpath = 'CreateTargetGroupResult/TargetGroups/member' for el in findall(element=data, xpath=xpath, namespace=NS): target_group = self._to_target_group(el) return target_group def ex_register_targets(self, target_group, members=None): """ Register members as targets at target group :param target_group: Target group dict where register members. :type target_group: ``dict`` :param members: List of Members to attach to the balancer. If 'port' attribute is set for the memeber - load balancer will send traffic there. Otherwise - load balancer port is used on the memeber's side. 'ip' attribute is ignored. :type members: ``list`` of :class:`Member` :return: True on success, False if no members provided. :rtype: ``bool`` """ members = members or [] # mandatory params params = { 'Action': 'RegisterTargets', 'TargetGroupArn': target_group.id } if not members: return False idx = 0 for member in members: idx += 1 params['Targets.member.' + str(idx) + '.Id'] = member.id if member.port: params['Targets.member.' + str(idx) + '.Port'] = member.port # RegisterTargets doesn't return any useful data self.connection.request(ROOT, params=params) target_group.members = members return True def ex_create_listener(self, balancer, port, proto, target_group, action="forward", ssl_cert_arn=None, ssl_policy=None): """ Create a listener for application load balancer :param balancer: LoadBalancer to create listener for :type balancer: :class:`LoadBalancer` :param port: Port number to setup load balancer listener :type port: ``int`` :param proto: Load balancer protocol, should be 'HTTP' or 'HTTPS'. :type proto: ``str`` :param target_group: Target group associated with the listener. :type target_group: :class:`ALBTargetGroup` :param action: Default action for the listener, valid value is 'forward' :type action: ``str`` :param ssl_cert_arn: SSL certificate ARN to use when listener protocol is 'HTTPS'. :type ssl_cert_arn: ``str`` :param ssl_policy: The security policy that defines which ciphers and protocols are supported. The default is the current predefined security policy. Example: 'ELBSecurityPolicy-2016-08' :type ssl_policy: ``str`` :return: Listener object :rtype: :class:`ALBListener` """ ssl_cert_arn = ssl_cert_arn or "" ssl_policy = ssl_policy or "" # mandatory params params = { 'Action': 'CreateListener', 'LoadBalancerArn': balancer.id, 'Protocol': proto, # Valid Values: HTTP | HTTPS 'Port': port, # Valid Range: Min value of 1. Max value of 65535. 'DefaultActions.member.1.Type': action, 'DefaultActions.member.1.TargetGroupArn': target_group.id } # optional params if proto == "HTTPS": params['Certificates.member.1.CertificateArn'] = ssl_cert_arn if ssl_policy: params['SslPolicy'] = ssl_policy data = self.connection.request(ROOT, params=params).object xpath = 'CreateListenerResult/Listeners/member' for el in findall(element=data, xpath=xpath, namespace=NS): listener = self._to_listener(el) listener.balancer = balancer return listener def ex_create_listener_rule(self, listener, priority, target_group, action="forward", condition_field=None, condition_value=None): """ Create a rule for listener. :param listener: Listener object where to create rule :type listener: :class:`ALBListener` :param priority: The priority for the rule. A listener can't have multiple rules with the same priority. :type priority: ``str`` :param target_group: Target group object to associate with rule :type target_group: :class:`ALBTargetGroup` :param action: Action for the rule, valid value is 'forward' :type action: ``str`` :param condition_field: Rule condition field name. The possible values are 'host-header' and 'path-pattern'. :type condition_field: ``str`` :param condition_value: Value to match. Wildcards are supported, for example: '/img/*' :return: Rule object :rtype: :class:`ALBRule` """ condition_field = condition_field or "" condition_value = condition_value or "" # mandatory params params = { 'Action': 'CreateRule', 'ListenerArn': listener.id, 'Priority': priority, # Valid Range: Min value of 1. Max: 99999. 'Actions.member.1.Type': action, 'Actions.member.1.TargetGroupArn': target_group.id, # Valid values are host-header and path-pattern. 'Conditions.member.1.Field': condition_field, 'Conditions.member.1.Values.member.1': condition_value } data = self.connection.request(ROOT, params=params).object xpath = 'CreateRuleResult/Rules/member' for el in findall(element=data, xpath=xpath, namespace=NS): rule = self._to_rule(el) rule.listener = listener return rule def ex_get_target_group(self, target_group_id): """ Get target group object by ARN :param target_group_id: ARN of target group :type target_group_id: ``str`` :return: Target group object :rtype: :class:`ALBTargetGroup` """ # mandatory params params = { 'Action': 'DescribeTargetGroups', 'TargetGroupArns.member.1': target_group_id } data = self.connection.request(ROOT, params=params).object return self._to_target_groups(data)[0] def ex_get_listener(self, listener_id): """ Get listener object by ARN :param listener_id: ARN of listener object to get :type listener_id: ``str`` :return: Listener object :rtype: :class:`ALBListener` """ # mandatory params params = { 'Action': 'DescribeListeners', 'ListenerArns.member.1': listener_id } data = self.connection.request(ROOT, params=params).object return self._to_listeners(data)[0] def ex_get_rule(self, rule_id): """ Get rule by ARN. :param rule_id: ARN of rule :type rule_id: ``str`` :return: Rule object :rtype: :class:`ALBRule` """ params = { 'Action': 'DescribeRules', 'RuleArns.member.1': rule_id } data = self.connection.request(ROOT, params=params).object return self._to_rules(data)[0] def _to_listeners(self, data): xpath = 'DescribeListenersResult/Listeners/member' return [self._to_listener(el) for el in findall( element=data, xpath=xpath, namespace=NS )] def _to_listener(self, el): listener = ALBListener( listener_id=findtext(element=el, xpath='ListenerArn', namespace=NS), protocol=findtext(element=el, xpath='Protocol', namespace=NS), port=int(findtext(element=el, xpath='Port', namespace=NS)), balancer=None, driver=self.connection.driver, action=findtext(element=el, xpath='DefaultActions/member/Type', namespace=NS), ssl_policy=findtext(element=el, xpath='SslPolicy', namespace=NS), ssl_certificate=findtext( element=el, xpath='Certificates/member/CertificateArn', namespace=NS ), ) listener._balancer_arn = findtext(element=el, xpath='LoadBalancerArn', namespace=NS) return listener def _to_balancer(self, el): balancer = LoadBalancer( id=findtext(element=el, xpath='LoadBalancerArn', namespace=NS), name=findtext(element=el, xpath='LoadBalancerName', namespace=NS), state=State.UNKNOWN, ip=findtext(el, xpath='DNSName', namespace=NS), port=None, driver=self.connection.driver ) balancer.extra = { 'listeners': self._ex_get_balancer_listeners(balancer), 'tags': self._ex_get_balancer_tags(balancer), 'vpc': findtext(el, xpath='VpcId', namespace=NS) } if len(balancer.extra['listeners']) > 0: balancer.port = balancer.extra['listeners'][0].port else: balancer.port = None return balancer def _to_balancers(self, data): xpath = 'DescribeLoadBalancersResult/LoadBalancers/member' return [self._to_balancer(el) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_tags(self, data): """ return tags dict """ tags = {} xpath = 'DescribeTagsResult/TagDescriptions/member/Tags/member' for el in findall(element=data, xpath=xpath, namespace=NS): key = findtext(element=el, xpath='Key', namespace=NS) value = findtext(element=el, xpath='Value', namespace=NS) if key: tags[key] = value return tags def _to_rule(self, el): def __to_bool__(val): return val.lower() in ("yes", "true", "t", "1") conditions = {} cond_members = findall( element=el, xpath='Conditions/member', namespace=NS ) for cond_member in cond_members: field = findtext(element=cond_member, xpath='Field', namespace=NS) conditions[field] = [] value_members = findall( element=cond_member, xpath='Values/member', namespace=NS ) for value_member in value_members: conditions[field].append(value_member.text) rule = ALBRule( rule_id=findtext(element=el, xpath='RuleArn', namespace=NS), is_default=__to_bool__( findtext(element=el, xpath='IsDefault', namespace=NS) ), # CreateRule API method accepts only int for priority, however # DescribeRules method returns 'default' string for default # listener rule. So leaving it as string. priority=findtext(element=el, xpath='Priority', namespace=NS), target_group=None, driver=self.connection.driver, conditions=conditions ) rule._target_group_arn = findtext( element=el, xpath='Actions/member/TargetGroupArn', namespace=NS ) return rule def _to_rules(self, data): xpath = 'DescribeRulesResult/Rules/member' return [self._to_rule(el) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_target_groups(self, data): xpath = 'DescribeTargetGroupsResult/TargetGroups/member' return [self._to_target_group(el) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_target_group(self, el): target_group = ALBTargetGroup( target_group_id=findtext(element=el, xpath='TargetGroupArn', namespace=NS), name=findtext(element=el, xpath='TargetGroupName', namespace=NS), protocol=findtext(element=el, xpath='Protocol', namespace=NS), port=int(findtext(element=el, xpath='Port', namespace=NS)), vpc=findtext(element=el, xpath='VpcId', namespace=NS), driver=self.connection.driver, health_check_timeout=int( findtext(element=el, xpath='HealthCheckTimeoutSeconds', namespace=NS) ), health_check_port=findtext(element=el, xpath='HealthCheckPort', namespace=NS), health_check_path=findtext(element=el, xpath='HealthCheckPath', namespace=NS), health_check_proto=findtext(element=el, xpath='HealthCheckProtocol', namespace=NS), health_check_interval=int(findtext( element=el, xpath='HealthCheckIntervalSeconds', namespace=NS) ), healthy_threshold=int(findtext( element=el, xpath='HealthyThresholdCount', namespace=NS) ), unhealthy_threshold=int(findtext(element=el, xpath='UnhealthyThresholdCount', namespace=NS) ), health_check_matcher=findtext(element=el, xpath='Matcher/HttpCode', namespace=NS) ) lbs = findall(element=el, xpath='LoadBalancerArns/member', namespace=NS) target_group._balancers_arns = [lb_arn.text for lb_arn in lbs] return target_group def _to_target_group_members(self, data): xpath = 'DescribeTargetHealthResult/TargetHealthDescriptions/member' return [self._to_target_group_member(el) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_target_group_member(self, el): member = Member( id=findtext(element=el, xpath='Target/Id', namespace=NS), ip=None, port=findtext(element=el, xpath='Target/Port', namespace=NS), balancer=None, extra={ 'health': findtext(element=el, xpath='TargetHealth/State', namespace=NS) } ) return member def _ex_get_target_group_members(self, target_group): """ Return a list of target group member dicts. :param target_group: target group to fetch members for :type target_group: :class:`ALBTargetGroup` :return: list of target group members :rtype: ``list`` of :class:`Member` """ params = { 'Action': 'DescribeTargetHealth', 'TargetGroupArn': target_group.id } data = self.connection.request(ROOT, params=params).object target_group_members = [] for tg_member in self._to_target_group_members(data): tg_member.extra['target_group'] = target_group target_group_members.append(tg_member) return target_group_members def _ex_get_balancer_listeners(self, balancer): """ Return a list of listeners associated with load balancer. :param balancer: Load balancer to fetch listeners for :type balancer: :class:`LoadBalancer` :return: list of listener objects :rtype: ``list`` of :class:`ALBListener` """ params = { 'Action': 'DescribeListeners', 'LoadBalancerArn': balancer.id } data = self.connection.request(ROOT, params=params).object return self._to_listeners(data) def _ex_get_rules_for_listener(self, listener): """ Get list of rules associated with listener. :param listener: Listener object to fetch rules for :type listener: :class:`ALBListener` :return: List of rules :rtype: ``list`` of :class:`ALBListener` """ params = { 'Action': 'DescribeRules', 'ListenerArn': listener.id } data = self.connection.request(ROOT, params=params).object rules = self._to_rules(data) for rule in rules: rule.listener = listener return rules def _ex_get_balancer_tags(self, balancer): """ Get a dict of load balancer tags. :param balancer: Load balancer to fetch tags for :type balancer: :class:`LoadBalancer` :return: Dictionary of tags (name/value) for load balancer :rtype: ``dict`` """ params = { 'Action': 'DescribeTags', 'ResourceArns.member.1': balancer.id } data = self.connection.request(ROOT, params=params).object return self._to_tags(data) def _ex_connection_class_kwargs(self): pdriver = super(ApplicationLBDriver, self) kwargs = pdriver._ex_connection_class_kwargs() if hasattr(self, 'token') and self.token is not None: kwargs['token'] = self.token kwargs['signature_version'] = '4' else: kwargs['signature_version'] = self.signature_version return kwargs # Commented out to avoid confusion. In AWS ALB relation between load balancer # and target group/members is indirect. So it's better to go through full chain # to obtain required object(s). # Chain is: balancer->listener->rule->target group->member # # def balancer_list_members(self, balancer): # """ # List memebers of load balancer # # :param balancer: LoadBalancer to list members for # :type balancer: :class:`LoadBalancer` # # :rtype: ``list`` of :class:`Member` # """ # return balancer.extra.get('members', []) # # def _ex_get_balancer_members(self, balancer): # """ # Fetch members across all listeners/rules/target groups # # :param balancer: load balancer to fetch memebers for # :type balancer: :class:`LoadBalancer` # # :return: list of load balancer members across all target groups # :rtype: ``list`` of :class:`Member` # """ # balancer_members = [] # for listener in balancer.extra.get('listeners', []): # for rule in listener.rules: # for tg_member in rule.target_group.memebers: # tg_member.balancer = balancer # tg_member.extra['target_group'] = rule.target_group # balancer_members.append(tg_member) # # return balancer_members # # def _ex_get_balancer_target_groups(self, balancer): # """ # Return a list of load balancer target groups. # # :param balancer: load balancer to fetch target groups for # :type balancer: :class:`LoadBalancer` # # :rtype: ``list`` of :class:`ALBTargetGroup` # """ # params = { # 'Action': 'DescribeTargetGroups', # 'LoadBalancerArn': balancer.id # } # # data = self.connection.request(ROOT, params=params).object # # return self._to_target_groups(data) apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/brightbox.py0000664000175000017500000001133713535474530024665 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import httplib from libcloud.common.brightbox import BrightboxConnection from libcloud.loadbalancer.base import Driver, Algorithm, Member from libcloud.loadbalancer.base import LoadBalancer from libcloud.loadbalancer.types import State from libcloud.utils.misc import reverse_dict API_VERSION = '1.0' class BrightboxLBDriver(Driver): connectionCls = BrightboxConnection name = 'Brightbox' website = 'http://www.brightbox.co.uk/' LB_STATE_MAP = { 'creating': State.PENDING, 'active': State.RUNNING, 'deleting': State.UNKNOWN, 'deleted': State.UNKNOWN, 'failing': State.UNKNOWN, 'failed': State.UNKNOWN, } _VALUE_TO_ALGORITHM_MAP = { 'round-robin': Algorithm.ROUND_ROBIN, 'least-connections': Algorithm.LEAST_CONNECTIONS } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) def list_protocols(self): return ['tcp', 'http'] def list_balancers(self): data = self.connection.request('/%s/load_balancers' % API_VERSION) \ .object return list(map(self._to_balancer, data)) def create_balancer(self, name, port, protocol, algorithm, members): response = self._post( '/%s/load_balancers' % API_VERSION, {'name': name, 'nodes': list(map(self._member_to_node, members)), 'policy': self._algorithm_to_value(algorithm), 'listeners': [{'in': port, 'out': port, 'protocol': protocol}], 'healthcheck': {'type': protocol, 'port': port}} ) return self._to_balancer(response.object) def destroy_balancer(self, balancer): response = self.connection.request('/%s/load_balancers/%s' % (API_VERSION, balancer.id), method='DELETE') return response.status == httplib.ACCEPTED def get_balancer(self, balancer_id): data = self.connection.request( '/%s/load_balancers/%s' % (API_VERSION, balancer_id)).object return self._to_balancer(data) def balancer_attach_compute_node(self, balancer, node): return self.balancer_attach_member(balancer, node) def balancer_attach_member(self, balancer, member): path = '/%s/load_balancers/%s/add_nodes' % (API_VERSION, balancer.id) self._post(path, {'nodes': [self._member_to_node(member)]}) return member def balancer_detach_member(self, balancer, member): path = '/%s/load_balancers/%s/remove_nodes' % (API_VERSION, balancer.id) response = self._post(path, {'nodes': [self._member_to_node(member)]}) return response.status == httplib.ACCEPTED def balancer_list_members(self, balancer): path = '/%s/load_balancers/%s' % (API_VERSION, balancer.id) data = self.connection.request(path).object def func(data): return self._node_to_member(data, balancer) return list(map(func, data['nodes'])) def _post(self, path, data={}): headers = {'Content-Type': 'application/json'} return self.connection.request(path, data=data, headers=headers, method='POST') def _to_balancer(self, data): return LoadBalancer( id=data['id'], name=data['name'], state=self.LB_STATE_MAP.get(data['status'], State.UNKNOWN), ip=self._public_ip(data), port=data['listeners'][0]['in'], driver=self.connection.driver ) def _member_to_node(self, member): return {'node': member.id} def _node_to_member(self, data, balancer): return Member(id=data['id'], ip=None, port=None, balancer=balancer) def _public_ip(self, data): if len(data['cloud_ips']) > 0: ip = data['cloud_ips'][0]['public_ip'] else: ip = None return ip apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/cloudstack.py0000664000175000017500000001706713535474530025037 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.cloudstack import CloudStackDriverMixIn from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm from libcloud.loadbalancer.base import DEFAULT_ALGORITHM from libcloud.loadbalancer.types import Provider from libcloud.loadbalancer.types import State from libcloud.utils.misc import reverse_dict class CloudStackLBDriver(CloudStackDriverMixIn, Driver): """Driver for CloudStack load balancers.""" api_name = 'cloudstack_lb' name = 'CloudStack' website = 'http://cloudstack.org/' type = Provider.CLOUDSTACK _VALUE_TO_ALGORITHM_MAP = { 'roundrobin': Algorithm.ROUND_ROBIN, 'leastconn': Algorithm.LEAST_CONNECTIONS } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) LB_STATE_MAP = { 'Active': State.RUNNING, } def __init__(self, key, secret=None, secure=True, host=None, path=None, port=None, *args, **kwargs): """ @inherits: :class:`Driver.__init__` """ host = host if host else self.host path = path if path else self.path if path is not None: self.path = path if host is not None: self.host = host if (self.type == Provider.CLOUDSTACK) and (not host or not path): raise Exception('When instantiating CloudStack driver directly ' + 'you also need to provide host and path argument') super(CloudStackLBDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port) def list_protocols(self): """ We don't actually have any protocol awareness beyond TCP. :rtype: ``list`` of ``str`` """ return ['tcp'] def list_balancers(self): balancers = self._sync_request(command='listLoadBalancerRules', method='GET') balancers = balancers.get('loadbalancerrule', []) return [self._to_balancer(balancer) for balancer in balancers] def get_balancer(self, balancer_id): balancer = self._sync_request(command='listLoadBalancerRules', params={'id': balancer_id}, method='GET') balancer = balancer.get('loadbalancerrule', []) if not balancer: raise Exception("no such load balancer: " + str(balancer_id)) return self._to_balancer(balancer[0]) def create_balancer(self, name, members, protocol='http', port=80, algorithm=DEFAULT_ALGORITHM, location=None, private_port=None, network_id=None, vpc_id=None): """ @inherits: :class:`Driver.create_balancer` :param location: Location :type location: :class:`NodeLocation` :param private_port: Private port :type private_port: ``int`` :param network_id: The guest network this rule will be created for. :type network_id: ``str`` """ args = {} ip_args = {} if location is None: locations = self._sync_request(command='listZones', method='GET') location = locations['zone'][0]['id'] else: location = location.id if private_port is None: private_port = port if network_id is not None: args['networkid'] = network_id ip_args['networkid'] = network_id if vpc_id is not None: ip_args['vpcid'] = vpc_id ip_args.update({'zoneid': location, 'networkid': network_id, 'vpc_id': vpc_id}) result = self._async_request(command='associateIpAddress', params=ip_args, method='GET') public_ip = result['ipaddress'] args.update({'algorithm': self._ALGORITHM_TO_VALUE_MAP[algorithm], 'name': name, 'privateport': private_port, 'publicport': port, 'publicipid': public_ip['id']}) result = self._sync_request( command='createLoadBalancerRule', params=args, method='GET') listbalancers = self._sync_request( command='listLoadBalancerRules', params=args, method='GET') listbalancers = [rule for rule in listbalancers['loadbalancerrule'] if rule['id'] == result['id']] if len(listbalancers) != 1: return None balancer = self._to_balancer(listbalancers[0]) for member in members: balancer.attach_member(member) return balancer def destroy_balancer(self, balancer): self._async_request(command='deleteLoadBalancerRule', params={'id': balancer.id}, method='GET') self._async_request(command='disassociateIpAddress', params={'id': balancer.ex_public_ip_id}, method='GET') def balancer_attach_member(self, balancer, member): member.port = balancer.ex_private_port self._async_request(command='assignToLoadBalancerRule', params={'id': balancer.id, 'virtualmachineids': member.id}, method='GET') return True def balancer_detach_member(self, balancer, member): self._async_request(command='removeFromLoadBalancerRule', params={'id': balancer.id, 'virtualmachineids': member.id}, method='GET') return True def balancer_list_members(self, balancer): members = self._sync_request(command='listLoadBalancerRuleInstances', params={'id': balancer.id}, method='GET') members = members['loadbalancerruleinstance'] return [self._to_member(m, balancer.ex_private_port, balancer) for m in members] def _to_balancer(self, obj): balancer = LoadBalancer( id=obj['id'], name=obj['name'], state=self.LB_STATE_MAP.get(obj['state'], State.UNKNOWN), ip=obj['publicip'], port=obj['publicport'], driver=self.connection.driver ) balancer.ex_private_port = obj['privateport'] balancer.ex_public_ip_id = obj['publicipid'] return balancer def _to_member(self, obj, port, balancer): return Member( id=obj['id'], ip=obj['nic'][0]['ipaddress'], port=port, balancer=balancer ) apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/dimensiondata.py0000664000175000017500000012457413535474530025524 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance withv # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import ET from libcloud.common.dimensiondata import DimensionDataConnection from libcloud.common.dimensiondata import DimensionDataPool from libcloud.common.dimensiondata import DimensionDataPoolMember from libcloud.common.dimensiondata import DimensionDataVirtualListener from libcloud.common.dimensiondata import DimensionDataVIPNode from libcloud.common.dimensiondata import DimensionDataDefaultHealthMonitor from libcloud.common.dimensiondata import DimensionDataPersistenceProfile from libcloud.common.dimensiondata import \ DimensionDataVirtualListenerCompatibility from libcloud.common.dimensiondata import DimensionDataDefaultiRule from libcloud.common.dimensiondata import API_ENDPOINTS from libcloud.common.dimensiondata import DEFAULT_REGION from libcloud.common.dimensiondata import TYPES_URN from libcloud.utils.misc import reverse_dict from libcloud.utils.xml import fixxpath, findtext, findall from libcloud.loadbalancer.types import State from libcloud.loadbalancer.base import Algorithm, Driver, LoadBalancer from libcloud.loadbalancer.base import Member from libcloud.loadbalancer.types import Provider class DimensionDataLBDriver(Driver): """ DimensionData node driver. """ selected_region = None connectionCls = DimensionDataConnection name = 'Dimension Data Load Balancer' website = 'https://cloud.dimensiondata.com/' type = Provider.DIMENSIONDATA api_version = 1.0 network_domain_id = None _VALUE_TO_ALGORITHM_MAP = { 'ROUND_ROBIN': Algorithm.ROUND_ROBIN, 'LEAST_CONNECTIONS': Algorithm.LEAST_CONNECTIONS, 'SHORTEST_RESPONSE': Algorithm.SHORTEST_RESPONSE, 'PERSISTENT_IP': Algorithm.PERSISTENT_IP } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) _VALUE_TO_STATE_MAP = { 'NORMAL': State.RUNNING, 'PENDING_ADD': State.PENDING, 'PENDING_CHANGE': State.PENDING, 'PENDING_DELETE': State.PENDING, 'FAILED_ADD': State.ERROR, 'FAILED_CHANGE': State.ERROR, 'FAILED_DELETE': State.ERROR, 'REQUIRES_SUPPORT': State.ERROR } def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): if region not in API_ENDPOINTS and host is None: raise ValueError( 'Invalid region: %s, no host specified' % (region)) if region is not None: self.selected_region = API_ENDPOINTS[region] super(DimensionDataLBDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) def _ex_connection_class_kwargs(self): """ Add the region to the kwargs before the connection is instantiated """ kwargs = super(DimensionDataLBDriver, self)._ex_connection_class_kwargs() kwargs['region'] = self.selected_region return kwargs def create_balancer(self, name, port=None, protocol=None, algorithm=None, members=None, ex_listener_ip_address=None): """ Create a new load balancer instance :param name: Name of the new load balancer (required) :type name: ``str`` :param port: An integer in the range of 1-65535. If not supplied, it will be taken to mean 'Any Port' :type port: ``int`` :param protocol: Loadbalancer protocol, defaults to http. :type protocol: ``str`` :param members: list of Members to attach to balancer (optional) :type members: ``list`` of :class:`Member` :param algorithm: Load balancing algorithm, defaults to ROUND_ROBIN. :type algorithm: :class:`.Algorithm` :param ex_listener_ip_address: Must be a valid IPv4 in dot-decimal notation (x.x.x.x). :type ex_listener_ip_address: ``str`` :rtype: :class:`LoadBalancer` """ network_domain_id = self.network_domain_id if protocol is None: protocol = 'http' if algorithm is None: algorithm = Algorithm.ROUND_ROBIN # Create a pool first pool = self.ex_create_pool( network_domain_id=network_domain_id, name=name, ex_description=None, balancer_method=self._ALGORITHM_TO_VALUE_MAP[algorithm]) # Attach the members to the pool as nodes if members is not None: for member in members: node = self.ex_create_node( network_domain_id=network_domain_id, name=member.ip, ip=member.ip, ex_description=None) self.ex_create_pool_member( pool=pool, node=node, port=port) # Create the virtual listener (balancer) listener = self.ex_create_virtual_listener( network_domain_id=network_domain_id, name=name, ex_description=name, port=port, pool=pool, listener_ip_address=ex_listener_ip_address) return LoadBalancer( id=listener.id, name=listener.name, state=State.RUNNING, ip=listener.ip, port=port, driver=self, extra={'pool_id': pool.id, 'network_domain_id': network_domain_id, 'listener_ip_address': ex_listener_ip_address} ) def list_balancers(self, ex_network_domain_id=None): """ List all loadbalancers inside a geography or in given network. In Dimension Data terminology these are known as virtual listeners :param ex_network_domain_id: UUID of Network Domain if not None returns only balancers in the given network if None then returns all pools for the organization :type ex_network_domain_id: ``str`` :rtype: ``list`` of :class:`LoadBalancer` """ params = None if ex_network_domain_id is not None: params = {"networkDomainId": ex_network_domain_id} return self._to_balancers( self.connection .request_with_orgId_api_2('networkDomainVip/virtualListener', params=params).object) def get_balancer(self, balancer_id): """ Return a :class:`LoadBalancer` object. :param balancer_id: id of a load balancer you want to fetch :type balancer_id: ``str`` :rtype: :class:`LoadBalancer` """ bal = self.connection \ .request_with_orgId_api_2('networkDomainVip/virtualListener/%s' % balancer_id).object return self._to_balancer(bal) def list_protocols(self): """ Return a list of supported protocols. Since all protocols are support by Dimension Data, this is a list of common protocols. :rtype: ``list`` of ``str`` """ return ['http', 'https', 'tcp', 'udp', 'ftp', 'smtp'] def balancer_list_members(self, balancer): """ Return list of members attached to balancer. In Dimension Data terminology these are the members of the pools within a virtual listener. :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :rtype: ``list`` of :class:`Member` """ pool_members = self.ex_get_pool_members(balancer.extra['pool_id']) members = [] for pool_member in pool_members: members.append(Member( id=pool_member.id, ip=pool_member.ip, port=pool_member.port, balancer=balancer, extra=None )) return members def balancer_attach_member(self, balancer, member): """ Attach a member to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member to join to the balancer :type member: :class:`Member` :return: Member after joining the balancer. :rtype: :class:`Member` """ node = self.ex_create_node( network_domain_id=balancer.extra['network_domain_id'], name='Member.' + member.ip, ip=member.ip, ex_description='' ) if node is False: return False pool = self.ex_get_pool(balancer.extra['pool_id']) pool_member = self.ex_create_pool_member( pool=pool, node=node, port=member.port) member.id = pool_member.id return member def balancer_detach_member(self, balancer, member): """ Detach member from balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member which should be used :type member: :class:`Member` :return: ``True`` if member detach was successful, otherwise ``False``. :rtype: ``bool`` """ create_pool_m = ET.Element('removePoolMember', {'xmlns': TYPES_URN, 'id': member.id}) result = self.connection.request_with_orgId_api_2( 'networkDomainVip/removePoolMember', method='POST', data=ET.tostring(create_pool_m)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def destroy_balancer(self, balancer): """ Destroy a load balancer (virtual listener) :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :return: ``True`` if the destroy was successful, otherwise ``False``. :rtype: ``bool`` """ delete_listener = ET.Element('deleteVirtualListener', {'xmlns': TYPES_URN, 'id': balancer.id}) result = self.connection.request_with_orgId_api_2( 'networkDomainVip/deleteVirtualListener', method='POST', data=ET.tostring(delete_listener)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_set_current_network_domain(self, network_domain_id): """ Set the network domain (part of the network) of the driver :param network_domain_id: ID of the pool (required) :type network_domain_id: ``str`` """ self.network_domain_id = network_domain_id def ex_get_current_network_domain(self): """ Get the current network domain ID of the driver. :return: ID of the network domain :rtype: ``str`` """ return self.network_domain_id def ex_create_pool_member(self, pool, node, port=None): """ Create a new member in an existing pool from an existing node :param pool: Instance of ``DimensionDataPool`` (required) :type pool: ``DimensionDataPool`` :param node: Instance of ``DimensionDataVIPNode`` (required) :type node: ``DimensionDataVIPNode`` :param port: Port the the service will listen on :type port: ``str`` :return: The node member, instance of ``DimensionDataPoolMember`` :rtype: ``DimensionDataPoolMember`` """ create_pool_m = ET.Element('addPoolMember', {'xmlns': TYPES_URN}) ET.SubElement(create_pool_m, "poolId").text = pool.id ET.SubElement(create_pool_m, "nodeId").text = node.id if port is not None: ET.SubElement(create_pool_m, "port").text = str(port) ET.SubElement(create_pool_m, "status").text = 'ENABLED' response = self.connection.request_with_orgId_api_2( 'networkDomainVip/addPoolMember', method='POST', data=ET.tostring(create_pool_m)).object member_id = None node_name = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'poolMemberId': member_id = info.get('value') if info.get('name') == 'nodeName': node_name = info.get('value') return DimensionDataPoolMember( id=member_id, name=node_name, status=State.RUNNING, ip=node.ip, port=port, node_id=node.id ) def ex_create_node(self, network_domain_id, name, ip, ex_description, connection_limit=25000, connection_rate_limit=2000): """ Create a new node :param network_domain_id: Network Domain ID (required) :type name: ``str`` :param name: name of the node (required) :type name: ``str`` :param ip: IPv4 address of the node (required) :type ip: ``str`` :param ex_description: Description of the node (required) :type ex_description: ``str`` :param connection_limit: Maximum number of concurrent connections per sec :type connection_limit: ``int`` :param connection_rate_limit: Maximum number of concurrent sessions :type connection_rate_limit: ``int`` :return: Instance of ``DimensionDataVIPNode`` :rtype: ``DimensionDataVIPNode`` """ create_node_elm = ET.Element('createNode', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "networkDomainId") \ .text = network_domain_id ET.SubElement(create_node_elm, "name").text = name ET.SubElement(create_node_elm, "description").text \ = str(ex_description) ET.SubElement(create_node_elm, "ipv4Address").text = ip ET.SubElement(create_node_elm, "status").text = 'ENABLED' ET.SubElement(create_node_elm, "connectionLimit") \ .text = str(connection_limit) ET.SubElement(create_node_elm, "connectionRateLimit") \ .text = str(connection_rate_limit) response = self.connection.request_with_orgId_api_2( action='networkDomainVip/createNode', method='POST', data=ET.tostring(create_node_elm)).object node_id = None node_name = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'nodeId': node_id = info.get('value') if info.get('name') == 'name': node_name = info.get('value') return DimensionDataVIPNode( id=node_id, name=node_name, status=State.RUNNING, ip=ip ) def ex_update_node(self, node): """ Update the properties of a node :param pool: The instance of ``DimensionDataNode`` to update :type pool: ``DimensionDataNode`` :return: The instance of ``DimensionDataNode`` :rtype: ``DimensionDataNode`` """ create_node_elm = ET.Element('editNode', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "connectionLimit") \ .text = str(node.connection_limit) ET.SubElement(create_node_elm, "connectionRateLimit") \ .text = str(node.connection_rate_limit) self.connection.request_with_orgId_api_2( action='networkDomainVip/createNode', method='POST', data=ET.tostring(create_node_elm)).object return node def ex_set_node_state(self, node, enabled): """ Change the state of a node (enable/disable) :param pool: The instance of ``DimensionDataNode`` to update :type pool: ``DimensionDataNode`` :param enabled: The target state of the node :type enabled: ``bool`` :return: The instance of ``DimensionDataNode`` :rtype: ``DimensionDataNode`` """ create_node_elm = ET.Element('editNode', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "status") \ .text = "ENABLED" if enabled is True else "DISABLED" self.connection.request_with_orgId_api_2( action='networkDomainVip/editNode', method='POST', data=ET.tostring(create_node_elm)).object return node def ex_create_pool(self, network_domain_id, name, balancer_method, ex_description, health_monitors=None, service_down_action='NONE', slow_ramp_time=30): """ Create a new pool :param network_domain_id: Network Domain ID (required) :type name: ``str`` :param name: name of the node (required) :type name: ``str`` :param balancer_method: The load balancer algorithm (required) :type balancer_method: ``str`` :param ex_description: Description of the node (required) :type ex_description: ``str`` :param health_monitors: A list of health monitors to use for the pool. :type health_monitors: ``list`` of :class:`DimensionDataDefaultHealthMonitor` :param service_down_action: What to do when node is unavailable NONE, DROP or RESELECT :type service_down_action: ``str`` :param slow_ramp_time: Number of seconds to stagger ramp up of nodes :type slow_ramp_time: ``int`` :return: Instance of ``DimensionDataPool`` :rtype: ``DimensionDataPool`` """ # Names cannot contain spaces. name.replace(' ', '_') create_node_elm = ET.Element('createPool', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "networkDomainId") \ .text = network_domain_id ET.SubElement(create_node_elm, "name").text = name ET.SubElement(create_node_elm, "description").text \ = str(ex_description) ET.SubElement(create_node_elm, "loadBalanceMethod") \ .text = str(balancer_method) if health_monitors is not None: for monitor in health_monitors: ET.SubElement(create_node_elm, "healthMonitorId") \ .text = str(monitor.id) ET.SubElement(create_node_elm, "serviceDownAction") \ .text = service_down_action ET.SubElement(create_node_elm, "slowRampTime").text \ = str(slow_ramp_time) response = self.connection.request_with_orgId_api_2( action='networkDomainVip/createPool', method='POST', data=ET.tostring(create_node_elm)).object pool_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'poolId': pool_id = info.get('value') return DimensionDataPool( id=pool_id, name=name, description=ex_description, status=State.RUNNING, load_balance_method=str(balancer_method), health_monitor_id=None, service_down_action=service_down_action, slow_ramp_time=str(slow_ramp_time) ) def ex_create_virtual_listener(self, network_domain_id, name, ex_description, port=None, pool=None, listener_ip_address=None, persistence_profile=None, fallback_persistence_profile=None, irule=None, protocol='TCP', connection_limit=25000, connection_rate_limit=2000, source_port_preservation='PRESERVE'): """ Create a new virtual listener (load balancer) :param network_domain_id: Network Domain ID (required) :type name: ``str`` :param name: name of the listener (required) :type name: ``str`` :param ex_description: Description of the node (required) :type ex_description: ``str`` :param port: An integer in the range of 1-65535. If not supplied, it will be taken to mean 'Any Port' :type port: ``int`` :param pool: The pool to use for the listener :type pool: :class:`DimensionDataPool` :param listener_ip_address: The IPv4 Address of the virtual listener :type listener_ip_address: ``str`` :param persistence_profile: Persistence profile :type persistence_profile: :class:`DimensionDataPersistenceProfile` :param fallback_persistence_profile: Fallback persistence profile :type fallback_persistence_profile: :class:`DimensionDataPersistenceProfile` :param irule: The iRule to apply :type irule: :class:`DimensionDataDefaultiRule` :param protocol: For STANDARD type, ANY, TCP or UDP for PERFORMANCE_LAYER_4 choice of ANY, TCP, UDP, HTTP :type protcol: ``str`` :param connection_limit: Maximum number of concurrent connections per sec :type connection_limit: ``int`` :param connection_rate_limit: Maximum number of concurrent sessions :type connection_rate_limit: ``int`` :param source_port_preservation: Choice of PRESERVE, PRESERVE_STRICT or CHANGE :type source_port_preservation: ``str`` :return: Instance of the listener :rtype: ``DimensionDataVirtualListener`` """ if (port == 80) or (port == 443): listener_type = 'PERFORMANCE_LAYER_4' else: listener_type = 'STANDARD' create_node_elm = ET.Element('createVirtualListener', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "networkDomainId") \ .text = network_domain_id ET.SubElement(create_node_elm, "name").text = name ET.SubElement(create_node_elm, "description").text = \ str(ex_description) ET.SubElement(create_node_elm, "type").text = listener_type ET.SubElement(create_node_elm, "protocol") \ .text = protocol if listener_ip_address is not None: ET.SubElement(create_node_elm, "listenerIpAddress").text = \ str(listener_ip_address) if port is not None: ET.SubElement(create_node_elm, "port").text = str(port) ET.SubElement(create_node_elm, "enabled").text = 'true' ET.SubElement(create_node_elm, "connectionLimit") \ .text = str(connection_limit) ET.SubElement(create_node_elm, "connectionRateLimit") \ .text = str(connection_rate_limit) ET.SubElement(create_node_elm, "sourcePortPreservation") \ .text = source_port_preservation if pool is not None: ET.SubElement(create_node_elm, "poolId") \ .text = pool.id if persistence_profile is not None: ET.SubElement(create_node_elm, "persistenceProfileId") \ .text = persistence_profile.id if fallback_persistence_profile is not None: ET.SubElement(create_node_elm, "fallbackPersistenceProfileId") \ .text = fallback_persistence_profile.id if irule is not None: ET.SubElement(create_node_elm, "iruleId") \ .text = irule.id response = self.connection.request_with_orgId_api_2( action='networkDomainVip/createVirtualListener', method='POST', data=ET.tostring(create_node_elm)).object virtual_listener_id = None virtual_listener_ip = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'virtualListenerId': virtual_listener_id = info.get('value') if info.get('name') == 'listenerIpAddress': virtual_listener_ip = info.get('value') return DimensionDataVirtualListener( id=virtual_listener_id, name=name, ip=virtual_listener_ip, status=State.RUNNING ) def ex_get_pools(self, ex_network_domain_id=None): """ Get all of the pools inside the current geography or in given network. :param ex_network_domain_id: UUID of Network Domain if not None returns only balancers in the given network if None then returns all pools for the organization :type ex_network_domain_id: ``str`` :return: Returns a ``list`` of type ``DimensionDataPool`` :rtype: ``list`` of ``DimensionDataPool`` """ params = None if ex_network_domain_id is not None: params = {"networkDomainId": ex_network_domain_id} pools = self.connection \ .request_with_orgId_api_2('networkDomainVip/pool', params=params).object return self._to_pools(pools) def ex_get_pool(self, pool_id): """ Get a specific pool inside the current geography :param pool_id: The identifier of the pool :type pool_id: ``str`` :return: Returns an instance of ``DimensionDataPool`` :rtype: ``DimensionDataPool`` """ pool = self.connection \ .request_with_orgId_api_2('networkDomainVip/pool/%s' % pool_id).object return self._to_pool(pool) def ex_update_pool(self, pool): """ Update the properties of an existing pool only method, serviceDownAction and slowRampTime are updated :param pool: The instance of ``DimensionDataPool`` to update :type pool: ``DimensionDataPool`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ create_node_elm = ET.Element('editPool', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "loadBalanceMethod") \ .text = str(pool.load_balance_method) ET.SubElement(create_node_elm, "serviceDownAction") \ .text = pool.service_down_action ET.SubElement(create_node_elm, "slowRampTime").text \ = str(pool.slow_ramp_time) response = self.connection.request_with_orgId_api_2( action='networkDomainVip/editPool', method='POST', data=ET.tostring(create_node_elm)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_destroy_pool(self, pool): """ Destroy an existing pool :param pool: The instance of ``DimensionDataPool`` to destroy :type pool: ``DimensionDataPool`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ destroy_request = ET.Element('deletePool', {'xmlns': TYPES_URN, 'id': pool.id}) result = self.connection.request_with_orgId_api_2( action='networkDomainVip/deletePool', method='POST', data=ET.tostring(destroy_request)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_pool_members(self, pool_id): """ Get the members of a pool :param pool: The instance of a pool :type pool: ``DimensionDataPool`` :return: Returns an ``list`` of ``DimensionDataPoolMember`` :rtype: ``list`` of ``DimensionDataPoolMember`` """ members = self.connection \ .request_with_orgId_api_2('networkDomainVip/poolMember?poolId=%s' % pool_id).object return self._to_members(members) def ex_get_pool_member(self, pool_member_id): """ Get a specific member of a pool :param pool: The id of a pool member :type pool: ``str`` :return: Returns an instance of ``DimensionDataPoolMember`` :rtype: ``DimensionDataPoolMember`` """ member = self.connection \ .request_with_orgId_api_2('networkDomainVip/poolMember/%s' % pool_member_id).object return self._to_member(member) def ex_set_pool_member_state(self, member, enabled=True): request = ET.Element('editPoolMember', {'xmlns': TYPES_URN, 'id': member.id}) state = "ENABLED" if enabled is True else "DISABLED" ET.SubElement(request, 'status').text = state result = self.connection.request_with_orgId_api_2( action='networkDomainVip/editPoolMember', method='POST', data=ET.tostring(request)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_destroy_pool_member(self, member, destroy_node=False): """ Destroy a specific member of a pool :param pool: The instance of a pool member :type pool: ``DimensionDataPoolMember`` :param destroy_node: Also destroy the associated node :type destroy_node: ``bool`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ # remove the pool member destroy_request = ET.Element('removePoolMember', {'xmlns': TYPES_URN, 'id': member.id}) result = self.connection.request_with_orgId_api_2( action='networkDomainVip/removePoolMember', method='POST', data=ET.tostring(destroy_request)).object if member.node_id is not None and destroy_node is True: return self.ex_destroy_node(member.node_id) else: response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_nodes(self, ex_network_domain_id=None): """ Get the nodes within this geography or in given network. :param ex_network_domain_id: UUID of Network Domain if not None returns only balancers in the given network if None then returns all pools for the organization :type ex_network_domain_id: ``str`` :return: Returns an ``list`` of ``DimensionDataVIPNode`` :rtype: ``list`` of ``DimensionDataVIPNode`` """ params = None if ex_network_domain_id is not None: params = {"networkDomainId": ex_network_domain_id} nodes = self.connection \ .request_with_orgId_api_2('networkDomainVip/node', params=params).object return self._to_nodes(nodes) def ex_get_node(self, node_id): """ Get the node specified by node_id :return: Returns an instance of ``DimensionDataVIPNode`` :rtype: Instance of ``DimensionDataVIPNode`` """ nodes = self.connection \ .request_with_orgId_api_2('networkDomainVip/node/%s' % node_id).object return self._to_node(nodes) def ex_destroy_node(self, node_id): """ Destroy a specific node :param node_id: The ID of of a ``DimensionDataVIPNode`` :type node_id: ``str`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ # Destroy the node destroy_request = ET.Element('deleteNode', {'xmlns': TYPES_URN, 'id': node_id}) result = self.connection.request_with_orgId_api_2( action='networkDomainVip/deleteNode', method='POST', data=ET.tostring(destroy_request)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_wait_for_state(self, state, func, poll_interval=2, timeout=60, *args, **kwargs): """ Wait for the function which returns a instance with field status to match Keep polling func until one of the desired states is matched :param state: Either the desired state (`str`) or a `list` of states :type state: ``str`` or ``list`` :param func: The function to call, e.g. ex_get_vlan :type func: ``function`` :param poll_interval: The number of seconds to wait between checks :type poll_interval: `int` :param timeout: The total number of seconds to wait to reach a state :type timeout: `int` :param args: The arguments for func :type args: Positional arguments :param kwargs: The arguments for func :type kwargs: Keyword arguments """ return self.connection.wait_for_state(state, func, poll_interval, timeout, *args, **kwargs) def ex_get_default_health_monitors(self, network_domain_id): """ Get the default health monitors available for a network domain :param network_domain_id: The ID of of a ``DimensionDataNetworkDomain`` :type network_domain_id: ``str`` :rtype: `list` of :class:`DimensionDataDefaultHealthMonitor` """ result = self.connection.request_with_orgId_api_2( action='networkDomainVip/defaultHealthMonitor', params={'networkDomainId': network_domain_id}, method='GET').object return self._to_health_monitors(result) def ex_get_default_persistence_profiles(self, network_domain_id): """ Get the default persistence profiles available for a network domain :param network_domain_id: The ID of of a ``DimensionDataNetworkDomain`` :type network_domain_id: ``str`` :rtype: `list` of :class:`DimensionDataPersistenceProfile` """ result = self.connection.request_with_orgId_api_2( action='networkDomainVip/defaultPersistenceProfile', params={'networkDomainId': network_domain_id}, method='GET').object return self._to_persistence_profiles(result) def ex_get_default_irules(self, network_domain_id): """ Get the default iRules available for a network domain :param network_domain_id: The ID of of a ``DimensionDataNetworkDomain`` :type network_domain_id: ``str`` :rtype: `list` of :class:`DimensionDataDefaultiRule` """ result = self.connection.request_with_orgId_api_2( action='networkDomainVip/defaultIrule', params={'networkDomainId': network_domain_id}, method='GET').object return self._to_irules(result) def _to_irules(self, object): irules = [] matches = object.findall( fixxpath('defaultIrule', TYPES_URN)) for element in matches: irules.append(self._to_irule(element)) return irules def _to_irule(self, element): compatible = [] matches = element.findall( fixxpath('virtualListenerCompatibility', TYPES_URN)) for match_element in matches: compatible.append( DimensionDataVirtualListenerCompatibility( type=match_element.get('type'), protocol=match_element.get('protocol', None))) irule_element = element.find(fixxpath('irule', TYPES_URN)) return DimensionDataDefaultiRule( id=irule_element.get('id'), name=irule_element.get('name'), compatible_listeners=compatible ) def _to_persistence_profiles(self, object): profiles = [] matches = object.findall( fixxpath('defaultPersistenceProfile', TYPES_URN)) for element in matches: profiles.append(self._to_persistence_profile(element)) return profiles def _to_persistence_profile(self, element): compatible = [] matches = element.findall( fixxpath('virtualListenerCompatibility', TYPES_URN)) for match_element in matches: compatible.append( DimensionDataVirtualListenerCompatibility( type=match_element.get('type'), protocol=match_element.get('protocol', None))) return DimensionDataPersistenceProfile( id=element.get('id'), fallback_compatible=bool( element.get('fallbackCompatible') == "true"), name=findtext(element, 'name', TYPES_URN), compatible_listeners=compatible ) def _to_health_monitors(self, object): monitors = [] matches = object.findall(fixxpath('defaultHealthMonitor', TYPES_URN)) for element in matches: monitors.append(self._to_health_monitor(element)) return monitors def _to_health_monitor(self, element): return DimensionDataDefaultHealthMonitor( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), node_compatible=bool( findtext(element, 'nodeCompatible', TYPES_URN) == "true"), pool_compatible=bool( findtext(element, 'poolCompatible', TYPES_URN) == "true"), ) def _to_nodes(self, object): nodes = [] for element in object.findall(fixxpath("node", TYPES_URN)): nodes.append(self._to_node(element)) return nodes def _to_node(self, element): ipaddress = findtext(element, 'ipv4Address', TYPES_URN) if ipaddress is None: ipaddress = findtext(element, 'ipv6Address', TYPES_URN) name = findtext(element, 'name', TYPES_URN) node = DimensionDataVIPNode( id=element.get('id'), name=name, status=self._VALUE_TO_STATE_MAP.get( findtext(element, 'state', TYPES_URN), State.UNKNOWN), connection_rate_limit=findtext(element, 'connectionRateLimit', TYPES_URN), connection_limit=findtext(element, 'connectionLimit', TYPES_URN), ip=ipaddress) return node def _to_balancers(self, object): loadbalancers = [] for element in object.findall(fixxpath("virtualListener", TYPES_URN)): loadbalancers.append(self._to_balancer(element)) return loadbalancers def _to_balancer(self, element): ipaddress = findtext(element, 'listenerIpAddress', TYPES_URN) name = findtext(element, 'name', TYPES_URN) port = findtext(element, 'port', TYPES_URN) extra = {} pool_element = element.find(fixxpath( 'pool', TYPES_URN)) if pool_element is None: extra['pool_id'] = None else: extra['pool_id'] = pool_element.get('id') extra['network_domain_id'] = findtext(element, 'networkDomainId', TYPES_URN) balancer = LoadBalancer( id=element.get('id'), name=name, state=self._VALUE_TO_STATE_MAP.get( findtext(element, 'state', TYPES_URN), State.UNKNOWN), ip=ipaddress, port=port, driver=self.connection.driver, extra=extra ) return balancer def _to_members(self, object): members = [] for element in object.findall(fixxpath("poolMember", TYPES_URN)): members.append(self._to_member(element)) return members def _to_member(self, element): port = findtext(element, 'port', TYPES_URN) if port is not None: port = int(port) pool_member = DimensionDataPoolMember( id=element.get('id'), name=element.find(fixxpath( 'node', TYPES_URN)).get('name'), status=findtext(element, 'state', TYPES_URN), node_id=element.find(fixxpath( 'node', TYPES_URN)).get('id'), ip=element.find(fixxpath( 'node', TYPES_URN)).get('ipAddress'), port=port ) return pool_member def _to_pools(self, object): pools = [] for element in object.findall(fixxpath("pool", TYPES_URN)): pools.append(self._to_pool(element)) return pools def _to_pool(self, element): pool = DimensionDataPool( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), status=findtext(element, 'state', TYPES_URN), description=findtext(element, 'description', TYPES_URN), load_balance_method=findtext(element, 'loadBalanceMethod', TYPES_URN), health_monitor_id=findtext(element, 'healthMonitorId', TYPES_URN), service_down_action=findtext(element, 'serviceDownAction', TYPES_URN), slow_ramp_time=findtext(element, 'slowRampTime', TYPES_URN), ) return pool apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/elb.py0000664000175000017500000003365613535474530023447 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'ElasticLBDriver' ] from libcloud.utils.py3 import httplib from libcloud.utils.xml import findtext, findall from libcloud.loadbalancer.types import State from libcloud.loadbalancer.base import Driver, LoadBalancer, Member from libcloud.common.aws import AWSGenericResponse, SignedAWSConnection VERSION = '2012-06-01' HOST = 'elasticloadbalancing.%s.amazonaws.com' ROOT = '/%s/' % (VERSION) NS = 'http://elasticloadbalancing.amazonaws.com/doc/%s/' % (VERSION, ) class ELBResponse(AWSGenericResponse): """ Amazon ELB response class. """ namespace = NS exceptions = {} xpath = 'Error' class ELBConnection(SignedAWSConnection): version = VERSION host = HOST responseCls = ELBResponse service_name = 'elasticloadbalancing' class ElasticLBDriver(Driver): name = 'Amazon Elastic Load Balancing' website = 'http://aws.amazon.com/elasticloadbalancing/' connectionCls = ELBConnection signature_version = '4' def __init__(self, access_id, secret, region, token=None): self.token = token self.region = region self.region_name = region super(ElasticLBDriver, self).__init__( access_id, secret, token=token, host=HOST % region, region=region ) def list_protocols(self): return ['tcp', 'ssl', 'http', 'https'] def list_balancers(self, ex_fetch_tags=False): params = {'Action': 'DescribeLoadBalancers'} data = self.connection.request(ROOT, params=params).object balancers = self._to_balancers(data) if ex_fetch_tags: for balancer in balancers: self._ex_populate_balancer_tags(balancer) return balancers def create_balancer(self, name, port, protocol, algorithm, members, ex_members_availability_zones=None): if ex_members_availability_zones is None: ex_members_availability_zones = ['a'] params = { 'Action': 'CreateLoadBalancer', 'LoadBalancerName': name, 'Listeners.member.1.InstancePort': str(port), 'Listeners.member.1.InstanceProtocol': protocol.upper(), 'Listeners.member.1.LoadBalancerPort': str(port), 'Listeners.member.1.Protocol': protocol.upper(), } for i, z in enumerate(ex_members_availability_zones): zone = ''.join((self.region, z)) params['AvailabilityZones.member.%d' % (i + 1)] = zone data = self.connection.request(ROOT, params=params).object balancer = LoadBalancer( id=name, name=name, state=State.PENDING, ip=findtext(element=data, xpath='DNSName', namespace=NS), port=port, driver=self.connection.driver ) balancer._members = [] return balancer def destroy_balancer(self, balancer): params = { 'Action': 'DeleteLoadBalancer', 'LoadBalancerName': balancer.id } self.connection.request(ROOT, params=params) return True def get_balancer(self, balancer_id, ex_fetch_tags=False): params = { 'Action': 'DescribeLoadBalancers', 'LoadBalancerNames.member.1': balancer_id } data = self.connection.request(ROOT, params=params).object balancer = self._to_balancers(data)[0] if ex_fetch_tags: balancer = self._ex_populate_balancer_tags(balancer) return balancer def balancer_attach_compute_node(self, balancer, node): params = { 'Action': 'RegisterInstancesWithLoadBalancer', 'LoadBalancerName': balancer.id, 'Instances.member.1.InstanceId': node.id } self.connection.request(ROOT, params=params) balancer._members.append(Member(node.id, None, None, balancer=self)) def balancer_detach_member(self, balancer, member): params = { 'Action': 'DeregisterInstancesFromLoadBalancer', 'LoadBalancerName': balancer.id, 'Instances.member.1.InstanceId': member.id } self.connection.request(ROOT, params=params) balancer._members = [m for m in balancer._members if m.id != member.id] return True def balancer_list_members(self, balancer): return balancer._members def ex_list_balancer_policies(self, balancer): """ Return a list of policy description string. :rtype: ``list`` of ``str`` """ params = { 'Action': 'DescribeLoadBalancerPolicies', 'LoadBalancerName': balancer.id } data = self.connection.request(ROOT, params=params).object return self._to_policies(data) def ex_list_balancer_policy_types(self): """ Return a list of policy type description string. :rtype: ``list`` of ``str`` """ params = {'Action': 'DescribeLoadBalancerPolicyTypes'} data = self.connection.request(ROOT, params=params).object return self._to_policy_types(data) def ex_create_balancer_policy(self, name, policy_name, policy_type, policy_attributes=None): """ Create a new load balancer policy :param name: Balancer name to create the policy for :type name: ``str`` :param policy_name: policy to be created :type policy_name: ``str`` :param policy_type: policy type being used to create policy. :type policy_type: ``str`` :param policy_attributes: Each list contain values, ['AttributeName', 'value'] :type policy_attributes: ``PolicyAttribute list`` """ params = { 'Action': 'CreateLoadBalancerPolicy', 'LoadBalancerName': name, 'PolicyName': policy_name, 'PolicyTypeName': policy_type } if policy_attributes is not None: for index, (name, value) in enumerate( policy_attributes.iteritems(), 1): params['PolicyAttributes.member.%d. \ AttributeName' % (index)] = name params['PolicyAttributes.member.%d. \ AttributeValue' % (index)] = value response = self.connection.request(ROOT, params=params) return response.status == httplib.OK def ex_delete_balancer_policy(self, name, policy_name): """ Delete a load balancer policy :param name: balancer name for which policy will be deleted :type name: ``str`` :param policy_name: The Mnemonic name for the policy being deleted :type policy_name: ``str`` """ params = { 'Action': 'DeleteLoadBalancerPolicy', 'LoadBalancerName': name, 'PolicyName': policy_name } response = self.connection.request(ROOT, params=params) return response.status == httplib.OK def ex_set_balancer_policies_listener(self, name, port, policies): """ Associates, updates, or disables a policy with a listener on the load balancer :param name: balancer name to set policies for listerner :type name: ``str`` :param port: port to use :type port: ``str`` :param policies: List of policies to be associated with the balancer :type policies: ``string list`` """ params = { 'Action': 'SetLoadBalancerPoliciesOfListener', 'LoadBalancerName': name, 'LoadBalancerPort': str(port) } if policies: params = self._create_list_params(params, policies, 'PolicyNames.member.%d') response = self.connection.request(ROOT, params=params) return response.status == httplib.OK def ex_set_balancer_policies_backend_server(self, name, instance_port, policies): """ Replaces the current set of policies associated with a port on which the back-end server is listening with a new set of policies :param name: balancer name to set policies of backend server :type name: ``str`` :param instance_port: Instance Port :type instance_port: ``int`` :param policies: List of policies to be associated with the balancer :type policies: ``string list` """ params = { 'Action': 'SetLoadBalancerPoliciesForBackendServer', 'LoadBalancerName': name, 'InstancePort': str(instance_port) } if policies: params = self._create_list_params(params, policies, 'PolicyNames.member.%d') response = self.connection.request(ROOT, params=params) return response.status == httplib.OK def ex_create_balancer_listeners(self, name, listeners=None): """ Creates one or more listeners on a load balancer for the specified port :param name: The mnemonic name associated with the load balancer :type name: ``str`` :param listeners: Each tuple contain values, (LoadBalancerPortNumber, InstancePortNumber, Protocol,[SSLCertificateId]) :type listeners: ``list of tuple` """ params = { 'Action': 'CreateLoadBalancerListeners', 'LoadBalancerName': name } for index, listener in enumerate(listeners): i = index + 1 protocol = listener[2].upper() params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0] params['Listeners.member.%d.InstancePort' % i] = listener[1] params['Listeners.member.%d.Protocol' % i] = listener[2] if protocol == 'HTTPS' or protocol == 'SSL': params['Listeners.member.%d. \ SSLCertificateId' % i] = listener[3] else: return False response = self.connection.request(ROOT, params=params) return response.status == httplib.OK def _to_policies(self, data): xpath = 'DescribeLoadBalancerPoliciesResult/PolicyDescriptions/member' return [findtext(element=el, xpath='PolicyName', namespace=NS) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_policy_types(self, data): xpath = 'DescribeLoadBalancerPolicyTypesResult/' xpath += 'PolicyTypeDescriptions/member' return [findtext(element=el, xpath='PolicyTypeName', namespace=NS) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_balancers(self, data): xpath = 'DescribeLoadBalancersResult/LoadBalancerDescriptions/member' return [self._to_balancer(el) for el in findall(element=data, xpath=xpath, namespace=NS)] def _to_balancer(self, el): name = findtext(element=el, xpath='LoadBalancerName', namespace=NS) dns_name = findtext(el, xpath='DNSName', namespace=NS) port = findtext(el, xpath='LoadBalancerPort', namespace=NS) balancer = LoadBalancer( id=name, name=name, state=State.UNKNOWN, ip=dns_name, port=port, driver=self.connection.driver ) xpath = 'Instances/member/InstanceId' members = findall(element=el, xpath=xpath, namespace=NS) balancer._members = [] for m in members: balancer._members.append(Member(m.text, None, None, balancer=balancer)) return balancer def _to_tags(self, data): """ return tags dict """ tags = {} xpath = 'DescribeTagsResult/TagDescriptions/member/Tags/member' for el in findall(element=data, xpath=xpath, namespace=NS): key = findtext(element=el, xpath='Key', namespace=NS) value = findtext(element=el, xpath='Value', namespace=NS) if key: tags[key] = value return tags def _create_list_params(self, params, items, label): """ return parameter list """ if isinstance(items, str): items = [items] for index, item in enumerate(items): params[label % (index + 1)] = item return params def _ex_connection_class_kwargs(self): kwargs = super(ElasticLBDriver, self)._ex_connection_class_kwargs() if hasattr(self, 'token') and self.token is not None: kwargs['token'] = self.token kwargs['signature_version'] = '4' else: kwargs['signature_version'] = self.signature_version return kwargs def _ex_list_balancer_tags(self, balancer_id): params = { 'Action': 'DescribeTags', 'LoadBalancerNames.member.1': balancer_id } data = self.connection.request(ROOT, params=params).object return self._to_tags(data) def _ex_populate_balancer_tags(self, balancer): tags = balancer.extra.get('tags', {}) tags.update(self._ex_list_balancer_tags(balancer.id)) if tags: balancer.extra['tags'] = tags return balancer apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/gce.py0000664000175000017500000003255013535474530023433 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. try: import simplejson as json except ImportError: import json # NOQA from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm from libcloud.compute.drivers.gce import GCEConnection, GCENodeDriver # GCE doesn't actually give you an algorithm choice, but this is here simply as # the closest match. The actual algorithm is described here: # https://developers.google.com/compute/docs/load-balancing/#overview DEFAULT_ALGORITHM = Algorithm.RANDOM class GCELBDriver(Driver): connectionCls = GCEConnection apiname = 'googleapis' name = 'Google Compute Engine Load Balancer' website = 'https://cloud.google.com/' _VALUE_TO_ALGORITHM_MAP = { 'RANDOM': Algorithm.RANDOM } def __init__(self, *args, **kwargs): if kwargs.get('gce_driver'): self.gce = kwargs['gce_driver'] else: self.gce = GCENodeDriver(*args, **kwargs) self.connection = self.gce.connection def _get_node_from_ip(self, ip): """ Return the node object that matches a given public IP address. :param ip: Public IP address to search for :type ip: ``str`` :return: Node object that has the given IP, or None if not found. :rtype: :class:`Node` or None """ all_nodes = self.gce.list_nodes(ex_zone='all') for node in all_nodes: if ip in node.public_ips: return node return None def list_protocols(self): """ Return a list of supported protocols. For GCE, this is simply a hardcoded list. :rtype: ``list`` of ``str`` """ return ['TCP', 'UDP'] def list_balancers(self, ex_region=None): """ List all loadbalancers :keyword ex_region: The region to return balancers from. If None, will default to self.region. If 'all', will return all balancers. :type ex_region: ``str`` or :class:`GCERegion` or ``None`` :rtype: ``list`` of :class:`LoadBalancer` """ balancers = [] for fwr in self.gce.ex_list_forwarding_rules(region=ex_region): balancers.append(self._forwarding_rule_to_loadbalancer(fwr)) return balancers def create_balancer(self, name, port, protocol, algorithm, members, ex_region=None, ex_healthchecks=None, ex_address=None, ex_session_affinity=None): """ Create a new load balancer instance. For GCE, this means creating a forwarding rule and a matching target pool, then adding the members to the target pool. :param name: Name of the new load balancer (required) :type name: ``str`` :param port: Port or range of ports the load balancer should listen on, defaults to all ports. Examples: '80', '5000-5999' :type port: ``str`` :param protocol: Load balancer protocol. Should be 'tcp' or 'udp', defaults to 'tcp'. :type protocol: ``str`` :param members: List of Members to attach to balancer. Can be Member objects or Node objects. Node objects are preferred for GCE, but Member objects are accepted to comply with the established libcloud API. Note that the 'port' attribute of the members is ignored. :type members: ``list`` of :class:`Member` or :class:`Node` :param algorithm: Load balancing algorithm. Ignored for GCE which uses a hashing-based algorithm. :type algorithm: :class:`Algorithm` or ``None`` :keyword ex_region: Optional region to create the load balancer in. Defaults to the default region of the GCE Node Driver. :type ex_region: C{GCERegion} or ``str`` :keyword ex_healthchecks: Optional list of healthcheck objects or names to add to the load balancer. :type ex_healthchecks: ``list`` of :class:`GCEHealthCheck` or ``list`` of ``str`` :keyword ex_address: Optional static address object to be assigned to the load balancer. :type ex_address: C{GCEAddress} :keyword ex_session_affinity: Optional algorithm to use for session affinity. This will modify the hashing algorithm such that a client will tend to stick to a particular Member. :type ex_session_affinity: ``str`` :return: LoadBalancer object :rtype: :class:`LoadBalancer` """ node_list = [] for member in members: # Member object if hasattr(member, 'ip'): if member.extra.get('node'): node_list.append(member.extra['node']) else: node_list.append(self._get_node_from_ip(member.ip)) # Node object elif hasattr(member, 'name'): node_list.append(member) # Assume it's a node name otherwise else: node_list.append(self.gce.ex_get_node(member, 'all')) # Create Target Pool tp_name = '%s-tp' % name targetpool = self.gce.ex_create_targetpool( tp_name, region=ex_region, healthchecks=ex_healthchecks, nodes=node_list, session_affinity=ex_session_affinity) # Create the Forwarding rule, but if it fails, delete the target pool. try: forwarding_rule = self.gce.ex_create_forwarding_rule( name, targetpool, region=ex_region, protocol=protocol, port_range=port, address=ex_address) except Exception: targetpool.destroy() raise # Reformat forwarding rule to LoadBalancer object return self._forwarding_rule_to_loadbalancer(forwarding_rule) def destroy_balancer(self, balancer): """ Destroy a load balancer. For GCE, this means destroying the associated forwarding rule, then destroying the target pool that was attached to the forwarding rule. :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :return: True if successful :rtype: ``bool`` """ destroy = balancer.extra['forwarding_rule'].destroy() if destroy: tp_destroy = balancer.extra['targetpool'].destroy() return tp_destroy else: return destroy def get_balancer(self, balancer_id): """ Return a :class:`LoadBalancer` object. :param balancer_id: Name of load balancer you wish to fetch. For GCE, this is the name of the associated forwarding rule. :param balancer_id: ``str`` :rtype: :class:`LoadBalancer` """ fwr = self.gce.ex_get_forwarding_rule(balancer_id) return self._forwarding_rule_to_loadbalancer(fwr) def balancer_attach_compute_node(self, balancer, node): """ Attach a compute node as a member to the load balancer. :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param node: Node to join to the balancer :type node: :class:`Node` :return: Member after joining the balancer. :rtype: :class:`Member` """ add_node = balancer.extra['targetpool'].add_node(node) if add_node: return self._node_to_member(node, balancer) def balancer_attach_member(self, balancer, member): """ Attach a member to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member to join to the balancer :type member: :class:`Member` :return: Member after joining the balancer. :rtype: :class:`Member` """ node = member.extra.get('node') or self._get_node_from_ip(member.ip) add_node = balancer.extra['targetpool'].add_node(node) if add_node: return self._node_to_member(node, balancer) def balancer_detach_member(self, balancer, member): """ Detach member from balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member which should be used :type member: :class:`Member` :return: True if member detach was successful, otherwise False :rtype: ``bool`` """ node = member.extra.get('node') or self._get_node_from_ip(member.ip) remove_node = balancer.extra['targetpool'].remove_node(node) return remove_node def balancer_list_members(self, balancer): """ Return list of members attached to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :rtype: ``list`` of :class:`Member` """ return [self._node_to_member(n, balancer) for n in balancer.extra['targetpool'].nodes] def ex_create_healthcheck(self, *args, **kwargs): return self.gce.ex_create_healthcheck(*args, **kwargs) def ex_list_healthchecks(self): return self.gce.ex_list_healthchecks() def ex_balancer_attach_healthcheck(self, balancer, healthcheck): """ Attach a healthcheck to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param healthcheck: Healthcheck to add :type healthcheck: :class:`GCEHealthCheck` :return: True if successful :rtype: ``bool`` """ return balancer.extra['targetpool'].add_healthcheck(healthcheck) def ex_balancer_detach_healthcheck(self, balancer, healthcheck): """ Detach healtcheck from balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param healthcheck: Healthcheck to remove :type healthcheck: :class:`GCEHealthCheck` :return: True if successful :rtype: ``bool`` """ return balancer.extra['targetpool'].remove_healthcheck(healthcheck) def ex_balancer_list_healthchecks(self, balancer): """ Return list of healthchecks attached to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :rtype: ``list`` of :class:`HealthChecks` """ return balancer.extra['healthchecks'] def _node_to_member(self, node, balancer): """ Return a Member object based on a Node. :param node: Node object :type node: :class:`Node` :keyword balancer: The balancer the member is attached to. :type balancer: :class:`LoadBalancer` :return: Member object :rtype: :class:`Member` """ # A balancer can have a node as a member, even if the node doesn't # exist. In this case, 'node' is simply a string to where the resource # would be found if it was there. if hasattr(node, 'name'): member_id = node.name else: member_id = node if hasattr(node, 'public_ips') and len(node.public_ips) > 0: member_ip = node.public_ips[0] else: member_ip = None extra = {'node': node} return Member(id=member_id, ip=member_ip, port=balancer.port, balancer=balancer, extra=extra) def _forwarding_rule_to_loadbalancer(self, forwarding_rule): """ Return a Load Balancer object based on a GCEForwardingRule object. :param forwarding_rule: ForwardingRule object :type forwarding_rule: :class:`GCEForwardingRule` :return: LoadBalancer object :rtype: :class:`LoadBalancer` """ extra = {} extra['forwarding_rule'] = forwarding_rule extra['targetpool'] = forwarding_rule.targetpool extra['healthchecks'] = forwarding_rule.targetpool.healthchecks return LoadBalancer(id=forwarding_rule.id, name=forwarding_rule.name, state=None, ip=forwarding_rule.address, port=forwarding_rule.extra['portRange'], driver=self, extra=extra) apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/gogrid.py0000664000175000017500000002025013570310635024134 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import time from libcloud.utils.py3 import httplib try: import simplejson as json except ImportError: import json from libcloud.utils.misc import reverse_dict from libcloud.common.types import LibcloudError from libcloud.common.gogrid import GoGridConnection, GoGridResponse,\ BaseGoGridDriver from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm from libcloud.loadbalancer.base import DEFAULT_ALGORITHM from libcloud.loadbalancer.types import State, LibcloudLBImmutableError class GoGridLBResponse(GoGridResponse): def success(self): if self.status == httplib.INTERNAL_SERVER_ERROR: # Hack, but at least this error message is more useful than # "unexpected server error" body = json.loads(self.body) if body['method'] == '/grid/loadbalancer/add' and \ len(body['list']) >= 1 and \ body['list'][0]['message'].find( 'unexpected server error') != -1: raise LibcloudError( value='You mostly likely tried to add a member with an IP' ' address not assigned to your account', driver=self) return super(GoGridLBResponse, self).success() class GoGridLBConnection(GoGridConnection): """ Connection class for the GoGrid load-balancer driver. """ responseCls = GoGridLBResponse class GoGridLBDriver(BaseGoGridDriver, Driver): connectionCls = GoGridLBConnection api_name = 'gogrid_lb' name = 'GoGrid LB' website = 'http://www.gogrid.com/' LB_STATE_MAP = {'On': State.RUNNING, 'Unknown': State.UNKNOWN} _VALUE_TO_ALGORITHM_MAP = { 'round robin': Algorithm.ROUND_ROBIN, 'least connect': Algorithm.LEAST_CONNECTIONS } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) def __init__(self, *args, **kwargs): """ @inherits: :class:`Driver.__init__` """ super(GoGridLBDriver, self).__init__(*args, **kwargs) def list_protocols(self): # GoGrid only supports http return ['http'] def list_balancers(self): return self._to_balancers( self.connection.request('/api/grid/loadbalancer/list').object) def ex_create_balancer_nowait(self, name, members, protocol='http', port=80, algorithm=DEFAULT_ALGORITHM): """ @inherits: :class:`Driver.create_balancer` """ algorithm = self._algorithm_to_value(algorithm) params = {'name': name, 'loadbalancer.type': algorithm, 'virtualip.ip': self._get_first_ip(), 'virtualip.port': port} params.update(self._members_to_params(members)) resp = self.connection.request('/api/grid/loadbalancer/add', method='GET', params=params) return self._to_balancers(resp.object)[0] def create_balancer(self, name, members, protocol='http', port=80, algorithm=DEFAULT_ALGORITHM): balancer = self.ex_create_balancer_nowait(name, members, protocol, port, algorithm) timeout = 60 * 20 waittime = 0 interval = 2 * 15 if balancer.id is not None: return balancer else: while waittime < timeout: balancers = self.list_balancers() for i in balancers: if i.name == balancer.name and i.id is not None: return i waittime += interval time.sleep(interval) raise Exception('Failed to get id') def destroy_balancer(self, balancer): try: resp = self.connection.request( '/api/grid/loadbalancer/delete', method='POST', params={'id': balancer.id}) except Exception as e: if "Update request for LoadBalancer" in str(e): raise LibcloudLBImmutableError( "Cannot delete immutable object", GoGridLBDriver) else: raise return resp.status == 200 def get_balancer(self, **kwargs): params = {} try: params['name'] = kwargs['ex_balancer_name'] except KeyError: balancer_id = kwargs['balancer_id'] params['id'] = balancer_id resp = self.connection.request('/api/grid/loadbalancer/get', params=params) return self._to_balancers(resp.object)[0] def balancer_attach_member(self, balancer, member): members = self.balancer_list_members(balancer) members.append(member) params = {"id": balancer.id} params.update(self._members_to_params(members)) resp = self._update_balancer(params) return [m for m in self._to_members(resp.object["list"][0]["realiplist"], balancer) if m.ip == member.ip][0] def balancer_detach_member(self, balancer, member): members = self.balancer_list_members(balancer) remaining_members = [n for n in members if n.id != member.id] params = {"id": balancer.id} params.update(self._members_to_params(remaining_members)) resp = self._update_balancer(params) return resp.status == 200 def balancer_list_members(self, balancer): resp = self.connection.request('/api/grid/loadbalancer/get', params={'id': balancer.id}) return self._to_members(resp.object["list"][0]["realiplist"], balancer) def _update_balancer(self, params): try: return self.connection.request('/api/grid/loadbalancer/edit', method='POST', params=params) except Exception as e: if "Update already pending" in str(e): raise LibcloudLBImmutableError( "Balancer is immutable", GoGridLBDriver) raise LibcloudError(value='Exception: %s' % str(e), driver=self) def _members_to_params(self, members): """ Helper method to convert list of :class:`Member` objects to GET params. """ params = {} i = 0 for member in members: params["realiplist.%s.ip" % i] = member.ip params["realiplist.%s.port" % i] = member.port i += 1 return params def _to_balancers(self, object): return [self._to_balancer(el) for el in object["list"]] def _to_balancer(self, el): lb = LoadBalancer(id=el.get("id"), name=el["name"], state=self.LB_STATE_MAP.get( el["state"]["name"], State.UNKNOWN), ip=el["virtualip"]["ip"]["ip"], port=el["virtualip"]["port"], driver=self.connection.driver) return lb def _to_members(self, object, balancer=None): return [self._to_member(el, balancer) for el in object] def _to_member(self, el, balancer=None): member = Member(id=el["ip"]["id"], ip=el["ip"]["ip"], port=el["port"], balancer=balancer) return member apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/ninefold.py0000664000175000017500000000222513535474530024467 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.loadbalancer.providers import Provider from libcloud.loadbalancer.drivers.cloudstack import CloudStackLBDriver class NinefoldLBDriver(CloudStackLBDriver): """Driver for load balancers on Ninefold's Compute platform.""" host = 'api.ninefold.com' path = '/compute/v1.0/' type = Provider.NINEFOLD name = 'Ninefold LB' website = 'http://ninefold.com/' apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/nttcis.py0000664000175000017500000017063113577507766024222 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance withv # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import ET from libcloud.common.nttcis import NttCisConnection from libcloud.common.nttcis import NttCisPool from libcloud.common.nttcis import NttCisPoolMember from libcloud.common.nttcis import NttCisVirtualListener from libcloud.common.nttcis import NttCisVIPNode from libcloud.common.nttcis import NttCisDefaultHealthMonitor from libcloud.common.nttcis import NttCisPersistenceProfile from libcloud.common.nttcis import \ NttCisVirtualListenerCompatibility from libcloud.common.nttcis import NttCisDefaultiRule from libcloud.common.nttcis import API_ENDPOINTS from libcloud.common.nttcis import DEFAULT_REGION from libcloud.common.nttcis import TYPES_URN from libcloud.common.nttcis import process_xml, get_params from libcloud.utils.misc import reverse_dict from libcloud.utils.xml import fixxpath, findtext, findall from libcloud.loadbalancer.types import State from libcloud.loadbalancer.base import Algorithm, Driver, \ LoadBalancer, DEFAULT_ALGORITHM from libcloud.loadbalancer.base import Member from libcloud.loadbalancer.types import Provider class NttCisLBDriver(Driver): """ NttCis LB driver. """ selected_region = None connectionCls = NttCisConnection name = 'NTTC-CIS Load Balancer' website = 'https://cloud.nttcis.com/' type = Provider.NTTCIS api_version = 1.0 _VALUE_TO_ALGORITHM_MAP = { 'ROUND_ROBIN': Algorithm.ROUND_ROBIN, 'LEAST_CONNECTIONS_MEMBER': Algorithm.LEAST_CONNECTIONS_MEMBER, 'LEAST_CONNECTIONS_NODE': Algorithm.LEAST_CONNECTIONS_NODE, 'OBSERVED_MEMBER': Algorithm.OBSERVED_MEMBER, 'OBSERVED_NODE': Algorithm.OBSERVED_NODE, 'PREDICTIVE_MEMBER': Algorithm.PREDICTIVE_MEMBER, 'PREDICTIVE_NODE': Algorithm.PREDICTIVE_NODE } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) _VALUE_TO_STATE_MAP = { 'NORMAL': State.RUNNING, 'PENDING_ADD': State.PENDING, 'PENDING_CHANGE': State.PENDING, 'PENDING_DELETE': State.PENDING, 'FAILED_ADD': State.ERROR, 'FAILED_CHANGE': State.ERROR, 'FAILED_DELETE': State.ERROR, 'REQUIRES_SUPPORT': State.ERROR } def __init__(self, key, network_domain_id, secret=None, secure=True, host=None, port=None, api_version=None, region=DEFAULT_REGION, **kwargs): self.network_domain_id = network_domain_id if region not in API_ENDPOINTS and host is None: raise ValueError( 'Invalid region: %s, no host specified' % (region)) if region is not None: self.selected_region = API_ENDPOINTS[region] super(NttCisLBDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, api_version=api_version, region=region, **kwargs) def _ex_connection_class_kwargs(self): """ Add the region to the kwargs before the connection is instantiated """ kwargs = super(NttCisLBDriver, self)._ex_connection_class_kwargs() kwargs['region'] = self.selected_region return kwargs def create_balancer(self, name, listener_port=None, port=None, protocol=None, algorithm=None, members=None, optimization_profile="TCP", ex_listener_ip_address=None): """ Create a new load balancer instance :param name: Name of the new load balancer (required) :type name: ``str`` :param listener_port: An integer in the range of 1-65535. If not supplied, it will be taken to mean 'Any Port' :type port: ``int :param port: An integer in the range of 1-65535. If not supplied, it will be taken to mean 'Any Port' Assumed that node ports will different from listener port. :type port: ``int`` :param protocol: Loadbalancer protocol, defaults to http. :type protocol: ``str`` :param members: list of Members to attach to balancer (optional) :type members: ``list`` of :class:`Member` :param algorithm: Load balancing algorithm, defaults to ROUND_ROBIN. :type algorithm: :class:`.Algorithm` :param optimization_profile: For STANDARD type and protocol TCP an optimization type of TCP, LAN_OPT, WAN_OPT, MOBILE_OPT, or TCP_LEGACY is required. Default is TCP :type protcol: ``str`` :param ex_listener_ip_address: Must be a valid IPv4 in dot-decimal notation (x.x.x.x). :type ex_listener_ip_address: ``str`` :rtype: :class:`LoadBalancer` """ network_domain_id = self.network_domain_id if protocol is None: protocol = 'http' if algorithm is None: algorithm = DEFAULT_ALGORITHM # Create a pool first pool = self.ex_create_pool( network_domain_id=network_domain_id, name=name, ex_description=None, balancer_method=self._ALGORITHM_TO_VALUE_MAP[algorithm]) # Attach the members to the pool as nodes if members is not None: for member in members: if not isinstance(member, Member): member = self.ex_create_node( network_domain_id=network_domain_id, name=member.name, ip=member.private_ips[0], ex_description=None) self.ex_create_pool_member( pool=pool, node=member, port=port) # Create the virtual listener (balancer) listener = self.ex_create_virtual_listener( network_domain_id=network_domain_id, name=name, ex_description=name, port=listener_port, pool=pool, protocol=protocol, optimization_profile=optimization_profile, listener_ip_address=ex_listener_ip_address) return LoadBalancer( id=listener.id, name=listener.name, state=State.RUNNING, ip=listener.ip, port=port, driver=self, extra={'pool_id': pool.id, 'network_domain_id': network_domain_id, 'listener_ip_address': ex_listener_ip_address} ) def ex_update_listener(self, virtual_listener, **kwargs): """ Update a current virtual listener. :param virtual_listener: The listener to be updated :return: The edited version of the listener """ edit_listener_elm = ET.Element('editVirtualListener', {'xmlns': TYPES_URN, 'id': virtual_listener.id, 'xmlns:xsi': "http://www.w3.org/2001/" "XMLSchema-instance"}) for k, v in kwargs.items(): if v is None: ET.SubElement(edit_listener_elm, k, {'xsi:nil': 'true'}) else: ET.SubElement(edit_listener_elm, k).text = v result = self.connection.request_with_orgId_api_2( 'networkDomainVip/editVirtualListener', method='POST', data=ET.tostring(edit_listener_elm)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def list_balancers(self, ex_network_domain_id=None): """ List all loadbalancers inside a geography or in given network. In NTTC-CIS terminology these are known as virtual listeners :param ex_network_domain_id: UUID of Network Domain if not None returns only balancers in the given network if None then returns all pools for the organization :type ex_network_domain_id: ``str`` :rtype: ``list`` of :class:`LoadBalancer` """ params = None if ex_network_domain_id is not None: params = {"networkDomainId": ex_network_domain_id} return self._to_balancers( self.connection .request_with_orgId_api_2('networkDomainVip/virtualListener', params=params).object) def get_balancer(self, balancer_id): """ Return a :class:`LoadBalancer` object. :param balancer_id: id of a load balancer you want to fetch :type balancer_id: ``str`` :rtype: :class:`LoadBalancer` """ bal = self.connection \ .request_with_orgId_api_2('networkDomainVip/virtualListener/%s' % balancer_id).object return self._to_balancer(bal) def list_protocols(self): """ Return a list of supported protocols. Since all protocols are support by NTTC-CIS, this is a list of common protocols. :rtype: ``list`` of ``str`` """ return ['http', 'https', 'tcp', 'udp', 'ftp', 'smtp'] def balancer_list_members(self, balancer): """ Return list of members attached to balancer. In NTTC-CIS terminology these are the members of the pools within a virtual listener. :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :rtype: ``list`` of :class:`Member` """ pool_members = self.ex_get_pool_members(balancer.extra['pool_id']) members = [] for pool_member in pool_members: members.append(Member( id=pool_member.id, ip=pool_member.ip, port=pool_member.port, balancer=balancer, extra=None )) return members def balancer_attach_member(self, balancer, member): """ Attach a member to balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member to join to the balancer :type member: :class:`Member` :return: Member after joining the balancer. :rtype: :class:`Member` """ node = self.ex_create_node( network_domain_id=balancer.extra['network_domain_id'], name='Member.' + member.ip, ip=member.ip, ex_description='' ) if node is False: return False pool = self.ex_get_pool(balancer.extra['pool_id']) pool_member = self.ex_create_pool_member( pool=pool, node=node, port=member.port) member.id = pool_member.id return member def balancer_detach_member(self, balancer, member): """ Detach member from balancer :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :param member: Member which should be used :type member: :class:`Member` :return: ``True`` if member detach was successful, otherwise ``False``. :rtype: ``bool`` """ create_pool_m = ET.Element('removePoolMember', {'xmlns': TYPES_URN, 'id': member.id}) result = self.connection.request_with_orgId_api_2( 'networkDomainVip/removePoolMember', method='POST', data=ET.tostring(create_pool_m)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def destroy_balancer(self, balancer): """ Destroy a load balancer (virtual listener) :param balancer: LoadBalancer which should be used :type balancer: :class:`LoadBalancer` :return: ``True`` if the destroy was successful, otherwise ``False``. :rtype: ``bool`` """ delete_listener = ET.Element('deleteVirtualListener', {'xmlns': TYPES_URN, 'id': balancer.id}) result = self.connection.request_with_orgId_api_2( 'networkDomainVip/deleteVirtualListener', method='POST', data=ET.tostring(delete_listener)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_set_current_network_domain(self, network_domain_id): """ Set the network domain (part of the network) of the driver :param network_domain_id: ID of the pool (required) :type network_domain_id: ``str`` """ self.network_domain_id = network_domain_id def ex_get_current_network_domain(self): """ Get the current network domain ID of the driver. :return: ID of the network domain :rtype: ``str`` """ return self.network_domain_id def ex_create_pool_member(self, pool, node, port=None): """ Create a new member in an existing pool from an existing node :param pool: Instance of ``NttCisPool`` (required) :type pool: ``NttCisPool`` :param node: Instance of ``NttCisVIPNode`` (required) :type node: ``NttCisVIPNode`` :param port: Port the the service will listen on :type port: ``str`` :return: The node member, instance of ``NttCisPoolMember`` :rtype: ``NttCisPoolMember`` """ create_pool_m = ET.Element('addPoolMember', {'xmlns': TYPES_URN}) ET.SubElement(create_pool_m, "poolId").text = pool.id ET.SubElement(create_pool_m, "nodeId").text = node.id if port is not None: ET.SubElement(create_pool_m, "port").text = str(port) ET.SubElement(create_pool_m, "status").text = 'ENABLED' response = self.connection.request_with_orgId_api_2( 'networkDomainVip/addPoolMember', method='POST', data=ET.tostring(create_pool_m)).object member_id = None node_name = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'poolMemberId': member_id = info.get('value') if info.get('name') == 'nodeName': node_name = info.get('value') return NttCisPoolMember( id=member_id, name=node_name, status=State.RUNNING, ip=node.ip, port=port, node_id=node.id ) def ex_create_node(self, network_domain_id, name, ip, ex_description=None, connection_limit=25000, connection_rate_limit=2000): """ Create a new node :param network_domain_id: Network Domain ID (required) :type name: ``str`` :param name: name of the node (required) :type name: ``str`` :param ip: IPv4 address of the node (required) :type ip: ``str`` :param ex_description: Description of the node (required) :type ex_description: ``str`` :param connection_limit: Maximum number of concurrent connections per sec :type connection_limit: ``int`` :param connection_rate_limit: Maximum number of concurrent sessions :type connection_rate_limit: ``int`` :return: Instance of ``NttCisVIPNode`` :rtype: ``NttCisVIPNode`` """ create_node_elm = ET.Element('createNode', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "networkDomainId") \ .text = network_domain_id ET.SubElement(create_node_elm, "name").text = name if ex_description is not None: ET.SubElement(create_node_elm, "description").text \ = str(ex_description) ET.SubElement(create_node_elm, "ipv4Address").text = ip ET.SubElement(create_node_elm, "status").text = 'ENABLED' ET.SubElement(create_node_elm, "connectionLimit") \ .text = str(connection_limit) ET.SubElement(create_node_elm, "connectionRateLimit") \ .text = str(connection_rate_limit) response = self.connection.request_with_orgId_api_2( action='networkDomainVip/createNode', method='POST', data=ET.tostring(create_node_elm)).object node_id = None node_name = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'nodeId': node_id = info.get('value') if info.get('name') == 'name': node_name = info.get('value') return NttCisVIPNode( id=node_id, name=node_name, status=State.RUNNING, ip=ip ) def ex_update_node(self, node): """ Update the properties of a node :param pool: The instance of ``NttCisNode`` to update :type pool: ``NttCisNode`` :return: The instance of ``NttCisNode`` :rtype: ``NttCisNode`` """ create_node_elm = ET.Element('editNode', {'xmlns': TYPES_URN}) create_node_elm.set('id', node.id) ET.SubElement(create_node_elm, 'healthMonitorId') \ .text = node.health_monitor_id ET.SubElement(create_node_elm, "connectionLimit") \ .text = str(node.connection_limit) ET.SubElement(create_node_elm, "connectionRateLimit") \ .text = str(node.connection_rate_limit) self.connection.request_with_orgId_api_2( action='networkDomainVip/editNode', method='POST', data=ET.tostring(create_node_elm)).object return node def ex_set_node_state(self, node, enabled): """ Change the state of a node (enable/disable) :param pool: The instance of ``NttCisNode`` to update :type pool: ``NttCisNode`` :param enabled: The target state of the node :type enabled: ``bool`` :return: The instance of ``NttCisNode`` :rtype: ``NttCisNode`` """ create_node_elm = ET.Element('editNode', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "status") \ .text = "ENABLED" if enabled is True else "DISABLED" self.connection.request_with_orgId_api_2( action='networkDomainVip/editNode', method='POST', data=ET.tostring(create_node_elm)).object return node def ex_create_pool(self, network_domain_id, name, balancer_method, ex_description, health_monitors=None, service_down_action='NONE', slow_ramp_time=30): """ Create a new pool :param network_domain_id: Network Domain ID (required) :type name: ``str`` :param name: name of the node (required) :type name: ``str`` :param balancer_method: The load balancer algorithm (required) :type balancer_method: ``str`` :param ex_description: Description of the node (required) :type ex_description: ``str`` :param health_monitors: A list of health monitors to use for the pool. :type health_monitors: ``list`` of :class:`NttCisDefaultHealthMonitor` :param service_down_action: What to do when node is unavailable NONE, DROP or RESELECT :type service_down_action: ``str`` :param slow_ramp_time: Number of seconds to stagger ramp up of nodes :type slow_ramp_time: ``int`` :return: Instance of ``NttCisPool`` :rtype: ``NttCisPool`` """ # Names cannot contain spaces. name.replace(' ', '_') create_node_elm = ET.Element('createPool', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "networkDomainId") \ .text = network_domain_id ET.SubElement(create_node_elm, "name").text = name ET.SubElement(create_node_elm, "description").text \ = str(ex_description) ET.SubElement(create_node_elm, "loadBalanceMethod") \ .text = str(balancer_method) if health_monitors is not None: for monitor in health_monitors: ET.SubElement(create_node_elm, "healthMonitorId") \ .text = str(monitor.id) ET.SubElement(create_node_elm, "serviceDownAction") \ .text = service_down_action ET.SubElement(create_node_elm, "slowRampTime").text \ = str(slow_ramp_time) response = self.connection.request_with_orgId_api_2( action='networkDomainVip/createPool', method='POST', data=ET.tostring(create_node_elm)).object pool_id = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'poolId': pool_id = info.get('value') return NttCisPool( id=pool_id, name=name, description=ex_description, status=State.RUNNING, load_balance_method=str(balancer_method), health_monitor_id=None, service_down_action=service_down_action, slow_ramp_time=str(slow_ramp_time) ) def ex_create_virtual_listener(self, network_domain_id, name, ex_description, port=None, pool=None, listener_ip_address=None, persistence_profile=None, fallback_persistence_profile=None, irule=None, protocol='TCP', optimization_profile="TCP", connection_limit=25000, connection_rate_limit=2000, source_port_preservation='PRESERVE'): """ Create a new virtual listener (load balancer) :param network_domain_id: Network Domain ID (required) :type name: ``str`` :param name: name of the listener (required) :type name: ``str`` :param ex_description: Description of the node (required) :type ex_description: ``str`` :param port: An integer in the range of 1-65535. If not supplied, it will be taken to mean 'Any Port' :type port: ``int`` :param pool: The pool to use for the listener :type pool: :class:`NttCisPool` :param listener_ip_address: The IPv4 Address of the virtual listener :type listener_ip_address: ``str`` :param persistence_profile: Persistence profile :type persistence_profile: :class:`NttCisPersistenceProfile` :param fallback_persistence_profile: Fallback persistence profile :type fallback_persistence_profile: :class:`NttCisPersistenceProfile` :param irule: The iRule to apply :type irule: :class:`NttCisDefaultiRule` :param protocol: For STANDARD type, ANY, TCP or UDP for PERFORMANCE_LAYER_4 choice of ANY, TCP, UDP, HTTP :type protcol: ``str`` :param optimization_profile: For STANDARD type and protocol TCP an optimization type of TCP, LAN_OPT, WAN_OPT, MOBILE_OPT, or TCP_LEGACY is required. Default is 'TCP'. :type protcol: ``str`` :param connection_limit: Maximum number of concurrent connections per sec :type connection_limit: ``int`` :param connection_rate_limit: Maximum number of concurrent sessions :type connection_rate_limit: ``int`` :param source_port_preservation: Choice of PRESERVE, PRESERVE_STRICT or CHANGE :type source_port_preservation: ``str`` :return: Instance of the listener :rtype: ``NttCisVirtualListener`` """ if (port == 80) or (port == 443): listener_type = 'PERFORMANCE_LAYER_4' else: listener_type = 'STANDARD' if listener_type == 'STANDARD' and optimization_profile is None: raise ValueError( " CONFIGURATION_NOT_SUPPORTED: optimizationProfile is" " required for type STANDARD and protocol TCP") create_node_elm = ET.Element('createVirtualListener', {'xmlns': TYPES_URN}) ET.SubElement(create_node_elm, "networkDomainId") \ .text = network_domain_id ET.SubElement(create_node_elm, "name").text = name ET.SubElement(create_node_elm, "description").text = \ str(ex_description) ET.SubElement(create_node_elm, "type").text = listener_type ET.SubElement(create_node_elm, "protocol") \ .text = protocol if listener_ip_address is not None: ET.SubElement(create_node_elm, "listenerIpAddress").text = \ str(listener_ip_address) if port is not None: ET.SubElement(create_node_elm, "port").text = str(port) ET.SubElement(create_node_elm, "enabled").text = 'true' ET.SubElement(create_node_elm, "connectionLimit") \ .text = str(connection_limit) ET.SubElement(create_node_elm, "connectionRateLimit") \ .text = str(connection_rate_limit) ET.SubElement(create_node_elm, "sourcePortPreservation") \ .text = source_port_preservation if pool is not None: ET.SubElement(create_node_elm, "poolId") \ .text = pool.id if persistence_profile is not None: ET.SubElement(create_node_elm, "persistenceProfileId") \ .text = persistence_profile.id if optimization_profile is not None: ET.SubElement(create_node_elm, 'optimizationProfile').text = \ optimization_profile if fallback_persistence_profile is not None: ET.SubElement(create_node_elm, "fallbackPersistenceProfileId") \ .text = fallback_persistence_profile.id if irule is not None: ET.SubElement(create_node_elm, "iruleId") \ .text = irule.id response = self.connection.request_with_orgId_api_2( action='networkDomainVip/createVirtualListener', method='POST', data=ET.tostring(create_node_elm)).object virtual_listener_id = None virtual_listener_ip = None for info in findall(response, 'info', TYPES_URN): if info.get('name') == 'virtualListenerId': virtual_listener_id = info.get('value') if info.get('name') == 'listenerIpAddress': virtual_listener_ip = info.get('value') return NttCisVirtualListener( id=virtual_listener_id, name=name, ip=virtual_listener_ip, status=State.RUNNING ) def ex_import_ssl_domain_certificate(self, network_domain_id, name, crt_file, key_file, description=None): """ Import an ssl cert for ssl offloading onto the the load balancer :param network_domain_id: The Network Domain's Id. :type network_domain_id: ``str`` :param name: The name of the ssl certificate :type name: ``str`` :param crt_file: The complete path to the certificate file :type crt_file: ``str`` :param key_file: The complete pathy to the key file :type key_file: ``str`` :param description: (Optional) A description of the certificate :type `description: `str`` :return: ``bool`` """ try: import OpenSSL except ImportError: raise ImportError('Missing "OpenSSL" dependency. You can install ' 'it using pip - pip install pyopenssl') with open(crt_file) as fp: c = OpenSSL.crypto.load_certificate( OpenSSL.crypto.FILETYPE_PEM, fp.read()) cert = OpenSSL.crypto.dump_certificate( OpenSSL.crypto.FILETYPE_PEM, c).decode(encoding='utf-8') with open(key_file) as fp: k = OpenSSL.crypto.load_privatekey( OpenSSL.crypto.FILETYPE_PEM, fp.read()) key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, k) \ .decode(encoding='utf-8') cert_elem = ET.Element("importSslDomainCertificate", {"xmlns": TYPES_URN}) ET.SubElement(cert_elem, "networkDomainId").text = network_domain_id ET.SubElement(cert_elem, "name").text = name if description is not None: ET.SubElement(cert_elem, "description").text = description ET.SubElement(cert_elem, "key").text = key ET.SubElement(cert_elem, "certificate").text = cert result = self.connection.request_with_orgId_api_2( 'networkDomainVip/importSslDomainCertificate', method='POST', data=ET.tostring(cert_elem)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_ssl_domain_certificate(self, dom_cert_id): """ Deletes an SSL domain certificate :param dom_cert_id: Id of certificate to delete :type dom_cert_id: ``str`` :return: ``bool`` """ del_dom_cert_elem = ET.Element("deleteSslDomainCertificate", {"id": dom_cert_id, "xmlns": TYPES_URN}) result = self.connection.request_with_orgId_api_2( 'networkDomainVip/deleteSslDomainCertificate', method='POST', data=ET.tostring(del_dom_cert_elem)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_import_ssl_cert_chain(self, network_domain_id, name, chain_crt_file, description=None): """ Import an ssl certificate chain for ssl offloading onto the the load balancer :param network_domain_id: The Network Domain's Id. :type network_domain_id: ``str`` :param name: The name of the ssl certificate chain :type name: ``str`` :param chain_crt_file: The complete path to the certificate chain file :type chain_crt_file: ``str`` :param description: (Optional) A description of the certificate chain :type description: ``str`` :return: ``bool`` """ try: import OpenSSL from OpenSSL import crypto except ImportError: raise ImportError('Missing "OpenSSL" dependency. You can install ' 'it using pip - pip install pyopenssl') c = crypto.load_certificate( crypto.FILETYPE_PEM, open(chain_crt_file).read()) cert = OpenSSL.crypto.dump_certificate( crypto.FILETYPE_PEM, c).decode(encoding='utf-8') cert_chain_elem = ET.Element("importSslCertificateChain", {"xmlns": TYPES_URN}) ET.SubElement(cert_chain_elem, "networkDomainId") \ .text = network_domain_id ET.SubElement(cert_chain_elem, "name").text = name if description is not None: ET.SubElement(cert_chain_elem, "description").text = description ET.SubElement(cert_chain_elem, "certificateChain").text = cert result = self.connection.request_with_orgId_api_2( "networkDomainVip/importSslCertificateChain", method="POST", data=ET.tostring(cert_chain_elem)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_ssl_certificate_chain(self, cert_chain_id): """ Deletes a certificate chain :param cert_chain_id: Id of certificate chain to delete :type cert_chain_id: ``str`` :return ``bool`` """ del_cert_chain_elem = ET.Element("deleteSslCertificateChain", {"id": cert_chain_id, "xmlns": TYPES_URN}) result = self.connection.request_with_orgId_api_2( "networkDomainVip/deleteSslCertificateChain", method="POST", data=ET.tostring(del_cert_chain_elem)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_create_ssl_offload_profile(self, netowrk_domain_id, name, ssl_domain_cert_id, description=None, ciphers=None, ssl_cert_chain_id=None): """ Creates an SSL Offload profile :param network_domain_id: The network domain's Id :type netowrk_domain_id: ``str`` :param name: Offload profile's name :type name: ``str`` :param ssl_domain_cert_id: Certificate's Id :type ssl_domain_cert_id: ``str`` :param description: (Optional) Profile's description :type description: ``str`` :param ciphers: (Optional) The default cipher string is: "MEDIUM:HIGH:!EXPORT:!ADH:!MD5:!RC4:!SSLv2:!SSLv3: !ECDHE+AES-GCM:!ECDHE+AES:!ECDHE+3DES:!ECDHE_ECDSA: !ECDH_RSA:!ECDH_ECDSA:@SPEED" It is possible to choose just a subset of this string :type ciphers: ``str`` :param ssl_cert_chain_id: (Optional) Bind the certificate chain to the profile. :type ssl_cert_chain_id: `str`` :returns: ``bool`` """ ssl_offload_elem = ET.Element("createSslOffloadProfile", {"xmlns": TYPES_URN}) ET.SubElement(ssl_offload_elem, "networkDomainId")\ .text = netowrk_domain_id ET.SubElement(ssl_offload_elem, "name").text = name if description is not None: ET.SubElement(ssl_offload_elem, "description")\ .text = description if ciphers is not None: ET.SubElement(ssl_offload_elem, "ciphers").text = ciphers ET.SubElement(ssl_offload_elem, "sslDomainCertificateId") \ .text = ssl_domain_cert_id if ssl_cert_chain_id is not None: ET.SubElement(ssl_offload_elem, "sslCertificateChainId") \ .text = ssl_cert_chain_id result = self.connection.request_with_orgId_api_2( "networkDomainVip/createSslOffloadProfile", method="POST", data=ET.tostring(ssl_offload_elem)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_edit_ssl_offload_profile(self, profile_id, name, ssl_domain_cert_id, description=None, ciphers=None, ssl_cert_chain_id=None): """ The function edits the ssl offload profile :param profil_id: The id of the profile to be edited :type profile_id: ``str`` :param name: The name of the profile, new name or previous name :type name: ``str`` :param ssl_domain_cert_id: The certificate id to use, new or current :type ssl_domain_cert_id: ``str`` :param description: (Optional) Profile's description :type description: ``str`` :param ciphers: (Optional) String of acceptable ciphers to use :type ciphers: ``str`` :param ssl_cert_chain_id: If using a certificate chain or changing to a new one :type: ssl_cert_chain_id: ``str`` :returns: ``bool`` """ ssl_offload_elem = ET.Element("editSslOffloadProfile", {"xmlns": TYPES_URN, "id": profile_id}) ET.SubElement(ssl_offload_elem, "name").text = name if description is not None: ET.SubElement(ssl_offload_elem, "description").text = description if ciphers is not None: ET.SubElement(ssl_offload_elem, "ciphers").text = ciphers ET.SubElement(ssl_offload_elem, "sslDomainCertificateId") \ .text = ssl_domain_cert_id if ssl_cert_chain_id is not None: ET.SubElement(ssl_offload_elem, "sslCertificateChainId") \ .text = ssl_cert_chain_id result = self.connection.request_with_orgId_api_2( "networkDomainVip/editSslOffloadProfile", method="POST", data=ET.tostring(ssl_offload_elem)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_delete_ssl_offload_profile(self, profile_id): """ Delete an offload profile :param profile_id: Id of profile to be deleted :type profile_id: ``str`` :returns: ``bool`` """ del_profile_elem = ET.Element("deleteSslOffloadProfile", {"id": profile_id, "xmlns": TYPES_URN}) result = self.connection.request_with_orgId_api_2( "networkDomainVip/deleteSslOffloadProfile", method="POST", data=ET.tostring(del_profile_elem)).object response_code = findtext(result, "responseCode", TYPES_URN) return response_code in ["IN_PROGRESS", "OK"] def ex_get_pools(self, ex_network_domain_id=None): """ Get all of the pools inside the current geography or in given network. :param ex_network_domain_id: UUID of Network Domain if not None returns only balancers in the given network if None then returns all pools for the organization :type ex_network_domain_id: ``str`` :return: Returns a ``list`` of type ``NttCisPool`` :rtype: ``list`` of ``NttCisPool`` """ params = None if ex_network_domain_id is not None: params = {"networkDomainId": ex_network_domain_id} pools = self.connection \ .request_with_orgId_api_2('networkDomainVip/pool', params=params).object return self._to_pools(pools) def ex_get_pool(self, pool_id): """ Get a specific pool inside the current geography :param pool_id: The identifier of the pool :type pool_id: ``str`` :return: Returns an instance of ``NttCisPool`` :rtype: ``NttCisPool`` """ pool = self.connection \ .request_with_orgId_api_2('networkDomainVip/pool/%s' % pool_id).object return self._to_pool(pool) def ex_update_pool(self, pool): """ Update the properties of an existing pool only method, serviceDownAction and slowRampTime are updated :param pool: The instance of ``NttCisPool`` to update :type pool: ``NttCisPool`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ create_node_elm = ET.Element('editPool', {'xmlns': TYPES_URN}) create_node_elm.set('id', pool.id) ET.SubElement(create_node_elm, "loadBalanceMethod") \ .text = str(pool.load_balance_method) ET.SubElement(create_node_elm, 'healthMonitorId').text \ = pool.health_monitor_id ET.SubElement(create_node_elm, "serviceDownAction") \ .text = pool.service_down_action ET.SubElement(create_node_elm, "slowRampTime").text \ = str(pool.slow_ramp_time) response = self.connection.request_with_orgId_api_2( action='networkDomainVip/editPool', method='POST', data=ET.tostring(create_node_elm)).object response_code = findtext(response, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_destroy_pool(self, pool): """ Destroy an existing pool :param pool: The instance of ``NttCisPool`` to destroy :type pool: ``NttCisPool`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ destroy_request = ET.Element('deletePool', {'xmlns': TYPES_URN, 'id': pool.id}) result = self.connection.request_with_orgId_api_2( action='networkDomainVip/deletePool', method='POST', data=ET.tostring(destroy_request)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_pool_members(self, pool_id): """ Get the members of a pool :param pool: The instance of a pool :type pool: ``NttCisPool`` :returns: Returns an ``list`` of ``NttCisPoolMember`` :rtype: ``list`` of ``NttCisPoolMember`` """ members = self.connection \ .request_with_orgId_api_2('networkDomainVip/poolMember?poolId=%s' % pool_id).object return self._to_members(members) def ex_get_pool_member(self, pool_member_id): """ Get a specific member of a pool :param pool: The id of a pool member :type pool: ``str`` :return: Returns an instance of ``NttCisPoolMember`` :rtype: ``NttCisPoolMember`` """ member = self.connection \ .request_with_orgId_api_2('networkDomainVip/poolMember/%s' % pool_member_id).object return self._to_member(member) def ex_set_pool_member_state(self, member, enabled=True): request = ET.Element('editPoolMember', {'xmlns': TYPES_URN, 'id': member.id}) state = "ENABLED" if enabled is True else "DISABLED" ET.SubElement(request, 'status').text = state result = self.connection.request_with_orgId_api_2( action='networkDomainVip/editPoolMember', method='POST', data=ET.tostring(request)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_destroy_pool_member(self, member, destroy_node=False): """ Destroy a specific member of a pool :param pool: The instance of a pool member :type pool: ``NttCisPoolMember`` :param destroy_node: Also destroy the associated node :type destroy_node: ``bool`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ # remove the pool member destroy_request = ET.Element('removePoolMember', {'xmlns': TYPES_URN, 'id': member.id}) result = self.connection.request_with_orgId_api_2( action='networkDomainVip/removePoolMember', method='POST', data=ET.tostring(destroy_request)).object if member.node_id is not None and destroy_node is True: return self.ex_destroy_node(member.node_id) else: response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_get_nodes(self, ex_network_domain_id=None): """ Get the nodes within this geography or in given network. :param ex_network_domain_id: UUID of Network Domain if not None returns only balancers in the given network if None then returns all pools for the organization :type ex_network_domain_id: ``str`` :return: Returns an ``list`` of ``NttCisVIPNode`` :rtype: ``list`` of ``NttCisVIPNode`` """ params = None if ex_network_domain_id is not None: params = {"networkDomainId": ex_network_domain_id} nodes = self.connection \ .request_with_orgId_api_2('networkDomainVip/node', params=params).object return self._to_nodes(nodes) def ex_get_node(self, node_id): """ Get the node specified by node_id :return: Returns an instance of ``NttCisVIPNode`` :rtype: Instance of ``NttCisVIPNode`` """ nodes = self.connection \ .request_with_orgId_api_2('networkDomainVip/node/%s' % node_id).object return self._to_node(nodes) def ex_destroy_node(self, node_id): """ Destroy a specific node :param node_id: The ID of of a ``NttCisVIPNode`` :type node_id: ``str`` :return: ``True`` for success, ``False`` for failure :rtype: ``bool`` """ # Destroy the node destroy_request = ET.Element('deleteNode', {'xmlns': TYPES_URN, 'id': node_id}) result = self.connection.request_with_orgId_api_2( action='networkDomainVip/deleteNode', method='POST', data=ET.tostring(destroy_request)).object response_code = findtext(result, 'responseCode', TYPES_URN) return response_code in ['IN_PROGRESS', 'OK'] def ex_wait_for_state(self, state, func, poll_interval=2, timeout=60, *args, **kwargs): """ Wait for the function which returns a instance with field status to match Keep polling func until one of the desired states is matched :param state: Either the desired state (`str`) or a `list` of states :type state: ``str`` or ``list`` :param func: The function to call, e.g. ex_get_vlan :type func: ``function`` :param poll_interval: The number of seconds to wait between checks :type poll_interval: `int` :param timeout: The total number of seconds to wait to reach a state :type timeout: `int` :param args: The arguments for func :type args: Positional arguments :param kwargs: The arguments for func :type kwargs: Keyword arguments """ return self.connection.wait_for_state(state, func, poll_interval, timeout, *args, **kwargs) def ex_get_default_health_monitors(self, network_domain): """ Get the default health monitors available for a network domain :param network_domain_id: The ID of of a ``NttCisNetworkDomain`` :type network_domain_id: ``str`` :rtype: `list` of :class:`NttCisDefaultHealthMonitor` """ result = self.connection.request_with_orgId_api_2( action='networkDomainVip/defaultHealthMonitor', params={'networkDomainId': network_domain}, method='GET').object return self._to_health_monitors(result) def ex_get_default_persistence_profiles(self, network_domain_id): """ Get the default persistence profiles available for a network domain :param network_domain_id: The ID of of a ``NttCisNetworkDomain`` :type network_domain_id: ``str`` :rtype: `list` of :class:`NttCisPersistenceProfile` """ result = self.connection.request_with_orgId_api_2( action='networkDomainVip/defaultPersistenceProfile', params={'networkDomainId': network_domain_id}, method='GET').object return self._to_persistence_profiles(result) def ex_get_default_irules(self, network_domain_id): """ Get the default iRules available for a network domain :param network_domain_id: The ID of of a ``NttCisNetworkDomain`` :type network_domain_id: ``str`` :rtype: `list` of :class:`NttCisDefaultiRule` """ result = self.connection.request_with_orgId_api_2( action='networkDomainVip/defaultIrule', params={'networkDomainId': network_domain_id}, method='GET').object return self._to_irules(result) @get_params def ex_list_ssl_domain_certs(self, params={}): """ Functions takes a named parameter that can be one or none of the following :param params: A sequence of comma separated keyword arguments and a value * id= * network_domain_id= * name= * state= * create_time= * expiry_time= :returns: `list` of :class: `NttCisDomaincertificate` """ result = self.connection.request_with_orgId_api_2( action="networkDomainVip/sslDomainCertificate", params=params, method="GET").object return self._to_certs(result) def ex_get_ssl_domain_cert(self, cert_id): """ Function gets the cert by id. Use this if only if the id is already known :param cert_id: The id of the specific cert :type cert_id: ``str`` :returns: :class: `NttCisdomaincertificate """ result = self.connection.request_with_orgId_api_2( action="networkDomainVip/sslDomainCertificate/%s" % cert_id, method="GET").object return self._to_cert(result) @get_params def ex_list_ssl_certificate_chains(self, params={}): """ Functions takes a named parameter that can be one or none of the following to filter returned items :param params: A sequence of comma separated keyword arguments and a value * id= * network_domain_id= * name= * state= * create_time= * expiry_time= :return: `list` of :class: `NttCissslcertficiatechain` """ result = self.connection.request_with_orgId_api_2( action="networkDomainVip/sslCertificateChain", params=params, method="GET").object return self._to_certificate_chains(result) def ex_get_ssl_certificate_chain(self, chain_id): """ Function gets the certificate chain by id. Use this if only if the id is already known :param cert_id: The id of the specific cert :return: :class: `NttCiscertificatechain """ result = self.connection.request_with_orgId_api_2( action="networkDomainVip/sslCertificateChain/%s" % chain_id, method="GET").object return self._to_certificate_chain(result) @get_params def ex_list_ssl_offload_profiles(self, params={}): """ Functions takes a named parameter that can be one or none of the following to filter returned items :param params: A sequence of comma separated keyword arguments and a value * id= * network_domain_id= * datacenter_id= * name= * state= * ssl_domain_certificate_id= * ssl_domain_certificate_name= * ssl_certificate_chain_id= * ssl_certificate_chain_name= * create_time= :return: `list` of :class: `NttCisSslssloffloadprofile` """ result = self.connection.request_with_orgId_api_2( action="networkDomainVip/sslOffloadProfile", params=params, method="GET").object return self._to_ssl_profiles(result) def ex_get_ssl_offload_profile(self, profile_id): result = self.connection.request_with_orgId_api_2( action="networkDomainVip/sslOffloadProfile/%s" % profile_id, method="GET").object return self._to_ssl_profile(result) def _to_irules(self, object): irules = [] matches = object.findall( fixxpath('defaultIrule', TYPES_URN)) for element in matches: irules.append(self._to_irule(element)) return irules def _to_irule(self, element): compatible = [] matches = element.findall( fixxpath('virtualListenerCompatibility', TYPES_URN)) for match_element in matches: compatible.append( NttCisVirtualListenerCompatibility( type=match_element.get('type'), protocol=match_element.get('protocol', None))) irule_element = element.find(fixxpath('irule', TYPES_URN)) return NttCisDefaultiRule( id=irule_element.get('id'), name=irule_element.get('name'), compatible_listeners=compatible ) def _to_persistence_profiles(self, object): profiles = [] matches = object.findall( fixxpath('defaultPersistenceProfile', TYPES_URN)) for element in matches: profiles.append(self._to_persistence_profile(element)) return profiles def _to_persistence_profile(self, element): compatible = [] matches = element.findall( fixxpath('virtualListenerCompatibility', TYPES_URN)) for match_element in matches: compatible.append( NttCisVirtualListenerCompatibility( type=match_element.get('type'), protocol=match_element.get('protocol', None))) return NttCisPersistenceProfile( id=element.get('id'), fallback_compatible=bool( element.get('fallbackCompatible') == "true"), name=findtext(element, 'name', TYPES_URN), compatible_listeners=compatible ) def _to_health_monitors(self, object): monitors = [] matches = object.findall(fixxpath('defaultHealthMonitor', TYPES_URN)) for element in matches: monitors.append(self._to_health_monitor(element)) return monitors def _to_health_monitor(self, element): return NttCisDefaultHealthMonitor( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), node_compatible=bool( findtext(element, 'nodeCompatible', TYPES_URN) == "true"), pool_compatible=bool( findtext(element, 'poolCompatible', TYPES_URN) == "true"), ) def _to_nodes(self, object): nodes = [] for element in object.findall(fixxpath("node", TYPES_URN)): nodes.append(self._to_node(element)) return nodes def _to_node(self, element): ipaddress = findtext(element, 'ipv4Address', TYPES_URN) if ipaddress is None: ipaddress = findtext(element, 'ipv6Address', TYPES_URN) name = findtext(element, 'name', TYPES_URN) try: hm = element.find(fixxpath('healthMonitor', TYPES_URN)).get('id') except AttributeError: hm = None node = NttCisVIPNode( id=element.get('id'), name=name, status=self._VALUE_TO_STATE_MAP.get( findtext(element, 'state', TYPES_URN), State.UNKNOWN), health_monitor=hm, connection_rate_limit=findtext(element, 'connectionRateLimit', TYPES_URN), connection_limit=findtext(element, 'connectionLimit', TYPES_URN), ip=ipaddress) return node def _to_balancers(self, object): loadbalancers = [] for element in object.findall(fixxpath("virtualListener", TYPES_URN)): loadbalancers.append(self._to_balancer(element)) return loadbalancers def _to_balancer(self, element): ipaddress = findtext(element, 'listenerIpAddress', TYPES_URN) name = findtext(element, 'name', TYPES_URN) port = findtext(element, 'port', TYPES_URN) extra = {} pool_element = element.find(fixxpath( 'pool', TYPES_URN)) if pool_element is None: extra['pool_id'] = None else: extra['pool_id'] = pool_element.get('id') extra['network_domain_id'] = findtext(element, 'networkDomainId', TYPES_URN) balancer = LoadBalancer( id=element.get('id'), name=name, state=self._VALUE_TO_STATE_MAP.get( findtext(element, 'state', TYPES_URN), State.UNKNOWN), ip=ipaddress, port=port, driver=self.connection.driver, extra=extra ) return balancer def _to_members(self, object): members = [] for element in object.findall(fixxpath("poolMember", TYPES_URN)): members.append(self._to_member(element)) return members def _to_member(self, element): port = findtext(element, 'port', TYPES_URN) if port is not None: port = int(port) pool_member = NttCisPoolMember( id=element.get('id'), name=element.find(fixxpath( 'node', TYPES_URN)).get('name'), status=findtext(element, 'state', TYPES_URN), node_id=element.find(fixxpath( 'node', TYPES_URN)).get('id'), ip=element.find(fixxpath( 'node', TYPES_URN)).get('ipAddress'), port=port ) return pool_member def _to_pools(self, object): pools = [] for element in object.findall(fixxpath("pool", TYPES_URN)): pools.append(self._to_pool(element)) return pools def _to_pool(self, element): pool = NttCisPool( id=element.get('id'), name=findtext(element, 'name', TYPES_URN), status=findtext(element, 'state', TYPES_URN), description=findtext(element, 'description', TYPES_URN), load_balance_method=findtext(element, 'loadBalanceMethod', TYPES_URN), health_monitor_id=findtext(element, 'healthMonitorId', TYPES_URN), service_down_action=findtext(element, 'serviceDownAction', TYPES_URN), slow_ramp_time=findtext(element, 'slowRampTime', TYPES_URN), ) return pool def _to_certs(self, object): certs = [] for element in object.findall(fixxpath("sslDomainCertificate", TYPES_URN)): certs.append(self._to_cert(element)) return certs def _to_cert(self, el): return process_xml(ET.tostring(el)) def _to_certificate_chains(self, object): cert_chains = [] for element in object.findall(fixxpath("sslCertificateChain", TYPES_URN)): cert_chains.append(self._to_certificate_chain(element)) return cert_chains def _to_certificate_chain(self, el): return process_xml(ET.tostring(el)) def _to_ssl_profiles(self, object): profiles = [] for element in object.findall(fixxpath("sslOffloadProfile", TYPES_URN)): profiles.append(self._to_ssl_profile(element)) return profiles def _to_ssl_profile(self, el): return process_xml(ET.tostring(el)) apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/rackspace.py0000664000175000017500000015706313535474530024640 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import httplib from libcloud.utils.misc import reverse_dict from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm from libcloud.loadbalancer.base import DEFAULT_ALGORITHM from libcloud.compute.drivers.rackspace import RackspaceConnection from libcloud.common.types import LibcloudError from libcloud.common.base import JsonResponse, PollingConnection from libcloud.loadbalancer.types import State, MemberCondition from libcloud.common.openstack import OpenStackDriverMixin from libcloud.common.rackspace import AUTH_URL ENDPOINT_ARGS_MAP = { 'dfw': {'service_type': 'rax:load-balancer', 'name': 'cloudLoadBalancers', 'region': 'DFW'}, 'ord': {'service_type': 'rax:load-balancer', 'name': 'cloudLoadBalancers', 'region': 'ORD'}, 'iad': {'service_type': 'rax:load-balancer', 'name': 'cloudLoadBalancers', 'region': 'IAD'}, 'lon': {'service_type': 'rax:load-balancer', 'name': 'cloudLoadBalancers', 'region': 'LON'}, 'syd': {'service_type': 'rax:load-balancer', 'name': 'cloudLoadBalancers', 'region': 'SYD'}, 'hkg': {'service_type': 'rax:load-balancer', 'name': 'cloudLoadBalancers', 'region': 'HKG'}, } class RackspaceResponse(JsonResponse): def parse_body(self): if not self.body: return None return super(RackspaceResponse, self).parse_body() def success(self): return 200 <= int(self.status) <= 299 class RackspaceHealthMonitor(object): """ :param type: type of load balancer. currently CONNECT (connection monitoring), HTTP, HTTPS (connection and HTTP monitoring) are supported. :type type: ``str`` :param delay: minimum seconds to wait before executing the health monitor. (Must be between 1 and 3600) :type delay: ``int`` :param timeout: maximum seconds to wait when establishing a connection before timing out. (Must be between 1 and 3600) :type timeout: ``int`` :param attempts_before_deactivation: Number of monitor failures before removing a node from rotation. (Must be between 1 and 10) :type attempts_before_deactivation: ``int`` """ def __init__(self, type, delay, timeout, attempts_before_deactivation): self.type = type self.delay = delay self.timeout = timeout self.attempts_before_deactivation = attempts_before_deactivation def __repr__(self): return ('' % (self.type, self.delay, self.timeout, self.attempts_before_deactivation)) def _to_dict(self): return { 'type': self.type, 'delay': self.delay, 'timeout': self.timeout, 'attemptsBeforeDeactivation': self.attempts_before_deactivation } class RackspaceHTTPHealthMonitor(RackspaceHealthMonitor): """ A HTTP health monitor adds extra features to a Rackspace health monitor. :param path: the HTTP path to monitor. :type path: ``str`` :param body_regex: Regular expression used to evaluate the body of the HTTP response. :type body_regex: ``str`` :param status_regex: Regular expression used to evaluate the HTTP status code of the response. :type status_regex: ``str`` """ def __init__(self, type, delay, timeout, attempts_before_deactivation, path, body_regex, status_regex): super(RackspaceHTTPHealthMonitor, self).__init__( type, delay, timeout, attempts_before_deactivation) self.path = path self.body_regex = body_regex self.status_regex = status_regex def __repr__(self): return ('' % (self.type, self.delay, self.timeout, self.attempts_before_deactivation, self.path, self.body_regex, self.status_regex)) def _to_dict(self): super_dict = super(RackspaceHTTPHealthMonitor, self)._to_dict() super_dict['path'] = self.path super_dict['statusRegex'] = self.status_regex if self.body_regex: super_dict['bodyRegex'] = self.body_regex return super_dict class RackspaceConnectionThrottle(object): """ :param min_connections: Minimum number of connections per IP address before applying throttling. :type min_connections: ``int`` :param max_connections: Maximum number of connections per IP address. (Must be between 0 and 100000, 0 allows an unlimited number of connections.) :type max_connections: ``int`` :param max_connection_rate: Maximum number of connections allowed from a single IP address within the given rate_interval_seconds. (Must be between 0 and 100000, 0 allows an unlimited number of connections.) :type max_connection_rate: ``int`` :param rate_interval_seconds: Interval at which the max_connection_rate is enforced. (Must be between 1 and 3600.) :type rate_interval_seconds: ``int`` """ def __init__(self, min_connections, max_connections, max_connection_rate, rate_interval_seconds): self.min_connections = min_connections self.max_connections = max_connections self.max_connection_rate = max_connection_rate self.rate_interval_seconds = rate_interval_seconds def __repr__(self): return ('' % (self.min_connections, self.max_connections, self.max_connection_rate, self.rate_interval_seconds)) def _to_dict(self): return { 'maxConnections': self.max_connections, 'minConnections': self.min_connections, 'maxConnectionRate': self.max_connection_rate, 'rateInterval': self.rate_interval_seconds } class RackspaceAccessRuleType(object): ALLOW = 0 DENY = 1 _RULE_TYPE_STRING_MAP = { ALLOW: 'ALLOW', DENY: 'DENY' } class RackspaceAccessRule(object): """ An access rule allows or denies traffic to a Load Balancer based on the incoming IPs. :param id: Unique identifier to refer to this rule by. :type id: ``str`` :param rule_type: RackspaceAccessRuleType.ALLOW or RackspaceAccessRuleType.DENY. :type id: ``int`` :param address: IP address or cidr (can be IPv4 or IPv6). :type address: ``str`` """ def __init__(self, id=None, rule_type=None, address=None): self.id = id self.rule_type = rule_type self.address = address def _to_dict(self): type_string =\ RackspaceAccessRuleType._RULE_TYPE_STRING_MAP[self.rule_type] as_dict = { 'type': type_string, 'address': self.address } if self.id is not None: as_dict['id'] = self.id return as_dict class RackspaceConnection(RackspaceConnection, PollingConnection): responseCls = RackspaceResponse auth_url = AUTH_URL poll_interval = 2 timeout = 80 cache_busting = True def request(self, action, params=None, data='', headers=None, method='GET'): if not headers: headers = {} if not params: params = {} if method in ('POST', 'PUT'): headers['Content-Type'] = 'application/json' return super(RackspaceConnection, self).request( action=action, params=params, data=data, method=method, headers=headers) def get_poll_request_kwargs(self, response, context, request_kwargs): return {'action': request_kwargs['action'], 'method': 'GET'} def has_completed(self, response): state = response.object['loadBalancer']['status'] if state == 'ERROR': raise LibcloudError("Load balancer entered an ERROR state.", driver=self.driver) return state == 'ACTIVE' def encode_data(self, data): return data class RackspaceLBDriver(Driver, OpenStackDriverMixin): connectionCls = RackspaceConnection api_name = 'rackspace_lb' name = 'Rackspace LB' website = 'http://www.rackspace.com/' LB_STATE_MAP = { 'ACTIVE': State.RUNNING, 'BUILD': State.PENDING, 'ERROR': State.ERROR, 'DELETED': State.DELETED, 'PENDING_UPDATE': State.PENDING, 'PENDING_DELETE': State.PENDING } LB_MEMBER_CONDITION_MAP = { 'ENABLED': MemberCondition.ENABLED, 'DISABLED': MemberCondition.DISABLED, 'DRAINING': MemberCondition.DRAINING } CONDITION_LB_MEMBER_MAP = reverse_dict(LB_MEMBER_CONDITION_MAP) _VALUE_TO_ALGORITHM_MAP = { 'RANDOM': Algorithm.RANDOM, 'ROUND_ROBIN': Algorithm.ROUND_ROBIN, 'LEAST_CONNECTIONS': Algorithm.LEAST_CONNECTIONS, 'WEIGHTED_ROUND_ROBIN': Algorithm.WEIGHTED_ROUND_ROBIN, 'WEIGHTED_LEAST_CONNECTIONS': Algorithm.WEIGHTED_LEAST_CONNECTIONS } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) def __init__(self, key, secret=None, secure=True, host=None, port=None, region='ord', **kwargs): ex_force_region = kwargs.pop('ex_force_region', None) if ex_force_region: # For backward compatibility region = ex_force_region OpenStackDriverMixin.__init__(self, **kwargs) super(RackspaceLBDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region) @classmethod def list_regions(cls): return ENDPOINT_ARGS_MAP.keys() def _ex_connection_class_kwargs(self): endpoint_args = ENDPOINT_ARGS_MAP[self.region] kwargs = self.openstack_connection_kwargs() kwargs['get_endpoint_args'] = endpoint_args return kwargs def list_protocols(self): return self._to_protocols( self.connection.request('/loadbalancers/protocols').object) def ex_list_protocols_with_default_ports(self): """ List protocols with default ports. :rtype: ``list`` of ``tuple`` :return: A list of protocols with default ports included. """ return self._to_protocols_with_default_ports( self.connection.request('/loadbalancers/protocols').object) def list_balancers(self, ex_member_address=None, ex_status=None, ex_changes_since=None, ex_params={}): """ @inherits: :class:`Driver.list_balancers` :param ex_member_address: Optional IP address of the attachment member. If provided, only the load balancers which have this member attached will be returned. :type ex_member_address: ``str`` :param ex_status: Optional. Filter balancers by status :type ex_status: ``str`` :param ex_changes_since: Optional. List all load balancers that have changed since the specified date/time :type ex_changes_since: ``str`` :param ex_params: Optional. Set parameters to be submitted to the API in the query string :type ex_params: ``dict`` """ params = {} if ex_member_address: params['nodeaddress'] = ex_member_address if ex_status: params['status'] = ex_status if ex_changes_since: params['changes-since'] = ex_changes_since for key, value in ex_params.items(): params[key] = value return self._to_balancers( self.connection.request('/loadbalancers', params=params).object) def create_balancer(self, name, members, protocol='http', port=80, algorithm=DEFAULT_ALGORITHM): return self.ex_create_balancer(name, members, protocol, port, algorithm) def ex_create_balancer(self, name, members, protocol='http', port=80, algorithm=DEFAULT_ALGORITHM, vip='PUBLIC'): """ Creates a new load balancer instance :param name: Name of the new load balancer (required) :type name: ``str`` :param members: ``list`` of:class:`Member`s to attach to balancer :type members: ``list`` of :class:`Member` :param protocol: Loadbalancer protocol, defaults to http. :type protocol: ``str`` :param port: Port the load balancer should listen on, defaults to 80 :type port: ``str`` :param algorithm: Load balancing algorithm, defaults to LBAlgorithm.ROUND_ROBIN :type algorithm: :class:`Algorithm` :param vip: Virtual ip type of PUBLIC, SERVICENET, or ID of a virtual ip :type vip: ``str`` :rtype: :class:`LoadBalancer` """ balancer_attrs = self._kwargs_to_mutable_attrs( name=name, protocol=protocol, port=port, algorithm=algorithm, vip=vip) balancer_attrs.update({ 'nodes': [self._member_attributes(member) for member in members], }) # balancer_attrs['nodes'] = ['fu'] balancer_object = {"loadBalancer": balancer_attrs} resp = self.connection.request('/loadbalancers', method='POST', data=json.dumps(balancer_object)) return self._to_balancer(resp.object['loadBalancer']) def _member_attributes(self, member): member_attributes = {'address': member.ip, 'port': member.port} member_attributes.update(self._kwargs_to_mutable_member_attrs( **member.extra)) # If the condition is not specified on the member, then it should be # set to ENABLED by default if 'condition' not in member_attributes: member_attributes['condition'] =\ self.CONDITION_LB_MEMBER_MAP[MemberCondition.ENABLED] return member_attributes def destroy_balancer(self, balancer): uri = '/loadbalancers/%s' % (balancer.id) resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.ACCEPTED def ex_destroy_balancers(self, balancers): """ Destroys a list of Balancers (the API supports up to 10). :param balancers: A list of Balancers to destroy. :type balancers: ``list`` of :class:`LoadBalancer` :return: Returns whether the destroy request was accepted. :rtype: ``bool`` """ ids = [('id', balancer.id) for balancer in balancers] resp = self.connection.request('/loadbalancers', method='DELETE', params=ids) return resp.status == httplib.ACCEPTED def get_balancer(self, balancer_id): uri = '/loadbalancers/%s' % (balancer_id) resp = self.connection.request(uri) return self._to_balancer(resp.object["loadBalancer"]) def balancer_attach_member(self, balancer, member): member_object = {"nodes": [self._member_attributes(member)]} uri = '/loadbalancers/%s/nodes' % (balancer.id) resp = self.connection.request(uri, method='POST', data=json.dumps(member_object)) return self._to_members(resp.object, balancer)[0] def ex_balancer_attach_members(self, balancer, members): """ Attaches a list of members to a load balancer. :param balancer: The Balancer to which members will be attached. :type balancer: :class:`LoadBalancer` :param members: A list of Members to attach. :type members: ``list`` of :class:`Member` :rtype: ``list`` of :class:`Member` """ member_objects = {"nodes": [self._member_attributes(member) for member in members]} uri = '/loadbalancers/%s/nodes' % (balancer.id) resp = self.connection.request(uri, method='POST', data=json.dumps(member_objects)) return self._to_members(resp.object, balancer) def balancer_detach_member(self, balancer, member): # Loadbalancer always needs to have at least 1 member. # Last member cannot be detached. You can only disable it or destroy # the balancer. uri = '/loadbalancers/%s/nodes/%s' % (balancer.id, member.id) resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.ACCEPTED def ex_balancer_detach_members(self, balancer, members): """ Detaches a list of members from a balancer (the API supports up to 10). This method blocks until the detach request has been processed and the balancer is in a RUNNING state again. :param balancer: The Balancer to detach members from. :type balancer: :class:`LoadBalancer` :param members: A list of Members to detach. :type members: ``list`` of :class:`Member` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ accepted = self.ex_balancer_detach_members_no_poll(balancer, members) if not accepted: msg = 'Detach members request was not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_balancer_detach_members_no_poll(self, balancer, members): """ Detaches a list of members from a balancer (the API supports up to 10). This method returns immediately. :param balancer: The Balancer to detach members from. :type balancer: :class:`LoadBalancer` :param members: A list of Members to detach. :type members: ``list`` of :class:`Member` :return: Returns whether the detach request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/nodes' % (balancer.id) ids = [('id', member.id) for member in members] resp = self.connection.request(uri, method='DELETE', params=ids) return resp.status == httplib.ACCEPTED def balancer_list_members(self, balancer): uri = '/loadbalancers/%s/nodes' % (balancer.id) data = self.connection.request(uri).object return self._to_members(data, balancer) def update_balancer(self, balancer, **kwargs): attrs = self._kwargs_to_mutable_attrs(**kwargs) resp = self.connection.async_request( action='/loadbalancers/%s' % balancer.id, method='PUT', data=json.dumps(attrs)) return self._to_balancer(resp.object["loadBalancer"]) def ex_update_balancer_no_poll(self, balancer, **kwargs): """ Update balancer no poll. @inherits: :class:`Driver.update_balancer` """ attrs = self._kwargs_to_mutable_attrs(**kwargs) resp = self.connection.request( action='/loadbalancers/%s' % balancer.id, method='PUT', data=json.dumps(attrs)) return resp.status == httplib.ACCEPTED def ex_balancer_update_member(self, balancer, member, **kwargs): """ Updates a Member's extra attributes for a Balancer. The attributes can include 'weight' or 'condition'. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to update the member on. :type balancer: :class:`LoadBalancer` :param member: Member which should be used :type member: :class:`Member` :keyword **kwargs: New attributes. Should contain either 'weight' or 'condition'. 'condition' can be set to 'ENABLED', 'DISABLED'. or 'DRAINING'. 'weight' can be set to a positive integer between 1 and 100, with a higher weight indicating that the node will receive more traffic (assuming the Balancer is using a weighted algorithm). :type **kwargs: ``dict`` :return: Updated Member. :rtype: :class:`Member` """ accepted = self.ex_balancer_update_member_no_poll( balancer, member, **kwargs) if not accepted: msg = 'Update member attributes was not accepted' raise LibcloudError(msg, driver=self) balancer = self._get_updated_balancer(balancer) members = balancer.extra['members'] updated_members = [m for m in members if m.id == member.id] if not updated_members: raise LibcloudError('Could not find updated member') return updated_members[0] def ex_balancer_update_member_no_poll(self, balancer, member, **kwargs): """ Updates a Member's extra attributes for a Balancer. The attribute can include 'weight' or 'condition'. This method returns immediately. :param balancer: Balancer to update the member on. :type balancer: :class:`LoadBalancer` :param member: Member which should be used :type member: :class:`Member` :keyword **kwargs: New attributes. Should contain either 'weight' or 'condition'. 'condition' can be set to 'ENABLED', 'DISABLED'. or 'DRAINING'. 'weight' can be set to a positive integer between 1 and 100, with a higher weight indicating that the node will receive more traffic (assuming the Balancer is using a weighted algorithm). :type **kwargs: ``dict`` :return: Returns whether the update request was accepted. :rtype: ``bool`` """ resp = self.connection.request( action='/loadbalancers/%s/nodes/%s' % (balancer.id, member.id), method='PUT', data=json.dumps(self._kwargs_to_mutable_member_attrs(**kwargs)) ) return resp.status == httplib.ACCEPTED def ex_list_algorithm_names(self): """ Lists algorithms supported by the API. Returned as strings because this list may change in the future. :rtype: ``list`` of ``str`` """ response = self.connection.request('/loadbalancers/algorithms') return [a["name"].upper() for a in response.object["algorithms"]] def ex_get_balancer_error_page(self, balancer): """ List error page configured for the specified load balancer. :param balancer: Balancer which should be used :type balancer: :class:`LoadBalancer` :rtype: ``str`` """ uri = '/loadbalancers/%s/errorpage' % (balancer.id) resp = self.connection.request(uri) return resp.object["errorpage"]["content"] def ex_balancer_access_list(self, balancer): """ List the access list. :param balancer: Balancer which should be used :type balancer: :class:`LoadBalancer` :rtype: ``list`` of :class:`RackspaceAccessRule` """ uri = '/loadbalancers/%s/accesslist' % (balancer.id) resp = self.connection.request(uri) return [self._to_access_rule(el) for el in resp.object["accessList"]] def _get_updated_balancer(self, balancer): """ Updating a balancer's attributes puts a balancer into 'PENDING_UPDATE' status. Wait until the balancer is back in 'ACTIVE' status and then return the individual balancer details call. """ resp = self.connection.async_request( action='/loadbalancers/%s' % balancer.id, method='GET') return self._to_balancer(resp.object['loadBalancer']) def ex_update_balancer_health_monitor(self, balancer, health_monitor): """ Sets a Balancer's health monitor. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to update. :type balancer: :class:`LoadBalancer` :param health_monitor: Health Monitor for the balancer. :type health_monitor: :class:`RackspaceHealthMonitor` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ accepted = self.ex_update_balancer_health_monitor_no_poll( balancer, health_monitor) if not accepted: msg = 'Update health monitor request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_update_balancer_health_monitor_no_poll(self, balancer, health_monitor): """ Sets a Balancer's health monitor. This method returns immediately. :param balancer: Balancer to update health monitor on. :type balancer: :class:`LoadBalancer` :param health_monitor: Health Monitor for the balancer. :type health_monitor: :class:`RackspaceHealthMonitor` :return: Returns whether the update request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/healthmonitor' % (balancer.id) resp = self.connection.request( uri, method='PUT', data=json.dumps(health_monitor._to_dict())) return resp.status == httplib.ACCEPTED def ex_disable_balancer_health_monitor(self, balancer): """ Disables a Balancer's health monitor. This method blocks until the disable request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to disable health monitor on. :type balancer: :class:`LoadBalancer` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ if not self.ex_disable_balancer_health_monitor_no_poll(balancer): msg = 'Disable health monitor request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_disable_balancer_health_monitor_no_poll(self, balancer): """ Disables a Balancer's health monitor. This method returns immediately. :param balancer: Balancer to disable health monitor on. :type balancer: :class:`LoadBalancer` :return: Returns whether the disable request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/healthmonitor' % (balancer.id) resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.ACCEPTED def ex_update_balancer_connection_throttle(self, balancer, connection_throttle): """ Updates a Balancer's connection throttle. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to update connection throttle on. :type balancer: :class:`LoadBalancer` :param connection_throttle: Connection Throttle for the balancer. :type connection_throttle: :class:`RackspaceConnectionThrottle` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ accepted = self.ex_update_balancer_connection_throttle_no_poll( balancer, connection_throttle) if not accepted: msg = 'Update connection throttle request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_update_balancer_connection_throttle_no_poll(self, balancer, connection_throttle): """ Sets a Balancer's connection throttle. This method returns immediately. :param balancer: Balancer to update connection throttle on. :type balancer: :class:`LoadBalancer` :param connection_throttle: Connection Throttle for the balancer. :type connection_throttle: :class:`RackspaceConnectionThrottle` :return: Returns whether the update request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/connectionthrottle' % (balancer.id) resp = self.connection.request( uri, method='PUT', data=json.dumps(connection_throttle._to_dict())) return resp.status == httplib.ACCEPTED def ex_disable_balancer_connection_throttle(self, balancer): """ Disables a Balancer's connection throttle. This method blocks until the disable request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to disable connection throttle on. :type balancer: :class:`LoadBalancer` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ if not self.ex_disable_balancer_connection_throttle_no_poll(balancer): msg = 'Disable connection throttle request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_disable_balancer_connection_throttle_no_poll(self, balancer): """ Disables a Balancer's connection throttle. This method returns immediately. :param balancer: Balancer to disable connection throttle on. :type balancer: :class:`LoadBalancer` :return: Returns whether the disable request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/connectionthrottle' % (balancer.id) resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.ACCEPTED def ex_enable_balancer_connection_logging(self, balancer): """ Enables connection logging for a Balancer. This method blocks until the enable request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to enable connection logging on. :type balancer: :class:`LoadBalancer` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ if not self.ex_enable_balancer_connection_logging_no_poll(balancer): msg = 'Enable connection logging request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_enable_balancer_connection_logging_no_poll(self, balancer): """ Enables connection logging for a Balancer. This method returns immediately. :param balancer: Balancer to enable connection logging on. :type balancer: :class:`LoadBalancer` :return: Returns whether the enable request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/connectionlogging' % (balancer.id) resp = self.connection.request( uri, method='PUT', data=json.dumps({'connectionLogging': {'enabled': True}}) ) return resp.status == httplib.ACCEPTED def ex_disable_balancer_connection_logging(self, balancer): """ Disables connection logging for a Balancer. This method blocks until the enable request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to disable connection logging on. :type balancer: :class:`LoadBalancer` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ if not self.ex_disable_balancer_connection_logging_no_poll(balancer): msg = 'Disable connection logging request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_disable_balancer_connection_logging_no_poll(self, balancer): """ Disables connection logging for a Balancer. This method returns immediately. :param balancer: Balancer to disable connection logging on. :type balancer: :class:`LoadBalancer` :return: Returns whether the disable request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/connectionlogging' % (balancer.id) resp = self.connection.request( uri, method='PUT', data=json.dumps({'connectionLogging': {'enabled': False}}) ) return resp.status == httplib.ACCEPTED def ex_enable_balancer_session_persistence(self, balancer): """ Enables session persistence for a Balancer by setting the persistence type to 'HTTP_COOKIE'. This method blocks until the enable request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to enable session persistence on. :type balancer: :class:`LoadBalancer` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ if not self.ex_enable_balancer_session_persistence_no_poll(balancer): msg = 'Enable session persistence request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_enable_balancer_session_persistence_no_poll(self, balancer): """ Enables session persistence for a Balancer by setting the persistence type to 'HTTP_COOKIE'. This method returns immediately. :param balancer: Balancer to enable session persistence on. :type balancer: :class:`LoadBalancer` :return: Returns whether the enable request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/sessionpersistence' % (balancer.id) resp = self.connection.request( uri, method='PUT', data=json.dumps( {'sessionPersistence': {'persistenceType': 'HTTP_COOKIE'}}) ) return resp.status == httplib.ACCEPTED def ex_disable_balancer_session_persistence(self, balancer): """ Disables session persistence for a Balancer. This method blocks until the disable request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to disable session persistence on. :type balancer: :class:`LoadBalancer` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ if not self.ex_disable_balancer_session_persistence_no_poll(balancer): msg = 'Disable session persistence request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_disable_balancer_session_persistence_no_poll(self, balancer): """ Disables session persistence for a Balancer. This method returns immediately. :param balancer: Balancer to disable session persistence for. :type balancer: :class:`LoadBalancer` :return: Returns whether the disable request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/sessionpersistence' % (balancer.id) resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.ACCEPTED def ex_update_balancer_error_page(self, balancer, page_content): """ Updates a Balancer's custom error page. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to update the custom error page for. :type balancer: :class:`LoadBalancer` :param page_content: HTML content for the custom error page. :type page_content: ``str`` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ accepted = self.ex_update_balancer_error_page_no_poll(balancer, page_content) if not accepted: msg = 'Update error page request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_update_balancer_error_page_no_poll(self, balancer, page_content): """ Updates a Balancer's custom error page. This method returns immediately. :param balancer: Balancer to update the custom error page for. :type balancer: :class:`LoadBalancer` :param page_content: HTML content for the custom error page. :type page_content: ``str`` :return: Returns whether the update request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/errorpage' % (balancer.id) resp = self.connection.request( uri, method='PUT', data=json.dumps({'errorpage': {'content': page_content}}) ) return resp.status == httplib.ACCEPTED def ex_disable_balancer_custom_error_page(self, balancer): """ Disables a Balancer's custom error page, returning its error page to the Rackspace-provided default. This method blocks until the disable request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to disable the custom error page for. :type balancer: :class:`LoadBalancer` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ if not self.ex_disable_balancer_custom_error_page_no_poll(balancer): msg = 'Disable custom error page request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_disable_balancer_custom_error_page_no_poll(self, balancer): """ Disables a Balancer's custom error page, returning its error page to the Rackspace-provided default. This method returns immediately. :param balancer: Balancer to disable the custom error page for. :type balancer: :class:`LoadBalancer` :return: Returns whether the disable request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/errorpage' % (balancer.id) resp = self.connection.request(uri, method='DELETE') # Load Balancer API currently returns 200 OK on custom error page # delete. return resp.status == httplib.OK or resp.status == httplib.ACCEPTED def ex_create_balancer_access_rule(self, balancer, rule): """ Adds an access rule to a Balancer's access list. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to create the access rule for. :type balancer: :class:`LoadBalancer` :param rule: Access Rule to add to the balancer. :type rule: :class:`RackspaceAccessRule` :return: The created access rule. :rtype: :class:`RackspaceAccessRule` """ accepted = self.ex_create_balancer_access_rule_no_poll(balancer, rule) if not accepted: msg = 'Create access rule not accepted' raise LibcloudError(msg, driver=self) balancer = self._get_updated_balancer(balancer) access_list = balancer.extra['accessList'] created_rule = self._find_matching_rule(rule, access_list) if not created_rule: raise LibcloudError('Could not find created rule') return created_rule def ex_create_balancer_access_rule_no_poll(self, balancer, rule): """ Adds an access rule to a Balancer's access list. This method returns immediately. :param balancer: Balancer to create the access rule for. :type balancer: :class:`LoadBalancer` :param rule: Access Rule to add to the balancer. :type rule: :class:`RackspaceAccessRule` :return: Returns whether the create request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/accesslist' % (balancer.id) resp = self.connection.request( uri, method='POST', data=json.dumps({'networkItem': rule._to_dict()}) ) return resp.status == httplib.ACCEPTED def ex_create_balancer_access_rules(self, balancer, rules): """ Adds a list of access rules to a Balancer's access list. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to create the access rule for. :type balancer: :class:`LoadBalancer` :param rules: List of :class:`RackspaceAccessRule` to add to the balancer. :type rules: ``list`` of :class:`RackspaceAccessRule` :return: The created access rules. :rtype: :class:`RackspaceAccessRule` """ accepted = self.ex_create_balancer_access_rules_no_poll(balancer, rules) if not accepted: msg = 'Create access rules not accepted' raise LibcloudError(msg, driver=self) balancer = self._get_updated_balancer(balancer) access_list = balancer.extra['accessList'] created_rules = [] for r in rules: matched_rule = self._find_matching_rule(r, access_list) if matched_rule: created_rules.append(matched_rule) if len(created_rules) != len(rules): raise LibcloudError('Could not find all created rules') return created_rules def _find_matching_rule(self, rule_to_find, access_list): """ LB API does not return the ID for the newly created rules, so we have to search the list to find the rule with a matching rule type and address to return an object with the right identifier.it. The API enforces rule type and address uniqueness. """ for r in access_list: if rule_to_find.rule_type == r.rule_type and\ rule_to_find.address == r.address: return r return None def ex_create_balancer_access_rules_no_poll(self, balancer, rules): """ Adds a list of access rules to a Balancer's access list. This method returns immediately. :param balancer: Balancer to create the access rule for. :type balancer: :class:`LoadBalancer` :param rules: List of :class:`RackspaceAccessRule` to add to the balancer. :type rules: ``list`` of :class:`RackspaceAccessRule` :return: Returns whether the create request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/accesslist' % (balancer.id) resp = self.connection.request( uri, method='POST', data=json.dumps({'accessList': [rule._to_dict() for rule in rules]}) ) return resp.status == httplib.ACCEPTED def ex_destroy_balancer_access_rule(self, balancer, rule): """ Removes an access rule from a Balancer's access list. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to remove the access rule from. :type balancer: :class:`LoadBalancer` :param rule: Access Rule to remove from the balancer. :type rule: :class:`RackspaceAccessRule` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ accepted = self.ex_destroy_balancer_access_rule_no_poll(balancer, rule) if not accepted: msg = 'Delete access rule not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_destroy_balancer_access_rule_no_poll(self, balancer, rule): """ Removes an access rule from a Balancer's access list. This method returns immediately. :param balancer: Balancer to remove the access rule from. :type balancer: :class:`LoadBalancer` :param rule: Access Rule to remove from the balancer. :type rule: :class:`RackspaceAccessRule` :return: Returns whether the destroy request was accepted. :rtype: ``bool`` """ uri = '/loadbalancers/%s/accesslist/%s' % (balancer.id, rule.id) resp = self.connection.request(uri, method='DELETE') return resp.status == httplib.ACCEPTED def ex_destroy_balancer_access_rules(self, balancer, rules): """ Removes a list of access rules from a Balancer's access list. This method blocks until the update request has been processed and the balancer is in a RUNNING state again. :param balancer: Balancer to remove the access rules from. :type balancer: :class:`LoadBalancer` :param rules: List of :class:`RackspaceAccessRule` objects to remove from the balancer. :type rules: ``list`` of :class:`RackspaceAccessRule` :return: Updated Balancer. :rtype: :class:`LoadBalancer` """ accepted = self.ex_destroy_balancer_access_rules_no_poll( balancer, rules) if not accepted: msg = 'Destroy access rules request not accepted' raise LibcloudError(msg, driver=self) return self._get_updated_balancer(balancer) def ex_destroy_balancer_access_rules_no_poll(self, balancer, rules): """ Removes a list of access rules from a Balancer's access list. This method returns immediately. :param balancer: Balancer to remove the access rules from. :type balancer: :class:`LoadBalancer` :param rules: List of :class:`RackspaceAccessRule` objects to remove from the balancer. :type rules: ``list`` of :class:`RackspaceAccessRule` :return: Returns whether the destroy request was accepted. :rtype: ``bool`` """ ids = [('id', rule.id) for rule in rules] uri = '/loadbalancers/%s/accesslist' % balancer.id resp = self.connection.request(uri, method='DELETE', params=ids) return resp.status == httplib.ACCEPTED def ex_list_current_usage(self, balancer): """ Return current load balancer usage report. :param balancer: Balancer to remove the access rules from. :type balancer: :class:`LoadBalancer` :return: Raw load balancer usage object. :rtype: ``dict`` """ uri = '/loadbalancers/%s/usage/current' % (balancer.id) resp = self.connection.request(uri, method='GET') return resp.object def _to_protocols(self, object): protocols = [] for item in object["protocols"]: protocols.append(item['name'].lower()) return protocols def _to_protocols_with_default_ports(self, object): protocols = [] for item in object["protocols"]: name = item['name'].lower() port = int(item['port']) protocols.append((name, port)) return protocols def _to_balancers(self, object): return [self._to_balancer(el) for el in object["loadBalancers"]] def _to_balancer(self, el): ip = None port = None sourceAddresses = {} if 'port' in el: port = el["port"] if 'sourceAddresses' in el: sourceAddresses = el['sourceAddresses'] extra = { "ipv6PublicSource": sourceAddresses.get("ipv6Public"), "ipv4PublicSource": sourceAddresses.get("ipv4Public"), "ipv4PrivateSource": sourceAddresses.get("ipv4Servicenet"), "service_name": self.connection.get_service_name(), "uri": "https://%s%s/loadbalancers/%s" % ( self.connection.host, self.connection.request_path, el["id"]), } if 'virtualIps' in el: ip = el['virtualIps'][0]['address'] extra['virtualIps'] = el['virtualIps'] if 'protocol' in el: extra['protocol'] = el['protocol'] if 'algorithm' in el and \ el["algorithm"] in self._VALUE_TO_ALGORITHM_MAP: extra["algorithm"] = self._value_to_algorithm(el["algorithm"]) if 'healthMonitor' in el: health_monitor = self._to_health_monitor(el) if health_monitor: extra["healthMonitor"] = health_monitor if 'connectionThrottle' in el: extra["connectionThrottle"] = self._to_connection_throttle(el) if 'sessionPersistence' in el: persistence = el["sessionPersistence"] extra["sessionPersistenceType"] =\ persistence.get("persistenceType") if 'connectionLogging' in el: logging = el["connectionLogging"] extra["connectionLoggingEnabled"] = logging.get("enabled") if 'nodes' in el: extra['members'] = self._to_members(el) if 'created' in el: extra['created'] = self._iso_to_datetime(el['created']['time']) if 'updated' in el: extra['updated'] = self._iso_to_datetime(el['updated']['time']) if 'accessList' in el: extra['accessList'] = [self._to_access_rule(rule) for rule in el['accessList']] return LoadBalancer(id=el["id"], name=el["name"], state=self.LB_STATE_MAP.get( el["status"], State.UNKNOWN), ip=ip, port=port, driver=self.connection.driver, extra=extra) def _to_members(self, object, balancer=None): return [self._to_member(el, balancer) for el in object["nodes"]] def _to_member(self, el, balancer=None): extra = {} if 'weight' in el: extra['weight'] = el["weight"] if 'condition' in el and\ el['condition'] in self.LB_MEMBER_CONDITION_MAP: extra['condition'] =\ self.LB_MEMBER_CONDITION_MAP.get(el["condition"]) if 'status' in el: extra['status'] = el["status"] lbmember = Member(id=el["id"], ip=el["address"], port=el["port"], balancer=balancer, extra=extra) return lbmember def _protocol_to_value(self, protocol): non_standard_protocols = {'imapv2': 'IMAPv2', 'imapv3': 'IMAPv3', 'imapv4': 'IMAPv4'} protocol_name = protocol.lower() if protocol_name in non_standard_protocols: protocol_value = non_standard_protocols[protocol_name] else: protocol_value = protocol.upper() return protocol_value def _kwargs_to_mutable_attrs(self, **attrs): update_attrs = {} if "name" in attrs: update_attrs['name'] = attrs['name'] if "algorithm" in attrs: algorithm_value = self._algorithm_to_value(attrs['algorithm']) update_attrs['algorithm'] = algorithm_value if "protocol" in attrs: update_attrs['protocol'] =\ self._protocol_to_value(attrs['protocol']) if "port" in attrs: update_attrs['port'] = int(attrs['port']) if "vip" in attrs: if attrs['vip'] == 'PUBLIC' or attrs['vip'] == 'SERVICENET': update_attrs['virtualIps'] = [{'type': attrs['vip']}] else: update_attrs['virtualIps'] = [{'id': attrs['vip']}] return update_attrs def _kwargs_to_mutable_member_attrs(self, **attrs): update_attrs = {} if 'condition' in attrs: update_attrs['condition'] =\ self.CONDITION_LB_MEMBER_MAP.get(attrs['condition']) if 'weight' in attrs: update_attrs['weight'] = attrs['weight'] return update_attrs def _to_health_monitor(self, el): health_monitor_data = el["healthMonitor"] type = health_monitor_data.get("type") delay = health_monitor_data.get("delay") timeout = health_monitor_data.get("timeout") attempts_before_deactivation =\ health_monitor_data.get("attemptsBeforeDeactivation") if type == "CONNECT": return RackspaceHealthMonitor( type=type, delay=delay, timeout=timeout, attempts_before_deactivation=attempts_before_deactivation) if type == "HTTP" or type == "HTTPS": return RackspaceHTTPHealthMonitor( type=type, delay=delay, timeout=timeout, attempts_before_deactivation=attempts_before_deactivation, path=health_monitor_data.get("path"), status_regex=health_monitor_data.get("statusRegex"), body_regex=health_monitor_data.get("bodyRegex", '')) return None def _to_connection_throttle(self, el): connection_throttle_data = el["connectionThrottle"] min_connections = connection_throttle_data.get("minConnections") max_connections = connection_throttle_data.get("maxConnections") max_connection_rate = connection_throttle_data.get("maxConnectionRate") rate_interval = connection_throttle_data.get("rateInterval") return RackspaceConnectionThrottle( min_connections=min_connections, max_connections=max_connections, max_connection_rate=max_connection_rate, rate_interval_seconds=rate_interval) def _to_access_rule(self, el): return RackspaceAccessRule( id=el.get("id"), rule_type=self._to_access_rule_type(el.get("type")), address=el.get("address")) def _to_access_rule_type(self, type): if type == "ALLOW": return RackspaceAccessRuleType.ALLOW elif type == "DENY": return RackspaceAccessRuleType.DENY def _iso_to_datetime(self, isodate): date_formats = ('%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%dT%H:%M:%S%z') date = None for date_format in date_formats: try: date = datetime.strptime(isodate, date_format) except ValueError: pass if date: break return date apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/slb.py0000664000175000017500000007346613570310635023462 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'SLB_API_VERSION', 'SLBDriver' ] try: import simplejson as json except ImportError: import json from libcloud.common.aliyun import AliyunXmlResponse, SignedAliyunConnection from libcloud.common.types import LibcloudError from libcloud.loadbalancer.types import State from libcloud.loadbalancer.base import Algorithm, Driver, LoadBalancer, Member from libcloud.utils.misc import ReprMixin from libcloud.utils.py3 import u from libcloud.utils.xml import findattr, findtext, findall SLB_API_VERSION = '2014-05-15' SLB_API_HOST = 'slb.aliyuncs.com' DEFAULT_SIGNATURE_VERSION = '1.0' STATE_MAPPINGS = { 'inactive': State.UNKNOWN, 'active': State.RUNNING, 'locked': State.PENDING } RESOURCE_EXTRA_ATTRIBUTES_MAP = { 'balancer': { 'create_timestamp': { 'xpath': 'CreateTimeStamp', 'transform_func': int }, 'address_type': { 'xpath': 'AddressType', 'transform_func': u }, 'region_id': { 'xpath': 'RegionId', 'transform_func': u }, 'region_id_alias': { 'xpath': 'RegionIdAlias', 'transform_func': u }, 'create_time': { 'xpath': 'CreateTime', 'transform_func': u }, 'master_zone_id': { 'xpath': 'MasterZoneId', 'transform_func': u }, 'slave_zone_id': { 'xpath': 'SlaveZoneId', 'transform_func': u }, 'network_type': { 'xpath': 'NetworkType', 'transform_func': u } } } SLB_SCHEDULER_TO_ALGORITHM = { 'wrr': Algorithm.WEIGHTED_ROUND_ROBIN, 'wlc': Algorithm.WEIGHTED_LEAST_CONNECTIONS } ALGORITHM_TO_SLB_SCHEDULER = { Algorithm.WEIGHTED_ROUND_ROBIN: 'wrr', Algorithm.WEIGHTED_LEAST_CONNECTIONS: 'wlc' } class SLBConnection(SignedAliyunConnection): api_version = SLB_API_VERSION host = SLB_API_HOST responseCls = AliyunXmlResponse service_name = 'slb' class SLBLoadBalancerAttribute(object): """ This class used to get listeners and backend servers related to a balancer listeners is a ``list`` of ``dict``, each element contains 'ListenerPort' and 'ListenerProtocol' keys. backend_servers is a ``list`` of ``dict``, each element contains 'ServerId' and 'Weight' keys. """ def __init__(self, balancer, listeners, backend_servers, extra=None): self.balancer = balancer self.listeners = listeners or [] self.backend_servers = backend_servers or [] self.extra = extra or {} def is_listening(self, port): for listener in self.listeners: if listener.get('ListenerPort') == port: return True return False def is_attached(self, member): for server in self.backend_servers: if server.get('Serverid') == member.id: return True return False def __repr__(self): return ('' % (self.balancer.id, self.listeners, self.backend_servers)) class SLBLoadBalancerListener(ReprMixin, object): """ Base SLB load balancer listener class """ _repr_attributes = ['port', 'backend_port', 'scheduler', 'bandwidth'] action = None option_keys = [] def __init__(self, port, backend_port, algorithm, bandwidth, extra=None): self.port = port self.backend_port = backend_port self.scheduler = ALGORITHM_TO_SLB_SCHEDULER.get(algorithm, 'wrr') self.bandwidth = bandwidth self.extra = extra or {} @classmethod def create(cls, port, backend_port, algorithm, bandwidth, extra=None): return cls(port, backend_port, algorithm, bandwidth, extra=extra) def get_create_params(self): params = self.get_required_params() options = self.get_optional_params() options.update(params) return options def get_required_params(self): params = {'Action': self.action, 'ListenerPort': self.port, 'BackendServerPort': self.backend_port, 'Scheduler': self.scheduler, 'Bandwidth': self.bandwidth} return params def get_optional_params(self): options = {} for option in self.option_keys: if self.extra and option in self.extra: options[option] = self.extra[option] return options class SLBLoadBalancerHttpListener(SLBLoadBalancerListener): """ This class represents a rule to route http request to the backends. """ action = 'CreateLoadBalancerHTTPListener' option_keys = ['XForwardedFor', 'StickySessionType', 'CookieTimeout', 'Cookie', 'HealthCheckDomain', 'HealthCheckURI', 'HealthCheckConnectPort', 'HealthyThreshold', 'UnhealthyThreshold', 'HealthCheckTimeout', 'HealthCheckInterval', 'HealthCheckHttpCode'] def __init__(self, port, backend_port, algorithm, bandwidth, sticky_session, health_check, extra=None): super(SLBLoadBalancerHttpListener, self).__init__( port, backend_port, algorithm, bandwidth, extra=extra) self.sticky_session = sticky_session self.health_check = health_check def get_required_params(self): params = super(SLBLoadBalancerHttpListener, self).get_required_params() params['StickySession'] = self.sticky_session params['HealthCheck'] = self.health_check return params @classmethod def create(cls, port, backend_port, algorithm, bandwidth, extra={}): if 'StickySession' not in extra: raise AttributeError('StickySession is required') if 'HealthCheck' not in extra: raise AttributeError('HealthCheck is required') sticky_session = extra['StickySession'] health_check = extra['HealthCheck'] return cls(port, backend_port, algorithm, bandwidth, sticky_session, health_check, extra=extra) class SLBLoadBalancerHttpsListener(SLBLoadBalancerListener): """ This class represents a rule to route https request to the backends. """ action = 'CreateLoadBalancerHTTPSListener' option_keys = ['XForwardedFor', 'StickySessionType', 'CookieTimeout', 'Cookie', 'HealthCheckDomain', 'HealthCheckURI', 'HealthCheckConnectPort', 'HealthyThreshold', 'UnhealthyThreshold', 'HealthCheckTimeout', 'HealthCheckInterval', 'HealthCheckHttpCode'] def __init__(self, port, backend_port, algorithm, bandwidth, sticky_session, health_check, certificate_id, extra=None): super(SLBLoadBalancerHttpsListener, self).__init__( port, backend_port, algorithm, bandwidth, extra=extra) self.sticky_session = sticky_session self.health_check = health_check self.certificate_id = certificate_id def get_required_params(self): params = super(SLBLoadBalancerHttpsListener, self).get_required_params() params['StickySession'] = self.sticky_session params['HealthCheck'] = self.health_check params['ServerCertificateId'] = self.certificate_id return params @classmethod def create(cls, port, backend_port, algorithm, bandwidth, extra={}): if 'StickySession' not in extra: raise AttributeError('StickySession is required') if 'HealthCheck' not in extra: raise AttributeError('HealthCheck is required') if 'ServerCertificateId' not in extra: raise AttributeError('ServerCertificateId is required') sticky_session = extra['StickySession'] health_check = extra['HealthCheck'] certificate_id = extra['ServerCertificateId'] return cls(port, backend_port, algorithm, bandwidth, sticky_session, health_check, certificate_id, extra=extra) class SLBLoadBalancerTcpListener(SLBLoadBalancerListener): """ This class represents a rule to route tcp request to the backends. """ action = 'CreateLoadBalancerTCPListener' option_keys = ['PersistenceTimeout', 'HealthCheckType', 'HealthCheckDomain', 'HealthCheckURI', 'HealthCheckConnectPort', 'HealthyThreshold', 'UnhealthyThreshold', 'HealthCheckConnectTimeout', 'HealthCheckInterval', 'HealthCheckHttpCode'] class SLBLoadBalancerUdpListener(SLBLoadBalancerTcpListener): """ This class represents a rule to route udp request to the backends. """ action = 'CreateLoadBalancerUDPListener' option_keys = ['PersistenceTimeout', 'HealthCheckConnectPort', 'HealthyThreshold', 'UnhealthyThreshold', 'HealthCheckConnectTimeout', 'HealthCheckInterval'] class SLBServerCertificate(ReprMixin, object): _repr_attributes = ['id', 'name', 'fingerprint'] def __init__(self, id, name, fingerprint): self.id = id self.name = name self.fingerprint = fingerprint PROTOCOL_TO_LISTENER_MAP = { 'http': SLBLoadBalancerHttpListener, 'https': SLBLoadBalancerHttpsListener, 'tcp': SLBLoadBalancerTcpListener, 'udp': SLBLoadBalancerUdpListener } class SLBDriver(Driver): """ Aliyun SLB load balancer driver. """ name = 'Aliyun Server Load Balancer' website = 'https://www.aliyun.com/product/slb' connectionCls = SLBConnection path = '/' namespace = None _VALUE_TO_ALGORITHM_MAP = SLB_SCHEDULER_TO_ALGORITHM _ALGORITHM_TO_VALUE_MAP = ALGORITHM_TO_SLB_SCHEDULER def __init__(self, access_id, secret, region): super(SLBDriver, self).__init__(access_id, secret) self.region = region def list_protocols(self): return list(PROTOCOL_TO_LISTENER_MAP.keys()) def list_balancers(self, ex_balancer_ids=None, ex_filters=None): """ List all loadbalancers @inherits :class:`Driver.list_balancers` :keyword ex_balancer_ids: a list of balancer ids to filter results Only balancers which's id in this list will be returned :type ex_balancer_ids: ``list`` of ``str`` :keyword ex_filters: attributes to filter results. Only balancers which have all the desired attributes and values will be returned :type ex_filters: ``dict`` """ params = {'Action': 'DescribeLoadBalancers', 'RegionId': self.region} if ex_balancer_ids and isinstance(ex_balancer_ids, list): params['LoadBalancerId'] = ','.join(ex_balancer_ids) if ex_filters and isinstance(ex_filters, dict): ex_filters.update(params) params = ex_filters resp_body = self.connection.request(self.path, params=params).object return self._to_balancers(resp_body) def create_balancer(self, name, port, protocol, algorithm, members, ex_bandwidth=None, ex_internet_charge_type=None, ex_address_type=None, ex_vswitch_id=None, ex_master_zone_id=None, ex_slave_zone_id=None, ex_client_token=None, **kwargs): """ Create a new load balancer instance @inherits: :class:`Driver.create_balancer` :keyword ex_bandwidth: The max bandwidth limit for `paybybandwidth` internet charge type, in Mbps unit :type ex_bandwidth: ``int`` in range [1, 1000] :keyword ex_internet_charge_type: The internet charge type :type ex_internet_charge_type: a ``str`` of `paybybandwidth` or `paybytraffic` :keyword ex_address_type: The listening IP address type :type ex_address_type: a ``str`` of `internet` or `intranet` :keyword ex_vswitch_id: The vswitch id in a VPC network :type ex_vswitch_id: ``str`` :keyword ex_master_zone_id: The id of the master availability zone :type ex_master_zone_id: ``str`` :keyword ex_slave_zone_id: The id of the slave availability zone :type ex_slave_zone_id: ``str`` :keyword ex_client_token: The token generated by client to identify requests :type ex_client_token: ``str`` """ # 1.Create load balancer params = {'Action': 'CreateLoadBalancer', 'RegionId': self.region} if name: params['LoadBalancerName'] = name if not port: raise AttributeError('port is required') if not protocol: # NOTE(samsong8610): Use http listener as default protocol = 'http' if protocol not in PROTOCOL_TO_LISTENER_MAP: raise AttributeError('unsupport protocol %s' % protocol) # Bandwidth in range [1, 1000] Mbps bandwidth = -1 if ex_bandwidth: try: bandwidth = int(ex_bandwidth) except ValueError: raise AttributeError('ex_bandwidth should be a integer in ' 'range [1, 1000].') params['Bandwidth'] = bandwidth if ex_internet_charge_type: if ex_internet_charge_type.lower() == 'paybybandwidth': if bandwidth == -1: raise AttributeError('PayByBandwidth internet charge type' ' need ex_bandwidth be set') params['InternetChargeType'] = ex_internet_charge_type if ex_address_type: if ex_address_type.lower() not in ('internet', 'intranet'): raise AttributeError('ex_address_type should be "internet" ' 'or "intranet"') params['AddressType'] = ex_address_type if ex_vswitch_id: params['VSwitchId'] = ex_vswitch_id if ex_master_zone_id: params['MasterZoneId'] = ex_master_zone_id if ex_slave_zone_id: params['SlaveZoneId'] = ex_slave_zone_id if ex_client_token: params['ClientToken'] = ex_client_token if members and isinstance(members, list): backend_ports = [member.port for member in members] if len(set(backend_ports)) != 1: raise AttributeError('the ports of members should be unique') # NOTE(samsong8610): If members do not provide backend port, # default to listening port backend_port = backend_ports[0] or port else: backend_port = port balancer = None try: resp_body = self.connection.request(self.path, params).object balancer = self._to_balancer(resp_body) balancer.port = port # 2.Add backend servers if members is None: members = [] for member in members: self.balancer_attach_member(balancer, member) # 3.Create listener # NOTE(samsong8610): Assume only create a listener which uses all # the bandwidth. self.ex_create_listener(balancer, backend_port, protocol, algorithm, bandwidth, **kwargs) self.ex_start_listener(balancer, port) return balancer except Exception as e: if balancer is not None: try: self.destroy_balancer(balancer) except Exception: pass raise e def destroy_balancer(self, balancer): params = {'Action': 'DeleteLoadBalancer', 'LoadBalancerId': balancer.id} resp = self.connection.request(self.path, params) return resp.success() def get_balancer(self, balancer_id): balancers = self.list_balancers(ex_balancer_ids=[balancer_id]) if len(balancers) != 1: raise LibcloudError('could not find load balancer with id %s' % balancer_id) return balancers[0] def balancer_attach_compute_node(self, balancer, node): if len(node.public_ips) > 0: ip = node.public_ips[0] else: ip = node.private_ips[0] member = Member(id=node.id, ip=ip, port=balancer.port) return self.balancer_attach_member(balancer, member) def balancer_attach_member(self, balancer, member): params = {'Action': 'AddBackendServers', 'LoadBalancerId': balancer.id} if member and isinstance(member, Member): params['BackendServers'] = self._to_servers_json([member]) self.connection.request(self.path, params) return member def balancer_detach_member(self, balancer, member): params = {'Action': 'RemoveBackendServers', 'LoadBalancerId': balancer.id} if member and isinstance(member, Member): params['BackendServers'] = self._list_to_json([member.id]) self.connection.request(self.path, params) return member def balancer_list_members(self, balancer): attribute = self.ex_get_balancer_attribute(balancer) members = [Member(server['ServerId'], None, None, balancer=balancer, extra={'Weight': server['Weight']}) for server in attribute.backend_servers] return members def ex_get_balancer_attribute(self, balancer): """ Get balancer attribute :param balancer: the balancer to get attribute :type balancer: ``LoadBalancer`` :return: the balancer attribute :rtype: ``SLBLoadBalancerAttribute`` """ params = {'Action': 'DescribeLoadBalancerAttribute', 'LoadBalancerId': balancer.id} resp_body = self.connection.request(self.path, params).object attribute = self._to_balancer_attribute(resp_body) return attribute def ex_list_listeners(self, balancer): """ Get all listener related to the given balancer :param balancer: the balancer to list listeners :type balancer: ``LoadBalancer`` :return: a list of listeners :rtype: ``list`` of ``SLBLoadBalancerListener`` """ attribute = self.ex_get_balancer_attribute(balancer) listeners = [SLBLoadBalancerListener(each['ListenerPort'], None, None, None) for each in attribute.listeners] return listeners def ex_create_listener(self, balancer, backend_port, protocol, algorithm, bandwidth, **kwargs): """ Create load balancer listening rule. :param balancer: the balancer which the rule belongs to. The listener created will listen on the port of the the balancer as default. 'ListenerPort' in kwargs will *OVERRIDE* it. :type balancer: ``LoadBalancer`` :param backend_port: the backend server port :type backend_port: ``int`` :param protocol: the balancer protocol, default to http :type protocol: ``str`` :param algorithm: the balancer routing algorithm :type algorithm: ``Algorithm`` :param bandwidth: the listener bandwidth limits :type bandwidth: ``str`` :return: the created listener :rtype: ``SLBLoadBalancerListener`` """ cls = PROTOCOL_TO_LISTENER_MAP.get(protocol, SLBLoadBalancerHttpListener) if 'ListenerPort' in kwargs: port = kwargs['ListenerPort'] else: port = balancer.port listener = cls.create(port, backend_port, algorithm, bandwidth, extra=kwargs) params = listener.get_create_params() params['LoadBalancerId'] = balancer.id params['RegionId'] = self.region resp = self.connection.request(self.path, params) return resp.success() def ex_start_listener(self, balancer, port): """ Start balancer's listener listening the given port. :param balancer: a load balancer :type balancer: ``LoadBalancer`` :param port: listening port :type port: ``int`` :return: whether operation is success :rtype: ``bool`` """ params = {'Action': 'StartLoadBalancerListener', 'LoadBalancerId': balancer.id, 'ListenerPort': port} resp = self.connection.request(self.path, params) return resp.success() def ex_stop_listener(self, balancer, port): """ Stop balancer's listener listening the given port. :param balancer: a load balancer :type balancer: ``LoadBalancer`` :param port: listening port :type port: ``int`` :return: whether operation is success :rtype: ``bool`` """ params = {'Action': 'StopLoadBalancerListener', 'LoadBalancerId': balancer.id, 'ListenerPort': port} resp = self.connection.request(self.path, params) return resp.success() def ex_upload_certificate(self, name, server_certificate, private_key): """ Upload certificate and private key for https load balancer listener :param name: the certificate name :type name: ``str`` :param server_certificate: the content of the certificate to upload in PEM format :type server_certificate: ``str`` :param private_key: the content of the private key to upload in PEM format :type private_key: ``str`` :return: new created certificate info :rtype: ``SLBServerCertificate`` """ params = {'Action': 'UploadServerCertificate', 'RegionId': self.region, 'ServerCertificate': server_certificate, 'PrivateKey': private_key} if name: params['ServerCertificateName'] = name resp_body = self.connection.request(self.path, params).object return self._to_server_certificate(resp_body) def ex_list_certificates(self, certificate_ids=[]): """ List all server certificates :param certificate_ids: certificate ids to filter results :type certificate_ids: ``str`` :return: certificates :rtype: ``SLBServerCertificate`` """ params = {'Action': 'DescribeServerCertificates', 'RegionId': self.region} if certificate_ids and isinstance(certificate_ids, list): params['ServerCertificateId'] = ','.join(certificate_ids) resp_body = self.connection.request(self.path, params).object cert_elements = findall(resp_body, 'ServerCertificates/ServerCertificate', namespace=self.namespace) certificates = [self._to_server_certificate(el) for el in cert_elements] return certificates def ex_delete_certificate(self, certificate_id): """ Delete the given server certificate :param certificate_id: the id of the certificate to delete :type certificate_id: ``str`` :return: whether process is success :rtype: ``bool`` """ params = {'Action': 'DeleteServerCertificate', 'RegionId': self.region, 'ServerCertificateId': certificate_id} resp = self.connection.request(self.path, params) return resp.success() def ex_set_certificate_name(self, certificate_id, name): """ Set server certificate name. :param certificate_id: the id of the server certificate to update :type certificate_id: ``str`` :param name: the new name :type name: ``str`` :return: whether updating is success :rtype: ``bool`` """ params = {'Action': 'SetServerCertificateName', 'RegionId': self.region, 'ServerCertificateId': certificate_id, 'ServerCertificateName': name} resp = self.connection.request(self.path, params) return resp.success() def _to_balancers(self, element): xpath = 'LoadBalancers/LoadBalancer' return [self._to_balancer(el) for el in findall(element=element, xpath=xpath, namespace=self.namespace)] def _to_balancer(self, el): _id = findtext(element=el, xpath='LoadBalancerId', namespace=self.namespace) name = findtext(element=el, xpath='LoadBalancerName', namespace=self.namespace) status = findtext(element=el, xpath='LoadBalancerStatus', namespace=self.namespace) state = STATE_MAPPINGS.get(status, State.UNKNOWN) address = findtext(element=el, xpath='Address', namespace=self.namespace) extra = self._get_extra_dict( el, RESOURCE_EXTRA_ATTRIBUTES_MAP['balancer']) balancer = LoadBalancer(id=_id, name=name, state=state, ip=address, port=None, driver=self, extra=extra) return balancer def _create_list_params(self, params, items, label): """ return parameter list """ if isinstance(items, str): items = [items] for index, item in enumerate(items): params[label % (index + 1)] = item return params def _get_extra_dict(self, element, mapping): """ Extract attributes from the element based on rules provided in the mapping dictionary. :param element: Element to parse the values from. :type element: xml.etree.ElementTree.Element. :param mapping: Dictionary with the extra layout :type node: :class:`Node` :rtype: ``dict`` """ extra = {} for attribute, values in mapping.items(): transform_func = values['transform_func'] value = findattr(element=element, xpath=values['xpath'], namespace=self.namespace) if value: try: extra[attribute] = transform_func(value) except Exception: extra[attribute] = None else: extra[attribute] = value return extra def _to_servers_json(self, members): servers = [] for each in members: server = {'ServerId': each.id, 'Weight': '100'} if 'Weight' in each.extra: server['Weight'] = each.extra['Weight'] servers.append(server) try: return json.dumps(servers) except Exception: raise AttributeError('could not convert member to backend server') def _to_balancer_attribute(self, element): balancer = self._to_balancer(element) port_proto_elements = findall( element, 'ListenerPortsAndProtocol/ListenerPortAndProtocol', namespace=self.namespace) if len(port_proto_elements) > 0: listeners = [self._to_port_and_protocol(el) for el in port_proto_elements] else: port_elements = findall(element, 'ListenerPorts/ListenerPort', namespace=self.namespace) listeners = [{'ListenerPort': el.text, 'ListenerProtocol': 'http'} for el in port_elements] server_elements = findall(element, 'BackendServers/BackendServer', namespace=self.namespace) backend_servers = [self._to_server_and_weight(el) for el in server_elements] return SLBLoadBalancerAttribute(balancer, listeners, backend_servers) def _to_port_and_protocol(self, el): port = findtext(el, 'ListenerPort', namespace=self.namespace) protocol = findtext(el, 'ListenerProtocol', namespace=self.namespace) return {'ListenerPort': port, 'ListenerProtocol': protocol} def _to_server_and_weight(self, el): server_id = findtext(el, 'ServerId', namespace=self.namespace) weight = findtext(el, 'Weight', namespace=self.namespace) return {'ServerId': server_id, 'Weight': weight} def _to_server_certificate(self, el): _id = findtext(el, 'ServerCertificateId', namespace=self.namespace) name = findtext(el, 'ServerCertificateName', namespace=self.namespace) fingerprint = findtext(el, 'Fingerprint', namespace=self.namespace) return SLBServerCertificate(id=_id, name=name, fingerprint=fingerprint) def _list_to_json(self, value): try: return json.dumps(value) except Exception: return '[]' apache-libcloud-2.8.0/libcloud/loadbalancer/drivers/softlayer.py0000664000175000017500000003543413535474530024711 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance withv # 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. __all__ = [ 'SoftlayerLBDriver' ] from libcloud.common.types import LibcloudError from libcloud.common.softlayer import SoftLayerConnection from libcloud.utils.misc import find, reverse_dict from libcloud.loadbalancer.types import State from libcloud.loadbalancer.base import Algorithm, Driver, LoadBalancer from libcloud.loadbalancer.base import DEFAULT_ALGORITHM, Member lb_service = 'SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_'\ 'VirtualIpAddress' class LBPackage(object): """ Defines a single Softlayer package to be used when placing orders ( e.g. via ex_place_balancer_order method). :param id: Package id. :type id: ``int`` :param name: Package name. :type name: ``str`` :param description: Package short description. :type description: ``str`` :param price_id: Id of the price for this package. :type price_id: ``int`` :param capacity: Provides a numerical representation of the capacity given in the description of this package. :type capacity: ``int`` """ def __init__(self, id, name, description, price_id, capacity): self.id = id self.name = name self.description = description self.price_id = price_id self.capacity = capacity def __repr__(self): return ( '' % (self.id, self.name, self.description, self.price_id, self.capacity)) class SoftlayerLBDriver(Driver): name = 'Softlayer Load Balancing' website = 'http://www.softlayer.com/' connectionCls = SoftLayerConnection _VALUE_TO_ALGORITHM_MAP = { 'ROUND_ROBIN': Algorithm.ROUND_ROBIN, 'LEAST_CONNECTIONS': Algorithm.LEAST_CONNECTIONS, 'SHORTEST_RESPONSE': Algorithm.SHORTEST_RESPONSE, 'PERSISTENT_IP': Algorithm.PERSISTENT_IP } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) def list_balancers(self): mask = { 'adcLoadBalancers': { 'ipAddress': '', 'loadBalancerHardware': { 'datacenter': '' }, 'virtualServers': { 'serviceGroups': { 'routingMethod': '', 'routingType': '', 'services': { 'ipAddress': '' } } } } } res = self.connection.request( 'SoftLayer_Account', 'getAdcLoadBalancers', object_mask=mask).object return [self._to_balancer(lb) for lb in res] def get_balancer(self, balancer_id): balancers = self.list_balancers() balancer = find(balancers, lambda b: b.id == balancer_id) if not balancer: raise LibcloudError(value='No balancer found for id: %s' % balancer_id, driver=self) return balancer def list_protocols(self): """ Return a list of supported protocols. :rtype: ``list`` of ``str`` """ return ['dns', 'ftp', 'http', 'https', 'tcp', 'udp'] def balancer_list_members(self, balancer): lb = self._get_balancer_model(balancer.id) members = [] vs = self._locate_service_group(lb, balancer.port) if vs: if vs['serviceGroups']: srvgrp = vs['serviceGroups'][0] members = [self._to_member(srv, balancer) for srv in srvgrp['services']] return members def balancer_attach_member(self, balancer, member): lb = self._get_balancer_model(balancer.id) vs = self._locate_service_group(lb, balancer.port) if not vs: raise LibcloudError(value='No service_group found for balancer ' 'port: %s' % balancer.port, driver=self) if vs['serviceGroups']: services = vs['serviceGroups'][0]['services'] services.append(self._to_service_template(member.ip, member.port)) self.connection.request(lb_service, 'editObject', lb, id=balancer.id) return [m for m in balancer.list_members() if m.ip == member.ip][0] def balancer_detach_member(self, balancer, member): svc_lbsrv = 'SoftLayer_Network_Application_Delivery_Controller_'\ 'LoadBalancer_Service' self.connection.request(svc_lbsrv, 'deleteObject', id=member.id) return True def destroy_balancer(self, balancer): res_billing = self.connection.request(lb_service, 'getBillingItem', id=balancer.id).object self.connection.request('SoftLayer_Billing_Item', 'cancelService', id=res_billing['id']) return True def ex_list_balancer_packages(self): """ Retrieves the available local load balancer packages. :rtype: ``list`` of :class:`LBPackage` """ mask = { 'prices': '' } res = self.connection.request('SoftLayer_Product_Package', 'getItems', id=0, object_mask=mask).object res_lb_pkgs = [r for r in res if r['description'].find ('Load Balancer') != -1] res_lb_pkgs = [r for r in res_lb_pkgs if not r['description']. startswith('Global')] return [self._to_lb_package(r) for r in res_lb_pkgs] def ex_place_balancer_order(self, package, location): """ Places an order for a local loadbalancer in the specified location. :param package: The package to create the loadbalancer from. :type package: :class:`LBPackage` :param string location: The location (datacenter) to create the loadbalancer. :type location: :class:`NodeLocation` :return: ``True`` if ex_place_balancer_order was successful. :rtype: ``bool`` """ data = { 'complexType': 'SoftLayer_Container_Product_Order_Network_' 'LoadBalancer', 'quantity': 1, 'packageId': 0, 'location': self._get_location(location.id), 'prices': [{'id': package.price_id}] } self.connection.request('SoftLayer_Product_Order', 'placeOrder', data) return True def ex_configure_load_balancer(self, balancer, port=80, protocol='http', algorithm=DEFAULT_ALGORITHM, ex_allocation=100): """ Configure the loadbalancer by adding it with a front-end port (aka a service group in the Softlayer loadbalancer model). Softlayer loadbalancer may be defined with multiple service groups (front-end ports) each defined with a unique port number. :param balancer: The loadbalancer. :type balancer: :class:`LoadBalancer` :param port: Port of the service group, defaults to 80. :type port: ``int`` :param protocol: Loadbalancer protocol, defaults to http. :type protocol: ``str`` :param algorithm: Load balancing algorithm, defaults to Algorithm.ROUND_ROBIN :type algorithm: :class:`Algorithm` :param ex_allocation: The percentage of the total connection allocations to allocate for this group. :type ex_allocation: ``int`` :return: ``True`` if ex_add_service_group was successful. :rtype: ``bool`` """ _types = self._get_routing_types() _methods = self._get_routing_methods() rt = find(_types, lambda t: t['keyname'] == protocol.upper()) if not rt: raise LibcloudError(value='Invalid protocol %s' % protocol, driver=self) value = self._algorithm_to_value(algorithm) meth = find(_methods, lambda m: m['keyname'] == value) if not meth: raise LibcloudError(value='Invalid algorithm %s' % algorithm, driver=self) service_group_template = { 'port': port, 'allocation': ex_allocation, 'serviceGroups': [{ 'routingTypeId': rt['id'], 'routingMethodId': meth['id'] }] } lb = self._get_balancer_model(balancer.id) if len(lb['virtualServers']) > 0: port = lb['virtualServers'][0]['port'] raise LibcloudError(value='Loadbalancer already configured with ' 'a service group (front-end port)' % port, driver=self) lb['virtualServers'].append(service_group_template) self.connection.request(lb_service, 'editObject', lb, id=balancer.id) return True def _get_balancer_model(self, balancer_id): """ Retrieve Softlayer loadbalancer model. """ lb_mask = { 'virtualServers': { 'serviceGroups': { 'services': { 'ipAddress': '', 'groupReferences': '', } } } } lb_res = self.connection.request(lb_service, 'getObject', object_mask=lb_mask, id=balancer_id).\ object return lb_res def _locate_service_group(self, lb, port): """ Locate service group with given port. Return virtualServers (vs) entry whose port matches the supplied parameter port. For a negative port, just return the first vs entry. None is returned if no match found. :param lb: Softlayer loadbalancer model. :type lb: ``dict`` :param port: loadbalancer front-end port. :type port: ``int`` :return: Matched entry in the virtualServers array of the supplied model. :rtype: ``dict`` """ vs = None if port < 0: vs = lb['virtualServers'][0] if lb['virtualServers']\ else None else: vs = find(lb['virtualServers'], lambda v: v['port'] == port) return vs def _get_routing_types(self): svc_rtype = 'SoftLayer_Network_Application_Delivery_Controller_'\ 'LoadBalancer_Routing_Type' return self.connection.request(svc_rtype, 'getAllObjects').object def _get_routing_methods(self): svc_rmeth = 'SoftLayer_Network_Application_Delivery_Controller_'\ 'LoadBalancer_Routing_Method' return self.connection.request(svc_rmeth, 'getAllObjects').object def _get_location(self, location_id): res = self.connection.request('SoftLayer_Location_Datacenter', 'getDatacenters').object dcenter = find(res, lambda d: d['name'] == location_id) if not dcenter: raise LibcloudError(value='Invalid value %s' % location_id, driver=self) return dcenter['id'] def _get_ipaddress(self, ip): svc_ipaddress = 'SoftLayer_Network_Subnet_IpAddress' return self.connection.request(svc_ipaddress, 'getByIpAddress', ip).object def _to_lb_package(self, pkg): try: price_id = pkg['prices'][0]['id'] except Exception: price_id = -1 capacity = int(pkg.get('capacity', 0)) return LBPackage(id=pkg['id'], name=pkg['keyName'], description=pkg['description'], price_id=price_id, capacity=capacity) def _to_service_template(self, ip, port): """ Builds single member entry in Softlayer loadbalancer model """ template = { 'enabled': 1, # enable the service 'port': port, # back-end port 'ipAddressId': self._get_ipaddress(ip)['id'], 'healthChecks': [{ 'healthCheckTypeId': 21 # default health check }], 'groupReferences': [{ 'weight': 1 }] } return template def _to_balancer(self, lb): ipaddress = lb['ipAddress']['ipAddress'] extra = {} extra['connection_limit'] = lb['connectionLimit'] extra['ssl_active'] = lb['sslActiveFlag'] extra['ssl_enabled'] = lb['sslEnabledFlag'] extra['ha'] = lb['highAvailabilityFlag'] extra['datacenter'] = \ lb['loadBalancerHardware'][0]['datacenter']['name'] # In Softlayer, there could be multiple group of members (aka service # groups), so retrieve the first one vs = self._locate_service_group(lb, -1) if vs: port = vs['port'] if vs['serviceGroups']: srvgrp = vs['serviceGroups'][0] routing_method = srvgrp['routingMethod']['keyname'] routing_type = srvgrp['routingType']['keyname'] try: extra['algorithm'] = self.\ _value_to_algorithm(routing_method) except Exception: pass extra['protocol'] = routing_type.lower() if not vs: port = -1 balancer = LoadBalancer( id=lb['id'], name='', state=State.UNKNOWN, ip=ipaddress, port=port, driver=self.connection.driver, extra=extra ) return balancer def _to_member(self, srv, balancer=None): svc_id = srv['id'] ip = srv['ipAddress']['ipAddress'] port = srv['port'] extra = {} extra['status'] = srv['status'] extra['enabled'] = srv['enabled'] return Member(id=svc_id, ip=ip, port=port, balancer=balancer, extra=extra) apache-libcloud-2.8.0/libcloud/loadbalancer/providers.py0000664000175000017500000000504013535474530023226 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.loadbalancer.types import Provider from libcloud.loadbalancer.types import OLD_CONSTANT_TO_NEW_MAPPING from libcloud.common.providers import get_driver as _get_provider_driver from libcloud.common.providers import set_driver as _set_provider_driver __all__ = [ "Provider", "DRIVERS", "get_driver", ] DRIVERS = { Provider.RACKSPACE: ('libcloud.loadbalancer.drivers.rackspace', 'RackspaceLBDriver'), Provider.GOGRID: ('libcloud.loadbalancer.drivers.gogrid', 'GoGridLBDriver'), Provider.NINEFOLD: ('libcloud.loadbalancer.drivers.ninefold', 'NinefoldLBDriver'), Provider.BRIGHTBOX: ('libcloud.loadbalancer.drivers.brightbox', 'BrightboxLBDriver'), Provider.ELB: ('libcloud.loadbalancer.drivers.elb', 'ElasticLBDriver'), Provider.ALB: ('libcloud.loadbalancer.drivers.alb', 'ApplicationLBDriver'), Provider.CLOUDSTACK: ('libcloud.loadbalancer.drivers.cloudstack', 'CloudStackLBDriver'), Provider.GCE: ('libcloud.loadbalancer.drivers.gce', 'GCELBDriver'), Provider.SOFTLAYER: ('libcloud.loadbalancer.drivers.softlayer', 'SoftlayerLBDriver'), Provider.DIMENSIONDATA: ('libcloud.loadbalancer.drivers.dimensiondata', 'DimensionDataLBDriver'), Provider.ALIYUN_SLB: ('libcloud.loadbalancer.drivers.slb', 'SLBDriver'), Provider.NTTCIS: ('libcloud.loadbalancer.drivers.nttcis', 'NttCisLBDriver'), } def get_driver(provider): deprecated_constants = OLD_CONSTANT_TO_NEW_MAPPING return _get_provider_driver(drivers=DRIVERS, provider=provider, deprecated_constants=deprecated_constants) def set_driver(provider, module, klass): return _set_provider_driver(drivers=DRIVERS, provider=provider, module=module, klass=klass) apache-libcloud-2.8.0/libcloud/loadbalancer/types.py0000664000175000017500000000444013535474530022360 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ "Provider", "State", "LibcloudLBError", "LibcloudLBImmutableError", "OLD_CONSTANT_TO_NEW_MAPPING" ] from libcloud.common.types import LibcloudError class LibcloudLBError(LibcloudError): pass class LibcloudLBImmutableError(LibcloudLBError): pass class Provider(object): """ Defines for each of the supported providers Non-Dummy drivers are sorted in alphabetical order. Please preserve this ordering when adding new drivers. :cvar ALIYUN_SLB: Aliyun SLB loadbalancer driver """ ALB = 'alb' ALIYUN_SLB = 'aliyun_slb' BRIGHTBOX = 'brightbox' CLOUDSTACK = 'cloudstack' DIMENSIONDATA = 'dimensiondata' ELB = 'elb' GCE = 'gce' GOGRID = 'gogrid' NINEFOLD = 'ninefold' NTTCIS = 'nttcis' RACKSPACE = 'rackspace' SOFTLAYER = 'softlayer' # Deprecated RACKSPACE_US = 'rackspace_us' RACKSPACE_UK = 'rackspace_uk' OLD_CONSTANT_TO_NEW_MAPPING = { Provider.RACKSPACE_US: Provider.RACKSPACE, Provider.RACKSPACE_UK: Provider.RACKSPACE, } class State(object): """ Standard states for a loadbalancer :cvar RUNNING: loadbalancer is running and ready to use :cvar UNKNOWN: loabalancer state is unknown """ RUNNING = 0 PENDING = 1 UNKNOWN = 2 ERROR = 3 DELETED = 4 class MemberCondition(object): """ Each member of a load balancer can have an associated condition which determines its role within the load balancer. """ ENABLED = 0 DISABLED = 1 DRAINING = 2 apache-libcloud-2.8.0/libcloud/pricing.py0000664000175000017500000001550213576514553020246 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement from typing import Dict """ A class which handles loading the pricing files. """ import os.path from os.path import join as pjoin try: import simplejson as json try: JSONDecodeError = json.JSONDecodeError except AttributeError: # simplejson < 2.1.0 does not have the JSONDecodeError exception class JSONDecodeError = ValueError # type: ignore except ImportError: import json # type: ignore JSONDecodeError = ValueError # type: ignore __all__ = [ 'get_pricing', 'get_size_price', 'set_pricing', 'clear_pricing_data', 'download_pricing_file' ] # Default URL to the pricing file DEFAULT_FILE_URL = 'https://git-wip-us.apache.org/repos/asf?p=libcloud.git;a=blob_plain;f=libcloud/data/pricing.json' # NOQA CURRENT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) DEFAULT_PRICING_FILE_PATH = pjoin(CURRENT_DIRECTORY, 'data/pricing.json') CUSTOM_PRICING_FILE_PATH = os.path.expanduser('~/.libcloud/pricing.json') # Pricing data cache PRICING_DATA = { 'compute': {}, 'storage': {} } # type: Dict[str, Dict] VALID_PRICING_DRIVER_TYPES = ['compute', 'storage'] def get_pricing_file_path(file_path=None): if os.path.exists(CUSTOM_PRICING_FILE_PATH) and \ os.path.isfile(CUSTOM_PRICING_FILE_PATH): # Custom pricing file is available, use it return CUSTOM_PRICING_FILE_PATH return DEFAULT_PRICING_FILE_PATH def get_pricing(driver_type, driver_name, pricing_file_path=None): """ Return pricing for the provided driver. :type driver_type: ``str`` :param driver_type: Driver type ('compute' or 'storage') :type driver_name: ``str`` :param driver_name: Driver name :type pricing_file_path: ``str`` :param pricing_file_path: Custom path to a price file. If not provided it uses a default path. :rtype: ``dict`` :return: Dictionary with pricing where a key name is size ID and the value is a price. """ if driver_type not in VALID_PRICING_DRIVER_TYPES: raise AttributeError('Invalid driver type: %s', driver_type) if driver_name in PRICING_DATA[driver_type]: return PRICING_DATA[driver_type][driver_name] if not pricing_file_path: pricing_file_path = get_pricing_file_path(file_path=pricing_file_path) with open(pricing_file_path) as fp: content = fp.read() pricing_data = json.loads(content) size_pricing = pricing_data[driver_type][driver_name] for driver_type in VALID_PRICING_DRIVER_TYPES: # pylint: disable=maybe-no-member pricing = pricing_data.get(driver_type, None) if pricing: PRICING_DATA[driver_type] = pricing return size_pricing def set_pricing(driver_type, driver_name, pricing): """ Populate the driver pricing dictionary. :type driver_type: ``str`` :param driver_type: Driver type ('compute' or 'storage') :type driver_name: ``str`` :param driver_name: Driver name :type pricing: ``dict`` :param pricing: Dictionary where a key is a size ID and a value is a price. """ PRICING_DATA[driver_type][driver_name] = pricing def get_size_price(driver_type, driver_name, size_id): """ Return price for the provided size. :type driver_type: ``str`` :param driver_type: Driver type ('compute' or 'storage') :type driver_name: ``str`` :param driver_name: Driver name :type size_id: ``str`` or ``int`` :param size_id: Unique size ID (can be an integer or a string - depends on the driver) :rtype: ``float`` :return: Size price. """ pricing = get_pricing(driver_type=driver_type, driver_name=driver_name) try: price = float(pricing[size_id]) except KeyError: # Price not available price = None return price def invalidate_pricing_cache(): """ Invalidate pricing cache for all the drivers. """ PRICING_DATA['compute'] = {} PRICING_DATA['storage'] = {} def clear_pricing_data(): """ Invalidate pricing cache for all the drivers. Note: This method does the same thing as invalidate_pricing_cache and is here for backward compatibility reasons. """ invalidate_pricing_cache() def invalidate_module_pricing_cache(driver_type, driver_name): """ Invalidate the cache for the specified driver. :type driver_type: ``str`` :param driver_type: Driver type ('compute' or 'storage') :type driver_name: ``str`` :param driver_name: Driver name """ if driver_name in PRICING_DATA[driver_type]: del PRICING_DATA[driver_type][driver_name] def download_pricing_file(file_url=DEFAULT_FILE_URL, file_path=CUSTOM_PRICING_FILE_PATH): """ Download pricing file from the file_url and save it to file_path. :type file_url: ``str`` :param file_url: URL pointing to the pricing file. :type file_path: ``str`` :param file_path: Path where a download pricing file will be saved. """ from libcloud.utils.connection import get_response_object dir_name = os.path.dirname(file_path) if not os.path.exists(dir_name): # Verify a valid path is provided msg = ('Can\'t write to %s, directory %s, doesn\'t exist' % (file_path, dir_name)) raise ValueError(msg) if os.path.exists(file_path) and os.path.isdir(file_path): msg = ('Can\'t write to %s file path because it\'s a' ' directory' % (file_path)) raise ValueError(msg) response = get_response_object(file_url) body = response.body # Verify pricing file is valid try: data = json.loads(body) except JSONDecodeError: msg = 'Provided URL doesn\'t contain valid pricing data' raise Exception(msg) # pylint: disable=maybe-no-member if not data.get('updated', None): msg = 'Provided URL doesn\'t contain valid pricing data' raise Exception(msg) # No need to stream it since file is small with open(file_path, 'w') as file_handle: file_handle.write(body) apache-libcloud-2.8.0/libcloud/py.typed0000664000175000017500000000000013577507766017734 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/security.py0000664000175000017500000000557413535474530020465 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Security (SSL) Settings Usage: import libcloud.security libcloud.security.VERIFY_SSL_CERT = True # Optional. libcloud.security.CA_CERTS_PATH = '/path/to/certfile' """ import os import ssl __all__ = [ 'VERIFY_SSL_CERT', 'SSL_VERSION', 'CA_CERTS_PATH' ] VERIFY_SSL_CERT = True SSL_VERSION = ssl.PROTOCOL_TLSv1 # True to use certifi CA bundle path when certifi library is available USE_CERTIFI = os.environ.get('LIBCLOUD_SSL_USE_CERTIFI', True) USE_CERTIFI = str(USE_CERTIFI).lower() in ['true', '1'] # File containing one or more PEM-encoded CA certificates # concatenated together. CA_CERTS_PATH = None # Insert certifi CA bundle path to the front of Libcloud CA bundle search # path if certifi is available try: import certifi except ImportError: has_certifi = False else: has_certifi = True if has_certifi and USE_CERTIFI: certifi_ca_bundle_path = certifi.where() CA_CERTS_PATH = certifi_ca_bundle_path # Allow user to explicitly specify which CA bundle to use, using an environment # variable environment_cert_file = os.getenv('SSL_CERT_FILE', None) if environment_cert_file is not None: # Make sure the file exists if not os.path.exists(environment_cert_file): raise ValueError('Certificate file %s doesn\'t exist' % (environment_cert_file)) if not os.path.isfile(environment_cert_file): raise ValueError('Certificate file can\'t be a directory') # If a provided file exists we ignore other common paths because we # don't want to fall-back to a potentially less restrictive bundle CA_CERTS_PATH = environment_cert_file CA_CERTS_UNAVAILABLE_ERROR_MSG = ( 'No CA Certificates were found in CA_CERTS_PATH. For information on ' 'how to get required certificate files, please visit ' 'https://libcloud.readthedocs.org/en/latest/other/' 'ssl-certificate-validation.html' ) VERIFY_SSL_DISABLED_MSG = ( 'SSL certificate verification is disabled, this can pose a ' 'security risk. For more information how to enable the SSL ' 'certificate verification, please visit the libcloud ' 'documentation.' ) apache-libcloud-2.8.0/libcloud/storage/0000775000175000017500000000000013600223624017662 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/storage/__init__.py0000664000175000017500000000146613570310635022007 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Module for working with Storage """ apache-libcloud-2.8.0/libcloud/storage/base.py0000664000175000017500000005475213576514553021203 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Provides base classes for working with storage """ # Backward compatibility for Python 2.5 from __future__ import with_statement from typing import Type import os.path # pylint: disable-msg=W0404 import hashlib from os.path import join as pjoin from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b import libcloud.utils.files from libcloud.common.types import LibcloudError from libcloud.common.base import Connection from libcloud.common.base import ConnectionUserAndKey, BaseDriver from libcloud.storage.types import ObjectDoesNotExistError __all__ = [ 'Object', 'Container', 'StorageDriver', 'CHUNK_SIZE', 'DEFAULT_CONTENT_TYPE' ] CHUNK_SIZE = 8096 # Default Content-Type which is sent when uploading an object if one is not # supplied and can't be detected when using non-strict mode. DEFAULT_CONTENT_TYPE = 'application/octet-stream' class Object(object): """ Represents an object (BLOB). """ def __init__(self, name, size, hash, extra, meta_data, container, driver): """ :param name: Object name (must be unique per container). :type name: ``str`` :param size: Object size in bytes. :type size: ``int`` :param hash: Object hash. :type hash: ``str`` :param container: Object container. :type container: :class:`Container` :param extra: Extra attributes. :type extra: ``dict`` :param meta_data: Optional object meta data. :type meta_data: ``dict`` :param driver: StorageDriver instance. :type driver: :class:`StorageDriver` """ self.name = name self.size = size self.hash = hash self.container = container self.extra = extra or {} self.meta_data = meta_data or {} self.driver = driver def get_cdn_url(self): return self.driver.get_object_cdn_url(obj=self) def enable_cdn(self, **kwargs): return self.driver.enable_object_cdn(obj=self, **kwargs) def download(self, destination_path, overwrite_existing=False, delete_on_failure=True): return self.driver.download_object(self, destination_path, overwrite_existing, delete_on_failure) def as_stream(self, chunk_size=None): return self.driver.download_object_as_stream(self, chunk_size) def delete(self): return self.driver.delete_object(self) def __repr__(self): return ('' % (self.name, self.size, self.hash, self.driver.name)) class Container(object): """ Represents a container (bucket) which can hold multiple objects. """ def __init__(self, name, extra, driver): """ :param name: Container name (must be unique). :type name: ``str`` :param extra: Extra attributes. :type extra: ``dict`` :param driver: StorageDriver instance. :type driver: :class:`StorageDriver` """ self.name = name self.extra = extra or {} self.driver = driver def iterate_objects(self): return self.driver.iterate_container_objects(container=self) def list_objects(self): return self.driver.list_container_objects(container=self) def get_cdn_url(self): return self.driver.get_container_cdn_url(container=self) def enable_cdn(self, **kwargs): return self.driver.enable_container_cdn(container=self, **kwargs) def get_object(self, object_name): return self.driver.get_object(container_name=self.name, object_name=object_name) def upload_object(self, file_path, object_name, extra=None, **kwargs): return self.driver.upload_object( file_path, self, object_name, extra=extra, **kwargs) def upload_object_via_stream(self, iterator, object_name, extra=None, **kwargs): return self.driver.upload_object_via_stream( iterator, self, object_name, extra=extra, **kwargs) def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): return self.driver.download_object( obj, destination_path, overwrite_existing=overwrite_existing, delete_on_failure=delete_on_failure) def download_object_as_stream(self, obj, chunk_size=None): return self.driver.download_object_as_stream(obj, chunk_size) def delete_object(self, obj): return self.driver.delete_object(obj) def delete(self): return self.driver.delete_container(self) def __repr__(self): return ('' % (self.name, self.driver.name)) class StorageDriver(BaseDriver): """ A base StorageDriver to derive from. """ connectionCls = ConnectionUserAndKey # type: Type[Connection] name = None # type: str hash_type = 'md5' # type: str supports_chunked_encoding = False # type: bool # When strict mode is used, exception will be thrown if no content type is # provided and none can be detected when uploading an object strict_mode = False # type: bool def iterate_containers(self): """ Return a generator of containers for the given account :return: A generator of Container instances. :rtype: ``generator`` of :class:`Container` """ raise NotImplementedError( 'iterate_containers not implemented for this driver') def list_containers(self): """ Return a list of containers. :return: A list of Container instances. :rtype: ``list`` of :class:`Container` """ return list(self.iterate_containers()) def iterate_container_objects(self, container): """ Return a generator of objects for the given container. :param container: Container instance :type container: :class:`Container` :return: A generator of Object instances. :rtype: ``generator`` of :class:`Object` """ raise NotImplementedError( 'iterate_container_objects not implemented for this driver') def list_container_objects(self, container, ex_prefix=None): """ Return a list of objects for the given container. :param container: Container instance. :type container: :class:`Container` :param ex_prefix: Filter objects starting with a prefix. :type ex_prefix: ``str`` :return: A list of Object instances. :rtype: ``list`` of :class:`Object` """ return list(self.iterate_container_objects(container)) def get_container(self, container_name): """ Return a container instance. :param container_name: Container name. :type container_name: ``str`` :return: :class:`Container` instance. :rtype: :class:`Container` """ raise NotImplementedError( 'get_object not implemented for this driver') def get_container_cdn_url(self, container): """ Return a container CDN URL. :param container: Container instance :type container: :class:`Container` :return: A CDN URL for this container. :rtype: ``str`` """ raise NotImplementedError( 'get_container_cdn_url not implemented for this driver') def get_object(self, container_name, object_name): """ Return an object instance. :param container_name: Container name. :type container_name: ``str`` :param object_name: Object name. :type object_name: ``str`` :return: :class:`Object` instance. :rtype: :class:`Object` """ raise NotImplementedError( 'get_object not implemented for this driver') def get_object_cdn_url(self, obj): """ Return an object CDN URL. :param obj: Object instance :type obj: :class:`Object` :return: A CDN URL for this object. :rtype: ``str`` """ raise NotImplementedError( 'get_object_cdn_url not implemented for this driver') def enable_container_cdn(self, container): """ Enable container CDN. :param container: Container instance :type container: :class:`Container` :rtype: ``bool`` """ raise NotImplementedError( 'enable_container_cdn not implemented for this driver') def enable_object_cdn(self, obj): """ Enable object CDN. :param obj: Object instance :type obj: :class:`Object` :rtype: ``bool`` """ raise NotImplementedError( 'enable_object_cdn not implemented for this driver') def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): """ Download an object to the specified destination path. :param obj: Object instance. :type obj: :class:`Object` :param destination_path: Full path to a file or a directory where the incoming file will be saved. :type destination_path: ``str`` :param overwrite_existing: True to overwrite an existing file, defaults to False. :type overwrite_existing: ``bool`` :param delete_on_failure: True to delete a partially downloaded file if the download was not successful (hash mismatch / file size). :type delete_on_failure: ``bool`` :return: True if an object has been successfully downloaded, False otherwise. :rtype: ``bool`` """ raise NotImplementedError( 'download_object not implemented for this driver') def download_object_as_stream(self, obj, chunk_size=None): """ Return a generator which yields object data. :param obj: Object instance :type obj: :class:`Object` :param chunk_size: Optional chunk size (in bytes). :type chunk_size: ``int`` """ raise NotImplementedError( 'download_object_as_stream not implemented for this driver') def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True, headers=None): """ Upload an object currently located on a disk. :param file_path: Path to the object on disk. :type file_path: ``str`` :param container: Destination container. :type container: :class:`Container` :param object_name: Object name. :type object_name: ``str`` :param verify_hash: Verify hash :type verify_hash: ``bool`` :param extra: Extra attributes (driver specific). (optional) :type extra: ``dict`` :param headers: (optional) Additional request headers, such as CORS headers. For example: headers = {'Access-Control-Allow-Origin': 'http://mozilla.com'} :type headers: ``dict`` :rtype: :class:`Object` """ raise NotImplementedError( 'upload_object not implemented for this driver') def upload_object_via_stream(self, iterator, container, object_name, extra=None, headers=None): """ Upload an object using an iterator. If a provider supports it, chunked transfer encoding is used and you don't need to know in advance the amount of data to be uploaded. Otherwise if a provider doesn't support it, iterator will be exhausted so a total size for data to be uploaded can be determined. Note: Exhausting the iterator means that the whole data must be buffered in memory which might result in memory exhausting when uploading a very large object. If a file is located on a disk you are advised to use upload_object function which uses fs.stat function to determine the file size and it doesn't need to buffer whole object in the memory. :param iterator: An object which implements the iterator interface. :type iterator: :class:`object` :param container: Destination container. :type container: :class:`Container` :param object_name: Object name. :type object_name: ``str`` :param extra: (optional) Extra attributes (driver specific). Note: This dictionary must contain a 'content_type' key which represents a content type of the stored object. :type extra: ``dict`` :param headers: (optional) Additional request headers, such as CORS headers. For example: headers = {'Access-Control-Allow-Origin': 'http://mozilla.com'} :type headers: ``dict`` :rtype: ``object`` """ raise NotImplementedError( 'upload_object_via_stream not implemented for this driver') def delete_object(self, obj): """ Delete an object. :param obj: Object instance. :type obj: :class:`Object` :return: ``bool`` True on success. :rtype: ``bool`` """ raise NotImplementedError( 'delete_object not implemented for this driver') def create_container(self, container_name): """ Create a new container. :param container_name: Container name. :type container_name: ``str`` :return: Container instance on success. :rtype: :class:`Container` """ raise NotImplementedError( 'create_container not implemented for this driver') def delete_container(self, container): """ Delete a container. :param container: Container instance :type container: :class:`Container` :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ raise NotImplementedError( 'delete_container not implemented for this driver') def _get_object(self, obj, callback, callback_kwargs, response, success_status_code=None): """ Call passed callback and start transfer of the object' :param obj: Object instance. :type obj: :class:`Object` :param callback: Function which is called with the passed callback_kwargs :type callback: :class:`function` :param callback_kwargs: Keyword arguments which are passed to the callback. :type callback_kwargs: ``dict`` :param response: Response instance. :type response: :class:`Response` :param success_status_code: Status code which represents a successful transfer (defaults to httplib.OK) :type success_status_code: ``int`` :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ success_status_code = success_status_code or httplib.OK if response.status == success_status_code: return callback(**callback_kwargs) elif response.status == httplib.NOT_FOUND: raise ObjectDoesNotExistError(object_name=obj.name, value='', driver=self) raise LibcloudError(value='Unexpected status code: %s' % (response.status), driver=self) def _save_object(self, response, obj, destination_path, overwrite_existing=False, delete_on_failure=True, chunk_size=None): """ Save object to the provided path. :param response: RawResponse instance. :type response: :class:`RawResponse` :param obj: Object instance. :type obj: :class:`Object` :param destination_path: Destination directory. :type destination_path: ``str`` :param delete_on_failure: True to delete partially downloaded object if the download fails. :type delete_on_failure: ``bool`` :param overwrite_existing: True to overwrite a local path if it already exists. :type overwrite_existing: ``bool`` :param chunk_size: Optional chunk size (defaults to ``libcloud.storage.base.CHUNK_SIZE``, 8kb) :type chunk_size: ``int`` :return: ``True`` on success, ``False`` otherwise. :rtype: ``bool`` """ chunk_size = chunk_size or CHUNK_SIZE base_name = os.path.basename(destination_path) if not base_name and not os.path.exists(destination_path): raise LibcloudError( value='Path %s does not exist' % (destination_path), driver=self) if not base_name: file_path = pjoin(destination_path, obj.name) else: file_path = destination_path if os.path.exists(file_path) and not overwrite_existing: raise LibcloudError( value='File %s already exists, but ' % (file_path) + 'overwrite_existing=False', driver=self) bytes_transferred = 0 with open(file_path, 'wb') as file_handle: for chunk in response._response.iter_content(chunk_size): file_handle.write(b(chunk)) bytes_transferred += len(chunk) if int(obj.size) != int(bytes_transferred): # Transfer failed, support retry? if delete_on_failure: try: os.unlink(file_path) except Exception: pass return False return True def _upload_object(self, object_name, content_type, request_path, request_method='PUT', headers=None, file_path=None, stream=None, upload_func=None, upload_func_kwargs=None, chunked=False, multipart=False): """ Helper function for setting common request headers and calling the passed in callback which uploads an object. """ headers = headers or {} if file_path and not os.path.exists(file_path): raise OSError('File %s does not exist' % (file_path)) if stream is not None and not hasattr(stream, 'next') and not \ hasattr(stream, '__next__'): raise AttributeError('iterator object must implement next() ' + 'method.') if not content_type: if file_path: name = file_path else: name = object_name content_type, _ = libcloud.utils.files.guess_file_mime_type(name) if not content_type: if self.strict_mode: raise AttributeError('File content-type could not be ' 'guessed and no content_type value ' 'is provided') else: # Fallback to a content-type content_type = DEFAULT_CONTENT_TYPE headers['Content-Type'] = content_type if stream: response = self.connection.request( request_path, method=request_method, data=stream, headers=headers, raw=True) stream_hash, stream_length = self._hash_buffered_stream( stream, self._get_hash_function()) else: with open(file_path, 'rb') as file_stream: response = self.connection.request( request_path, method=request_method, data=file_stream, headers=headers, raw=True) with open(file_path, 'rb') as file_stream: stream_hash, stream_length = self._hash_buffered_stream( file_stream, self._get_hash_function()) if not response.success(): response.parse_error() if upload_func: upload_func(**upload_func_kwargs) return {'response': response, 'bytes_transferred': stream_length, 'data_hash': stream_hash} def _hash_buffered_stream(self, stream, hasher, blocksize=65536): total_len = 0 if hasattr(stream, '__next__') or hasattr(stream, 'next'): # Ensure we start from the begining of a stream in case stream is # not at the beginning if hasattr(stream, 'seek'): stream.seek(0) for chunk in libcloud.utils.files.read_in_chunks(iterator=stream): hasher.update(b(chunk)) total_len += len(chunk) return (hasher.hexdigest(), total_len) if not hasattr(stream, '__exit__'): for s in stream: hasher.update(s) total_len = total_len + len(s) return (hasher.hexdigest(), total_len) with stream: buf = stream.read(blocksize) while len(buf) > 0: total_len = total_len + len(buf) hasher.update(buf) buf = stream.read(blocksize) return (hasher.hexdigest(), total_len) def _get_hash_function(self): """ Return instantiated hash function for the hash type supported by the provider. """ try: func = getattr(hashlib, self.hash_type)() except AttributeError: raise RuntimeError('Invalid or unsupported hash type: %s' % (self.hash_type)) return func apache-libcloud-2.8.0/libcloud/storage/drivers/0000775000175000017500000000000013600223624021340 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/storage/drivers/__init__.py0000664000175000017500000000156013535474530023466 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Drivers for working with different providers """ __all__ = [ 'dummy', 'cloudfiles' ] apache-libcloud-2.8.0/libcloud/storage/drivers/atmos.py0000664000175000017500000004072213570310635023047 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import hashlib import hmac import time from libcloud.utils.py3 import PY3 from libcloud.utils.py3 import b from libcloud.utils.py3 import httplib from libcloud.utils.py3 import next from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import urlencode from libcloud.utils.py3 import urlquote from libcloud.utils.py3 import urlunquote if PY3: from io import FileIO as file from libcloud.utils.files import read_in_chunks, guess_file_mime_type from libcloud.common.base import ConnectionUserAndKey, XmlResponse from libcloud.common.types import LibcloudError from libcloud.storage.base import Object, Container, StorageDriver, CHUNK_SIZE from libcloud.storage.types import ContainerAlreadyExistsError, \ ContainerDoesNotExistError, ContainerIsNotEmptyError, \ ObjectDoesNotExistError def collapse(s): return ' '.join([x for x in s.split(' ') if x]) class AtmosError(LibcloudError): def __init__(self, code, message, driver=None): super(AtmosError, self).__init__(value=message, driver=driver) self.code = code class AtmosResponse(XmlResponse): def success(self): return self.status in (httplib.OK, httplib.CREATED, httplib.NO_CONTENT, httplib.PARTIAL_CONTENT) def parse_error(self): tree = self.parse_body() if tree is None: return None code = int(tree.find('Code').text) message = tree.find('Message').text raise AtmosError(code=code, message=message, driver=self.connection.driver) class AtmosConnection(ConnectionUserAndKey): responseCls = AtmosResponse def add_default_headers(self, headers): headers['x-emc-uid'] = self.user_id headers['Date'] = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime()) headers['x-emc-date'] = headers['Date'] if 'Content-Type' not in headers: headers['Content-Type'] = 'application/octet-stream' if 'Accept' not in headers: headers['Accept'] = '*/*' return headers def pre_connect_hook(self, params, headers): headers['x-emc-signature'] = self._calculate_signature(params, headers) return params, headers def _calculate_signature(self, params, headers): pathstring = urlunquote(self.action) driver_path = self.driver.path # pylint: disable=no-member if pathstring.startswith(driver_path): pathstring = pathstring[len(driver_path):] if params: if type(params) is dict: params = list(params.items()) pathstring += '?' + urlencode(params) pathstring = pathstring.lower() xhdrs = [(k, v) for k, v in list(headers.items()) if k.startswith('x-emc-')] xhdrs.sort(key=lambda x: x[0]) signature = [ self.method, headers.get('Content-Type', ''), headers.get('Range', ''), headers.get('Date', ''), pathstring, ] signature.extend([k + ':' + collapse(v) for k, v in xhdrs]) signature = '\n'.join(signature) key = base64.b64decode(self.key) signature = hmac.new(b(key), b(signature), hashlib.sha1).digest() return base64.b64encode(b(signature)).decode('utf-8') class AtmosDriver(StorageDriver): connectionCls = AtmosConnection host = None path = None api_name = 'atmos' supports_chunked_encoding = True website = 'http://atmosonline.com/' name = 'atmos' DEFAULT_CDN_TTL = 60 * 60 * 24 * 7 # 1 week def __init__(self, key, secret=None, secure=True, host=None, port=None): host = host or self.host super(AtmosDriver, self).__init__(key, secret, secure, host, port) def iterate_containers(self): result = self.connection.request(self._namespace_path('')) entries = self._list_objects(result.object, object_type='directory') for entry in entries: extra = { 'object_id': entry['id'] } yield Container(entry['name'], extra, self) def get_container(self, container_name): path = self._namespace_path(container_name) + '/?metadata/system' try: result = self.connection.request(path) except AtmosError as e: if e.code != 1003: raise raise ContainerDoesNotExistError(e, self, container_name) meta = self._emc_meta(result) extra = { 'object_id': meta['objectid'] } return Container(container_name, extra, self) def create_container(self, container_name): path = self._namespace_path(container_name) + '/' try: self.connection.request(path, method='POST') except AtmosError as e: if e.code != 1016: raise raise ContainerAlreadyExistsError(e, self, container_name) return self.get_container(container_name) def delete_container(self, container): try: self.connection.request(self._namespace_path(container.name) + '/', method='DELETE') except AtmosError as e: if e.code == 1003: raise ContainerDoesNotExistError(e, self, container.name) elif e.code == 1023: raise ContainerIsNotEmptyError(e, self, container.name) return True def get_object(self, container_name, object_name): container = self.get_container(container_name) object_name_cleaned = self._clean_object_name(object_name) path = self._namespace_path(container_name) + '/' + object_name_cleaned try: result = self.connection.request(path + '?metadata/system') system_meta = self._emc_meta(result) result = self.connection.request(path + '?metadata/user') user_meta = self._emc_meta(result) except AtmosError as e: if e.code != 1003: raise raise ObjectDoesNotExistError(e, self, object_name) last_modified = time.strptime(system_meta['mtime'], '%Y-%m-%dT%H:%M:%SZ') last_modified = time.strftime('%a, %d %b %Y %H:%M:%S GMT', last_modified) extra = { 'object_id': system_meta['objectid'], 'last_modified': last_modified } data_hash = user_meta.pop('md5', '') return Object(object_name, int(system_meta['size']), data_hash, extra, user_meta, container, self) def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True): method = 'PUT' extra = extra or {} object_name_cleaned = self._clean_object_name(object_name) request_path = self._namespace_path(container.name) + '/' +\ object_name_cleaned content_type = extra.get('content_type', None) try: self.connection.request(request_path + '?metadata/system') except AtmosError as e: if e.code != 1003: raise method = 'POST' result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method=method, headers={}, file_path=file_path) bytes_transferred = result_dict['bytes_transferred'] if extra is None: meta_data = {} else: meta_data = extra.get('meta_data', {}) meta_data['md5'] = result_dict['data_hash'] user_meta = ', '.join([k + '=' + str(v) for k, v in list(meta_data.items())]) self.connection.request(request_path + '?metadata/user', method='POST', headers={'x-emc-meta': user_meta}) result = self.connection.request(request_path + '?metadata/system') meta = self._emc_meta(result) del meta_data['md5'] extra = { 'object_id': meta['objectid'], 'meta_data': meta_data, } return Object(object_name, bytes_transferred, result_dict['data_hash'], extra, meta_data, container, self) def upload_object_via_stream(self, iterator, container, object_name, extra=None): if isinstance(iterator, file): iterator = iter(iterator) data_hash = hashlib.md5() generator = read_in_chunks(iterator, CHUNK_SIZE, True) bytes_transferred = 0 try: chunk = next(generator) except StopIteration: chunk = '' path = self._namespace_path(container.name + '/' + object_name) method = 'PUT' if extra is not None: content_type = extra.get('content_type', None) else: content_type = None if not content_type: content_type, _ = guess_file_mime_type(object_name) if not content_type: raise AttributeError( 'File content-type could not be guessed and' + ' no content_type value provided') try: self.connection.request(path + '?metadata/system') except AtmosError as e: if e.code != 1003: raise method = 'POST' while True: end = bytes_transferred + len(chunk) - 1 data_hash.update(b(chunk)) headers = { 'x-emc-meta': 'md5=' + data_hash.hexdigest(), 'Content-Type': content_type, } if len(chunk) > 0 and bytes_transferred > 0: headers['Range'] = 'Bytes=%d-%d' % (bytes_transferred, end) method = 'PUT' result = self.connection.request(path, method=method, data=chunk, headers=headers) bytes_transferred += len(chunk) try: chunk = next(generator) except StopIteration: break if len(chunk) == 0: break data_hash = data_hash.hexdigest() if extra is None: meta_data = {} else: meta_data = extra.get('meta_data', {}) meta_data['md5'] = data_hash user_meta = ', '.join([k + '=' + str(v) for k, v in list(meta_data.items())]) self.connection.request(path + '?metadata/user', method='POST', headers={'x-emc-meta': user_meta}) result = self.connection.request(path + '?metadata/system') meta = self._emc_meta(result) extra = { 'object_id': meta['objectid'], 'meta_data': meta_data, } return Object(object_name, bytes_transferred, data_hash, extra, meta_data, container, self) def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): path = self._namespace_path(obj.container.name + '/' + obj.name) response = self.connection.request(path, method='GET', raw=True) return self._get_object(obj=obj, callback=self._save_object, response=response, callback_kwargs={ 'obj': obj, 'response': response.response, 'destination_path': destination_path, 'overwrite_existing': overwrite_existing, 'delete_on_failure': delete_on_failure }, success_status_code=httplib.OK) def download_object_as_stream(self, obj, chunk_size=None): path = self._namespace_path(obj.container.name + '/' + obj.name) response = self.connection.request(path, method='GET', raw=True) return self._get_object(obj=obj, callback=read_in_chunks, response=response, callback_kwargs={ 'iterator': response.response, 'chunk_size': chunk_size }, success_status_code=httplib.OK) def delete_object(self, obj): path = self._namespace_path(obj.container.name) + '/' +\ self._clean_object_name(obj.name) try: self.connection.request(path, method='DELETE') except AtmosError as e: if e.code != 1003: raise raise ObjectDoesNotExistError(e, self, obj.name) return True def enable_object_cdn(self, obj): return True def get_object_cdn_url(self, obj, expiry=None, use_object=False): """ Return an object CDN URL. :param obj: Object instance :type obj: :class:`Object` :param expiry: Expiry :type expiry: ``str`` :param use_object: Use object :type use_object: ``bool`` :rtype: ``str`` """ if use_object: path = '/rest/objects' + obj.meta_data['object_id'] else: path = '/rest/namespace/' + obj.container.name + '/' + obj.name if self.secure: protocol = 'https' else: protocol = 'http' expiry = str(expiry or int(time.time()) + self.DEFAULT_CDN_TTL) params = [ ('uid', self.key), ('expires', expiry), ] params.append(('signature', self._cdn_signature(path, params, expiry))) params = urlencode(params) path = self.path + path return urlparse.urlunparse((protocol, self.host, path, '', params, '')) def _cdn_signature(self, path, params, expiry): key = base64.b64decode(self.secret) signature = '\n'.join(['GET', path.lower(), self.key, expiry]) signature = hmac.new(key, signature, hashlib.sha1).digest() return base64.b64encode(signature) def _list_objects(self, tree, object_type=None): listing = tree.find(self._emc_tag('DirectoryList')) entries = [] for entry in listing.findall(self._emc_tag('DirectoryEntry')): file_type = entry.find(self._emc_tag('FileType')).text if object_type is not None and object_type != file_type: continue entries.append({ 'id': entry.find(self._emc_tag('ObjectID')).text, 'type': file_type, 'name': entry.find(self._emc_tag('Filename')).text }) return entries def _clean_object_name(self, name): return urlquote(name.encode('ascii')) def _namespace_path(self, path): return self.path + '/rest/namespace/' + urlquote(path.encode('ascii')) def _object_path(self, object_id): return self.path + '/rest/objects/' + object_id.encode('ascii') @staticmethod def _emc_tag(tag): return '{http://www.emc.com/cos/}' + tag def _emc_meta(self, response): meta = response.headers.get('x-emc-meta', '') if len(meta) == 0: return {} meta = meta.split(', ') return dict([x.split('=', 1) for x in meta]) def iterate_container_objects(self, container): headers = {'x-emc-include-meta': '1'} path = self._namespace_path(container.name) + '/' result = self.connection.request(path, headers=headers) entries = self._list_objects(result.object, object_type='regular') for entry in entries: metadata = {'object_id': entry['id']} yield Object(entry['name'], 0, '', {}, metadata, container, self) apache-libcloud-2.8.0/libcloud/storage/drivers/auroraobjects.py0000664000175000017500000000361513535474530024575 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.types import LibcloudError from libcloud.storage.providers import Provider from libcloud.storage.drivers.s3 import BaseS3StorageDriver, BaseS3Connection __all__ = [ 'AuroraObjectsStorageDriver' ] AURORA_OBJECTS_EU_HOST = 'o.auroraobjects.eu' NO_CDN_SUPPORT_ERROR = 'CDN is not supported by AuroraObjects' class BaseAuroraObjectsConnection(BaseS3Connection): host = AURORA_OBJECTS_EU_HOST class BaseAuroraObjectsStorageDriver(BaseS3StorageDriver): type = Provider.AURORAOBJECTS name = 'PCextreme AuroraObjects' website = 'https://www.pcextreme.com/aurora/objects' class AuroraObjectsStorageDriver(BaseAuroraObjectsStorageDriver): connectionCls = BaseAuroraObjectsConnection def enable_container_cdn(self, *argv): raise LibcloudError(NO_CDN_SUPPORT_ERROR, driver=self) def enable_object_cdn(self, *argv): raise LibcloudError(NO_CDN_SUPPORT_ERROR, driver=self) def get_container_cdn_url(self, *argv): raise LibcloudError(NO_CDN_SUPPORT_ERROR, driver=self) def get_object_cdn_url(self, *argv): raise LibcloudError(NO_CDN_SUPPORT_ERROR, driver=self) apache-libcloud-2.8.0/libcloud/storage/drivers/azure_blobs.py0000664000175000017500000011324413570310635024233 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import base64 import os import binascii from io import BytesIO from libcloud.utils.py3 import ET from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlquote from libcloud.utils.py3 import tostring from libcloud.utils.py3 import b from libcloud.utils.xml import fixxpath from libcloud.utils.files import read_in_chunks from libcloud.common.types import LibcloudError from libcloud.common.azure import AzureConnection from libcloud.storage.base import Object, Container, StorageDriver from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import ContainerAlreadyExistsError from libcloud.storage.types import InvalidContainerNameError from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError # Desired number of items in each response inside a paginated request RESPONSES_PER_REQUEST = 100 # As per the Azure documentation, if the upload file size is less than # 100MB, we can upload it in a single request. AZURE_BLOCK_MAX_SIZE = 100 * 1024 * 1024 # Azure block blocks must be maximum 4MB # Azure page blobs must be aligned in 512 byte boundaries (4MB fits that) AZURE_CHUNK_SIZE = 4 * 1024 * 1024 # Azure page blob must be aligned in 512 byte boundaries AZURE_PAGE_CHUNK_SIZE = 512 # The time period (in seconds) for which a lease must be obtained. # If set as -1, we get an infinite lease, but that is a bad idea. If # after getting an infinite lease, there was an issue in releasing the # lease, the object will remain 'locked' forever, unless the lease is # released using the lease_id (which is not exposed to the user) AZURE_LEASE_PERIOD = 60 AZURE_STORAGE_HOST_SUFFIX = 'blob.core.windows.net' class AzureBlobLease(object): """ A class to help in leasing an azure blob and renewing the lease """ def __init__(self, driver, object_path, use_lease): """ :param driver: The Azure storage driver that is being used :type driver: :class:`AzureStorageDriver` :param object_path: The path of the object we need to lease :type object_path: ``str`` :param use_lease: Indicates if we must take a lease or not :type use_lease: ``bool`` """ self.object_path = object_path self.driver = driver self.use_lease = use_lease self.lease_id = None self.params = {'comp': 'lease'} def renew(self): """ Renew the lease if it is older than a predefined time period """ if self.lease_id is None: return headers = {'x-ms-lease-action': 'renew', 'x-ms-lease-id': self.lease_id, 'x-ms-lease-duration': '60'} response = self.driver.connection.request(self.object_path, headers=headers, params=self.params, method='PUT') if response.status != httplib.OK: raise LibcloudError('Unable to obtain lease', driver=self) def update_headers(self, headers): """ Update the lease id in the headers """ if self.lease_id: headers['x-ms-lease-id'] = self.lease_id def __enter__(self): if not self.use_lease: return self headers = {'x-ms-lease-action': 'acquire', 'x-ms-lease-duration': '60'} response = self.driver.connection.request(self.object_path, headers=headers, params=self.params, method='PUT') if response.status == httplib.NOT_FOUND: return self elif response.status != httplib.CREATED: raise LibcloudError('Unable to obtain lease', driver=self) self.lease_id = response.headers['x-ms-lease-id'] return self def __exit__(self, type, value, traceback): if self.lease_id is None: return headers = {'x-ms-lease-action': 'release', 'x-ms-lease-id': self.lease_id} response = self.driver.connection.request(self.object_path, headers=headers, params=self.params, method='PUT') if response.status != httplib.OK: raise LibcloudError('Unable to release lease', driver=self) class AzureBlobsConnection(AzureConnection): """ Represents a single connection to Azure Blobs. The main Azure Blob Storage service uses a prefix in the hostname to distinguish between accounts, e.g. ``theaccount.blob.core.windows.net``. However, some custom deployments of the service, such as the Azurite emulator, instead use a URL prefix such as ``/theaccount``. To support these deployments, the parameter ``account_prefix`` must be set on the connection. This is done by instantiating the driver with arguments such as ``host='somewhere.tld'`` and ``key='theaccount'``. To specify a custom host without an account prefix, e.g. for use-cases where the custom host implements an auditing proxy or similar, the driver can be instantiated with ``host='theaccount.somewhere.tld'`` and ``key=''``. :param account_prefix: Optional prefix identifying the sotrage account. Used when connecting to a custom deployment of the storage service like Azurite or IoT Edge Storage. :type account_prefix: ``str`` """ def __init__(self, *args, **kwargs): self.account_prefix = kwargs.pop('account_prefix', None) super(AzureBlobsConnection, self).__init__(*args, **kwargs) def morph_action_hook(self, action): action = super(AzureBlobsConnection, self).morph_action_hook(action) if self.account_prefix is not None: action = '/%s%s' % (self.account_prefix, action) return action API_VERSION = '2016-05-31' class AzureBlobsStorageDriver(StorageDriver): name = 'Microsoft Azure (blobs)' website = 'http://windows.azure.com/' connectionCls = AzureBlobsConnection hash_type = 'md5' supports_chunked_encoding = False ex_blob_type = 'BlockBlob' def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs): self._host_argument_set = bool(host) # B64decode() this key and keep it, so that we don't have to do # so for every request. Minor performance improvement secret = base64.b64decode(b(secret)) super(AzureBlobsStorageDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def _ex_connection_class_kwargs(self): result = {} # host argument has precedence if not self._host_argument_set: result['host'] = '%s.%s' % (self.key, AZURE_STORAGE_HOST_SUFFIX) else: result['account_prefix'] = self.key return result def _xml_to_container(self, node): """ Converts a container XML node to a container instance :param node: XML info of the container :type node: :class:`xml.etree.ElementTree.Element` :return: A container instance :rtype: :class:`Container` """ name = node.findtext(fixxpath(xpath='Name')) props = node.find(fixxpath(xpath='Properties')) metadata = node.find(fixxpath(xpath='Metadata')) extra = { 'url': node.findtext(fixxpath(xpath='Url')), 'last_modified': node.findtext(fixxpath(xpath='Last-Modified')), 'etag': props.findtext(fixxpath(xpath='Etag')), 'lease': { 'status': props.findtext(fixxpath(xpath='LeaseStatus')), 'state': props.findtext(fixxpath(xpath='LeaseState')), 'duration': props.findtext(fixxpath(xpath='LeaseDuration')), }, 'meta_data': {} } if metadata is not None: for meta in list(metadata): extra['meta_data'][meta.tag] = meta.text return Container(name=name, extra=extra, driver=self) def _response_to_container(self, container_name, response): """ Converts a HTTP response to a container instance :param container_name: Name of the container :type container_name: ``str`` :param response: HTTP Response :type node: L{} :return: A container instance :rtype: :class:`Container` """ headers = response.headers extra = { 'url': 'http://%s%s' % (response.connection.host, response.connection.action), 'etag': headers['etag'], 'last_modified': headers['last-modified'], 'lease': { 'status': headers.get('x-ms-lease-status', None), 'state': headers.get('x-ms-lease-state', None), 'duration': headers.get('x-ms-lease-duration', None), }, 'meta_data': {} } for key, value in response.headers.items(): if key.startswith('x-ms-meta-'): key = key.split('x-ms-meta-')[1] extra['meta_data'][key] = value return Container(name=container_name, extra=extra, driver=self) def _xml_to_object(self, container, blob): """ Converts a BLOB XML node to an object instance :param container: Instance of the container holding the blob :type: :class:`Container` :param blob: XML info of the blob :type blob: L{} :return: An object instance :rtype: :class:`Object` """ name = blob.findtext(fixxpath(xpath='Name')) props = blob.find(fixxpath(xpath='Properties')) metadata = blob.find(fixxpath(xpath='Metadata')) etag = props.findtext(fixxpath(xpath='Etag')) size = int(props.findtext(fixxpath(xpath='Content-Length'))) extra = { 'content_type': props.findtext(fixxpath(xpath='Content-Type')), 'etag': etag, 'md5_hash': props.findtext(fixxpath(xpath='Content-MD5')), 'last_modified': props.findtext(fixxpath(xpath='Last-Modified')), 'url': blob.findtext(fixxpath(xpath='Url')), 'hash': props.findtext(fixxpath(xpath='Etag')), 'lease': { 'status': props.findtext(fixxpath(xpath='LeaseStatus')), 'state': props.findtext(fixxpath(xpath='LeaseState')), 'duration': props.findtext(fixxpath(xpath='LeaseDuration')), }, 'content_encoding': props.findtext(fixxpath( xpath='Content-Encoding')), 'content_language': props.findtext(fixxpath( xpath='Content-Language')), 'blob_type': props.findtext(fixxpath(xpath='BlobType')) } if extra['md5_hash']: value = binascii.hexlify(base64.b64decode(b(extra['md5_hash']))) value = value.decode('ascii') extra['md5_hash'] = value meta_data = {} if metadata is not None: for meta in list(metadata): meta_data[meta.tag] = meta.text return Object(name=name, size=size, hash=etag, meta_data=meta_data, extra=extra, container=container, driver=self) def _response_to_object(self, object_name, container, response): """ Converts a HTTP response to an object (from headers) :param object_name: Name of the object :type object_name: ``str`` :param container: Instance of the container holding the blob :type: :class:`Container` :param response: HTTP Response :type node: L{} :return: An object instance :rtype: :class:`Object` """ headers = response.headers size = int(headers['content-length']) etag = headers['etag'] extra = { 'url': 'http://%s%s' % (response.connection.host, response.connection.action), 'etag': etag, 'md5_hash': headers.get('content-md5', None), 'content_type': headers.get('content-type', None), 'content_language': headers.get('content-language', None), 'content_encoding': headers.get('content-encoding', None), 'last_modified': headers['last-modified'], 'lease': { 'status': headers.get('x-ms-lease-status', None), 'state': headers.get('x-ms-lease-state', None), 'duration': headers.get('x-ms-lease-duration', None), }, 'blob_type': headers['x-ms-blob-type'] } if extra['md5_hash']: value = binascii.hexlify(base64.b64decode(b(extra['md5_hash']))) value = value.decode('ascii') extra['md5_hash'] = value meta_data = {} for key, value in response.headers.items(): if key.startswith('x-ms-meta-'): key = key.split('x-ms-meta-')[1] meta_data[key] = value return Object(name=object_name, size=size, hash=etag, extra=extra, meta_data=meta_data, container=container, driver=self) def iterate_containers(self): """ @inherits: :class:`StorageDriver.iterate_containers` """ params = {'comp': 'list', 'maxresults': RESPONSES_PER_REQUEST, 'include': 'metadata'} while True: response = self.connection.request('/', params) if response.status != httplib.OK: raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) body = response.parse_body() containers = body.find(fixxpath(xpath='Containers')) containers = containers.findall(fixxpath(xpath='Container')) for container in containers: yield self._xml_to_container(container) params['marker'] = body.findtext('NextMarker') if not params['marker']: break def iterate_container_objects(self, container, ex_prefix=None): """ @inherits: :class:`StorageDriver.iterate_container_objects` """ params = {'restype': 'container', 'comp': 'list', 'maxresults': RESPONSES_PER_REQUEST, 'include': 'metadata'} if ex_prefix: params['prefix'] = ex_prefix container_path = self._get_container_path(container) while True: response = self.connection.request(container_path, params=params) if response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(value=None, driver=self, container_name=container.name) elif response.status != httplib.OK: raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) body = response.parse_body() blobs = body.find(fixxpath(xpath='Blobs')) blobs = blobs.findall(fixxpath(xpath='Blob')) for blob in blobs: yield self._xml_to_object(container, blob) params['marker'] = body.findtext('NextMarker') if not params['marker']: break def list_container_objects(self, container, ex_prefix=None): """ Return a list of objects for the given container. :param container: Container instance. :type container: :class:`Container` :param ex_prefix: Only return objects starting with ex_prefix :type ex_prefix: ``str`` :return: A list of Object instances. :rtype: ``list`` of :class:`Object` """ return list(self.iterate_container_objects(container, ex_prefix=ex_prefix)) def get_container(self, container_name): """ @inherits: :class:`StorageDriver.get_container` """ params = {'restype': 'container'} container_path = '/%s' % (container_name) response = self.connection.request(container_path, params=params, method='HEAD') if response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError('Container %s does not exist' % (container_name), driver=self, container_name=container_name) elif response.status != httplib.OK: raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) return self._response_to_container(container_name, response) def get_object(self, container_name, object_name): """ @inherits: :class:`StorageDriver.get_object` """ container = self.get_container(container_name=container_name) object_path = self._get_object_path(container, object_name) response = self.connection.request(object_path, method='HEAD') if response.status == httplib.OK: obj = self._response_to_object(object_name, container, response) return obj raise ObjectDoesNotExistError(value=None, driver=self, object_name=object_name) def _get_container_path(self, container): """ Return a container path :param container: Container instance :type container: :class:`Container` :return: A path for this container. :rtype: ``str`` """ return '/%s' % (container.name) def _get_object_path(self, container, object_name): """ Return an object's CDN path. :param container: Container instance :type container: :class:`Container` :param object_name: Object name :type object_name: :class:`str` :return: A path for this object. :rtype: ``str`` """ container_url = self._get_container_path(container) object_name_cleaned = urlquote(object_name) object_path = '%s/%s' % (container_url, object_name_cleaned) return object_path def create_container(self, container_name): """ @inherits: :class:`StorageDriver.create_container` """ params = {'restype': 'container'} container_path = '/%s' % (container_name) response = self.connection.request(container_path, params=params, method='PUT') if response.status == httplib.CREATED: return self._response_to_container(container_name, response) elif response.status == httplib.CONFLICT: raise ContainerAlreadyExistsError( value='Container with this name already exists. The name must ' 'be unique among all the containers in the system', container_name=container_name, driver=self) elif response.status == httplib.BAD_REQUEST: raise InvalidContainerNameError(value='Container name contains ' + 'invalid characters.', container_name=container_name, driver=self) raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) def delete_container(self, container): """ @inherits: :class:`StorageDriver.delete_container` """ # Azure does not check if the container is empty. So, we will do # a check to ensure that the behaviour is similar to other drivers for obj in container.iterate_objects(): raise ContainerIsNotEmptyError( value='Container must be empty before it can be deleted.', container_name=container.name, driver=self) params = {'restype': 'container'} container_path = self._get_container_path(container) # Note: All the objects in the container must be deleted first response = self.connection.request(container_path, params=params, method='DELETE') if response.status == httplib.ACCEPTED: return True elif response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(value=None, driver=self, container_name=container.name) return False def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): """ @inherits: :class:`StorageDriver.download_object` """ obj_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(obj_path, raw=True, data=None) return self._get_object(obj=obj, callback=self._save_object, response=response, callback_kwargs={ 'obj': obj, 'response': response.response, 'destination_path': destination_path, 'overwrite_existing': overwrite_existing, 'delete_on_failure': delete_on_failure}, success_status_code=httplib.OK) def download_object_as_stream(self, obj, chunk_size=None): """ @inherits: :class:`StorageDriver.download_object_as_stream` """ obj_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(obj_path, method='GET', stream=True, raw=True) iterator = response.iter_content(AZURE_CHUNK_SIZE) return self._get_object(obj=obj, callback=read_in_chunks, response=response, callback_kwargs={'iterator': iterator, 'chunk_size': chunk_size}, success_status_code=httplib.OK) def _upload_in_chunks(self, response, data, iterator, object_path, blob_type, lease, calculate_hash=True): """ Uploads data from an interator in fixed sized chunks to S3 :param response: Response object from the initial POST request :type response: :class:`RawResponse` :param data: Any data from the initial POST request :type data: ``str`` :param iterator: The generator for fetching the upload data :type iterator: ``generator`` :param object_path: The path of the object to which we are uploading :type object_name: ``str`` :param blob_type: The blob type being uploaded :type blob_type: ``str`` :param lease: The lease object to be used for renewal :type lease: :class:`AzureBlobLease` :keyword calculate_hash: Indicates if we must calculate the data hash :type calculate_hash: ``bool`` :return: A tuple of (status, checksum, bytes transferred) :rtype: ``tuple`` """ # Get the upload id from the response xml if response.status != httplib.CREATED: raise LibcloudError('Error initializing upload. Code: %d' % (response.status), driver=self) data_hash = None if calculate_hash: data_hash = self._get_hash_function() bytes_transferred = 0 count = 1 chunks = [] headers = {} lease.update_headers(headers) if blob_type == 'BlockBlob': params = {'comp': 'block'} else: params = {'comp': 'page'} # Read the input data in chunk sizes suitable for AWS for data in read_in_chunks(iterator, AZURE_CHUNK_SIZE): data = b(data) content_length = len(data) offset = bytes_transferred bytes_transferred += content_length if calculate_hash: data_hash.update(data) chunk_hash = self._get_hash_function() chunk_hash.update(data) chunk_hash = base64.b64encode(b(chunk_hash.digest())) headers['Content-MD5'] = chunk_hash.decode('utf-8') headers['Content-Length'] = str(content_length) if blob_type == 'BlockBlob': # Block id can be any unique string that is base64 encoded # A 10 digit number can hold the max value of 50000 blocks # that are allowed for azure block_id = base64.b64encode(b('%10d' % (count))) block_id = block_id.decode('utf-8') params['blockid'] = block_id # Keep this data for a later commit chunks.append(block_id) else: headers['x-ms-page-write'] = 'update' headers['x-ms-range'] = 'bytes=%d-%d' % \ (offset, (bytes_transferred - 1)) # Renew lease before updating lease.renew() resp = self.connection.request(object_path, method='PUT', data=data, headers=headers, params=params) if resp.status != httplib.CREATED: resp.parse_error() raise LibcloudError('Error uploading chunk %d. Code: %d' % (count, resp.status), driver=self) count += 1 if calculate_hash: data_hash = data_hash.hexdigest() if blob_type == 'BlockBlob': self._commit_blocks(object_path, chunks, lease) # The Azure service does not return a hash immediately for # chunked uploads. It takes some time for the data to get synced response.headers['content-md5'] = None return (True, data_hash, bytes_transferred) def _commit_blocks(self, object_path, chunks, lease): """ Makes a final commit of the data. :param object_path: Server side object path. :type object_path: ``str`` :param upload_id: A list of (chunk_number, chunk_hash) tuples. :type upload_id: ``list`` """ root = ET.Element('BlockList') for block_id in chunks: part = ET.SubElement(root, 'Uncommitted') part.text = str(block_id) data = tostring(root) params = {'comp': 'blocklist'} headers = {} lease.update_headers(headers) lease.renew() response = self.connection.request(object_path, data=data, params=params, headers=headers, method='PUT') if response.status != httplib.CREATED: raise LibcloudError('Error in blocklist commit', driver=self) def _check_values(self, blob_type, object_size): """ Checks if extension arguments are valid :param blob_type: The blob type that is being uploaded :type blob_type: ``str`` :param object_size: The (max) size of the object being uploaded :type object_size: ``int`` """ if blob_type not in ['BlockBlob', 'PageBlob']: raise LibcloudError('Invalid blob type', driver=self) if blob_type == 'PageBlob': if not object_size: raise LibcloudError('Max blob size is mandatory for page blob', driver=self) if object_size % AZURE_PAGE_CHUNK_SIZE: raise LibcloudError('Max blob size is not aligned to ' 'page boundary', driver=self) def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True, ex_blob_type=None, ex_use_lease=False): """ Upload an object currently located on a disk. @inherits: :class:`StorageDriver.upload_object` :param ex_blob_type: Storage class :type ex_blob_type: ``str`` :param ex_use_lease: Indicates if we must take a lease before upload :type ex_use_lease: ``bool`` """ if ex_blob_type is None: ex_blob_type = self.ex_blob_type # Get the size of the file file_size = os.stat(file_path).st_size # The presumed size of the object object_size = file_size self._check_values(ex_blob_type, file_size) # If size is greater than 64MB or type is Page, upload in chunks if ex_blob_type == 'PageBlob' or file_size > AZURE_BLOCK_MAX_SIZE: # For chunked upload of block blobs, the initial size must # be 0. if ex_blob_type == 'BlockBlob': object_size = None return self._put_object(container=container, object_name=object_name, object_size=object_size, file_path=file_path, extra=extra, verify_hash=verify_hash, blob_type=ex_blob_type, use_lease=ex_use_lease) def upload_object_via_stream(self, iterator, container, object_name, verify_hash=False, extra=None, ex_use_lease=False, ex_blob_type=None, ex_page_blob_size=None): """ @inherits: :class:`StorageDriver.upload_object_via_stream` Note that if ``iterator`` does not support ``seek``, the entire generator will be buffered in memory. :param ex_blob_type: Storage class :type ex_blob_type: ``str`` :param ex_page_blob_size: The maximum size to which the page blob can grow to :type ex_page_blob_size: ``int`` :param ex_use_lease: Indicates if we must take a lease before upload :type ex_use_lease: ``bool`` """ if ex_blob_type is None: ex_blob_type = self.ex_blob_type """ Azure requires that for page blobs that a maximum size that the page can grow to. For block blobs, it is required that the Content-Length header be set. The size of the block blob will be the total size of the stream minus the current position, so in this case ex_page_blob_size should be 0 (and will be checked in self._check_values). Source: https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob """ self._check_values(ex_blob_type, ex_page_blob_size) if ex_blob_type == "BlockBlob": try: iterator.seek(0, os.SEEK_END) except AttributeError: buffer = BytesIO() buffer.writelines(iterator) iterator = buffer blob_size = iterator.tell() iterator.seek(0) else: blob_size = ex_page_blob_size return self._put_object(container=container, object_name=object_name, object_size=blob_size, extra=extra, verify_hash=verify_hash, blob_type=ex_blob_type, use_lease=ex_use_lease, stream=iterator) def delete_object(self, obj): """ @inherits: :class:`StorageDriver.delete_object` """ object_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(object_path, method='DELETE') if response.status == httplib.ACCEPTED: return True elif response.status == httplib.NOT_FOUND: raise ObjectDoesNotExistError(value=None, driver=self, object_name=obj.name) return False def _update_metadata(self, headers, meta_data): """ Update the given metadata in the headers :param headers: The headers dictionary to be updated :type headers: ``dict`` :param meta_data: Metadata key value pairs :type meta_data: ``dict`` """ for key, value in list(meta_data.items()): key = 'x-ms-meta-%s' % (key) headers[key] = value def _prepare_upload_headers(self, object_name, object_size, extra, meta_data, blob_type): """ Prepare headers for uploading an object :param object_name: The full name of the object being updated :type object_name: ``str`` :param object_size: The size of the object. In case of PageBlobs, this indicates the maximum size the blob can grow to :type object_size: ``int`` :param extra: Extra control data for the upload :type extra: ``dict`` :param meta_data: Metadata key value pairs :type meta_data: ``dict`` :param blob_type: Page or Block blob type :type blob_type: ``str`` """ headers = {} if blob_type is None: blob_type = self.ex_blob_type headers['x-ms-blob-type'] = blob_type self._update_metadata(headers, meta_data) if object_size is not None: headers['Content-Length'] = str(object_size) if blob_type == 'PageBlob': headers['Content-Length'] = str('0') headers['x-ms-blob-content-length'] = str(object_size) return headers def _put_object(self, container, object_name, object_size, file_path=None, extra=None, verify_hash=True, blob_type=None, use_lease=False, stream=None): """ Control function that does the real job of uploading data to a blob """ extra = extra or {} meta_data = extra.get('meta_data', {}) content_type = extra.get('content_type', None) headers = self._prepare_upload_headers(object_name, object_size, extra, meta_data, blob_type) object_path = self._get_object_path(container, object_name) # Get a lease if required and do the operations with AzureBlobLease(self, object_path, use_lease) as lease: lease.update_headers(headers) result_dict = self._upload_object(object_name, content_type, object_path, headers=headers, file_path=file_path, stream=stream) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] data_hash = result_dict['data_hash'] headers = response.headers if response.status != httplib.CREATED: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self) server_hash = headers.get('content-md5') if server_hash: server_hash = binascii.hexlify(base64.b64decode(b(server_hash))) server_hash = server_hash.decode('utf-8') else: # TODO: HACK - We could poll the object for a while and get # the hash pass if (verify_hash and server_hash and data_hash != server_hash): raise ObjectHashMismatchError( value='MD5 hash checksum does not match', object_name=object_name, driver=self) return Object(name=object_name, size=bytes_transferred, hash=headers['etag'], extra=None, meta_data=meta_data, container=container, driver=self) def ex_set_object_metadata(self, obj, meta_data): """ Set metadata for an object :param obj: The blob object :type obj: :class:`Object` :param meta_data: Metadata key value pairs :type meta_data: ``dict`` """ object_path = self._get_object_path(obj.container, obj.name) params = {'comp': 'metadata'} headers = {} self._update_metadata(headers, meta_data) response = self.connection.request(object_path, method='PUT', params=params, headers=headers) if response.status != httplib.OK: response.parse_error('Setting metadata') apache-libcloud-2.8.0/libcloud/storage/drivers/backblaze_b2.py0000664000175000017500000004757613570310635024243 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Driver for Backblaze B2 service. """ import base64 import hashlib try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import b from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import next from libcloud.utils.files import read_in_chunks from libcloud.utils.files import exhaust_iterator from libcloud.utils.escape import sanitize_object_name from libcloud.common.base import ConnectionUserAndKey from libcloud.common.base import JsonResponse from libcloud.common.types import InvalidCredsError from libcloud.common.types import LibcloudError from libcloud.storage.providers import Provider from libcloud.storage.base import Object, Container, StorageDriver from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ObjectDoesNotExistError __all__ = [ 'BackblazeB2StorageDriver', 'BackblazeB2Connection', 'BackblazeB2AuthConnection' ] AUTH_API_HOST = 'api.backblaze.com' API_PATH = '/b2api/v1/' class BackblazeB2Response(JsonResponse): def success(self): return self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED] def parse_error(self): status = int(self.status) body = self.parse_body() if status == httplib.UNAUTHORIZED: raise InvalidCredsError(body['message']) return self.body class BackblazeB2AuthConnection(ConnectionUserAndKey): host = AUTH_API_HOST secure = True responseCls = BackblazeB2Response def __init__(self, *args, **kwargs): super(BackblazeB2AuthConnection, self).__init__(*args, **kwargs) # Those attributes are populated after authentication self.account_id = None self.api_url = None self.api_host = None self.download_url = None self.download_host = None self.auth_token = None def authenticate(self, force=False): """ :param force: Force authentication if if we have already obtained the token. :type force: ``bool`` """ if not self._is_authentication_needed(force=force): return self headers = {} action = 'b2_authorize_account' auth_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key))) headers['Authorization'] = 'Basic %s' % (auth_b64.decode('utf-8')) action = API_PATH + 'b2_authorize_account' resp = self.request(action=action, headers=headers, method='GET') if resp.status == httplib.OK: self._parse_and_set_auth_info(data=resp.object) else: raise Exception('Failed to authenticate: %s' % (str(resp.object))) return self def _parse_and_set_auth_info(self, data): result = {} self.account_id = data['accountId'] self.api_url = data['apiUrl'] self.download_url = data['downloadUrl'] self.auth_token = data['authorizationToken'] parsed_api_url = urlparse.urlparse(self.api_url) self.api_host = parsed_api_url.netloc parsed_download_url = urlparse.urlparse(self.download_url) self.download_host = parsed_download_url.netloc return result def _is_authentication_needed(self, force=False): if not self.auth_token or force: return True return False class BackblazeB2Connection(ConnectionUserAndKey): host = None # Note: host is set after authentication secure = True responseCls = BackblazeB2Response authCls = BackblazeB2AuthConnection def __init__(self, *args, **kwargs): super(BackblazeB2Connection, self).__init__(*args, **kwargs) # Stores info retrieved after authentication (auth token, api url, # dowload url). self._auth_conn = self.authCls(*args, **kwargs) def download_request(self, action, params=None): # Lazily perform authentication auth_conn = self._auth_conn.authenticate() # Set host to the download server self._set_host(auth_conn.download_host) action = '/file/' + action method = 'GET' raw = True response = self._request(auth_conn=auth_conn, action=action, params=params, method=method, raw=raw) return response def upload_request(self, action, headers, upload_host, auth_token, data): # Lazily perform authentication auth_conn = self._auth_conn.authenticate() # Upload host is dynamically retrieved for each upload request self._set_host(host=upload_host) method = 'POST' raw = False response = self._request(auth_conn=auth_conn, action=action, params=None, data=data, headers=headers, method=method, raw=raw, auth_token=auth_token) return response def request(self, action, params=None, data=None, headers=None, method='GET', raw=False, include_account_id=False): params = params or {} headers = headers or {} # Lazily perform authentication auth_conn = self._auth_conn.authenticate() # Set host self._set_host(host=auth_conn.api_host) # Include Content-Type if not raw and data: headers['Content-Type'] = 'application/json' # Include account id if include_account_id: if method == 'GET': params['accountId'] = auth_conn.account_id elif method == 'POST': data = data or {} data['accountId'] = auth_conn.account_id action = API_PATH + action if data: data = json.dumps(data) response = self._request(auth_conn=self._auth_conn, action=action, params=params, data=data, method=method, headers=headers, raw=raw) return response def _request(self, auth_conn, action, params=None, data=None, headers=None, method='GET', raw=False, auth_token=None): params = params or {} headers = headers or {} if not auth_token: # If auth token is not explicitly provided, use the default one auth_token = self._auth_conn.auth_token # Include auth token headers['Authorization'] = '%s' % (auth_token) response = super(BackblazeB2Connection, self).request(action=action, params=params, data=data, method=method, headers=headers, raw=raw) return response def _set_host(self, host): """ Dynamically set host which will be used for the following HTTP requests. NOTE: This is needed because Backblaze uses different hosts for API, download and upload requests. """ self.host = host self.connection.host = 'https://%s' % (host) class BackblazeB2StorageDriver(StorageDriver): connectionCls = BackblazeB2Connection name = 'Backblaze B2' website = 'https://www.backblaze.com/b2/' type = Provider.BACKBLAZE_B2 hash_type = 'sha1' supports_chunked_encoding = False def iterate_containers(self): # pylint: disable=unexpected-keyword-arg resp = self.connection.request(action='b2_list_buckets', method='GET', include_account_id=True) containers = self._to_containers(data=resp.object) return containers def iterate_container_objects(self, container): # TODO: Support pagination params = {'bucketId': container.extra['id']} resp = self.connection.request(action='b2_list_file_names', method='GET', params=params) objects = self._to_objects(data=resp.object, container=container) return objects def get_container(self, container_name): containers = self.iterate_containers() container = next((c for c in containers if c.name == container_name), None) if container: return container else: raise ContainerDoesNotExistError(value=None, driver=self, container_name=container_name) def get_object(self, container_name, object_name): container = self.get_container(container_name=container_name) objects = self.iterate_container_objects(container=container) obj = next((obj for obj in objects if obj.name == object_name), None) if obj is not None: return obj else: raise ObjectDoesNotExistError(value=None, driver=self, object_name=object_name) def create_container(self, container_name, ex_type='allPrivate'): data = {} data['bucketName'] = container_name data['bucketType'] = ex_type # pylint: disable=unexpected-keyword-arg resp = self.connection.request(action='b2_create_bucket', data=data, method='POST', include_account_id=True) container = self._to_container(item=resp.object) return container def delete_container(self, container): data = {} data['bucketId'] = container.extra['id'] # pylint: disable=unexpected-keyword-arg resp = self.connection.request(action='b2_delete_bucket', data=data, method='POST', include_account_id=True) return resp.status == httplib.OK def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): action = self._get_object_download_path(container=obj.container, obj=obj) # pylint: disable=no-member response = self.connection.download_request(action=action) # TODO: Include metadata from response headers return self._get_object(obj=obj, callback=self._save_object, response=response, callback_kwargs={ 'obj': obj, 'response': response.response, 'destination_path': destination_path, 'overwrite_existing': overwrite_existing, 'delete_on_failure': delete_on_failure }, success_status_code=httplib.OK) def download_object_as_stream(self, obj, chunk_size=None): action = self._get_object_download_path(container=obj.container, obj=obj) # pylint: disable=no-member response = self.connection.download_request(action=action) return self._get_object(obj=obj, callback=read_in_chunks, response=response, callback_kwargs={ 'iterator': response.iter_content( chunk_size ), 'chunk_size': chunk_size}, success_status_code=httplib.OK) def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True, headers=None): """ Upload an object. Note: This will override file with a same name if it already exists. """ # Note: We don't use any of the base driver functions since Backblaze # API requires you to provide SHA1 has upfront and the base methods # don't support that with open(file_path, 'rb') as fp: iterator = iter(fp) iterator = read_in_chunks(iterator=iterator) data = exhaust_iterator(iterator=iterator) obj = self._perform_upload(data=data, container=container, object_name=object_name, extra=extra, verify_hash=verify_hash, headers=headers) return obj def upload_object_via_stream(self, iterator, container, object_name, extra=None, headers=None): """ Upload an object. Note: Backblaze does not yet support uploading via stream, so this calls upload_object internally requiring the object data to be loaded into memory at once """ iterator = read_in_chunks(iterator=iterator) data = exhaust_iterator(iterator=iterator) obj = self._perform_upload(data=data, container=container, object_name=object_name, extra=extra, headers=headers) return obj def delete_object(self, obj): data = {} data['fileName'] = obj.name data['fileId'] = obj.extra['fileId'] resp = self.connection.request(action='b2_delete_file_version', data=data, method='POST') return resp.status == httplib.OK def ex_get_object(self, object_id): params = {} params['fileId'] = object_id resp = self.connection.request(action='b2_get_file_info', method='GET', params=params) obj = self._to_object(item=resp.object, container=None) return obj def ex_hide_object(self, container_id, object_name): data = {} data['bucketId'] = container_id data['fileName'] = object_name resp = self.connection.request(action='b2_hide_file', data=data, method='POST') obj = self._to_object(item=resp.object, container=None) return obj def ex_list_object_versions(self, container_id, ex_start_file_name=None, ex_start_file_id=None, ex_max_file_count=None): params = {} params['bucketId'] = container_id if ex_start_file_name: params['startFileName'] = ex_start_file_name if ex_start_file_id: params['startFileId'] = ex_start_file_id if ex_max_file_count: params['maxFileCount'] = ex_max_file_count resp = self.connection.request(action='b2_list_file_versions', params=params, method='GET') objects = self._to_objects(data=resp.object, container=None) return objects def ex_get_upload_data(self, container_id): """ Retrieve information used for uploading files (upload url, auth token, etc). :rype: ``dict`` """ # TODO: This is static (AFAIK) so it could be cached params = {} params['bucketId'] = container_id response = self.connection.request(action='b2_get_upload_url', method='GET', params=params) return response.object def ex_get_upload_url(self, container_id): """ Retrieve URL used for file uploads. :rtype: ``str`` """ result = self.ex_get_upload_data(container_id=container_id) upload_url = result['uploadUrl'] return upload_url def _to_containers(self, data): result = [] for item in data['buckets']: container = self._to_container(item=item) result.append(container) return result def _to_container(self, item): extra = {} extra['id'] = item['bucketId'] extra['bucketType'] = item['bucketType'] container = Container(name=item['bucketName'], extra=extra, driver=self) return container def _to_objects(self, data, container): result = [] for item in data['files']: obj = self._to_object(item=item, container=container) result.append(obj) return result def _to_object(self, item, container=None): extra = {} extra['fileId'] = item['fileId'] extra['uploadTimestamp'] = item.get('uploadTimestamp', None) size = item.get('size', item.get('contentLength', None)) hash = item.get('contentSha1', None) meta_data = item.get('fileInfo', {}) obj = Object(name=item['fileName'], size=size, hash=hash, extra=extra, meta_data=meta_data, container=container, driver=self) return obj def _get_object_download_path(self, container, obj): """ Return a path used in the download requests. :rtype: ``str`` """ path = container.name + '/' + obj.name return path def _perform_upload(self, data, container, object_name, extra=None, verify_hash=True, headers=None): if isinstance(data, str): data = bytearray(data) object_name = sanitize_object_name(object_name) extra = extra or {} content_type = extra.get('content_type', 'b2/x-auto') meta_data = extra.get('meta_data', {}) # Note: Backblaze API doesn't support chunked encoding and we need to # provide Content-Length up front (this is one inside _upload_object):/ headers = headers or {} headers['X-Bz-File-Name'] = object_name headers['Content-Type'] = content_type sha1 = hashlib.sha1() sha1.update(b(data)) headers['X-Bz-Content-Sha1'] = sha1.hexdigest() # Include optional meta-data (up to 10 items) for key, value in meta_data: # TODO: Encode / escape key headers['X-Bz-Info-%s' % (key)] = value upload_data = self.ex_get_upload_data( container_id=container.extra['id']) upload_token = upload_data['authorizationToken'] parsed_url = urlparse.urlparse(upload_data['uploadUrl']) upload_host = parsed_url.netloc request_path = parsed_url.path # pylint: disable=no-member response = self.connection.upload_request(action=request_path, headers=headers, upload_host=upload_host, auth_token=upload_token, data=data) if response.status == httplib.OK: obj = self._to_object(item=response.object, container=container) return obj else: body = response.response.read() raise LibcloudError('Upload failed. status_code=%s, body=%s' % (response.status, body), driver=self) apache-libcloud-2.8.0/libcloud/storage/drivers/cloudfiles.py0000664000175000017500000011174613576514553024075 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atexit import hmac import os from time import time from hashlib import sha1 from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlencode try: import simplejson as json except ImportError: import json # type: ignore from libcloud.utils.py3 import PY3 from libcloud.utils.py3 import b from libcloud.utils.py3 import urlquote if PY3: from io import FileIO as file from libcloud.utils.files import read_in_chunks from libcloud.common.types import MalformedResponseError, LibcloudError from libcloud.common.base import Response, RawResponse from libcloud.storage.providers import Provider from libcloud.storage.base import Object, Container, StorageDriver from libcloud.storage.types import ContainerAlreadyExistsError from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError from libcloud.storage.types import InvalidContainerNameError from libcloud.common.openstack import OpenStackBaseConnection from libcloud.common.openstack import OpenStackDriverMixin from libcloud.common.rackspace import AUTH_URL CDN_HOST = 'cdn.clouddrive.com' API_VERSION = 'v1.0' # Keys which are used to select a correct endpoint from the service catalog. INTERNAL_ENDPOINT_KEY = 'internalURL' PUBLIC_ENDPOINT_KEY = 'publicURL' class CloudFilesResponse(Response): valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT] def success(self): i = int(self.status) return 200 <= i <= 299 or i in self.valid_response_codes def parse_body(self): if not self.body: return None if 'content-type' in self.headers: key = 'content-type' elif 'Content-Type' in self.headers: key = 'Content-Type' else: raise LibcloudError('Missing content-type header') content_type = self.headers[key] if content_type.find(';') != -1: content_type = content_type.split(';')[0] if content_type == 'application/json': try: data = json.loads(self.body) except Exception: raise MalformedResponseError('Failed to parse JSON', body=self.body, driver=CloudFilesStorageDriver) elif content_type == 'text/plain': data = self.body else: data = self.body return data class CloudFilesRawResponse(CloudFilesResponse, RawResponse): pass class OpenStackSwiftConnection(OpenStackBaseConnection): """ Connection class for the OpenStack Swift endpoint. """ responseCls = CloudFilesResponse rawResponseCls = CloudFilesRawResponse auth_url = AUTH_URL _auth_version = '1.0' # TODO: Reverse the relationship - Swift -> CloudFiles def __init__(self, user_id, key, secure=True, **kwargs): # Ignore this for now kwargs.pop('use_internal_url', None) super(OpenStackSwiftConnection, self).__init__(user_id, key, secure=secure, **kwargs) self.api_version = API_VERSION self.accept_format = 'application/json' self._service_type = self._ex_force_service_type or 'object-store' self._service_name = self._ex_force_service_name or 'swift' if self._ex_force_service_region: self._service_region = self._ex_force_service_region else: self._service_region = None def get_endpoint(self, *args, **kwargs): if ('2.0' in self._auth_version) or ('3.x' in self._auth_version): endpoint = self.service_catalog.get_endpoint( service_type=self._service_type, name=self._service_name, region=self._service_region) elif ('1.1' in self._auth_version) or ('1.0' in self._auth_version): endpoint = self.service_catalog.get_endpoint( name=self._service_name, region=self._service_region) else: endpoint = None if endpoint: return endpoint.url else: raise LibcloudError('Could not find specified endpoint') def request(self, action, params=None, data='', headers=None, method='GET', raw=False, cdn_request=False): if not headers: headers = {} if not params: params = {} self.cdn_request = cdn_request params['format'] = 'json' if method in ['POST', 'PUT'] and 'Content-Type' not in headers: headers.update({'Content-Type': 'application/json; charset=UTF-8'}) return super(OpenStackSwiftConnection, self).request( action=action, params=params, data=data, method=method, headers=headers, raw=raw) class CloudFilesConnection(OpenStackSwiftConnection): """ Base connection class for the Cloudfiles driver. """ responseCls = CloudFilesResponse rawResponseCls = CloudFilesRawResponse auth_url = AUTH_URL _auth_version = '2.0' def __init__(self, user_id, key, secure=True, use_internal_url=False, **kwargs): super(CloudFilesConnection, self).__init__(user_id, key, secure=secure, **kwargs) self.api_version = API_VERSION self.accept_format = 'application/json' self.cdn_request = False self.use_internal_url = use_internal_url def get_endpoint(self): region = self._ex_force_service_region.upper() if self.use_internal_url: endpoint_type = 'internal' else: endpoint_type = 'external' if '2.0' in self._auth_version: ep = self.service_catalog.get_endpoint( service_type='object-store', name='cloudFiles', region=region, endpoint_type=endpoint_type) cdn_ep = self.service_catalog.get_endpoint( service_type='rax:object-cdn', name='cloudFilesCDN', region=region, endpoint_type=endpoint_type) else: raise LibcloudError( 'Auth version "%s" not supported' % (self._auth_version)) # if this is a CDN request, return the cdn url instead if self.cdn_request: ep = cdn_ep if not ep or not ep.url: raise LibcloudError('Could not find specified endpoint') return ep.url def request(self, action, params=None, data='', headers=None, method='GET', raw=False, cdn_request=False): if not headers: headers = {} if not params: params = {} self.cdn_request = cdn_request params['format'] = 'json' if method in ['POST', 'PUT'] and 'Content-Type' not in headers: headers.update({'Content-Type': 'application/json; charset=UTF-8'}) return super(CloudFilesConnection, self).request( action=action, params=params, data=data, method=method, headers=headers, raw=raw, cdn_request=cdn_request) class CloudFilesStorageDriver(StorageDriver, OpenStackDriverMixin): """ CloudFiles driver. """ name = 'CloudFiles' website = 'http://www.rackspace.com/' connectionCls = CloudFilesConnection hash_type = 'md5' supports_chunked_encoding = True def __init__(self, key, secret=None, secure=True, host=None, port=None, region='ord', use_internal_url=False, **kwargs): """ @inherits: :class:`StorageDriver.__init__` :param region: ID of the region which should be used. :type region: ``str`` """ # This is here for backard compatibility if 'ex_force_service_region' in kwargs: region = kwargs['ex_force_service_region'] self.use_internal_url = use_internal_url OpenStackDriverMixin.__init__(self, **kwargs) super(CloudFilesStorageDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) @classmethod def list_regions(cls): return ['ord', 'dfw', 'iad', 'lon', 'hkg', 'syd'] def iterate_containers(self): response = self.connection.request('') if response.status == httplib.NO_CONTENT: return [] elif response.status == httplib.OK: return self._to_container_list(json.loads(response.body)) raise LibcloudError('Unexpected status code: %s' % (response.status)) def get_container(self, container_name): container_name_encoded = self._encode_container_name(container_name) response = self.connection.request('/%s' % (container_name_encoded), method='HEAD') if response.status == httplib.NO_CONTENT: container = self._headers_to_container( container_name, response.headers) return container elif response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(None, self, container_name) raise LibcloudError('Unexpected status code: %s' % (response.status)) def get_object(self, container_name, object_name): container = self.get_container(container_name) container_name_encoded = self._encode_container_name(container_name) object_name_encoded = self._encode_object_name(object_name) response = self.connection.request('/%s/%s' % (container_name_encoded, object_name_encoded), method='HEAD') if response.status in [httplib.OK, httplib.NO_CONTENT]: obj = self._headers_to_object( object_name, container, response.headers) return obj elif response.status == httplib.NOT_FOUND: raise ObjectDoesNotExistError(None, self, object_name) raise LibcloudError('Unexpected status code: %s' % (response.status)) def get_container_cdn_url(self, container, ex_ssl_uri=False): # pylint: disable=unexpected-keyword-arg container_name_encoded = self._encode_container_name(container.name) response = self.connection.request('/%s' % (container_name_encoded), method='HEAD', cdn_request=True) if response.status == httplib.NO_CONTENT: if ex_ssl_uri: cdn_url = response.headers['x-cdn-ssl-uri'] else: cdn_url = response.headers['x-cdn-uri'] return cdn_url elif response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(value='', container_name=container.name, driver=self) raise LibcloudError('Unexpected status code: %s' % (response.status)) def get_object_cdn_url(self, obj): container_cdn_url = self.get_container_cdn_url(container=obj.container) return '%s/%s' % (container_cdn_url, obj.name) def enable_container_cdn(self, container, ex_ttl=None): """ @inherits: :class:`StorageDriver.enable_container_cdn` :param ex_ttl: cache time to live :type ex_ttl: ``int`` """ container_name = self._encode_container_name(container.name) headers = {'X-CDN-Enabled': 'True'} if ex_ttl: headers['X-TTL'] = ex_ttl # pylint: disable=unexpected-keyword-arg response = self.connection.request('/%s' % (container_name), method='PUT', headers=headers, cdn_request=True) return response.status in [httplib.CREATED, httplib.ACCEPTED] def create_container(self, container_name): container_name_encoded = self._encode_container_name(container_name) response = self.connection.request( '/%s' % (container_name_encoded), method='PUT') if response.status == httplib.CREATED: # Accepted mean that container is not yet created but it will be # eventually extra = {'object_count': 0} container = Container(name=container_name, extra=extra, driver=self) return container elif response.status == httplib.ACCEPTED: error = ContainerAlreadyExistsError(None, self, container_name) raise error raise LibcloudError('Unexpected status code: %s' % (response.status)) def delete_container(self, container): name = self._encode_container_name(container.name) # Only empty container can be deleted response = self.connection.request('/%s' % (name), method='DELETE') if response.status == httplib.NO_CONTENT: return True elif response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(value='', container_name=name, driver=self) elif response.status == httplib.CONFLICT: # @TODO: Add "delete_all_objects" parameter? raise ContainerIsNotEmptyError(value='', container_name=name, driver=self) def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): container_name = obj.container.name object_name = obj.name response = self.connection.request('/%s/%s' % (container_name, object_name), method='GET', raw=True) return self._get_object( obj=obj, callback=self._save_object, response=response, callback_kwargs={'obj': obj, 'response': response.response, 'destination_path': destination_path, 'overwrite_existing': overwrite_existing, 'delete_on_failure': delete_on_failure}, success_status_code=httplib.OK) def download_object_as_stream(self, obj, chunk_size=None): container_name = obj.container.name object_name = obj.name response = self.connection.request('/%s/%s' % (container_name, object_name), method='GET', raw=True) return self._get_object(obj=obj, callback=read_in_chunks, response=response, callback_kwargs={ 'iterator': response.iter_content( chunk_size ), 'chunk_size': chunk_size }, success_status_code=httplib.OK) def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True, headers=None): """ Upload an object. Note: This will override file with a same name if it already exists. """ return self._put_object(container=container, object_name=object_name, extra=extra, file_path=file_path, verify_hash=verify_hash, headers=headers) def upload_object_via_stream(self, iterator, container, object_name, extra=None, headers=None): if isinstance(iterator, file): iterator = iter(iterator) return self._put_object(container=container, object_name=object_name, extra=extra, stream=iterator, headers=headers) def delete_object(self, obj): container_name = self._encode_container_name(obj.container.name) object_name = self._encode_object_name(obj.name) response = self.connection.request( '/%s/%s' % (container_name, object_name), method='DELETE') if response.status == httplib.NO_CONTENT: return True elif response.status == httplib.NOT_FOUND: raise ObjectDoesNotExistError(value='', object_name=object_name, driver=self) raise LibcloudError('Unexpected status code: %s' % (response.status)) def ex_purge_object_from_cdn(self, obj, email=None): """ Purge edge cache for the specified object. :param email: Email where a notification will be sent when the job completes. (optional) :type email: ``str`` """ container_name = self._encode_container_name(obj.container.name) object_name = self._encode_object_name(obj.name) headers = {'X-Purge-Email': email} if email else {} # pylint: disable=unexpected-keyword-arg response = self.connection.request('/%s/%s' % (container_name, object_name), method='DELETE', headers=headers, cdn_request=True) return response.status == httplib.NO_CONTENT def ex_get_meta_data(self): """ Get meta data :rtype: ``dict`` """ response = self.connection.request('', method='HEAD') if response.status == httplib.NO_CONTENT: container_count = response.headers.get( 'x-account-container-count', 'unknown') object_count = response.headers.get( 'x-account-object-count', 'unknown') bytes_used = response.headers.get( 'x-account-bytes-used', 'unknown') temp_url_key = response.headers.get( 'x-account-meta-temp-url-key', None) return {'container_count': int(container_count), 'object_count': int(object_count), 'bytes_used': int(bytes_used), 'temp_url_key': temp_url_key} raise LibcloudError('Unexpected status code: %s' % (response.status)) def ex_multipart_upload_object(self, file_path, container, object_name, chunk_size=33554432, extra=None, verify_hash=True): object_size = os.path.getsize(file_path) if object_size < chunk_size: return self.upload_object(file_path, container, object_name, extra=extra, verify_hash=verify_hash) iter_chunk_reader = FileChunkReader(file_path, chunk_size) for index, iterator in enumerate(iter_chunk_reader): self._upload_object_part(container=container, object_name=object_name, part_number=index, iterator=iterator, verify_hash=verify_hash) return self._upload_object_manifest(container=container, object_name=object_name, extra=extra, verify_hash=verify_hash) def ex_enable_static_website(self, container, index_file='index.html'): """ Enable serving a static website. :param container: Container instance :type container: :class:`Container` :param index_file: Name of the object which becomes an index page for every sub-directory in this container. :type index_file: ``str`` :rtype: ``bool`` """ container_name = container.name headers = {'X-Container-Meta-Web-Index': index_file} # pylint: disable=unexpected-keyword-arg response = self.connection.request('/%s' % (container_name), method='POST', headers=headers, cdn_request=False) return response.status in [httplib.CREATED, httplib.ACCEPTED] def ex_set_error_page(self, container, file_name='error.html'): """ Set a custom error page which is displayed if file is not found and serving of a static website is enabled. :param container: Container instance :type container: :class:`Container` :param file_name: Name of the object which becomes the error page. :type file_name: ``str`` :rtype: ``bool`` """ container_name = container.name headers = {'X-Container-Meta-Web-Error': file_name} # pylint: disable=unexpected-keyword-arg response = self.connection.request('/%s' % (container_name), method='POST', headers=headers, cdn_request=False) return response.status in [httplib.CREATED, httplib.ACCEPTED] def ex_set_account_metadata_temp_url_key(self, key): """ Set the metadata header X-Account-Meta-Temp-URL-Key on your Cloud Files account. :param key: X-Account-Meta-Temp-URL-Key :type key: ``str`` :rtype: ``bool`` """ headers = {'X-Account-Meta-Temp-URL-Key': key} # pylint: disable=unexpected-keyword-arg response = self.connection.request('', method='POST', headers=headers, cdn_request=False) return response.status in [httplib.OK, httplib.NO_CONTENT, httplib.CREATED, httplib.ACCEPTED] def ex_get_object_temp_url(self, obj, method='GET', timeout=60): """ Create a temporary URL to allow others to retrieve or put objects in your Cloud Files account for as long or as short a time as you wish. This method is specifically for allowing users to retrieve or update an object. :param obj: The object that you wish to make temporarily public :type obj: :class:`Object` :param method: Which method you would like to allow, 'PUT' or 'GET' :type method: ``str`` :param timeout: Time (in seconds) after which you want the TempURL to expire. :type timeout: ``int`` :rtype: ``bool`` """ # pylint: disable=no-member self.connection._populate_hosts_and_request_paths() expires = int(time() + timeout) path = '%s/%s/%s' % (self.connection.request_path, obj.container.name, obj.name) try: key = self.ex_get_meta_data()['temp_url_key'] assert key is not None except Exception: raise KeyError('You must first set the ' + 'X-Account-Meta-Temp-URL-Key header on your ' + 'Cloud Files account using ' + 'ex_set_account_metadata_temp_url_key before ' + 'you can use this method.') hmac_body = '%s\n%s\n%s' % (method, expires, path) sig = hmac.new(b(key), b(hmac_body), sha1).hexdigest() params = urlencode({'temp_url_sig': sig, 'temp_url_expires': expires}) temp_url = 'https://%s/%s/%s?%s' %\ (self.connection.host + self.connection.request_path, obj.container.name, obj.name, params) return temp_url def _upload_object_part(self, container, object_name, part_number, iterator, verify_hash=True): part_name = object_name + '/%08d' % part_number extra = {'content_type': 'application/octet-stream'} self._put_object(container=container, object_name=part_name, extra=extra, stream=iterator, verify_hash=verify_hash) def _upload_object_manifest(self, container, object_name, extra=None, verify_hash=True): extra = extra or {} meta_data = extra.get('meta_data') container_name_encoded = self._encode_container_name(container.name) object_name_encoded = self._encode_object_name(object_name) request_path = '/%s/%s' % (container_name_encoded, object_name_encoded) # pylint: disable=no-member headers = {'X-Auth-Token': self.connection.auth_token, 'X-Object-Manifest': '%s/%s/' % (container_name_encoded, object_name_encoded)} data = '' response = self.connection.request(request_path, method='PUT', data=data, headers=headers, raw=True) object_hash = None if verify_hash: hash_function = self._get_hash_function() hash_function.update(b(data)) data_hash = hash_function.hexdigest() object_hash = response.headers.get('etag') if object_hash != data_hash: raise ObjectHashMismatchError( value=('MD5 hash checksum does not match (expected=%s, ' + 'actual=%s)') % (data_hash, object_hash), object_name=object_name, driver=self) obj = Object(name=object_name, size=0, hash=object_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj def list_container_objects(self, container, ex_prefix=None): """ Return a list of objects for the given container. :param container: Container instance. :type container: :class:`Container` :param ex_prefix: Only get objects with names starting with ex_prefix :type ex_prefix: ``str`` :return: A list of Object instances. :rtype: ``list`` of :class:`Object` """ return list(self.iterate_container_objects(container, ex_prefix=ex_prefix)) def iterate_container_objects(self, container, ex_prefix=None): """ Return a generator of objects for the given container. :param container: Container instance :type container: :class:`Container` :param ex_prefix: Only get objects with names starting with ex_prefix :type ex_prefix: ``str`` :return: A generator of Object instances. :rtype: ``generator`` of :class:`Object` """ params = {} if ex_prefix: params['prefix'] = ex_prefix while True: container_name_encoded = \ self._encode_container_name(container.name) response = self.connection.request('/%s' % (container_name_encoded), params=params) if response.status == httplib.NO_CONTENT: # Empty or non-existent container break elif response.status == httplib.OK: objects = self._to_object_list(json.loads(response.body), container) if len(objects) == 0: break for obj in objects: yield obj params['marker'] = obj.name else: raise LibcloudError('Unexpected status code: %s' % (response.status)) def _put_object(self, container, object_name, extra=None, file_path=None, stream=None, verify_hash=True, headers=None): extra = extra or {} container_name_encoded = self._encode_container_name(container.name) object_name_encoded = self._encode_object_name(object_name) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) content_disposition = extra.get('content_disposition', None) headers = headers or {} if meta_data: for key, value in list(meta_data.items()): key = 'X-Object-Meta-%s' % (key) headers[key] = value if content_disposition is not None: headers['Content-Disposition'] = content_disposition request_path = '/%s/%s' % (container_name_encoded, object_name_encoded) result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method='PUT', headers=headers, file_path=file_path, stream=stream) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] server_hash = result_dict['response'].headers.get('etag', None) if response.status == httplib.EXPECTATION_FAILED: raise LibcloudError(value='Missing content-type header', driver=self) elif verify_hash and not server_hash: raise LibcloudError(value='Server didn\'t return etag', driver=self) elif (verify_hash and result_dict['data_hash'] != server_hash): raise ObjectHashMismatchError( value=('MD5 hash checksum does not match (expected=%s, ' + 'actual=%s)') % (result_dict['data_hash'], server_hash), object_name=object_name, driver=self) elif response.status == httplib.CREATED: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra=None, meta_data=meta_data, container=container, driver=self) return obj else: # @TODO: Add test case for this condition (probably 411) raise LibcloudError('status_code=%s' % (response.status), driver=self) def _encode_container_name(self, name): """ Encode container name so it can be used as part of the HTTP request. """ if name.startswith('/'): name = name[1:] name = urlquote(name) if name.find('/') != -1: raise InvalidContainerNameError(value='Container name cannot' ' contain slashes', container_name=name, driver=self) if len(name) > 256: raise InvalidContainerNameError( value='Container name cannot be longer than 256 bytes', container_name=name, driver=self) return name def _encode_object_name(self, name): name = urlquote(name) return name def _to_container_list(self, response): # @TODO: Handle more than 10k containers - use "lazy list"? for container in response: extra = {'object_count': int(container['count']), 'size': int(container['bytes'])} yield Container(name=container['name'], extra=extra, driver=self) def _to_object_list(self, response, container): objects = [] for obj in response: name = obj['name'] size = int(obj['bytes']) hash = obj['hash'] extra = {'content_type': obj['content_type'], 'last_modified': obj['last_modified']} objects.append(Object( name=name, size=size, hash=hash, extra=extra, meta_data=None, container=container, driver=self)) return objects def _headers_to_container(self, name, headers): size = int(headers.get('x-container-bytes-used', 0)) object_count = int(headers.get('x-container-object-count', 0)) extra = {'object_count': object_count, 'size': size} container = Container(name=name, extra=extra, driver=self) return container def _headers_to_object(self, name, container, headers): size = int(headers.pop('content-length', 0)) last_modified = headers.pop('last-modified', None) etag = headers.pop('etag', None) content_type = headers.pop('content-type', None) meta_data = {} for key, value in list(headers.items()): if key.find('x-object-meta-') != -1: key = key.replace('x-object-meta-', '') meta_data[key] = value extra = {'content_type': content_type, 'last_modified': last_modified} obj = Object(name=name, size=size, hash=etag, extra=extra, meta_data=meta_data, container=container, driver=self) return obj def _ex_connection_class_kwargs(self): kwargs = self.openstack_connection_kwargs() kwargs['ex_force_service_region'] = self.region kwargs['use_internal_url'] = self.use_internal_url return kwargs class OpenStackSwiftStorageDriver(CloudFilesStorageDriver): """ Storage driver for the OpenStack Swift. """ type = Provider.CLOUDFILES_SWIFT name = 'OpenStack Swift' connectionCls = OpenStackSwiftConnection # TODO: Reverse the relationship - Swift -> CloudFiles def __init__(self, key, secret=None, secure=True, host=None, port=None, region=None, **kwargs): super(OpenStackSwiftStorageDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, **kwargs) class FileChunkReader(object): def __init__(self, file_path, chunk_size): self.file_path = file_path self.total = os.path.getsize(file_path) self.chunk_size = chunk_size self.bytes_read = 0 self.stop_iteration = False def __iter__(self): return self def next(self): if self.stop_iteration: raise StopIteration start_block = self.bytes_read end_block = start_block + self.chunk_size if end_block >= self.total: end_block = self.total self.stop_iteration = True self.bytes_read += end_block - start_block return ChunkStreamReader(file_path=self.file_path, start_block=start_block, end_block=end_block, chunk_size=8192) def __next__(self): return self.next() class ChunkStreamReader(object): def __init__(self, file_path, start_block, end_block, chunk_size): self.fd = open(file_path, 'rb') self.fd.seek(start_block) self.start_block = start_block self.end_block = end_block self.chunk_size = chunk_size self.bytes_read = 0 self.stop_iteration = False # Work around to make sure file description is closed even if the # iterator is never read from or if it's not fully exhausted def close_file(fd): try: fd.close() except Exception: pass atexit.register(close_file, self.fd) def __iter__(self): return self def next(self): if self.stop_iteration: self.fd.close() raise StopIteration block_size = self.chunk_size if self.bytes_read + block_size > \ self.end_block - self.start_block: block_size = self.end_block - self.start_block - self.bytes_read self.stop_iteration = True block = self.fd.read(block_size) self.bytes_read += block_size return block def __next__(self): return self.next() apache-libcloud-2.8.0/libcloud/storage/drivers/digitalocean_spaces.py0000664000175000017500000001062313576514553025715 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.types import LibcloudError from libcloud.common.aws import SignedAWSConnection from libcloud.storage.drivers.s3 import BaseS3Connection, S3Connection from libcloud.storage.drivers.s3 import BaseS3StorageDriver __all__ = [ 'DigitalOceanSpacesStorageDriver' ] DO_SPACES_HOSTS_BY_REGION = {'nyc3': 'nyc3.digitaloceanspaces.com', 'ams3': 'ams3.digitaloceanspaces.com', 'sgp1': 'sgp1.digitaloceanspaces.com'} DO_SPACES_DEFAULT_REGION = 'nyc3' DEFAULT_SIGNATURE_VERSION = '2' S3_API_VERSION = '2006-03-01' class DOSpacesConnectionAWS4(SignedAWSConnection, BaseS3Connection): service_name = 's3' version = S3_API_VERSION def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, token=None, retry_delay=None, backoff=None, **kwargs): super(DOSpacesConnectionAWS4, self).__init__(user_id, key, secure, host, port, url, timeout, proxy_url, token, retry_delay, backoff, signature_version=4) class DOSpacesConnectionAWS2(S3Connection): def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, token=None, retry_delay=None, backoff=None, **kwargs): super(DOSpacesConnectionAWS2, self).__init__(user_id, key, secure, host, port, url, timeout, proxy_url, token, retry_delay, backoff) class DigitalOceanSpacesStorageDriver(BaseS3StorageDriver): name = 'DigitalOcean Spaces' website = 'https://www.digitalocean.com/products/object-storage/' supports_chunked_encoding = False supports_s3_multipart_upload = True def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=DO_SPACES_DEFAULT_REGION, **kwargs): if region not in DO_SPACES_HOSTS_BY_REGION: raise LibcloudError('Unknown region (%s)' % (region), driver=self) host = DO_SPACES_HOSTS_BY_REGION[region] self.name = 'DigitalOcean Spaces (%s)' % (region) self.region_name = region self.signature_version = str(kwargs.pop('signature_version', DEFAULT_SIGNATURE_VERSION)) if self.signature_version == '2': self.connectionCls = DOSpacesConnectionAWS2 elif self.signature_version == '4': self.connectionCls = DOSpacesConnectionAWS4 else: raise ValueError('Invalid signature_version: %s' % (self.signature_version)) self.connectionCls.host = host super(DigitalOceanSpacesStorageDriver, self).__init__(key, secret, secure, host, port, api_version, region, **kwargs) def _ex_connection_class_kwargs(self): kwargs = {} kwargs['signature_version'] = self.signature_version return kwargs apache-libcloud-2.8.0/libcloud/storage/drivers/dummy.py0000664000175000017500000004514313535474530023067 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os.path import random import hashlib from libcloud.utils.py3 import PY3 from libcloud.utils.py3 import b if PY3: from io import FileIO as file from libcloud.common.types import LibcloudError from libcloud.storage.base import Object, Container, StorageDriver from libcloud.storage.types import ContainerAlreadyExistsError from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import ObjectDoesNotExistError class DummyFileObject(file): def __init__(self, yield_count=5, chunk_len=10): self._yield_count = yield_count self._chunk_len = chunk_len def read(self, size): i = 0 while i < self._yield_count: yield self._get_chunk(self._chunk_len) i += 1 def _get_chunk(self, chunk_len): chunk = [str(x) for x in random.randint(97, 120)] return chunk def __len__(self): return self._yield_count * self._chunk_len class DummyIterator(object): def __init__(self, data=None): self.hash = hashlib.md5() self._data = data or [] self._current_item = 0 def get_md5_hash(self): return self.hash.hexdigest() def next(self): if self._current_item == len(self._data): raise StopIteration value = self._data[self._current_item] self.hash.update(b(value)) self._current_item += 1 return value def __next__(self): return self.next() def __enter__(self): pass def __exit__(self, type, value, traceback): pass class DummyStorageDriver(StorageDriver): """ Dummy Storage driver. >>> from libcloud.storage.drivers.dummy import DummyStorageDriver >>> driver = DummyStorageDriver('key', 'secret') >>> container = driver.create_container(container_name='test container') >>> container >>> container.name 'test container' >>> container.extra['object_count'] 0 """ name = 'Dummy Storage Provider' website = 'http://example.com' def __init__(self, api_key, api_secret): """ :param api_key: API key or username to used (required) :type api_key: ``str`` :param api_secret: Secret password to be used (required) :type api_secret: ``str`` :rtype: ``None`` """ self._containers = {} def get_meta_data(self): """ >>> driver = DummyStorageDriver('key', 'secret') >>> driver.get_meta_data()['object_count'] 0 >>> driver.get_meta_data()['container_count'] 0 >>> driver.get_meta_data()['bytes_used'] 0 >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container_name = 'test container 2' >>> container = driver.create_container(container_name=container_name) >>> obj = container.upload_object_via_stream( ... object_name='test object', iterator=DummyFileObject(5, 10), ... extra={}) >>> driver.get_meta_data()['object_count'] 1 >>> driver.get_meta_data()['container_count'] 2 >>> driver.get_meta_data()['bytes_used'] 50 :rtype: ``dict`` """ container_count = len(self._containers) object_count = sum([len(self._containers[container]['objects']) for container in self._containers]) bytes_used = 0 for container in self._containers: objects = self._containers[container]['objects'] for _, obj in objects.items(): bytes_used += obj.size return {'container_count': int(container_count), 'object_count': int(object_count), 'bytes_used': int(bytes_used)} def iterate_containers(self): """ >>> driver = DummyStorageDriver('key', 'secret') >>> list(driver.iterate_containers()) [] >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container >>> container.name 'test container 1' >>> container_name = 'test container 2' >>> container = driver.create_container(container_name=container_name) >>> container >>> container = driver.create_container( ... container_name='test container 2') ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ContainerAlreadyExistsError: >>> container_list=list(driver.iterate_containers()) >>> sorted([c.name for c in container_list]) ['test container 1', 'test container 2'] @inherits: :class:`StorageDriver.iterate_containers` """ for container in list(self._containers.values()): yield container['container'] def list_container_objects(self, container, ex_prefix=None): container = self.get_container(container.name) objects = list(self._containers[container.name]['objects'].values()) if ex_prefix is not None: objects = [o for o in objects if o.name.startswith(ex_prefix)] return objects def get_container(self, container_name): """ >>> driver = DummyStorageDriver('key', 'secret') >>> driver.get_container('unknown') #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ContainerDoesNotExistError: >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container >>> container.name 'test container 1' >>> driver.get_container('test container 1') @inherits: :class:`StorageDriver.get_container` """ if container_name not in self._containers: raise ContainerDoesNotExistError(driver=self, value=None, container_name=container_name) return self._containers[container_name]['container'] def get_container_cdn_url(self, container): """ >>> driver = DummyStorageDriver('key', 'secret') >>> driver.get_container('unknown') #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ContainerDoesNotExistError: >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container >>> container.name 'test container 1' >>> container.get_cdn_url() 'http://www.test.com/container/test_container_1' @inherits: :class:`StorageDriver.get_container_cdn_url` """ if container.name not in self._containers: raise ContainerDoesNotExistError(driver=self, value=None, container_name=container.name) return self._containers[container.name]['cdn_url'] def get_object(self, container_name, object_name): """ >>> driver = DummyStorageDriver('key', 'secret') >>> driver.get_object('unknown', 'unknown') ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ContainerDoesNotExistError: >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container >>> driver.get_object( ... 'test container 1', 'unknown') #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ObjectDoesNotExistError: >>> obj = container.upload_object_via_stream(object_name='test object', ... iterator=DummyFileObject(5, 10), extra={}) >>> obj.name 'test object' >>> obj.size 50 @inherits: :class:`StorageDriver.get_object` """ self.get_container(container_name) container_objects = self._containers[container_name]['objects'] if object_name not in container_objects: raise ObjectDoesNotExistError(object_name=object_name, value=None, driver=self) return container_objects[object_name] def get_object_cdn_url(self, obj): """ >>> driver = DummyStorageDriver('key', 'secret') >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container >>> obj = container.upload_object_via_stream( ... object_name='test object 5', ... iterator=DummyFileObject(5, 10), extra={}) >>> obj.name 'test object 5' >>> obj.get_cdn_url() 'http://www.test.com/object/test_object_5' @inherits: :class:`StorageDriver.get_object_cdn_url` """ container_name = obj.container.name container_objects = self._containers[container_name]['objects'] if obj.name not in container_objects: raise ObjectDoesNotExistError(object_name=obj.name, value=None, driver=self) return container_objects[obj.name].meta_data['cdn_url'] def create_container(self, container_name): """ >>> driver = DummyStorageDriver('key', 'secret') >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container >>> container = driver.create_container( ... container_name='test container 1') ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ContainerAlreadyExistsError: @inherits: :class:`StorageDriver.create_container` """ if container_name in self._containers: raise ContainerAlreadyExistsError(container_name=container_name, value=None, driver=self) extra = {'object_count': 0} container = Container(name=container_name, extra=extra, driver=self) self._containers[container_name] = {'container': container, 'objects': {}, 'cdn_url': 'http://www.test.com/container/%s' % (container_name.replace(' ', '_')) } return container def delete_container(self, container): """ >>> driver = DummyStorageDriver('key', 'secret') >>> container = Container(name = 'test container', ... extra={'object_count': 0}, driver=driver) >>> driver.delete_container(container=container) ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ContainerDoesNotExistError: >>> container = driver.create_container( ... container_name='test container 1') ... #doctest: +IGNORE_EXCEPTION_DETAIL >>> len(driver._containers) 1 >>> driver.delete_container(container=container) True >>> len(driver._containers) 0 >>> container = driver.create_container( ... container_name='test container 1') ... #doctest: +IGNORE_EXCEPTION_DETAIL >>> obj = container.upload_object_via_stream( ... object_name='test object', iterator=DummyFileObject(5, 10), ... extra={}) >>> driver.delete_container(container=container) ... #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ContainerIsNotEmptyError: @inherits: :class:`StorageDriver.delete_container` """ container_name = container.name if container_name not in self._containers: raise ContainerDoesNotExistError(container_name=container_name, value=None, driver=self) container = self._containers[container_name] if len(container['objects']) > 0: raise ContainerIsNotEmptyError(container_name=container_name, value=None, driver=self) del self._containers[container_name] return True def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): kwargs_dict = {'obj': obj, 'response': DummyFileObject(), 'destination_path': destination_path, 'overwrite_existing': overwrite_existing, 'delete_on_failure': delete_on_failure} return self._save_object(**kwargs_dict) def download_object_as_stream(self, obj, chunk_size=None): """ >>> driver = DummyStorageDriver('key', 'secret') >>> container = driver.create_container( ... container_name='test container 1') ... #doctest: +IGNORE_EXCEPTION_DETAIL >>> obj = container.upload_object_via_stream(object_name='test object', ... iterator=DummyFileObject(5, 10), extra={}) >>> stream = container.download_object_as_stream(obj) >>> stream #doctest: +ELLIPSIS <...closed...> @inherits: :class:`StorageDriver.download_object_as_stream` """ return DummyFileObject() def upload_object(self, file_path, container, object_name, extra=None, file_hash=None): """ >>> driver = DummyStorageDriver('key', 'secret') >>> container_name = 'test container 1' >>> container = driver.create_container(container_name=container_name) >>> container.upload_object(file_path='/tmp/inexistent.file', ... object_name='test') #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): LibcloudError: >>> file_path = path = os.path.abspath(__file__) >>> file_size = os.path.getsize(file_path) >>> obj = container.upload_object(file_path=file_path, ... object_name='test') >>> obj #doctest: +ELLIPSIS >>> obj.size == file_size True @inherits: :class:`StorageDriver.upload_object` :param file_hash: File hash :type file_hash: ``str`` """ if not os.path.exists(file_path): raise LibcloudError(value='File %s does not exist' % (file_path), driver=self) size = os.path.getsize(file_path) return self._add_object(container=container, object_name=object_name, size=size, extra=extra) def upload_object_via_stream(self, iterator, container, object_name, extra=None): """ >>> driver = DummyStorageDriver('key', 'secret') >>> container = driver.create_container( ... container_name='test container 1') ... #doctest: +IGNORE_EXCEPTION_DETAIL >>> obj = container.upload_object_via_stream( ... object_name='test object', iterator=DummyFileObject(5, 10), ... extra={}) >>> obj #doctest: +ELLIPSIS @inherits: :class:`StorageDriver.upload_object_via_stream` """ size = len(iterator) return self._add_object(container=container, object_name=object_name, size=size, extra=extra) def delete_object(self, obj): """ >>> driver = DummyStorageDriver('key', 'secret') >>> container = driver.create_container( ... container_name='test container 1') ... #doctest: +IGNORE_EXCEPTION_DETAIL >>> obj = container.upload_object_via_stream(object_name='test object', ... iterator=DummyFileObject(5, 10), extra={}) >>> obj #doctest: +ELLIPSIS >>> container.delete_object(obj=obj) True >>> obj = Object(name='test object 2', ... size=1000, hash=None, extra=None, ... meta_data=None, container=container,driver=None) >>> container.delete_object(obj=obj) #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ObjectDoesNotExistError: @inherits: :class:`StorageDriver.delete_object` """ container_name = obj.container.name object_name = obj.name obj = self.get_object(container_name=container_name, object_name=object_name) del self._containers[container_name]['objects'][object_name] return True def _add_object(self, container, object_name, size, extra=None): container = self.get_container(container.name) extra = extra or {} meta_data = extra.get('meta_data', {}) meta_data.update({'cdn_url': 'http://www.test.com/object/%s' % (object_name.replace(' ', '_'))}) obj = Object(name=object_name, size=size, extra=extra, hash=None, meta_data=meta_data, container=container, driver=self) self._containers[container.name]['objects'][object_name] = obj return obj if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/storage/drivers/google_storage.py0000664000175000017500000003534113535474530024733 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import copy import json import email.utils from libcloud.common.base import ConnectionUserAndKey from libcloud.common.google import GoogleAuthType from libcloud.common.google import GoogleOAuth2Credential from libcloud.common.google import GoogleResponse from libcloud.common.types import ProviderError from libcloud.storage.drivers.s3 import BaseS3Connection from libcloud.storage.drivers.s3 import BaseS3StorageDriver from libcloud.storage.drivers.s3 import S3RawResponse from libcloud.storage.drivers.s3 import S3Response from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlquote # Docs are a lie. Actual namespace returned is different that the one listed # in the docs. SIGNATURE_IDENTIFIER = 'GOOG1' API_VERSION = '2006-03-01' NAMESPACE = 'http://doc.s3.amazonaws.com/%s' % (API_VERSION) def _clean_object_name(name): """ Return the URL encoded name. name=None returns None. Useful for input checking without having to check for None first. :param name: The object name :type name: ``str`` or ``None`` :return: The url-encoded object name or None if name=None. :rtype ``str`` or ``None`` """ return urlquote(name, safe='') if name else None class ContainerPermissions(object): values = ['NONE', 'READER', 'WRITER', 'OWNER'] NONE = 0 READER = 1 WRITER = 2 OWNER = 3 class ObjectPermissions(object): values = ['NONE', 'READER', 'OWNER'] NONE = 0 READER = 1 OWNER = 2 class GoogleStorageConnection(ConnectionUserAndKey): """ Represents a single connection to the Google storage API endpoint. This can either authenticate via the Google OAuth2 methods or via the S3 HMAC interoperability method. """ host = 'storage.googleapis.com' responseCls = S3Response rawResponseCls = S3RawResponse PROJECT_ID_HEADER = 'x-goog-project-id' def __init__(self, user_id, key, secure=True, auth_type=None, credential_file=None, **kwargs): self.auth_type = auth_type or GoogleAuthType.guess_type(user_id) if GoogleAuthType.is_oauth2(self.auth_type): self.oauth2_credential = GoogleOAuth2Credential( user_id, key, self.auth_type, credential_file, **kwargs) else: self.oauth2_credential = None super(GoogleStorageConnection, self).__init__(user_id, key, secure, **kwargs) def add_default_headers(self, headers): date = email.utils.formatdate(usegmt=True) headers['Date'] = date project = self.get_project() if project: headers[self.PROJECT_ID_HEADER] = project return headers def get_project(self): return getattr(self.driver, 'project', None) def pre_connect_hook(self, params, headers): if self.auth_type == GoogleAuthType.GCS_S3: signature = self._get_s3_auth_signature(params, headers) headers['Authorization'] = '%s %s:%s' % (SIGNATURE_IDENTIFIER, self.user_id, signature) else: headers['Authorization'] = ('Bearer ' + self.oauth2_credential.access_token) return params, headers def _get_s3_auth_signature(self, params, headers): """Hacky wrapper to work with S3's get_auth_signature.""" headers_copy = {} params_copy = copy.deepcopy(params) # Lowercase all headers except 'date' and Google header values for k, v in headers.items(): k_lower = k.lower() if (k_lower == 'date' or k_lower.startswith( GoogleStorageDriver.http_vendor_prefix) or not isinstance(v, str)): headers_copy[k_lower] = v else: headers_copy[k_lower] = v.lower() return BaseS3Connection.get_auth_signature( method=self.method, headers=headers_copy, params=params_copy, expires=None, secret_key=self.key, path=self.action, vendor_prefix=GoogleStorageDriver.http_vendor_prefix) class GCSResponse(GoogleResponse): pass class GoogleStorageJSONConnection(GoogleStorageConnection): """ Represents a single connection to the Google storage JSON API endpoint. This can either authenticate via the Google OAuth2 methods or via the S3 HMAC interoperability method. """ host = 'www.googleapis.com' responseCls = GCSResponse rawResponseCls = None def add_default_headers(self, headers): headers = super(GoogleStorageJSONConnection, self).add_default_headers( headers) headers['Content-Type'] = 'application/json' return headers class GoogleStorageDriver(BaseS3StorageDriver): """ Driver for Google Cloud Storage. Can authenticate via standard Google Cloud methods (Service Accounts, Installed App credentials, and GCE instance service accounts) Examples: Service Accounts:: driver = GoogleStorageDriver(key=client_email, secret=private_key, ...) Installed Application:: driver = GoogleStorageDriver(key=client_id, secret=client_secret, ...) From GCE instance:: driver = GoogleStorageDriver(key=foo, secret=bar, ...) Can also authenticate via Google Cloud Storage's S3 HMAC interoperability API. S3 user keys are 20 alphanumeric characters, starting with GOOG. Example:: driver = GoogleStorageDriver(key='GOOG0123456789ABCXYZ', secret=key_secret) """ name = 'Google Cloud Storage' website = 'http://cloud.google.com/storage' connectionCls = GoogleStorageConnection jsonConnectionCls = GoogleStorageJSONConnection hash_type = 'md5' namespace = NAMESPACE supports_chunked_encoding = False supports_s3_multipart_upload = False http_vendor_prefix = 'x-goog' def __init__(self, key, secret=None, project=None, **kwargs): super(GoogleStorageDriver, self).__init__(key, secret, **kwargs) self.project = project self.json_connection = GoogleStorageJSONConnection( key, secret, **kwargs) def _get_container_permissions(self, container_name): """ Return the container permissions for the current authenticated user. :param container_name: The container name. :param container_name: ``str`` :return: The permissions on the container. :rtype: ``int`` from ContainerPermissions """ # Try OWNER permissions first: try listing the bucket ACL. # FORBIDDEN -> exists, but not an OWNER. # NOT_FOUND -> bucket DNE, return NONE. try: self.json_connection.request( '/storage/v1/b/%s/acl' % container_name) return ContainerPermissions.OWNER except ProviderError as e: if e.http_code == httplib.FORBIDDEN: pass elif e.http_code == httplib.NOT_FOUND: return ContainerPermissions.NONE else: raise # Try WRITER permissions with a noop request: try delete with an # impossible precondition. Authorization is checked before file # existence or preconditions. So, if we get a NOT_FOUND or a # PRECONDITION_FAILED, then we must be authorized. try: self.json_connection.request( '/storage/v1/b/%s/o/writecheck' % container_name, headers={'x-goog-if-generation-match': '0'}, method='DELETE') except ProviderError as e: if e.http_code in [httplib.NOT_FOUND, httplib.PRECONDITION_FAILED]: return ContainerPermissions.WRITER elif e.http_code != httplib.FORBIDDEN: raise # Last, try READER permissions: try getting container metadata. try: self.json_connection.request('/storage/v1/b/%s' % container_name) return ContainerPermissions.READER except ProviderError as e: if e.http_code not in [httplib.FORBIDDEN, httplib.NOT_FOUND]: raise return ContainerPermissions.NONE def _get_user(self): """Gets this drivers' authenticated user, if any.""" oauth2_creds = getattr(self.connection, 'oauth2_credential') if oauth2_creds: return oauth2_creds.user_id else: return None def _get_object_permissions(self, container_name, object_name): """ Return the object permissions for the current authenticated user. If the object does not exist, or no object_name is given, return the default object permissions. :param container_name: The container name. :type container_name: ``str`` :param object_name: The object name. :type object_name: ``str`` :return: The permissions on the object or default object permissions. :rtype: ``int`` from ObjectPermissions """ # Try OWNER permissions first: try listing the object ACL. try: self.json_connection.request( '/storage/v1/b/%s/o/%s/acl' % (container_name, object_name)) return ObjectPermissions.OWNER except ProviderError as e: if e.http_code not in [httplib.FORBIDDEN, httplib.NOT_FOUND]: raise # Try READER permissions: try getting the object. try: self.json_connection.request( '/storage/v1/b/%s/o/%s' % (container_name, object_name)) return ObjectPermissions.READER except ProviderError as e: if e.http_code not in [httplib.FORBIDDEN, httplib.NOT_FOUND]: raise return ObjectPermissions.NONE def ex_delete_permissions(self, container_name, object_name=None, entity=None): """ Delete permissions for an ACL entity on a container or object. :param container_name: The container name. :type container_name: ``str`` :param object_name: The object name. Optional. Not providing an object will delete a container permission. :type object_name: ``str`` :param entity: The entity to whose permission will be deleted. Optional. If not provided, the role will be applied to the authenticated user, if using an OAuth2 authentication scheme. :type entity: ``str`` or ``None`` """ object_name = _clean_object_name(object_name) if not entity: user_id = self._get_user() if not user_id: raise ValueError( 'Must provide an entity. Driver is not using an ' 'authenticated user.') else: entity = 'user-%s' % user_id if object_name: url = ('/storage/v1/b/%s/o/%s/acl/%s' % (container_name, object_name, entity)) else: url = '/storage/v1/b/%s/acl/%s' % (container_name, entity) self.json_connection.request(url, method='DELETE') def ex_get_permissions(self, container_name, object_name=None): """ Return the permissions for the currently authenticated user. :param container_name: The container name. :type container_name: ``str`` :param object_name: The object name. Optional. Not providing an object will return only container permissions. :type object_name: ``str`` or ``None`` :return: A tuple of container and object permissions. :rtype: ``tuple`` of (``int``, ``int`` or ``None``) from ContainerPermissions and ObjectPermissions, respectively. """ object_name = _clean_object_name(object_name) obj_perms = self._get_object_permissions( container_name, object_name) if object_name else None return self._get_container_permissions(container_name), obj_perms def ex_set_permissions(self, container_name, object_name=None, entity=None, role=None): """ Set the permissions for an ACL entity on a container or an object. :param container_name: The container name. :type container_name: ``str`` :param object_name: The object name. Optional. Not providing an object will apply the acl to the container. :type object_name: ``str`` :param entity: The entity to which apply the role. Optional. If not provided, the role will be applied to the authenticated user, if using an OAuth2 authentication scheme. :type entity: ``str`` :param role: The permission/role to set on the entity. :type role: ``int`` from ContainerPermissions or ObjectPermissions or ``str``. :raises ValueError: If no entity was given, but was required. Or if the role isn't valid for the bucket or object. """ object_name = _clean_object_name(object_name) if isinstance(role, int): perms = ObjectPermissions if object_name else ContainerPermissions try: role = perms.values[role] except IndexError: raise ValueError( '%s is not a valid role level for container=%s object=%s' % (role, container_name, object_name)) elif not isinstance(role, str): raise ValueError('%s is not a valid permission.' % role) if not entity: user_id = self._get_user() if not user_id: raise ValueError( 'Must provide an entity. Driver is not using an ' 'authenticated user.') else: entity = 'user-%s' % user_id if object_name: url = '/storage/v1/b/%s/o/%s/acl' % (container_name, object_name) else: url = '/storage/v1/b/%s/acl' % container_name self.json_connection.request( url, method='POST', data=json.dumps({'role': role, 'entity': entity})) apache-libcloud-2.8.0/libcloud/storage/drivers/ktucloud.py0000664000175000017500000000363213535474530023563 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.types import LibcloudError from libcloud.storage.providers import Provider from libcloud.storage.drivers.cloudfiles import CloudFilesConnection from libcloud.storage.drivers.cloudfiles import CloudFilesStorageDriver KTUCLOUDSTORAGE_AUTH_URL = "https://ssproxy.ucloudbiz.olleh.com/auth/v1.0" KTUCLOUDSTORAGE_API_VERSION = "1.0" class KTUCloudStorageConnection(CloudFilesConnection): """ Connection class for the KT UCloud Storage endpoint. """ auth_url = KTUCLOUDSTORAGE_AUTH_URL _auth_version = KTUCLOUDSTORAGE_API_VERSION def get_endpoint(self): eps = self.service_catalog.get_endpoints(name='cloudFiles') if len(eps) == 0: raise LibcloudError('Could not find specified endpoint') ep = eps[0] public_url = ep.url if not public_url: raise LibcloudError('Could not find specified endpoint') return public_url class KTUCloudStorageDriver(CloudFilesStorageDriver): """ Cloudfiles storage driver for the UK endpoint. """ type = Provider.KTUCLOUD name = 'KTUCloud Storage' connectionCls = KTUCloudStorageConnection apache-libcloud-2.8.0/libcloud/storage/drivers/local.py0000664000175000017500000004507013570310635023017 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Provides storage driver for working with local filesystem """ from __future__ import with_statement import errno import os import shutil try: import lockfile from lockfile import LockTimeout, mkdirlockfile except ImportError: raise ImportError('Missing lockfile dependency, you can install it ' 'using pip: pip install lockfile') from libcloud.utils.files import read_in_chunks from libcloud.utils.py3 import relpath from libcloud.utils.py3 import u from libcloud.common.base import Connection from libcloud.storage.base import Object, Container, StorageDriver from libcloud.common.types import LibcloudError from libcloud.storage.types import ContainerAlreadyExistsError from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import ObjectError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import InvalidContainerNameError IGNORE_FOLDERS = ['.lock', '.hash'] class LockLocalStorage(object): """ A class to help in locking a local path before being updated """ def __init__(self, path): self.path = path self.lock = mkdirlockfile.MkdirLockFile(self.path, threaded=True) def __enter__(self): try: self.lock.acquire(timeout=0.1) except LockTimeout: raise LibcloudError('Lock timeout') def __exit__(self, type, value, traceback): if self.lock.is_locked(): self.lock.release() if value is not None: raise value class LocalStorageDriver(StorageDriver): """ Implementation of local file-system based storage. This is helpful where the user would want to use the same code (using libcloud) and switch between cloud storage and local storage """ connectionCls = Connection name = 'Local Storage' website = 'http://example.com' hash_type = 'md5' def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs): # Use the key as the path to the storage self.base_path = key if not os.path.isdir(self.base_path): raise LibcloudError('The base path is not a directory') super(LocalStorageDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, **kwargs) def _make_path(self, path, ignore_existing=True): """ Create a path by checking if it already exists """ try: os.makedirs(path) except OSError as exp: if exp.errno == errno.EEXIST and not ignore_existing: raise exp def _check_container_name(self, container_name): """ Check if the container name is valid :param container_name: Container name :type container_name: ``str`` """ if '/' in container_name or '\\' in container_name: raise InvalidContainerNameError(value=None, driver=self, container_name=container_name) def _make_container(self, container_name): """ Create a container instance :param container_name: Container name. :type container_name: ``str`` :return: Container instance. :rtype: :class:`Container` """ self._check_container_name(container_name) full_path = os.path.join(self.base_path, container_name) try: stat = os.stat(full_path) if not os.path.isdir(full_path): raise OSError('Target path is not a directory') except OSError: raise ContainerDoesNotExistError(value=None, driver=self, container_name=container_name) extra = {} extra['creation_time'] = stat.st_ctime extra['access_time'] = stat.st_atime extra['modify_time'] = stat.st_mtime return Container(name=container_name, extra=extra, driver=self) def _make_object(self, container, object_name): """ Create an object instance :param container: Container. :type container: :class:`Container` :param object_name: Object name. :type object_name: ``str`` :return: Object instance. :rtype: :class:`Object` """ full_path = os.path.join(self.base_path, container.name, object_name) if os.path.isdir(full_path): raise ObjectError(value=None, driver=self, object_name=object_name) try: stat = os.stat(full_path) except Exception: raise ObjectDoesNotExistError(value=None, driver=self, object_name=object_name) # Make a hash for the file based on the metadata. We can safely # use only the mtime attribute here. If the file contents change, # the underlying file-system will change mtime data_hash = self._get_hash_function() data_hash.update(u(stat.st_mtime).encode('ascii')) data_hash = data_hash.hexdigest() extra = {} extra['creation_time'] = stat.st_ctime extra['access_time'] = stat.st_atime extra['modify_time'] = stat.st_mtime return Object(name=object_name, size=stat.st_size, extra=extra, driver=self, container=container, hash=data_hash, meta_data=None) def iterate_containers(self): """ Return a generator of containers. :return: A generator of Container instances. :rtype: ``generator`` of :class:`Container` """ for container_name in os.listdir(self.base_path): full_path = os.path.join(self.base_path, container_name) if not os.path.isdir(full_path): continue yield self._make_container(container_name) def _get_objects(self, container): """ Recursively iterate through the file-system and return the object names """ cpath = self.get_container_cdn_url(container, check=True) for folder, subfolders, files in os.walk(cpath, topdown=True): # Remove unwanted subfolders for subf in IGNORE_FOLDERS: if subf in subfolders: subfolders.remove(subf) for name in files: full_path = os.path.join(folder, name) object_name = relpath(full_path, start=cpath) yield self._make_object(container, object_name) def iterate_container_objects(self, container): """ Returns a generator of objects for the given container. :param container: Container instance :type container: :class:`Container` :return: A generator of Object instances. :rtype: ``generator`` of :class:`Object` """ return self._get_objects(container) def get_container(self, container_name): """ Return a container instance. :param container_name: Container name. :type container_name: ``str`` :return: :class:`Container` instance. :rtype: :class:`Container` """ return self._make_container(container_name) def get_container_cdn_url(self, container, check=False): """ Return a container CDN URL. :param container: Container instance :type container: :class:`Container` :param check: Indicates if the path's existence must be checked :type check: ``bool`` :return: A CDN URL for this container. :rtype: ``str`` """ path = os.path.join(self.base_path, container.name) if check and not os.path.isdir(path): raise ContainerDoesNotExistError(value=None, driver=self, container_name=container.name) return path def get_object(self, container_name, object_name): """ Return an object instance. :param container_name: Container name. :type container_name: ``str`` :param object_name: Object name. :type object_name: ``str`` :return: :class:`Object` instance. :rtype: :class:`Object` """ container = self._make_container(container_name) return self._make_object(container, object_name) def get_object_cdn_url(self, obj): """ Return an object CDN URL. :param obj: Object instance :type obj: :class:`Object` :return: A CDN URL for this object. :rtype: ``str`` """ return os.path.join(self.base_path, obj.container.name, obj.name) def enable_container_cdn(self, container): """ Enable container CDN. :param container: Container instance :type container: :class:`Container` :rtype: ``bool`` """ path = self.get_container_cdn_url(container) lockfile.MkdirFileLock(path, threaded=True) with LockLocalStorage(path): self._make_path(path) return True def enable_object_cdn(self, obj): """ Enable object CDN. :param obj: Object instance :type obj: :class:`Object` :rtype: ``bool`` """ path = self.get_object_cdn_url(obj) with LockLocalStorage(path): if os.path.exists(path): return False try: obj_file = open(path, 'w') obj_file.close() except Exception: return False return True def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): """ Download an object to the specified destination path. :param obj: Object instance. :type obj: :class:`Object` :param destination_path: Full path to a file or a directory where the incoming file will be saved. :type destination_path: ``str`` :param overwrite_existing: True to overwrite an existing file, defaults to False. :type overwrite_existing: ``bool`` :param delete_on_failure: True to delete a partially downloaded file if the download was not successful (hash mismatch / file size). :type delete_on_failure: ``bool`` :return: True if an object has been successfully downloaded, False otherwise. :rtype: ``bool`` """ obj_path = self.get_object_cdn_url(obj) base_name = os.path.basename(destination_path) if not base_name and not os.path.exists(destination_path): raise LibcloudError( value='Path %s does not exist' % (destination_path), driver=self) if not base_name: file_path = os.path.join(destination_path, obj.name) else: file_path = destination_path if os.path.exists(file_path) and not overwrite_existing: raise LibcloudError( value='File %s already exists, but ' % (file_path) + 'overwrite_existing=False', driver=self) try: shutil.copy(obj_path, file_path) except IOError: if delete_on_failure: try: os.unlink(file_path) except Exception: pass return False return True def download_object_as_stream(self, obj, chunk_size=None): """ Return a generator which yields object data. :param obj: Object instance :type obj: :class:`Object` :param chunk_size: Optional chunk size (in bytes). :type chunk_size: ``int`` :return: A stream of binary chunks of data. :rtype: ``object`` """ path = self.get_object_cdn_url(obj) with open(path, 'rb') as obj_file: for data in read_in_chunks(obj_file, chunk_size=chunk_size): yield data def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True): """ Upload an object currently located on a disk. :param file_path: Path to the object on disk. :type file_path: ``str`` :param container: Destination container. :type container: :class:`Container` :param object_name: Object name. :type object_name: ``str`` :param verify_hash: Verify hast :type verify_hash: ``bool`` :param extra: (optional) Extra attributes (driver specific). :type extra: ``dict`` :rtype: ``object`` """ path = self.get_container_cdn_url(container, check=True) obj_path = os.path.join(path, object_name) base_path = os.path.dirname(obj_path) self._make_path(base_path) with LockLocalStorage(obj_path): shutil.copy(file_path, obj_path) os.chmod(obj_path, int('664', 8)) return self._make_object(container, object_name) def upload_object_via_stream(self, iterator, container, object_name, extra=None): """ Upload an object using an iterator. If a provider supports it, chunked transfer encoding is used and you don't need to know in advance the amount of data to be uploaded. Otherwise if a provider doesn't support it, iterator will be exhausted so a total size for data to be uploaded can be determined. Note: Exhausting the iterator means that the whole data must be buffered in memory which might result in memory exhausting when uploading a very large object. If a file is located on a disk you are advised to use upload_object function which uses fs.stat function to determine the file size and it doesn't need to buffer whole object in the memory. :type iterator: ``object`` :param iterator: An object which implements the iterator interface and yields binary chunks of data. :type container: :class:`Container` :param container: Destination container. :type object_name: ``str`` :param object_name: Object name. :type extra: ``dict`` :param extra: (optional) Extra attributes (driver specific). Note: This dictionary must contain a 'content_type' key which represents a content type of the stored object. :rtype: ``object`` """ path = self.get_container_cdn_url(container, check=True) obj_path = os.path.join(path, object_name) base_path = os.path.dirname(obj_path) self._make_path(base_path) with LockLocalStorage(obj_path): with open(obj_path, 'wb') as obj_file: for data in iterator: obj_file.write(data) os.chmod(obj_path, int('664', 8)) return self._make_object(container, object_name) def delete_object(self, obj): """ Delete an object. :type obj: :class:`Object` :param obj: Object instance. :return: ``bool`` True on success. :rtype: ``bool`` """ path = self.get_object_cdn_url(obj) with LockLocalStorage(path): try: os.unlink(path) except Exception: return False # Check and delete all the empty parent folders path = os.path.dirname(path) container_url = obj.container.get_cdn_url() # Delete the empty parent folders till the container's level while path != container_url: try: os.rmdir(path) except OSError as exp: if exp.errno == errno.ENOTEMPTY: break raise exp path = os.path.dirname(path) return True def create_container(self, container_name): """ Create a new container. :type container_name: ``str`` :param container_name: Container name. :return: :class:`Container` instance on success. :rtype: :class:`Container` """ self._check_container_name(container_name) path = os.path.join(self.base_path, container_name) try: self._make_path(path, ignore_existing=False) except OSError as exp: if exp.errno == errno.EEXIST: raise ContainerAlreadyExistsError( value='Container with this name already exists. The name ' 'must be unique among all the containers in the ' 'system', container_name=container_name, driver=self) else: raise LibcloudError( 'Error creating container %s' % container_name, driver=self) except Exception: raise LibcloudError( 'Error creating container %s' % container_name, driver=self) return self._make_container(container_name) def delete_container(self, container): """ Delete a container. :type container: :class:`Container` :param container: Container instance :return: True on success, False otherwise. :rtype: ``bool`` """ # Check if there are any objects inside this for obj in self._get_objects(container): raise ContainerIsNotEmptyError(value='Container is not empty', container_name=container.name, driver=self) path = self.get_container_cdn_url(container, check=True) with LockLocalStorage(path): try: shutil.rmtree(path) except Exception: return False return True apache-libcloud-2.8.0/libcloud/storage/drivers/nimbus.py0000664000175000017500000001033013535474530023217 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import time import hashlib import hmac try: import simplejson as json except ImportError: import json # NOQA from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlencode from libcloud.common.base import ConnectionUserAndKey, JsonResponse from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.storage.base import Container, StorageDriver class NimbusResponse(JsonResponse): valid_response_codes = [httplib.OK, httplib.NOT_FOUND, httplib.CONFLICT, httplib.BAD_REQUEST] def success(self): return self.status in self.valid_response_codes def parse_error(self): if self.status in [httplib.UNAUTHORIZED]: raise InvalidCredsError(self.body) raise LibcloudError('Unknown error. Status code: %d' % (self.status), driver=self.connection.driver) class NimbusConnection(ConnectionUserAndKey): host = 'nimbus.io' responseCls = NimbusResponse def __init__(self, *args, **kwargs): self.id = kwargs.pop('id') super(NimbusConnection, self).__init__(*args, **kwargs) def pre_connect_hook(self, params, headers): timestamp = str(int(time.time())) signature = self._calculate_signature(user_id=self.user_id, method=self.method, params=params, path=self.action, timestamp=timestamp, key=self.key) headers['X-NIMBUS-IO-Timestamp'] = timestamp headers['Authorization'] = 'NIMBUS.IO %s:%s' % (self.id, signature) return params, headers def _calculate_signature(self, user_id, method, params, path, timestamp, key): if params: uri_path = path + '?' + urlencode(params) else: uri_path = path string_to_sign = [user_id, method, str(timestamp), uri_path] string_to_sign = '\n'.join(string_to_sign) hmac_value = hmac.new(key, string_to_sign, hashlib.sha256) return hmac_value.hexdigest() class NimbusStorageDriver(StorageDriver): name = 'Nimbus.io' website = 'https://nimbus.io/' connectionCls = NimbusConnection def __init__(self, *args, **kwargs): self.user_id = kwargs['user_id'] super(NimbusStorageDriver, self).__init__(*args, **kwargs) def iterate_containers(self): response = self.connection.request('/customers/%s/collections' % (self.user_id)) return self._to_containers(response.object) def create_container(self, container_name): params = {'action': 'create', 'name': container_name} response = self.connection.request('/customers/%s/collections' % (self.user_id), params=params, method='POST') return self._to_container(response.object) def _to_containers(self, data): for item in data: yield self._to_container(item) def _to_container(self, data): name = data[0] extra = {'date_created': data[2]} return Container(name=name, extra=extra, driver=self) def _ex_connection_class_kwargs(self): result = {'id': self.user_id} return result apache-libcloud-2.8.0/libcloud/storage/drivers/ninefold.py0000664000175000017500000000206313535474530023524 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.storage.providers import Provider from libcloud.storage.drivers.atmos import AtmosDriver class NinefoldStorageDriver(AtmosDriver): host = 'api.ninefold.com' path = '/storage/v1.0' type = Provider.NINEFOLD name = 'Ninefold' website = 'http://ninefold.com/' apache-libcloud-2.8.0/libcloud/storage/drivers/oss.py0000664000175000017500000010755313570310635022536 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # pylint: disable=unexpected-keyword-arg import base64 import codecs import hmac import time from hashlib import sha1 from libcloud.utils.py3 import ET try: from lxml.etree import Element, SubElement except ImportError: from xml.etree.ElementTree import Element, SubElement from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlquote from libcloud.utils.py3 import urlencode from libcloud.utils.py3 import b from libcloud.utils.py3 import tostring from libcloud.utils.py3 import PY3 from libcloud.utils.xml import fixxpath, findtext from libcloud.utils.files import read_in_chunks from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.common.base import ConnectionUserAndKey, RawResponse, \ XmlResponse from libcloud.common.types import MalformedResponseError from libcloud.storage.base import Object, Container, StorageDriver from libcloud.storage.types import ContainerError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import InvalidContainerNameError from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError __all__ = [ 'OSSStorageDriver', 'OSSMultipartUpload', 'EXPIRATION_SECONDS', 'CHUNK_SIZE', 'MAX_UPLOADS_PER_RESPONSE' ] GMT_TIME_FORMAT = "%a, %d %b %Y %H:%M:%S GMT" EXPIRATION_SECONDS = 15 * 60 # OSS multi-part chunks must be great than 100KB except the last one CHUNK_SIZE = 100 * 1024 # Desired number of items in each response inside a paginated request in # ex_iterate_multipart_uploads. MAX_UPLOADS_PER_RESPONSE = 1000 class OSSResponse(XmlResponse): namespace = None valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT, httplib.BAD_REQUEST] def success(self): i = int(self.status) return 200 <= i <= 299 or i in self.valid_response_codes def parse_body(self): """ OSSResponse body is in utf-8 encoding. """ if len(self.body) == 0 and not self.parse_zero_length_body: return self.body try: if PY3: parser = ET.XMLParser(encoding='utf-8') body = ET.XML(self.body.encode('utf-8'), parser=parser) else: body = ET.XML(self.body) except Exception: raise MalformedResponseError('Failed to parse XML', body=self.body, driver=self.connection.driver) return body def parse_error(self): if self.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]: raise InvalidCredsError(self.body) elif self.status == httplib.MOVED_PERMANENTLY: raise LibcloudError('This bucket is located in a different ' + 'region. Please use the correct driver.', driver=OSSStorageDriver) elif self.status == httplib.METHOD_NOT_ALLOWED: raise LibcloudError('The method is not allowed. Status code: %d, ' 'headers: %s' % (self.status, self.headers)) raise LibcloudError('Unknown error. Status code: %d, body: %s' % (self.status, self.body), driver=OSSStorageDriver) class OSSRawResponse(OSSResponse, RawResponse): pass class OSSConnection(ConnectionUserAndKey): """ Represents a single connection to the Aliyun OSS Endpoint """ _domain = 'aliyuncs.com' _default_location = 'oss' responseCls = OSSResponse rawResponseCls = OSSRawResponse @staticmethod def _get_auth_signature(method, headers, params, expires, secret_key, path, vendor_prefix): """ Signature = base64(hmac-sha1(AccessKeySecret, VERB + "\n" + CONTENT-MD5 + "\n" + CONTENT-TYPE + "\n" + EXPIRES + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource)) """ special_headers = {'content-md5': '', 'content-type': '', 'expires': ''} vendor_headers = {} for key, value in list(headers.items()): key_lower = key.lower() if key_lower in special_headers: special_headers[key_lower] = value.strip() elif key_lower.startswith(vendor_prefix): vendor_headers[key_lower] = value.strip() if expires: special_headers['expires'] = str(expires) buf = [method] for _, value in sorted(special_headers.items()): buf.append(value) string_to_sign = '\n'.join(buf) buf = [] for key, value in sorted(vendor_headers.items()): buf.append('%s:%s' % (key, value)) header_string = '\n'.join(buf) values_to_sign = [] for value in [string_to_sign, header_string, path]: if value: values_to_sign.append(value) string_to_sign = '\n'.join(values_to_sign) b64_hmac = base64.b64encode( hmac.new(b(secret_key), b(string_to_sign), digestmod=sha1).digest() ) return b64_hmac @staticmethod def _get_expires(params): """ Get expires timeout seconds from parameters. """ expires = None if 'expires' in params: expires = params['expires'] elif 'Expires' in params: expires = params['Expires'] if expires: try: return int(expires) except Exception: pass return int(time.time()) + EXPIRATION_SECONDS def add_default_params(self, params): expires_at = self._get_expires(params) expires = str(expires_at) params['OSSAccessKeyId'] = self.user_id params['Expires'] = expires return params def add_default_headers(self, headers): headers['Date'] = time.strftime(GMT_TIME_FORMAT, time.gmtime()) return headers def pre_connect_hook(self, params, headers): if self._container: path = '/%s%s' % (self._container.name, self.action) else: path = self.action # pylint: disable=no-member params['Signature'] = self._get_auth_signature( method=self.method, headers=headers, params=params, expires=params['Expires'], secret_key=self.key, path=path, vendor_prefix=self.driver.http_vendor_prefix) return params, headers def request(self, action, params=None, data=None, headers=None, method='GET', raw=False, container=None): self.host = '%s.%s' % (self._default_location, self._domain) self._container = container if container and container.name: if 'location' in container.extra: self.host = '%s.%s.%s' % (container.name, container.extra['location'], self._domain) else: self.host = '%s.%s' % (container.name, self.host) return super(OSSConnection, self).request(action=action, params=params, data=data, headers=headers, method=method, raw=raw) class OSSMultipartUpload(object): """ Class representing an Aliyun OSS multipart upload """ def __init__(self, key, id, initiated): """ Class representing an Aliyun OSS multipart upload :param key: The object/key that was being uploaded :type key: ``str`` :param id: The upload id assigned by Aliyun :type id: ``str`` :param initiated: The date/time at which the upload was started :type created_at: ``str`` """ self.key = key self.id = id self.initiated = initiated def __repr__(self): return ('' % (self.key)) class OSSStorageDriver(StorageDriver): name = 'Aliyun OSS' website = 'http://www.aliyun.com/product/oss' connectionCls = OSSConnection hash_type = 'md5' supports_chunked_encoding = False supports_multipart_upload = True namespace = None http_vendor_prefix = 'x-oss-' def iterate_containers(self): response = self.connection.request('/') if response.status == httplib.OK: containers = self._to_containers(obj=response.object, xpath='Buckets/Bucket') return containers raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) def list_container_objects(self, container, ex_prefix=None): """ Return a list of objects for the given container. :param container: Container instance. :type container: :class:`Container` :keyword ex_prefix: Only return objects starting with ex_prefix :type ex_prefix: ``str`` :return: A list of Object instances. :rtype: ``list`` of :class:`Object` """ return list(self.iterate_container_objects(container, ex_prefix=ex_prefix)) def iterate_container_objects(self, container, ex_prefix=None): """ Return a generator of objects for the given container. :param container: Container instance :type container: :class:`Container` :keyword ex_prefix: Only return objects starting with ex_prefix :type ex_prefix: ``str`` :return: A generator of Object instances. :rtype: ``generator`` of :class:`Object` """ params = {} if ex_prefix: params['prefix'] = ex_prefix last_key = None exhausted = False while not exhausted: if last_key: params['marker'] = last_key response = self.connection.request('/', params=params, container=container) if response.status != httplib.OK: raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) objects = self._to_objs(obj=response.object, xpath='Contents', container=container) is_truncated = response.object.findtext(fixxpath( xpath='IsTruncated', namespace=self.namespace)).lower() exhausted = (is_truncated == 'false') last_key = None for obj in objects: last_key = obj.name yield obj def get_container(self, container_name): for container in self.iterate_containers(): if container.name == container_name: return container raise ContainerDoesNotExistError(value=None, driver=self, container_name=container_name) def get_object(self, container_name, object_name): container = self.get_container(container_name=container_name) object_path = self._get_object_path(container, object_name) response = self.connection.request(object_path, method='HEAD', container=container) if response.status == httplib.OK: obj = self._headers_to_object(object_name=object_name, container=container, headers=response.headers) return obj raise ObjectDoesNotExistError(value=None, driver=self, object_name=object_name) def create_container(self, container_name, ex_location=None): """ @inherits :class:`StorageDriver.create_container` :keyword ex_location: The desired location where to create container :type keyword: ``str`` """ extra = None if ex_location: root = Element('CreateBucketConfiguration') child = SubElement(root, 'LocationConstraint') child.text = ex_location data = tostring(root) extra = {'location': ex_location} else: data = '' container = Container(name=container_name, extra=extra, driver=self) response = self.connection.request('/', data=data, method='PUT', container=container) if response.status == httplib.OK: return container elif response.status == httplib.CONFLICT: raise InvalidContainerNameError( value='Container with this name already exists. The name must ' 'be unique among all the containers in the system', container_name=container_name, driver=self) elif response.status == httplib.BAD_REQUEST: raise ContainerError( value='Bad request when creating container: %s' % response.body, container_name=container_name, driver=self) raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) def delete_container(self, container): # Note: All the objects in the container must be deleted first response = self.connection.request('/', method='DELETE', container=container) if response.status == httplib.NO_CONTENT: return True elif response.status == httplib.CONFLICT: raise ContainerIsNotEmptyError( value='Container must be empty before it can be deleted.', container_name=container.name, driver=self) elif response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(value=None, driver=self, container_name=container.name) return False def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): obj_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(obj_path, method='GET', raw=True, container=obj.container) return self._get_object(obj=obj, callback=self._save_object, response=response, callback_kwargs={ 'obj': obj, 'response': response.response, 'destination_path': destination_path, 'overwrite_existing': overwrite_existing, 'delete_on_failure': delete_on_failure}, success_status_code=httplib.OK) def download_object_as_stream(self, obj, chunk_size=None): obj_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(obj_path, method='GET', raw=True, container=obj.container) return self._get_object(obj=obj, callback=read_in_chunks, response=response, callback_kwargs={'iterator': response.response, 'chunk_size': chunk_size}, success_status_code=httplib.OK) def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True, headers=None): return self._put_object(container=container, object_name=object_name, extra=extra, file_path=file_path, verify_hash=verify_hash) def upload_object_via_stream(self, iterator, container, object_name, extra=None, headers=None): method = 'PUT' params = None if self.supports_multipart_upload: # @TODO: This needs implementing again from scratch. pass return self._put_object(container=container, object_name=object_name, extra=extra, method=method, query_args=params, stream=iterator, verify_hash=False) def delete_object(self, obj): object_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(object_path, method='DELETE', container=obj.container) if response.status == httplib.NO_CONTENT: return True elif response.status == httplib.NOT_FOUND: raise ObjectDoesNotExistError(value=None, driver=self, object_name=obj.name) return False def ex_iterate_multipart_uploads(self, container, prefix=None, delimiter=None, max_uploads=MAX_UPLOADS_PER_RESPONSE): """ Extension method for listing all in-progress OSS multipart uploads. Each multipart upload which has not been committed or aborted is considered in-progress. :param container: The container holding the uploads :type container: :class:`Container` :keyword prefix: Print only uploads of objects with this prefix :type prefix: ``str`` :keyword delimiter: The object/key names are grouped based on being split by this delimiter :type delimiter: ``str`` :keyword max_uploads: The max uplod items returned for one request :type max_uploads: ``int`` :return: A generator of OSSMultipartUpload instances. :rtype: ``generator`` of :class:`OSSMultipartUpload` """ if not self.supports_multipart_upload: raise LibcloudError('Feature not supported', driver=self) request_path = '/?uploads' params = {'max-uploads': max_uploads} if prefix: params['prefix'] = prefix if delimiter: params['delimiter'] = delimiter def finder(node, text): return node.findtext(fixxpath(xpath=text, namespace=self.namespace)) while True: response = self.connection.request(request_path, params=params, container=container) if response.status != httplib.OK: raise LibcloudError('Error fetching multipart uploads. ' 'Got code: %s' % response.status, driver=self) body = response.parse_body() # pylint: disable=maybe-no-member for node in body.findall(fixxpath(xpath='Upload', namespace=self.namespace)): key = finder(node, 'Key') upload_id = finder(node, 'UploadId') initiated = finder(node, 'Initiated') yield OSSMultipartUpload(key, upload_id, initiated) # Check if this is the last entry in the listing # pylint: disable=maybe-no-member is_truncated = body.findtext(fixxpath(xpath='IsTruncated', namespace=self.namespace)) if is_truncated.lower() == 'false': break # Provide params for the next request upload_marker = body.findtext(fixxpath(xpath='NextUploadIdMarker', namespace=self.namespace)) key_marker = body.findtext(fixxpath(xpath='NextKeyMarker', namespace=self.namespace)) params['key-marker'] = key_marker params['upload-id-marker'] = upload_marker def ex_abort_all_multipart_uploads(self, container, prefix=None): """ Extension method for removing all partially completed OSS multipart uploads. :param container: The container holding the uploads :type container: :class:`Container` :keyword prefix: Delete only uploads of objects with this prefix :type prefix: ``str`` """ # Iterate through the container and delete the upload ids for upload in self.ex_iterate_multipart_uploads(container, prefix, delimiter=None): object_path = self._get_object_path(container, upload.key) self._abort_multipart(object_path, upload.id, container=container) def _clean_object_name(self, name): name = urlquote(name) return name def _put_object(self, container, object_name, method='PUT', query_args=None, extra=None, file_path=None, stream=None, verify_hash=False): """ Create an object and upload data using the given function. """ headers = {} extra = extra or {} content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) acl = extra.get('acl', None) if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + 'meta-%s' % (key) headers[key] = value if acl: if acl not in ['public-read', 'private', 'public-read-write']: raise AttributeError('invalid acl value: %s' % acl) headers[self.http_vendor_prefix + 'object-acl'] = acl request_path = self._get_object_path(container, object_name) if query_args: request_path = '?'.join((request_path, query_args)) result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method=method, headers=headers, file_path=file_path, stream=stream) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers server_hash = headers['etag'].replace('"', '') if (verify_hash and result_dict['data_hash'] != server_hash): raise ObjectHashMismatchError( value='MD5 hash {0} checksum does not match {1}'.format( server_hash, result_dict['data_hash']), object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra={'acl': acl}, meta_data=meta_data, container=container, driver=self) return obj else: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self) def _upload_multipart(self, response, data, iterator, container, object_name, calculate_hash=True): """ Callback invoked for uploading data to OSS using Aliyun's multipart upload mechanism :param response: Response object from the initial POST request :type response: :class:`OSSRawResponse` :param data: Any data from the initial POST request :type data: ``str`` :param iterator: The generator for fetching the upload data :type iterator: ``generator`` :param container: The container owning the object to which data is being uploaded :type container: :class:`Container` :param object_name: The name of the object to which we are uploading :type object_name: ``str`` :keyword calculate_hash: Indicates if we must calculate the data hash :type calculate_hash: ``bool`` :return: A tuple of (status, checksum, bytes transferred) :rtype: ``tuple`` """ object_path = self._get_object_path(container, object_name) # Get the upload id from the response xml response.body = response.response.read() body = response.parse_body() upload_id = body.find(fixxpath(xpath='UploadId', namespace=self.namespace)).text try: # Upload the data through the iterator result = self._upload_from_iterator(iterator, object_path, upload_id, calculate_hash, container=container) (chunks, data_hash, bytes_transferred) = result # Commit the chunk info and complete the upload etag = self._commit_multipart(object_path, upload_id, chunks, container=container) except Exception as e: # Amazon provides a mechanism for aborting an upload. self._abort_multipart(object_path, upload_id, container=container) raise e # Modify the response header of the first request. This is used # by other functions once the callback is done response.headers['etag'] = etag return (True, data_hash, bytes_transferred) def _upload_from_iterator(self, iterator, object_path, upload_id, calculate_hash=True, container=None): """ Uploads data from an interator in fixed sized chunks to OSS :param iterator: The generator for fetching the upload data :type iterator: ``generator`` :param object_path: The path of the object to which we are uploading :type object_name: ``str`` :param upload_id: The upload id allocated for this multipart upload :type upload_id: ``str`` :keyword calculate_hash: Indicates if we must calculate the data hash :type calculate_hash: ``bool`` :keyword container: the container object to upload object to :type container: :class:`Container` :return: A tuple of (chunk info, checksum, bytes transferred) :rtype: ``tuple`` """ data_hash = None if calculate_hash: data_hash = self._get_hash_function() bytes_transferred = 0 count = 1 chunks = [] params = {'uploadId': upload_id} # Read the input data in chunk sizes suitable for AWS for data in read_in_chunks(iterator, chunk_size=CHUNK_SIZE, fill_size=True, yield_empty=True): bytes_transferred += len(data) if calculate_hash: data_hash.update(data) chunk_hash = self._get_hash_function() chunk_hash.update(data) chunk_hash = base64.b64encode(chunk_hash.digest()).decode('utf-8') # OSS will calculate hash of the uploaded data and # check this header. headers = {'Content-MD5': chunk_hash} params['partNumber'] = count request_path = '?'.join((object_path, urlencode(params))) resp = self.connection.request(request_path, method='PUT', data=data, headers=headers, container=container) if resp.status != httplib.OK: raise LibcloudError('Error uploading chunk', driver=self) server_hash = resp.headers['etag'] # Keep this data for a later commit chunks.append((count, server_hash)) count += 1 if calculate_hash: data_hash = data_hash.hexdigest() return (chunks, data_hash, bytes_transferred) def _commit_multipart(self, object_path, upload_id, chunks, container=None): """ Makes a final commit of the data. :param object_path: Server side object path. :type object_path: ``str`` :param upload_id: ID of the multipart upload. :type upload_id: ``str`` :param upload_id: A list of (chunk_number, chunk_hash) tuples. :type upload_id: ``list`` :keyword container: The container owning the object to which data is being uploaded :type container: :class:`Container` """ root = Element('CompleteMultipartUpload') for (count, etag) in chunks: part = SubElement(root, 'Part') part_no = SubElement(part, 'PartNumber') part_no.text = str(count) etag_id = SubElement(part, 'ETag') etag_id.text = str(etag) data = tostring(root) params = {'uploadId': upload_id} request_path = '?'.join((object_path, urlencode(params))) response = self.connection.request(request_path, data=data, method='POST', container=container) if response.status != httplib.OK: element = response.object # pylint: disable=maybe-no-member code, message = response._parse_error_details(element=element) msg = 'Error in multipart commit: %s (%s)' % (message, code) raise LibcloudError(msg, driver=self) # Get the server's etag to be passed back to the caller body = response.parse_body() server_hash = body.find(fixxpath(xpath='ETag', namespace=self.namespace)).text return server_hash def _abort_multipart(self, object_path, upload_id, container=None): """ Aborts an already initiated multipart upload :param object_path: Server side object path. :type object_path: ``str`` :param upload_id: ID of the multipart upload. :type upload_id: ``str`` :keyword container: The container owning the object to which data is being uploaded :type container: :class:`Container` """ params = {'uploadId': upload_id} request_path = '?'.join((object_path, urlencode(params))) resp = self.connection.request(request_path, method='DELETE', container=container) if resp.status != httplib.NO_CONTENT: raise LibcloudError('Error in multipart abort. status_code=%d' % (resp.status), driver=self) def _to_containers(self, obj, xpath): for element in obj.findall(fixxpath(xpath=xpath, namespace=self.namespace)): yield self._to_container(element) def _to_container(self, element): extra = { 'creation_date': findtext(element=element, xpath='CreationDate', namespace=self.namespace), 'location': findtext(element=element, xpath='Location', namespace=self.namespace) } container = Container(name=findtext(element=element, xpath='Name', namespace=self.namespace), extra=extra, driver=self ) return container def _to_objs(self, obj, xpath, container): return [self._to_obj(element, container) for element in obj.findall(fixxpath(xpath=xpath, namespace=self.namespace))] def _to_obj(self, element, container): owner_id = findtext(element=element, xpath='Owner/ID', namespace=self.namespace) owner_display_name = findtext(element=element, xpath='Owner/DisplayName', namespace=self.namespace) meta_data = {'owner': {'id': owner_id, 'display_name': self._safe_decode( owner_display_name)}} last_modified = findtext(element=element, xpath='LastModified', namespace=self.namespace) extra = {'last_modified': last_modified} name = self._safe_decode(findtext(element=element, xpath='Key', namespace=self.namespace)) obj = Object(name=name, size=int(findtext(element=element, xpath='Size', namespace=self.namespace)), hash=findtext(element=element, xpath='ETag', namespace=self.namespace).replace('"', ''), extra=extra, meta_data=meta_data, container=container, driver=self ) return obj def _safe_decode(self, encoded): """ Decode it as an escaped string and then treate the content as UTF-8 encoded. """ try: if encoded: unescaped, _ign = codecs.escape_decode(encoded) return unescaped.decode('utf-8') return encoded except Exception: return encoded def _get_container_path(self, container): """ Return a container path :param container: Container instance :type container: :class:`Container` :return: A path for this container. :rtype: ``str`` """ return '/%s' % (container.name) def _get_object_path(self, container, object_name): """ Return an object's path. Aliyun OSS api puts the container name in the host, so ignore container here. :param container: Container instance :type container: :class:`Container` :param object_name: Object name :type object_name: :class:`str` :return: A path for this object. :rtype: ``str`` """ object_name_cleaned = self._clean_object_name(object_name) object_path = '/%s' % object_name_cleaned return object_path def _headers_to_object(self, object_name, container, headers): hash = headers['etag'].replace('"', '') extra = {'content_type': headers['content-type'], 'etag': headers['etag']} meta_data = {} if 'last-modified' in headers: extra['last_modified'] = headers['last-modified'] for key, value in headers.items(): if not key.lower().startswith(self.http_vendor_prefix + 'meta-'): continue key = key.replace(self.http_vendor_prefix + 'meta-', '') meta_data[key] = value obj = Object(name=object_name, size=int(headers['content-length']), hash=hash, extra=extra, meta_data=meta_data, container=container, driver=self) return obj apache-libcloud-2.8.0/libcloud/storage/drivers/rgw.py0000664000175000017500000001235513576514553022537 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.types import LibcloudError from libcloud.common.aws import SignedAWSConnection, DEFAULT_SIGNATURE_VERSION from libcloud.storage.drivers.s3 import BaseS3Connection, S3Connection from libcloud.storage.drivers.s3 import BaseS3StorageDriver, API_VERSION __all__ = [ 'S3RGWStorageDriver', 'S3RGWOutscaleStorageDriver' ] S3_RGW_DEFAULT_REGION = 'default' S3_RGW_OUTSCALE_HOSTS_BY_REGION =\ {'eu-west-1': 'osu.eu-west-1.outscale.com', 'eu-west-2': 'osu.eu-west-2.outscale.com', 'us-west-1': 'osu.us-west-1.outscale.com', 'us-east-2': 'osu.us-east-2.outscale.com', 'cn-southeast-1': 'osu.cn-southeast-1.outscale.hk'} S3_RGW_OUTSCALE_DEFAULT_REGION = 'eu-west-2' class S3RGWConnectionAWS4(SignedAWSConnection, BaseS3Connection): service_name = 's3' version = API_VERSION def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, token=None, retry_delay=None, backoff=None, **kwargs): super(S3RGWConnectionAWS4, self).__init__(user_id, key, secure, host, port, url, timeout, proxy_url, token, retry_delay, backoff, 4) # force aws4 class S3RGWConnectionAWS2(S3Connection): def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, token=None, retry_delay=None, backoff=None, **kwargs): super(S3RGWConnectionAWS2, self).__init__(user_id, key, secure, host, port, url, timeout, proxy_url, token, retry_delay, backoff) class S3RGWStorageDriver(BaseS3StorageDriver): name = 'Ceph RGW' website = 'http://ceph.com/' def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=S3_RGW_DEFAULT_REGION, **kwargs): if host is None: raise LibcloudError('host required', driver=self) self.name = kwargs.pop('name', None) if self.name is None: self.name = 'Ceph RGW S3 (%s)' % (region) self.ex_location_name = region self.region_name = region self.signature_version = str(kwargs.pop('signature_version', DEFAULT_SIGNATURE_VERSION)) if self.signature_version not in ['2', '4']: raise ValueError('Invalid signature_version: %s' % (self.signature_version)) if self.signature_version == '2': self.connectionCls = S3RGWConnectionAWS2 elif self.signature_version == '4': self.connectionCls = S3RGWConnectionAWS4 self.connectionCls.host = host super(S3RGWStorageDriver, self).__init__(key, secret, secure, host, port, api_version, region, **kwargs) def _ex_connection_class_kwargs(self): kwargs = {} kwargs['signature_version'] = self.signature_version return kwargs class S3RGWOutscaleStorageDriver(S3RGWStorageDriver): name = 'RGW Outscale' website = 'https://en.outscale.com/' def __init__(self, key, secret=None, secure=True, host=None, port=None, api_version=None, region=S3_RGW_OUTSCALE_DEFAULT_REGION, **kwargs): if region not in S3_RGW_OUTSCALE_HOSTS_BY_REGION: raise LibcloudError('Unknown region (%s)' % (region), driver=self) host = S3_RGW_OUTSCALE_HOSTS_BY_REGION[region] kwargs['name'] = 'OUTSCALE Ceph RGW S3 (%s)' % region super(S3RGWOutscaleStorageDriver, self).__init__(key, secret, secure, host, port, api_version, region, **kwargs) apache-libcloud-2.8.0/libcloud/storage/drivers/s3.py0000664000175000017500000013114113577507766022271 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import hmac import time from hashlib import sha1 import libcloud.utils.py3 try: if libcloud.utils.py3.DEFAULT_LXML: from lxml.etree import Element, SubElement else: from xml.etree.ElementTree import Element, SubElement except ImportError: from xml.etree.ElementTree import Element, SubElement from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlquote from libcloud.utils.py3 import b from libcloud.utils.py3 import tostring from libcloud.utils.xml import fixxpath, findtext from libcloud.utils.files import read_in_chunks from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.common.base import ConnectionUserAndKey, RawResponse from libcloud.common.aws import AWSBaseResponse, AWSDriver, \ AWSTokenConnection, SignedAWSConnection from libcloud.storage.base import Object, Container, StorageDriver from libcloud.storage.types import ContainerError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import InvalidContainerNameError from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError # How long before the token expires EXPIRATION_SECONDS = 15 * 60 S3_US_STANDARD_HOST = 's3.amazonaws.com' S3_US_EAST2_HOST = 's3-us-east-2.amazonaws.com' S3_US_WEST_HOST = 's3-us-west-1.amazonaws.com' S3_US_WEST_OREGON_HOST = 's3-us-west-2.amazonaws.com' S3_US_GOV_WEST_HOST = 's3-us-gov-west-1.amazonaws.com' S3_CN_NORTH_HOST = 's3.cn-north-1.amazonaws.com.cn' S3_CN_NORTHWEST_HOST = 's3.cn-northwest-1.amazonaws.com.cn' S3_EU_WEST_HOST = 's3-eu-west-1.amazonaws.com' S3_EU_WEST2_HOST = 's3-eu-west-2.amazonaws.com' S3_EU_CENTRAL_HOST = 's3-eu-central-1.amazonaws.com' S3_EU_NORTH1_HOST = 's3-eu-north-1.amazonaws.com' S3_AP_SOUTH_HOST = 's3-ap-south-1.amazonaws.com' S3_AP_SOUTHEAST_HOST = 's3-ap-southeast-1.amazonaws.com' S3_AP_SOUTHEAST2_HOST = 's3-ap-southeast-2.amazonaws.com' S3_AP_NORTHEAST1_HOST = 's3-ap-northeast-1.amazonaws.com' S3_AP_NORTHEAST2_HOST = 's3-ap-northeast-2.amazonaws.com' S3_AP_NORTHEAST_HOST = S3_AP_NORTHEAST1_HOST S3_SA_EAST_HOST = 's3-sa-east-1.amazonaws.com' S3_SA_SOUTHEAST2_HOST = 's3-sa-east-2.amazonaws.com' S3_CA_CENTRAL_HOST = 's3-ca-central-1.amazonaws.com' # Maps AWS region name to connection hostname REGION_TO_HOST_MAP = { 'us-east-1': S3_US_STANDARD_HOST, 'us-east-2': S3_US_EAST2_HOST, 'us-west-1': S3_US_WEST_HOST, 'us-west-2': S3_US_WEST_OREGON_HOST, 'us-gov-west-1': S3_US_GOV_WEST_HOST, 'cn-north-1': S3_CN_NORTH_HOST, 'cn-northwest-1': S3_CN_NORTHWEST_HOST, 'eu-west-1': S3_EU_WEST_HOST, 'eu-west-2': S3_EU_WEST2_HOST, 'eu-west-3': 's3.eu-west-3.amazonaws.com', 'eu-north-1': 's3.eu-north-1.amazonaws.com', 'eu-central-1': S3_EU_CENTRAL_HOST, 'ap-south-1': S3_AP_SOUTH_HOST, 'ap-southeast-1': S3_AP_SOUTHEAST_HOST, 'ap-southeast-2': S3_AP_SOUTHEAST2_HOST, 'ap-northeast-1': S3_AP_NORTHEAST1_HOST, 'ap-northeast-2': S3_AP_NORTHEAST2_HOST, 'ap-northeast-3': 's3.ap-northeast-3.amazonaws.com', 'sa-east-1': S3_SA_EAST_HOST, 'sa-east-2': S3_SA_SOUTHEAST2_HOST, 'ca-central-1': S3_CA_CENTRAL_HOST, 'me-south-1': 's3.me-south-1.amazonaws.com' } API_VERSION = '2006-03-01' NAMESPACE = 'http://s3.amazonaws.com/doc/%s/' % (API_VERSION) # AWS multi-part chunks must be minimum 5MB CHUNK_SIZE = 5 * 1024 * 1024 # Desired number of items in each response inside a paginated request in # ex_iterate_multipart_uploads. RESPONSES_PER_REQUEST = 100 class S3Response(AWSBaseResponse): namespace = None valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT, httplib.BAD_REQUEST] def success(self): i = int(self.status) return 200 <= i <= 299 or i in self.valid_response_codes def parse_error(self): if self.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]: raise InvalidCredsError(self.body) elif self.status == httplib.MOVED_PERMANENTLY: bucket_region = self.headers.get('x-amz-bucket-region', None) used_region = self.connection.driver.region raise LibcloudError('This bucket is located in a different ' 'region. Please use the correct driver. ' 'Bucket region "%s", used region "%s".' % (bucket_region, used_region), driver=S3StorageDriver) raise LibcloudError('Unknown error. Status code: %d' % (self.status), driver=S3StorageDriver) class S3RawResponse(S3Response, RawResponse): pass class BaseS3Connection(ConnectionUserAndKey): """ Represents a single connection to the S3 Endpoint """ host = 's3.amazonaws.com' responseCls = S3Response rawResponseCls = S3RawResponse @staticmethod def get_auth_signature(method, headers, params, expires, secret_key, path, vendor_prefix): """ Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) ) ); StringToSign = HTTP-VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Expires + "\n" + CanonicalizedVendorHeaders + CanonicalizedResource; """ special_headers = {'content-md5': '', 'content-type': '', 'date': ''} vendor_headers = {} for key, value in list(headers.items()): key_lower = key.lower() if key_lower in special_headers: special_headers[key_lower] = value.strip() elif key_lower.startswith(vendor_prefix): vendor_headers[key_lower] = value.strip() if expires: special_headers['date'] = str(expires) buf = [method] for _, value in sorted(special_headers.items()): buf.append(value) string_to_sign = '\n'.join(buf) buf = [] for key, value in sorted(vendor_headers.items()): buf.append('%s:%s' % (key, value)) header_string = '\n'.join(buf) values_to_sign = [] for value in [string_to_sign, header_string, path]: if value: values_to_sign.append(value) string_to_sign = '\n'.join(values_to_sign) b64_hmac = base64.b64encode( hmac.new(b(secret_key), b(string_to_sign), digestmod=sha1).digest() ) return b64_hmac.decode('utf-8') def add_default_params(self, params): expires = str(int(time.time()) + EXPIRATION_SECONDS) params['AWSAccessKeyId'] = self.user_id params['Expires'] = expires return params def pre_connect_hook(self, params, headers): # pylint: disable=no-member params['Signature'] = self.get_auth_signature( method=self.method, headers=headers, params=params, expires=params['Expires'], secret_key=self.key, path=self.action, vendor_prefix=self.driver.http_vendor_prefix) return params, headers class S3Connection(AWSTokenConnection, BaseS3Connection): """ Represents a single connection to the S3 endpoint, with AWS-specific features. """ pass class S3SignatureV4Connection(SignedAWSConnection, BaseS3Connection): service_name = 's3' version = API_VERSION def __init__(self, user_id, key, secure=True, host=None, port=None, url=None, timeout=None, proxy_url=None, token=None, retry_delay=None, backoff=None): super(S3SignatureV4Connection, self).__init__( user_id, key, secure, host, port, url, timeout, proxy_url, token, retry_delay, backoff, 4) # force version 4 class S3MultipartUpload(object): """ Class representing an amazon s3 multipart upload """ def __init__(self, key, id, created_at, initiator, owner): """ Class representing an amazon s3 multipart upload :param key: The object/key that was being uploaded :type key: ``str`` :param id: The upload id assigned by amazon :type id: ``str`` :param created_at: The date/time at which the upload was started :type created_at: ``str`` :param initiator: The AWS owner/IAM user who initiated this :type initiator: ``str`` :param owner: The AWS owner/IAM who will own this object :type owner: ``str`` """ self.key = key self.id = id self.created_at = created_at self.initiator = initiator self.owner = owner def __repr__(self): return ('' % (self.key)) class BaseS3StorageDriver(StorageDriver): name = 'Amazon S3 (standard)' website = 'http://aws.amazon.com/s3/' connectionCls = BaseS3Connection hash_type = 'md5' supports_chunked_encoding = False supports_s3_multipart_upload = True ex_location_name = '' namespace = NAMESPACE http_vendor_prefix = 'x-amz' def iterate_containers(self): response = self.connection.request('/') if response.status == httplib.OK: containers = self._to_containers(obj=response.object, xpath='Buckets/Bucket') return containers raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) def list_container_objects(self, container, ex_prefix=None): """ Return a list of objects for the given container. :param container: Container instance. :type container: :class:`Container` :param ex_prefix: Only return objects starting with ex_prefix :type ex_prefix: ``str`` :return: A list of Object instances. :rtype: ``list`` of :class:`Object` """ return list(self.iterate_container_objects(container, ex_prefix=ex_prefix)) def iterate_container_objects(self, container, ex_prefix=None): """ Return a generator of objects for the given container. :param container: Container instance :type container: :class:`Container` :param ex_prefix: Only return objects starting with ex_prefix :type ex_prefix: ``str`` :return: A generator of Object instances. :rtype: ``generator`` of :class:`Object` """ params = {} if ex_prefix: params['prefix'] = ex_prefix last_key = None exhausted = False container_path = self._get_container_path(container) while not exhausted: if last_key: params['marker'] = last_key response = self.connection.request(container_path, params=params) if response.status != httplib.OK: raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) objects = self._to_objs(obj=response.object, xpath='Contents', container=container) is_truncated = response.object.findtext(fixxpath( xpath='IsTruncated', namespace=self.namespace)).lower() exhausted = (is_truncated == 'false') last_key = None for obj in objects: last_key = obj.name yield obj def get_container(self, container_name): try: response = self.connection.request('/%s' % container_name, method='HEAD') if response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(value=None, driver=self, container_name=container_name) except InvalidCredsError: # This just means the user doesn't have IAM permissions to do a # HEAD request but other requests might work. pass return Container(name=container_name, extra=None, driver=self) def get_object(self, container_name, object_name): container = self.get_container(container_name=container_name) object_path = self._get_object_path(container, object_name) response = self.connection.request(object_path, method='HEAD') if response.status == httplib.OK: obj = self._headers_to_object(object_name=object_name, container=container, headers=response.headers) return obj raise ObjectDoesNotExistError(value=None, driver=self, object_name=object_name) def _get_container_path(self, container): """ Return a container path :param container: Container instance :type container: :class:`Container` :return: A path for this container. :rtype: ``str`` """ return '/%s' % (container.name) def _get_object_path(self, container, object_name): """ Return an object's CDN path. :param container: Container instance :type container: :class:`Container` :param object_name: Object name :type object_name: :class:`str` :return: A path for this object. :rtype: ``str`` """ container_url = self._get_container_path(container) object_name_cleaned = self._clean_object_name(object_name) object_path = '%s/%s' % (container_url, object_name_cleaned) return object_path def create_container(self, container_name): if self.ex_location_name: root = Element('CreateBucketConfiguration') child = SubElement(root, 'LocationConstraint') child.text = self.ex_location_name data = tostring(root) else: data = '' response = self.connection.request('/%s' % (container_name), data=data, method='PUT') if response.status == httplib.OK: container = Container(name=container_name, extra=None, driver=self) return container elif response.status == httplib.CONFLICT: raise InvalidContainerNameError( value='Container with this name already exists. The name must ' 'be unique among all the containers in the system', container_name=container_name, driver=self) elif response.status == httplib.BAD_REQUEST: raise ContainerError( value='Bad request when creating container: %s' % response.body, container_name=container_name, driver=self) raise LibcloudError('Unexpected status code: %s' % (response.status), driver=self) def delete_container(self, container): # Note: All the objects in the container must be deleted first response = self.connection.request('/%s' % (container.name), method='DELETE') if response.status == httplib.NO_CONTENT: return True elif response.status == httplib.CONFLICT: raise ContainerIsNotEmptyError( value='Container must be empty before it can be deleted.', container_name=container.name, driver=self) elif response.status == httplib.NOT_FOUND: raise ContainerDoesNotExistError(value=None, driver=self, container_name=container.name) return False def download_object(self, obj, destination_path, overwrite_existing=False, delete_on_failure=True): obj_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(obj_path, method='GET', raw=True) return self._get_object(obj=obj, callback=self._save_object, response=response, callback_kwargs={ 'obj': obj, 'response': response.response, 'destination_path': destination_path, 'overwrite_existing': overwrite_existing, 'delete_on_failure': delete_on_failure}, success_status_code=httplib.OK) def download_object_as_stream(self, obj, chunk_size=None): obj_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(obj_path, method='GET', stream=True, raw=True) return self._get_object( obj=obj, callback=read_in_chunks, response=response, callback_kwargs={'iterator': response.iter_content(CHUNK_SIZE), 'chunk_size': chunk_size}, success_status_code=httplib.OK) def upload_object(self, file_path, container, object_name, extra=None, verify_hash=True, ex_storage_class=None): """ @inherits: :class:`StorageDriver.upload_object` :param ex_storage_class: Storage class :type ex_storage_class: ``str`` """ return self._put_object(container=container, object_name=object_name, extra=extra, file_path=file_path, verify_hash=verify_hash, storage_class=ex_storage_class) def _initiate_multipart(self, container, object_name, headers=None): """ Initiates a multipart upload to S3 :param container: The destination container :type container: :class:`Container` :param object_name: The name of the object which we are uploading :type object_name: ``str`` :keyword headers: Additional headers to send with the request :type headers: ``dict`` :return: The id of the newly created multipart upload :rtype: ``str`` """ headers = headers or {} request_path = self._get_object_path(container, object_name) params = {'uploads': ''} response = self.connection.request(request_path, method='POST', headers=headers, params=params) if response.status != httplib.OK: raise LibcloudError('Error initiating multipart upload', driver=self) return findtext(element=response.object, xpath='UploadId', namespace=self.namespace) def _upload_multipart_chunks(self, container, object_name, upload_id, stream, calculate_hash=True): """ Uploads data from an iterator in fixed sized chunks to S3 :param container: The destination container :type container: :class:`Container` :param object_name: The name of the object which we are uploading :type object_name: ``str`` :param upload_id: The upload id allocated for this multipart upload :type upload_id: ``str`` :param stream: The generator for fetching the upload data :type stream: ``generator`` :keyword calculate_hash: Indicates if we must calculate the data hash :type calculate_hash: ``bool`` :return: A tuple of (chunk info, checksum, bytes transferred) :rtype: ``tuple`` """ data_hash = None if calculate_hash: data_hash = self._get_hash_function() bytes_transferred = 0 count = 1 chunks = [] params = {'uploadId': upload_id} request_path = self._get_object_path(container, object_name) # Read the input data in chunk sizes suitable for AWS for data in read_in_chunks(stream, chunk_size=CHUNK_SIZE, fill_size=True, yield_empty=True): bytes_transferred += len(data) if calculate_hash: data_hash.update(data) chunk_hash = self._get_hash_function() chunk_hash.update(data) chunk_hash = base64.b64encode(chunk_hash.digest()).decode('utf-8') # The Content-MD5 header provides an extra level of data check and # is recommended by amazon headers = { 'Content-Length': len(data), 'Content-MD5': chunk_hash, } params['partNumber'] = count resp = self.connection.request(request_path, method='PUT', data=data, headers=headers, params=params) if resp.status != httplib.OK: raise LibcloudError('Error uploading chunk', driver=self) server_hash = resp.headers['etag'].replace('"', '') # Keep this data for a later commit chunks.append((count, server_hash)) count += 1 if calculate_hash: data_hash = data_hash.hexdigest() return (chunks, data_hash, bytes_transferred) def _commit_multipart(self, container, object_name, upload_id, chunks): """ Makes a final commit of the data. :param container: The destination container :type container: :class:`Container` :param object_name: The name of the object which we are uploading :type object_name: ``str`` :param upload_id: The upload id allocated for this multipart upload :type upload_id: ``str`` :param chunks: A list of (chunk_number, chunk_hash) tuples. :type chunks: ``list`` :return: The server side hash of the uploaded data :rtype: ``str`` """ root = Element('CompleteMultipartUpload') for (count, etag) in chunks: part = SubElement(root, 'Part') part_no = SubElement(part, 'PartNumber') part_no.text = str(count) etag_id = SubElement(part, 'ETag') etag_id.text = str(etag) data = tostring(root) headers = {'Content-Length': len(data)} params = {'uploadId': upload_id} request_path = self._get_object_path(container, object_name) response = self.connection.request(request_path, headers=headers, params=params, data=data, method='POST') if response.status != httplib.OK: element = response.object # pylint: disable=maybe-no-member code, message = response._parse_error_details(element=element) msg = 'Error in multipart commit: %s (%s)' % (message, code) raise LibcloudError(msg, driver=self) # Get the server's etag to be passed back to the caller body = response.parse_body() server_hash = body.find(fixxpath(xpath='ETag', namespace=self.namespace)).text return server_hash def _abort_multipart(self, container, object_name, upload_id): """ Aborts an already initiated multipart upload :param container: The destination container :type container: :class:`Container` :param object_name: The name of the object which we are uploading :type object_name: ``str`` :param upload_id: The upload id allocated for this multipart upload :type upload_id: ``str`` """ params = {'uploadId': upload_id} request_path = self._get_object_path(container, object_name) resp = self.connection.request(request_path, method='DELETE', params=params) if resp.status != httplib.NO_CONTENT: raise LibcloudError('Error in multipart abort. status_code=%d' % (resp.status), driver=self) def upload_object_via_stream(self, iterator, container, object_name, extra=None, ex_storage_class=None): """ @inherits: :class:`StorageDriver.upload_object_via_stream` :param ex_storage_class: Storage class :type ex_storage_class: ``str`` """ method = 'PUT' params = None # This driver is used by other S3 API compatible drivers also. # Amazon provides a different (complex?) mechanism to do multipart # uploads if self.supports_s3_multipart_upload: return self._put_object_multipart(container=container, object_name=object_name, extra=extra, stream=iterator, verify_hash=False, storage_class=ex_storage_class) return self._put_object(container=container, object_name=object_name, extra=extra, method=method, query_args=params, stream=iterator, verify_hash=False, storage_class=ex_storage_class) def delete_object(self, obj): object_path = self._get_object_path(obj.container, obj.name) response = self.connection.request(object_path, method='DELETE') if response.status == httplib.NO_CONTENT: return True elif response.status == httplib.NOT_FOUND: raise ObjectDoesNotExistError(value=None, driver=self, object_name=obj.name) return False def ex_iterate_multipart_uploads(self, container, prefix=None, delimiter=None): """ Extension method for listing all in-progress S3 multipart uploads. Each multipart upload which has not been committed or aborted is considered in-progress. :param container: The container holding the uploads :type container: :class:`Container` :keyword prefix: Print only uploads of objects with this prefix :type prefix: ``str`` :keyword delimiter: The object/key names are grouped based on being split by this delimiter :type delimiter: ``str`` :return: A generator of S3MultipartUpload instances. :rtype: ``generator`` of :class:`S3MultipartUpload` """ if not self.supports_s3_multipart_upload: raise LibcloudError('Feature not supported', driver=self) # Get the data for a specific container request_path = self._get_container_path(container) params = {'max-uploads': RESPONSES_PER_REQUEST, 'uploads': ''} if prefix: params['prefix'] = prefix if delimiter: params['delimiter'] = delimiter def finder(node, text): return node.findtext(fixxpath(xpath=text, namespace=self.namespace)) while True: response = self.connection.request(request_path, params=params) if response.status != httplib.OK: raise LibcloudError('Error fetching multipart uploads. ' 'Got code: %s' % response.status, driver=self) body = response.parse_body() # pylint: disable=maybe-no-member for node in body.findall(fixxpath(xpath='Upload', namespace=self.namespace)): initiator = node.find(fixxpath(xpath='Initiator', namespace=self.namespace)) owner = node.find(fixxpath(xpath='Owner', namespace=self.namespace)) key = finder(node, 'Key') upload_id = finder(node, 'UploadId') created_at = finder(node, 'Initiated') initiator = finder(initiator, 'DisplayName') owner = finder(owner, 'DisplayName') yield S3MultipartUpload(key, upload_id, created_at, initiator, owner) # Check if this is the last entry in the listing # pylint: disable=maybe-no-member is_truncated = body.findtext(fixxpath(xpath='IsTruncated', namespace=self.namespace)) if is_truncated.lower() == 'false': break # Provide params for the next request upload_marker = body.findtext(fixxpath(xpath='NextUploadIdMarker', namespace=self.namespace)) key_marker = body.findtext(fixxpath(xpath='NextKeyMarker', namespace=self.namespace)) params['key-marker'] = key_marker params['upload-id-marker'] = upload_marker def ex_cleanup_all_multipart_uploads(self, container, prefix=None): """ Extension method for removing all partially completed S3 multipart uploads. :param container: The container holding the uploads :type container: :class:`Container` :keyword prefix: Delete only uploads of objects with this prefix :type prefix: ``str`` """ # Iterate through the container and delete the upload ids for upload in self.ex_iterate_multipart_uploads(container, prefix, delimiter=None): self._abort_multipart(container, upload.key, upload.id) def _clean_object_name(self, name): name = urlquote(name) return name def _put_object(self, container, object_name, method='PUT', query_args=None, extra=None, file_path=None, stream=None, verify_hash=True, storage_class=None): headers = {} extra = extra or {} headers.update(self._to_storage_class_headers(storage_class)) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) acl = extra.get('acl', None) if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + '-meta-%s' % (key) headers[key] = value if acl: headers[self.http_vendor_prefix + '-acl'] = acl request_path = self._get_object_path(container, object_name) if query_args: request_path = '?'.join((request_path, query_args)) result_dict = self._upload_object( object_name=object_name, content_type=content_type, request_path=request_path, request_method=method, headers=headers, file_path=file_path, stream=stream) response = result_dict['response'] bytes_transferred = result_dict['bytes_transferred'] headers = response.headers response = response server_hash = headers.get('etag', '').replace('"', '') if (verify_hash and result_dict['data_hash'] != server_hash): raise ObjectHashMismatchError( value='MD5 hash {0} checksum does not match {1}'.format( server_hash, result_dict['data_hash']), object_name=object_name, driver=self) elif response.status == httplib.OK: obj = Object( name=object_name, size=bytes_transferred, hash=server_hash, extra={'acl': acl}, meta_data=meta_data, container=container, driver=self) return obj else: raise LibcloudError( 'Unexpected status code, status_code=%s' % (response.status), driver=self) def _put_object_multipart(self, container, object_name, stream, extra=None, verify_hash=False, storage_class=None): """ Uploads an object using the S3 multipart algorithm. :param container: The destination container :type container: :class:`Container` :param object_name: The name of the object which we are uploading :type object_name: ``str`` :param stream: The generator for fetching the upload data :type stream: ``generator`` :keyword verify_hash: Indicates if we must calculate the data hash :type verify_hash: ``bool`` :keyword extra: Additional options :type extra: ``dict`` :keyword storage_class: The name of the S3 object's storage class :type extra: ``str`` :return: The uploaded object :rtype: :class:`Object` """ headers = {} extra = extra or {} headers.update(self._to_storage_class_headers(storage_class)) content_type = extra.get('content_type', None) meta_data = extra.get('meta_data', None) acl = extra.get('acl', None) if not content_type: content_type, _ = libcloud.utils.files.guess_file_mime_type( object_name) if content_type: headers['Content-Type'] = content_type if meta_data: for key, value in list(meta_data.items()): key = self.http_vendor_prefix + '-meta-%s' % (key) headers[key] = value if acl: headers[self.http_vendor_prefix + '-acl'] = acl upload_id = self._initiate_multipart(container, object_name, headers=headers) try: result = self._upload_multipart_chunks(container, object_name, upload_id, stream, calculate_hash=verify_hash) chunks, data_hash, bytes_transferred = result # Commit the chunk info and complete the upload etag = self._commit_multipart(container, object_name, upload_id, chunks) except Exception: # Amazon provides a mechanism for aborting an upload. self._abort_multipart(container, object_name, upload_id) raise return Object( name=object_name, size=bytes_transferred, hash=etag, extra={'acl': acl}, meta_data=meta_data, container=container, driver=self) def _to_storage_class_headers(self, storage_class): """ Generates request headers given a storage class name. :keyword storage_class: The name of the S3 object's storage class :type extra: ``str`` :return: Headers to include in a request :rtype: :dict: """ headers = {} storage_class = storage_class or 'standard' if storage_class not in ['standard', 'reduced_redundancy']: raise ValueError( 'Invalid storage class value: %s' % (storage_class)) key = self.http_vendor_prefix + '-storage-class' headers[key] = storage_class.upper() return headers def _to_containers(self, obj, xpath): for element in obj.findall(fixxpath(xpath=xpath, namespace=self.namespace)): yield self._to_container(element) def _to_objs(self, obj, xpath, container): return [self._to_obj(element, container) for element in obj.findall(fixxpath(xpath=xpath, namespace=self.namespace))] def _to_container(self, element): extra = { 'creation_date': findtext(element=element, xpath='CreationDate', namespace=self.namespace) } container = Container(name=findtext(element=element, xpath='Name', namespace=self.namespace), extra=extra, driver=self ) return container def _headers_to_object(self, object_name, container, headers): hash = headers['etag'].replace('"', '') extra = {'content_type': headers['content-type'], 'etag': headers['etag']} meta_data = {} if 'last-modified' in headers: extra['last_modified'] = headers['last-modified'] for key, value in headers.items(): if not key.lower().startswith(self.http_vendor_prefix + '-meta-'): continue key = key.replace(self.http_vendor_prefix + '-meta-', '') meta_data[key] = value obj = Object(name=object_name, size=headers['content-length'], hash=hash, extra=extra, meta_data=meta_data, container=container, driver=self) return obj def _to_obj(self, element, container): owner_id = findtext(element=element, xpath='Owner/ID', namespace=self.namespace) owner_display_name = findtext(element=element, xpath='Owner/DisplayName', namespace=self.namespace) meta_data = {'owner': {'id': owner_id, 'display_name': owner_display_name}} last_modified = findtext(element=element, xpath='LastModified', namespace=self.namespace) extra = {'last_modified': last_modified} obj = Object(name=findtext(element=element, xpath='Key', namespace=self.namespace), size=int(findtext(element=element, xpath='Size', namespace=self.namespace)), hash=findtext(element=element, xpath='ETag', namespace=self.namespace).replace('"', ''), extra=extra, meta_data=meta_data, container=container, driver=self ) return obj class S3StorageDriver(AWSDriver, BaseS3StorageDriver): name = 'Amazon S3' connectionCls = S3SignatureV4Connection region_name = 'us-east-1' def __init__(self, key, secret=None, secure=True, host=None, port=None, region=None, token=None, **kwargs): # Here for backward compatibility for old and deprecated driver class # per region approach if hasattr(self, 'region_name') and not region: region = self.region_name # pylint: disable=no-member self.region_name = region if region and region not in REGION_TO_HOST_MAP.keys(): raise ValueError('Invalid or unsupported region: %s' % (region)) self.name = 'Amazon S3 (%s)' % (region) if host is None: host = REGION_TO_HOST_MAP[region] super(S3StorageDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port, region=region, token=token, **kwargs) @classmethod def list_regions(self): return REGION_TO_HOST_MAP.keys() class S3USEast2Connection(S3SignatureV4Connection): host = S3_US_EAST2_HOST class S3USEast2StorageDriver(S3StorageDriver): name = 'Amazon S3 (us-east-2)' connectionCls = S3USEast2Connection ex_location_name = 'us-east-2' region_name = 'us-east-2' class S3USWestConnection(S3SignatureV4Connection): host = S3_US_WEST_HOST class S3USWestStorageDriver(S3StorageDriver): name = 'Amazon S3 (us-west-1)' connectionCls = S3USWestConnection ex_location_name = 'us-west-1' region_name = 'us-west-1' class S3USWestOregonConnection(S3SignatureV4Connection): host = S3_US_WEST_OREGON_HOST class S3USWestOregonStorageDriver(S3StorageDriver): name = 'Amazon S3 (us-west-2)' connectionCls = S3USWestOregonConnection ex_location_name = 'us-west-2' region_name = 'us-west-2' class S3USGovWestConnection(S3SignatureV4Connection): host = S3_US_GOV_WEST_HOST class S3USGovWestStorageDriver(S3StorageDriver): name = 'Amazon S3 (us-gov-west-1)' connectionCls = S3USGovWestConnection ex_location_name = 'us-gov-west-1' region_name = 'us-gov-west-1' class S3CNNorthWestConnection(S3SignatureV4Connection): host = S3_CN_NORTHWEST_HOST class S3CNNorthWestStorageDriver(S3StorageDriver): name = 'Amazon S3 (cn-northwest-1)' connectionCls = S3CNNorthWestConnection ex_location_name = 'cn-northwest-1' region_name = 'cn-northwest-1' class S3CNNorthConnection(S3SignatureV4Connection): host = S3_CN_NORTH_HOST class S3CNNorthStorageDriver(S3StorageDriver): name = 'Amazon S3 (cn-north-1)' connectionCls = S3CNNorthConnection ex_location_name = 'cn-north-1' region_name = 'cn-north-1' class S3EUWestConnection(S3SignatureV4Connection): host = S3_EU_WEST_HOST class S3EUWestStorageDriver(S3StorageDriver): name = 'Amazon S3 (eu-west-1)' connectionCls = S3EUWestConnection ex_location_name = 'EU' region_name = 'eu-west-1' class S3EUWest2Connection(S3SignatureV4Connection): host = S3_EU_WEST2_HOST class S3EUWest2StorageDriver(S3StorageDriver): name = 'Amazon S3 (eu-west-2)' connectionCls = S3EUWest2Connection ex_location_name = 'eu-west-2' region_name = 'eu-west-2' class S3EUCentralConnection(S3SignatureV4Connection): host = S3_EU_CENTRAL_HOST class S3EUCentralStorageDriver(S3StorageDriver): name = 'Amazon S3 (eu-central-1)' connectionCls = S3EUCentralConnection ex_location_name = 'eu-central-1' region_name = 'eu-central-1' class S3APSEConnection(S3SignatureV4Connection): host = S3_AP_SOUTHEAST_HOST class S3EUNorth1Connection(S3SignatureV4Connection): host = S3_EU_NORTH1_HOST class S3EUNorth1StorageDriver(S3StorageDriver): name = 'Amazon S3 (eu-north-1)' connectionCls = S3EUNorth1Connection ex_location_name = 'eu-north-1' region_name = 'eu-north-1' class S3APSEStorageDriver(S3StorageDriver): name = 'Amazon S3 (ap-southeast-1)' connectionCls = S3APSEConnection ex_location_name = 'ap-southeast-1' region_name = 'ap-southeast-1' class S3APSE2Connection(S3SignatureV4Connection): host = S3_AP_SOUTHEAST2_HOST class S3APSE2StorageDriver(S3StorageDriver): name = 'Amazon S3 (ap-southeast-2)' connectionCls = S3APSE2Connection ex_location_name = 'ap-southeast-2' region_name = 'ap-southeast-2' class S3APNE1Connection(S3SignatureV4Connection): host = S3_AP_NORTHEAST1_HOST S3APNEConnection = S3APNE1Connection class S3APNE1StorageDriver(S3StorageDriver): name = 'Amazon S3 (ap-northeast-1)' connectionCls = S3APNEConnection ex_location_name = 'ap-northeast-1' region_name = 'ap-northeast-1' S3APNEStorageDriver = S3APNE1StorageDriver class S3APNE2Connection(S3SignatureV4Connection): host = S3_AP_NORTHEAST2_HOST class S3APNE2StorageDriver(S3StorageDriver): name = 'Amazon S3 (ap-northeast-2)' connectionCls = S3APNE2Connection ex_location_name = 'ap-northeast-2' region_name = 'ap-northeast-2' class S3APSouthConnection(S3SignatureV4Connection): host = S3_AP_SOUTH_HOST class S3APSouthStorageDriver(S3StorageDriver): name = 'Amazon S3 (ap-south-1)' connectionCls = S3APSouthConnection ex_location_name = 'ap-south-1' region_name = 'ap-south-1' class S3SAEastConnection(S3SignatureV4Connection): host = S3_SA_EAST_HOST class S3SAEastStorageDriver(S3StorageDriver): name = 'Amazon S3 (sa-east-1)' connectionCls = S3SAEastConnection ex_location_name = 'sa-east-1' region_name = 'sa-east-1' class S3CACentralConnection(S3SignatureV4Connection): host = S3_CA_CENTRAL_HOST class S3CACentralStorageDriver(S3StorageDriver): name = 'Amazon S3 (ca-central-1)' connectionCls = S3CACentralConnection ex_location_name = 'ca-central-1' region_name = 'ca-central-1' apache-libcloud-2.8.0/libcloud/storage/providers.py0000664000175000017500000001076213576514553022277 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.providers import get_driver as _get_provider_driver from libcloud.common.providers import set_driver as _set_provider_driver from libcloud.storage.types import OLD_CONSTANT_TO_NEW_MAPPING from libcloud.storage.types import Provider DRIVERS = { Provider.DUMMY: ('libcloud.storage.drivers.dummy', 'DummyStorageDriver'), Provider.CLOUDFILES: ('libcloud.storage.drivers.cloudfiles', 'CloudFilesStorageDriver'), Provider.OPENSTACK_SWIFT: ('libcloud.storage.drivers.cloudfiles', 'OpenStackSwiftStorageDriver'), Provider.S3: ('libcloud.storage.drivers.s3', 'S3StorageDriver'), Provider.S3_US_EAST2: ('libcloud.storage.drivers.s3', 'S3USEast2StorageDriver'), Provider.S3_US_WEST: ('libcloud.storage.drivers.s3', 'S3USWestStorageDriver'), Provider.S3_US_WEST_OREGON: ('libcloud.storage.drivers.s3', 'S3USWestOregonStorageDriver'), Provider.S3_US_GOV_WEST: ('libcloud.storage.drivers.s3', 'S3USGovWestStorageDriver'), Provider.S3_CN_NORTH: ('libcloud.storage.drivers.s3', 'S3CNNorthStorageDriver'), Provider.S3_CN_NORTHWEST: ('libcloud.storage.drivers.s3', 'S3CNNorthWestStorageDriver'), Provider.S3_EU_WEST: ('libcloud.storage.drivers.s3', 'S3EUWestStorageDriver'), Provider.S3_EU_WEST2: ('libcloud.storage.drivers.s3', 'S3EUWest2StorageDriver'), Provider.S3_EU_CENTRAL: ('libcloud.storage.drivers.s3', 'S3EUCentralStorageDriver'), Provider.S3_EU_NORTH1: ('libcloud.storage.drivers.s3', 'S3EUNorth1StorageDriver'), Provider.S3_AP_SOUTH: ('libcloud.storage.drivers.s3', 'S3APSouthStorageDriver'), Provider.S3_AP_SOUTHEAST: ('libcloud.storage.drivers.s3', 'S3APSEStorageDriver'), Provider.S3_AP_SOUTHEAST2: ('libcloud.storage.drivers.s3', 'S3APSE2StorageDriver'), Provider.S3_AP_NORTHEAST: ('libcloud.storage.drivers.s3', 'S3APNE1StorageDriver'), Provider.S3_AP_NORTHEAST1: ('libcloud.storage.drivers.s3', 'S3APNE1StorageDriver'), Provider.S3_AP_NORTHEAST2: ('libcloud.storage.drivers.s3', 'S3APNE2StorageDriver'), Provider.S3_SA_EAST: ('libcloud.storage.drivers.s3', 'S3SAEastStorageDriver'), Provider.S3_CA_CENTRAL: ('libcloud.storage.drivers.s3', 'S3CACentralStorageDriver'), Provider.S3_RGW: ('libcloud.storage.drivers.rgw', 'S3RGWStorageDriver'), Provider.S3_RGW_OUTSCALE: ('libcloud.storage.drivers.rgw', 'S3RGWOutscaleStorageDriver'), Provider.NINEFOLD: ('libcloud.storage.drivers.ninefold', 'NinefoldStorageDriver'), Provider.GOOGLE_STORAGE: ('libcloud.storage.drivers.google_storage', 'GoogleStorageDriver'), Provider.NIMBUS: ('libcloud.storage.drivers.nimbus', 'NimbusStorageDriver'), Provider.LOCAL: ('libcloud.storage.drivers.local', 'LocalStorageDriver'), Provider.AZURE_BLOBS: ('libcloud.storage.drivers.azure_blobs', 'AzureBlobsStorageDriver'), Provider.KTUCLOUD: ('libcloud.storage.drivers.ktucloud', 'KTUCloudStorageDriver'), Provider.AURORAOBJECTS: ('libcloud.storage.drivers.auroraobjects', 'AuroraObjectsStorageDriver'), Provider.BACKBLAZE_B2: ('libcloud.storage.drivers.backblaze_b2', 'BackblazeB2StorageDriver'), Provider.ALIYUN_OSS: ('libcloud.storage.drivers.oss', 'OSSStorageDriver'), Provider.DIGITALOCEAN_SPACES: ('libcloud.storage.drivers.digitalocean_spaces', 'DigitalOceanSpacesStorageDriver'), } def get_driver(provider): deprecated_constants = OLD_CONSTANT_TO_NEW_MAPPING return _get_provider_driver(drivers=DRIVERS, provider=provider, deprecated_constants=deprecated_constants) def set_driver(provider, module, klass): return _set_provider_driver(drivers=DRIVERS, provider=provider, module=module, klass=klass) apache-libcloud-2.8.0/libcloud/storage/types.py0000664000175000017500000001363713576514553021432 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.common.types import LibcloudError __all__ = [ 'Provider', 'ContainerError', 'ObjectError', 'ContainerAlreadyExistsError', 'ContainerDoesNotExistError', 'ContainerIsNotEmptyError', 'ObjectDoesNotExistError', 'ObjectHashMismatchError', 'InvalidContainerNameError', 'OLD_CONSTANT_TO_NEW_MAPPING' ] class Provider(object): """ Defines for each of the supported providers Non-Dummy drivers are sorted in alphabetical order. Please preserve this ordering when adding new drivers. :cvar DUMMY: Example provider :cvar ALIYUN_OSS: Aliyun OSS storage driver :cvar AURORAOBJECTS: AuroraObjects storage driver :cvar AZURE_BLOBS: Azure Blob Storage driver :cvar BACKBLAZE_B2: Backblaze B2 Cloud Storage driver :cvar CLOUDFILES: CloudFiles :cvar DIGITALOCEAN_SPACES: Digital Ocean Spaces driver :cvar GOOGLE_STORAGE Google Storage :cvar KTUCLOUD: KT UCloud Storage driver :cvar LOCAL: Local storage driver :cvar NIMBUS: Nimbus.io driver :cvar NINEFOLD: Ninefold :cvar OPENSTACK_SWIFT: OpenStack Swift driver :cvar S3: Amazon S3 US :cvar S3_AP_NORTHEAST: Amazon S3 Asia North East (Tokyo) :cvar S3_AP_NORTHEAST1: Amazon S3 Asia North East (Tokyo) :cvar S3_AP_NORTHEAST2: Amazon S3 Asia North East (Seoul) :cvar S3_AP_SOUTH: Amazon S3 Asia South (Mumbai) :cvar S3_AP_SOUTHEAST: Amazon S3 Asia South East (Singapore) :cvar S3_AP_SOUTHEAST2: Amazon S3 Asia South East 2 (Sydney) :cvar S3_CA_CENTRAL: Amazon S3 Canada (Central) :cvar S3_CN_NORTH: Amazon S3 CN North (Beijing) :cvar S3_EU_WEST: Amazon S3 EU West (Ireland) :cvar S3_EU_WEST2: Amazon S3 EU West 2 (London) :cvar S3_EU_CENTRAL: Amazon S3 EU Central (Frankfurt) :cvar S3_EU_NORTH1: Amazon S3 EU North 1 (Stockholm) :cvar S3_SA_EAST: Amazon S3 South America East (Sao Paulo) :cvar S3_US_EAST2: Amazon S3 US East 2 (Ohio) :cvar S3_US_WEST: Amazon S3 US West (Northern California) :cvar S3_US_WEST_OREGON: Amazon S3 US West 2 (Oregon) :cvar S3_US_GOV_WEST: Amazon S3 GovCloud (US) :cvar S3_RGW: S3 RGW :cvar S3_RGW_OUTSCALE: OUTSCALE S3 RGW """ DUMMY = 'dummy' ALIYUN_OSS = 'aliyun_oss' AURORAOBJECTS = 'auroraobjects' AZURE_BLOBS = 'azure_blobs' BACKBLAZE_B2 = 'backblaze_b2' CLOUDFILES = 'cloudfiles' DIGITALOCEAN_SPACES = 'digitalocean_spaces' GOOGLE_STORAGE = 'google_storage' KTUCLOUD = 'ktucloud' LOCAL = 'local' NIMBUS = 'nimbus' NINEFOLD = 'ninefold' OPENSTACK_SWIFT = 'openstack_swift' S3 = 's3' S3_AP_NORTHEAST = 's3_ap_northeast' S3_AP_NORTHEAST1 = 's3_ap_northeast_1' S3_AP_NORTHEAST2 = 's3_ap_northeast_2' S3_AP_SOUTH = 's3_ap_south' S3_AP_SOUTHEAST = 's3_ap_southeast' S3_AP_SOUTHEAST2 = 's3_ap_southeast2' S3_CA_CENTRAL = 's3_ca_central' S3_CN_NORTH = 's3_cn_north' S3_CN_NORTHWEST = 's3_cn_northwest' S3_EU_WEST = 's3_eu_west' S3_EU_WEST2 = 's3_eu_west_2' S3_EU_CENTRAL = 's3_eu_central' S3_EU_NORTH1 = 's3_eu_north_1' S3_SA_EAST = 's3_sa_east' S3_US_EAST2 = 's3_us_east_2' S3_US_WEST = 's3_us_west' S3_US_WEST_OREGON = 's3_us_west_oregon' S3_US_GOV_WEST = 's3_us_gov_west' S3_RGW = 's3_rgw' S3_RGW_OUTSCALE = 's3_rgw_outscale' # Deperecated CLOUDFILES_US = 'cloudfiles_us' CLOUDFILES_UK = 'cloudfiles_uk' CLOUDFILES_SWIFT = 'cloudfiles_swift' OLD_CONSTANT_TO_NEW_MAPPING = { # CloudFiles Provider.CLOUDFILES_US: Provider.CLOUDFILES, Provider.CLOUDFILES_UK: Provider.CLOUDFILES_UK, Provider.CLOUDFILES_SWIFT: Provider.OPENSTACK_SWIFT } class ContainerError(LibcloudError): error_type = 'ContainerError' def __init__(self, value, driver, container_name): self.container_name = container_name super(ContainerError, self).__init__(value=value, driver=driver) def __str__(self): return ('<%s in %s, container=%s, value=%s>' % (self.error_type, repr(self.driver), self.container_name, self.value)) class ObjectError(LibcloudError): error_type = 'ContainerError' def __init__(self, value, driver, object_name): self.object_name = object_name super(ObjectError, self).__init__(value=value, driver=driver) def __str__(self): return self.__repr__() def __repr__(self): return '<%s in %s, value=%s, object = %s>' % (self.error_type, repr(self.driver), self.value, self.object_name) class ContainerAlreadyExistsError(ContainerError): error_type = 'ContainerAlreadyExistsError' class ContainerDoesNotExistError(ContainerError): error_type = 'ContainerDoesNotExistError' class ContainerIsNotEmptyError(ContainerError): error_type = 'ContainerIsNotEmptyError' class ObjectDoesNotExistError(ObjectError): error_type = 'ObjectDoesNotExistError' class ObjectHashMismatchError(ObjectError): error_type = 'ObjectHashMismatchError' class InvalidContainerNameError(ContainerError): error_type = 'InvalidContainerNameError' apache-libcloud-2.8.0/libcloud/test/0000775000175000017500000000000013600223624017175 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/__init__.py0000664000175000017500000002060513535474530021324 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import random import requests from libcloud.common.base import Response from libcloud.http import LibcloudConnection from libcloud.utils.py3 import PY2 if PY2: from StringIO import StringIO else: from io import StringIO import requests_mock from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qs from libcloud.utils.py3 import parse_qsl from libcloud.utils.py3 import urlquote XML_HEADERS = {'content-type': 'application/xml'} class LibcloudTestCase(unittest.TestCase): def __init__(self, *args, **kwargs): self._visited_urls = [] self._executed_mock_methods = [] super(LibcloudTestCase, self).__init__(*args, **kwargs) def setUp(self): self._visited_urls = [] self._executed_mock_methods = [] def _add_visited_url(self, url): self._visited_urls.append(url) def _add_executed_mock_method(self, method_name): self._executed_mock_methods.append(method_name) def assertExecutedMethodCount(self, expected): actual = len(self._executed_mock_methods) self.assertEqual(actual, expected, 'expected %d, but %d mock methods were executed' % (expected, actual)) class multipleresponse(object): """ A decorator that allows MockHttp objects to return multi responses """ count = 0 func = None def __init__(self, f): self.func = f def __call__(self, *args, **kwargs): ret = self.func(self.func.__class__, *args, **kwargs) response = ret[self.count] self.count = self.count + 1 return response class BodyStream(StringIO): def next(self, chunk_size=None): return StringIO.next(self) def __next__(self, chunk_size=None): return StringIO.__next__(self) def read(self, chunk_size=None): return StringIO.read(self) class MockHttp(LibcloudConnection): """ A mock HTTP client/server suitable for testing purposes. This replaces `HTTPConnection` by implementing its API and returning a mock response. Define methods by request path, replacing slashes (/) with underscores (_). Each of these mock methods should return a tuple of: (int status, str body, dict headers, str reason) """ type = None use_param = None # will use this param to namespace the request function test = None # TestCase instance which is using this mock proxy_url = None def __init__(self, *args, **kwargs): # Load assertion methods into the class, incase people want to assert # within a response if isinstance(self, unittest.TestCase): unittest.TestCase.__init__(self, '__init__') super(MockHttp, self).__init__(*args, **kwargs) def _get_request(self, method, url, body=None, headers=None): # Find a method we can use for this request parsed = urlparse.urlparse(url) _, _, path, _, query, _ = parsed qs = parse_qs(query) if path.endswith('/'): path = path[:-1] meth_name = self._get_method_name(type=self.type, use_param=self.use_param, qs=qs, path=path) meth = getattr(self, meth_name.replace('%', '_')) if self.test and isinstance(self.test, LibcloudTestCase): self.test._add_visited_url(url=url) self.test._add_executed_mock_method(method_name=meth_name) return meth(method, url, body, headers) def request(self, method, url, body=None, headers=None, raw=False, stream=False): headers = self._normalize_headers(headers=headers) r_status, r_body, r_headers, r_reason = self._get_request(method, url, body, headers) if r_body is None: r_body = '' # this is to catch any special chars e.g. ~ in the request. URL url = urlquote(url) with requests_mock.mock() as m: m.register_uri(method, url, text=r_body, reason=r_reason, headers=r_headers, status_code=r_status) try: super(MockHttp, self).request( method=method, url=url, body=body, headers=headers, raw=raw, stream=stream) except requests_mock.exceptions.NoMockAddress as nma: raise AttributeError("Failed to mock out URL {0} - {1}".format( url, nma.request.url )) def prepared_request(self, method, url, body=None, headers=None, raw=False, stream=False): headers = self._normalize_headers(headers=headers) r_status, r_body, r_headers, r_reason = self._get_request(method, url, body, headers) with requests_mock.mock() as m: m.register_uri(method, url, text=r_body, reason=r_reason, headers=r_headers, status_code=r_status) super(MockHttp, self).prepared_request( method=method, url=url, body=body, headers=headers, raw=raw, stream=stream) # Mock request/response example def _example(self, method, url, body, headers): """ Return a simple message and header, regardless of input. """ return (httplib.OK, 'Hello World!', {'X-Foo': 'libcloud'}, httplib.responses[httplib.OK]) def _example_fail(self, method, url, body, headers): return (httplib.FORBIDDEN, 'Oh Noes!', {'X-Foo': 'fail'}, httplib.responses[httplib.FORBIDDEN]) def _get_method_name(self, type, use_param, qs, path): path = path.split('?')[0] meth_name = ( path .replace('/', '_') .replace('.', '_') .replace('-', '_') .replace('~', '%7E')) # Python 3.7 no longer quotes ~ if type: meth_name = '%s_%s' % (meth_name, self.type) if use_param and use_param in qs: param = qs[use_param][0].replace('.', '_').replace('-', '_') meth_name = '%s_%s' % (meth_name, param) if meth_name == '': meth_name = 'root' return meth_name def assertUrlContainsQueryParams(self, url, expected_params, strict=False): """ Assert that provided url contains provided query parameters. :param url: URL to assert. :type url: ``str`` :param expected_params: Dictionary of expected query parameters. :type expected_params: ``dict`` :param strict: Assert that provided url contains only expected_params. (defaults to ``False``) :type strict: ``bool`` """ question_mark_index = url.find('?') if question_mark_index != -1: url = url[question_mark_index + 1:] params = dict(parse_qsl(url)) if strict: assert params == expected_params else: for key, value in expected_params.items(): assert key in params assert params[key] == value class MockConnection(object): def __init__(self, action): self.action = action StorageMockHttp = MockHttp def make_response(status=200, headers={}, connection=None): response = requests.Response() response.status_code = status response.headers = headers return Response(response, connection) def generate_random_data(size): data = '' current_size = 0 while current_size < size: value = str(random.randint(0, 9)) value_size = len(value) data += value current_size += value_size return data if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/test/backup/0000775000175000017500000000000013600223624020442 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/backup/__init__.py0000664000175000017500000000262513535474530022573 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.backup.base import BackupTarget, BackupTargetType class TestCaseMixin(object): def get_supported_target_types(self): targets = self.driver.get_supported_target_types() self.assertTrue(isinstance(targets, list)) for target in targets: self.assertTrue(isinstance(target, BackupTargetType)) def test_list_targets_response(self): targets = self.driver.list_targets() self.assertTrue(isinstance(targets, list)) for target in targets: self.assertTrue(isinstance(target, BackupTarget)) if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/test/backup/fixtures/0000775000175000017500000000000013600223624022313 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/0000775000175000017500000000000013600223624025132 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_DISABLE.xml0000664000175000017500000000231413535474530030416 0ustar kamikami00000000000000 Disable Backup for Server SUCCESS Backup disabled for Server REASON_0 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_ENABLE.xml0000664000175000017500000000274713535474530030313 0ustar kamikami00000000000000 Enable Backup for Server SUCCESS Backup enabled for Server - see additional Information for Asset ID REASON_0 ee7c4b64-f7af-4a4f-8384-be362273530f apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_EXISTS.xml0000664000175000017500000000063413535474530030375 0ustar kamikami00000000000000 Enable Backup for Server ERROR Cloud backup for this server is already enabled or being enabled (state: NORMAL). REASON_550 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_INFO.xml0000664000175000017500000000402413535474530030106 0ustar kamikami00000000000000 Linux File Agent 12AM - 6AM 14 Day Storage Policy fake_email@example.com fake_email2@example.com 0 https://backups-na.cloud-vpn.net/PCS/BackupClientInstallerDownload/cbb8a8c607ca4144e8828814edfc1634c8dd8782 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_INFO_DISABLED.xml0000664000175000017500000000236013535474530031336 0ustar kamikami00000000000000 Get Backup Details ERROR Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup REASON_543 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_INFO_NOCLIENT.xml0000664000175000017500000000207213535474530031402 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_INFO_NOJOB.xml0000664000175000017500000000333613535474530031042 0ustar kamikami00000000000000 Linux File Agent 12AM - 6AM 14 Day Storage Policy 0 https://backups-na.cloud-vpn.net/PCS/BackupClientInstallerDownload/cbb8a8c607ca4144e8828814edfc1634c8dd8782 ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xmlapache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_30b1ff76_c76d_4d7c_0000664000175000017500000000226313535474530033056 0ustar kamikami00000000000000 Cancel Backup Job SUCCESS Backup Job Canceled REASON_0 ././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xmlapache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_30b1ff76_c76d_4d7c_0000664000175000017500000000231113535474530033050 0ustar kamikami00000000000000 Cancel Backup Job ERROR No backup job currently running on client REASON_547 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_SUCCESS_PUT.xml0000664000175000017500000000312313535474530032550 0ustar kamikami00000000000000 Add Backup Client SUCCESS Backup Client added REASON_0 a26cead0-6bab-4446-9a16-c227e6ab201f https://backups-na.cloud-vpn.net/PCS/BackupClientInstallerDownload/4b3f35815b848ce7270186b52e5817fa5de0fe42 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_schedulePolicy.xml0000664000175000017500000000047213535474530033670 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_storagePolicy.xml0000664000175000017500000000057013535474530033537 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_client_type.xml0000664000175000017500000000045513535474530031676 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_backup_modify.xml0000664000175000017500000000230413535474530030641 0ustar kamikami00000000000000 Change Backup Service Plan SUCCESS Backup Service Plan changed REASON_0 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_remove_backup_client.xml0000664000175000017500000000226313535474530032211 0ustar kamikami00000000000000 Disable Backup Client SUCCESS Backup Client disabled REASON_0 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/_remove_backup_client_FAIL.xml0000664000175000017500000000274413535474530033010 0ustar kamikami00000000000000 Disable Backup Client ERROR DISABLE_BACKUP_CLIENT 'didata-backup-test6[172-16-1-14]' - failed - Unexpected error occurred with NA9 Backup system at 2016-02-12 00:03:50.952, TransactionId: (9d483a7a-1cc9-441b-920c-e11fb0e94ba6), PCSOperation: DeprovisionBackupClient, Backup Client is currently performing another operation: Backup client is currently busy REASON_547 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/oec_0_9_myaccount.xml0000664000175000017500000000303413535474530031166 0ustar kamikami00000000000000 testuser Test User Test User test@example.com 8a8f6abc-2745-4d8a-9cbc-8dabe5a7d0e4 create image reports server primary administrator network apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/server_server.xml0000664000175000017500000000604113535474530030564 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/server_server_NOBACKUP.xml0000664000175000017500000000344513535474530032053 0ustar kamikami00000000000000 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xmlapache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/server_server_e75ead52_692f_4314_80000664000175000017500000000327213535474530032741 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE DEPLOY_SERVER 2015-12-02T11:07:40.000Z devuser1 ././@LongLink0000000000000000000000000000020100000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xmlapache-libcloud-2.8.0/libcloud/test/backup/fixtures/dimensiondata/server_server_e75ead52_692f_4314_80000664000175000017500000000327013535474530032737 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE DEPLOY_SERVER 2015-12-02T11:07:40.000Z devuser1 apache-libcloud-2.8.0/libcloud/test/backup/test_dimensiondata_v2_3.py0000664000175000017500000005660713535474530025554 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.utils.py3 import httplib from libcloud.utils.py3 import ET from libcloud.common.dimensiondata import DimensionDataAPIException from libcloud.common.types import InvalidCredsError from libcloud.backup.base import BackupTargetJob from libcloud.backup.drivers.dimensiondata import DimensionDataBackupDriver as DimensionData from libcloud.backup.drivers.dimensiondata import DEFAULT_BACKUP_PLAN from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import BackupFileFixtures from libcloud.test.secrets import DIMENSIONDATA_PARAMS class DimensionData_v2_3_Tests(unittest.TestCase): def setUp(self): DimensionData.connectionCls.active_api_version = '2.3' DimensionData.connectionCls.conn_class = DimensionDataMockHttp DimensionDataMockHttp.type = None self.driver = DimensionData(*DIMENSIONDATA_PARAMS) def test_invalid_region(self): with self.assertRaises(ValueError): self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah') def test_invalid_creds(self): DimensionDataMockHttp.type = 'UNAUTHORIZED' with self.assertRaises(InvalidCredsError): self.driver.list_targets() def test_list_targets(self): targets = self.driver.list_targets() self.assertEqual(len(targets), 2) self.assertEqual(targets[0].id, '5579f3a7-4c32-4cf5-8a7e-b45c36a35c10') self.assertEqual(targets[0].address, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(targets[0].extra['servicePlan'], 'Enterprise') def test_create_target(self): target = self.driver.create_target( 'name', 'e75ead52-692f-4314-8725-c8a4f4d13a87', extra={'servicePlan': 'Enterprise'}) self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f') self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(target.extra['servicePlan'], 'Enterprise') def test_create_target_DEFAULT(self): DimensionDataMockHttp.type = 'DEFAULT' target = self.driver.create_target( 'name', 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f') self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87') def test_create_target_EXISTS(self): DimensionDataMockHttp.type = 'EXISTS' with self.assertRaises(DimensionDataAPIException) as context: self.driver.create_target( 'name', 'e75ead52-692f-4314-8725-c8a4f4d13a87', extra={'servicePlan': 'Enterprise'}) self.assertEqual(context.exception.code, 'ERROR') self.assertEqual(context.exception.msg, 'Cloud backup for this server is already enabled or being enabled (state: NORMAL).') def test_update_target(self): target = self.driver.list_targets()[0] extra = {'servicePlan': 'Essentials'} new_target = self.driver.update_target(target, extra=extra) self.assertEqual(new_target.extra['servicePlan'], 'Essentials') def test_update_target_DEFAULT(self): DimensionDataMockHttp.type = 'DEFAULT' target = 'e75ead52-692f-4314-8725-c8a4f4d13a87' self.driver.update_target(target) def test_update_target_STR(self): target = 'e75ead52-692f-4314-8725-c8a4f4d13a87' extra = {'servicePlan': 'Essentials'} new_target = self.driver.update_target(target, extra=extra) self.assertEqual(new_target.extra['servicePlan'], 'Essentials') def test_delete_target(self): target = self.driver.list_targets()[0] self.assertTrue(self.driver.delete_target(target)) def test_ex_add_client_to_target(self): target = self.driver.list_targets()[0] client = self.driver.ex_list_available_client_types(target)[0] storage_policy = self.driver.ex_list_available_storage_policies(target)[0] schedule_policy = self.driver.ex_list_available_schedule_policies(target)[0] self.assertTrue( self.driver.ex_add_client_to_target(target, client, storage_policy, schedule_policy, 'ON_FAILURE', 'nobody@example.com') ) def test_ex_add_client_to_target_STR(self): self.assertTrue( self.driver.ex_add_client_to_target('e75ead52-692f-4314-8725-c8a4f4d13a87', 'FA.Linux', '14 Day Storage Policy', '12AM - 6AM', 'ON_FAILURE', 'nobody@example.com') ) def test_ex_get_backup_details_for_target(self): target = self.driver.list_targets()[0] response = self.driver.ex_get_backup_details_for_target(target) self.assertEqual(response.service_plan, 'Enterprise') client = response.clients[0] self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8') self.assertEqual(client.type.type, 'FA.Linux') self.assertEqual(client.running_job.progress, 5) self.assertTrue(isinstance(client.running_job, BackupTargetJob)) self.assertEqual(len(client.alert.notify_list), 2) self.assertTrue(isinstance(client.alert.notify_list, list)) def test_ex_get_backup_details_for_target_NOBACKUP(self): target = self.driver.list_targets()[0].address DimensionDataMockHttp.type = 'NOBACKUP' response = self.driver.ex_get_backup_details_for_target(target) self.assertTrue(response is None) def test_ex_cancel_target_job(self): target = self.driver.list_targets()[0] response = self.driver.ex_get_backup_details_for_target(target) client = response.clients[0] self.assertTrue(isinstance(client.running_job, BackupTargetJob)) success = client.running_job.cancel() self.assertTrue(success) def test_ex_cancel_target_job_with_extras(self): success = self.driver.cancel_target_job( None, ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8', ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87' ) self.assertTrue(success) def test_ex_cancel_target_job_FAIL(self): DimensionDataMockHttp.type = 'FAIL' with self.assertRaises(DimensionDataAPIException) as context: self.driver.cancel_target_job( None, ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8', ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87' ) self.assertEqual(context.exception.code, 'ERROR') """Test a backup info for a target that does not have a client""" def test_ex_get_backup_details_for_target_NO_CLIENT(self): DimensionDataMockHttp.type = 'NOCLIENT' response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(response.service_plan, 'Essentials') self.assertEqual(len(response.clients), 0) """Test a backup details that has a client, but no alerting or running jobs""" def test_ex_get_backup_details_for_target_NO_JOB_OR_ALERT(self): DimensionDataMockHttp.type = 'NOJOB' response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314_8725-c8a4f4d13a87') self.assertEqual(response.service_plan, 'Enterprise') self.assertTrue(isinstance(response.clients, list)) self.assertEqual(len(response.clients), 1) client = response.clients[0] self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8') self.assertEqual(client.type.type, 'FA.Linux') self.assertIsNone(client.running_job) self.assertIsNone(client.alert) """Test getting backup info for a server that doesn't exist""" def test_ex_get_backup_details_for_target_DISABLED(self): DimensionDataMockHttp.type = 'DISABLED' with self.assertRaises(DimensionDataAPIException) as context: self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(context.exception.code, 'ERROR') self.assertEqual(context.exception.msg, 'Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup') def test_ex_list_available_client_types(self): target = self.driver.list_targets()[0] answer = self.driver.ex_list_available_client_types(target) self.assertEqual(len(answer), 1) self.assertEqual(answer[0].type, 'FA.Linux') self.assertEqual(answer[0].is_file_system, True) self.assertEqual(answer[0].description, 'Linux File system') def test_ex_list_available_storage_policies(self): target = self.driver.list_targets()[0] answer = self.driver.ex_list_available_storage_policies(target) self.assertEqual(len(answer), 1) self.assertEqual(answer[0].name, '30 Day Storage Policy + Secondary Copy') self.assertEqual(answer[0].retention_period, 30) self.assertEqual(answer[0].secondary_location, 'Primary') def test_ex_list_available_schedule_policies(self): target = self.driver.list_targets()[0] answer = self.driver.ex_list_available_schedule_policies(target) self.assertEqual(len(answer), 1) self.assertEqual(answer[0].name, '12AM - 6AM') self.assertEqual(answer[0].description, 'Daily backup will start between 12AM - 6AM') def test_ex_remove_client_from_target(self): target = self.driver.list_targets()[0] client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0] self.assertTrue(self.driver.ex_remove_client_from_target(target, client)) def test_ex_remove_client_from_target_STR(self): self.assertTrue( self.driver.ex_remove_client_from_target( 'e75ead52-692f-4314-8725-c8a4f4d13a87', '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) ) def test_ex_remove_client_from_target_FAIL(self): DimensionDataMockHttp.type = 'FAIL' with self.assertRaises(DimensionDataAPIException) as context: self.driver.ex_remove_client_from_target( 'e75ead52-692f-4314-8725-c8a4f4d13a87', '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) self.assertEqual(context.exception.code, 'ERROR') self.assertTrue('Backup Client is currently performing another operation' in context.exception.msg) def test_priv_target_to_target_address(self): target = self.driver.list_targets()[0] self.assertEqual( self.driver._target_to_target_address(target), 'e75ead52-692f-4314-8725-c8a4f4d13a87' ) def test_priv_target_to_target_address_STR(self): self.assertEqual( self.driver._target_to_target_address('e75ead52-692f-4314-8725-c8a4f4d13a87'), 'e75ead52-692f-4314-8725-c8a4f4d13a87' ) def test_priv_target_to_target_address_TYPEERROR(self): with self.assertRaises(TypeError): self.driver._target_to_target_address([1, 2, 3]) def test_priv_client_to_client_id(self): client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0] self.assertEqual( self.driver._client_to_client_id(client), '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) def test_priv_client_to_client_id_STR(self): self.assertEqual( self.driver._client_to_client_id('30b1ff76-c76d-4d7c-b39d-3b72be0384c8'), '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) def test_priv_client_to_client_id_TYPEERROR(self): with self.assertRaises(TypeError): self.driver._client_to_client_id([1, 2, 3]) class InvalidRequestError(Exception): def __init__(self, tag): super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag) class DimensionDataMockHttp(MockHttp): fixtures = BackupFileFixtures('dimensiondata') def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_EXISTS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_DEFAULT(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_FAIL(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_NOCLIENT(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_DISABLED(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_NOJOB(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers): body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type(self, method, url, body, headers): body = self.fixtures.load( '_backup_client_type.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy( self, method, url, body, headers): body = self.fixtures.load( '_backup_client_storagePolicy.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy( self, method, url, body, headers): body = self.fixtures.load( '_backup_client_schedulePolicy.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client( self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( '_backup_client_SUCCESS_PUT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: raise ValueError("Unknown Method {0}".format(method)) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOCLIENT( self, method, url, body, headers): # only gets here are implemented # If we get any other method something has gone wrong assert(method == 'GET') body = self.fixtures.load( '_backup_INFO_NOCLIENT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLED( self, method, url, body, headers): # only gets here are implemented # If we get any other method something has gone wrong assert(method == 'GET') body = self.fixtures.load( '_backup_INFO_DISABLED.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOJOB( self, method, url, body, headers): # only gets here are implemented # If we get any other method something has gone wrong assert(method == 'GET') body = self.fixtures.load( '_backup_INFO_NOJOB.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DEFAULT( self, method, url, body, headers): if method != 'POST': raise InvalidRequestError('Only POST is accepted for this test') request = ET.fromstring(body) service_plan = request.get('servicePlan') if service_plan != DEFAULT_BACKUP_PLAN: raise InvalidRequestError('The default plan %s should have been passed in. Not %s' % (DEFAULT_BACKUP_PLAN, service_plan)) body = self.fixtures.load( '_backup_ENABLE.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup( self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( '_backup_ENABLE.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'GET': if url.endswith('disable'): body = self.fixtures.load( '_backup_DISABLE.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( '_backup_INFO.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: raise ValueError("Unknown Method {0}".format(method)) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP( self, method, url, body, headers): assert(method == 'GET') body = self.fixtures.load('server_server_NOBACKUP.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS( self, method, url, body, headers): # only POSTs are implemented # If we get any other method something has gone wrong assert(method == 'POST') body = self.fixtures.load( '_backup_EXISTS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify( self, method, url, body, headers): request = ET.fromstring(body) service_plan = request.get('servicePlan') if service_plan != 'Essentials': raise InvalidRequestError("Expected Essentials backup plan in request") body = self.fixtures.load('_backup_modify.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify_DEFAULT( self, method, url, body, headers): request = ET.fromstring(body) service_plan = request.get('servicePlan') if service_plan != DEFAULT_BACKUP_PLAN: raise InvalidRequestError("Expected % backup plan in test" % DEFAULT_BACKUP_PLAN) body = self.fixtures.load('_backup_modify.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8( self, method, url, body, headers): if url.endswith('disable'): body = self.fixtures.load( ('_remove_backup_client.xml') ) elif url.endswith('cancelJob'): body = self.fixtures.load( ('' '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml') ) else: raise ValueError("Unknown URL: %s" % url) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_FAIL( self, method, url, body, headers): if url.endswith('disable'): body = self.fixtures.load( ('_remove_backup_client_FAIL.xml') ) elif url.endswith('cancelJob'): body = self.fixtures.load( ('' '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml') ) else: raise ValueError("Unknown URL: %s" % url) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/backup/test_dimensiondata_v2_4.py0000664000175000017500000005757013535474530025555 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.utils.py3 import httplib from libcloud.utils.py3 import ET from libcloud.common.dimensiondata import DimensionDataAPIException from libcloud.common.types import InvalidCredsError from libcloud.backup.base import BackupTargetJob from libcloud.backup.drivers.dimensiondata import DimensionDataBackupDriver as DimensionData from libcloud.backup.drivers.dimensiondata import DEFAULT_BACKUP_PLAN from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import BackupFileFixtures from libcloud.test.secrets import DIMENSIONDATA_PARAMS class DimensionData_v2_4_Tests(unittest.TestCase): def setUp(self): DimensionData.connectionCls.active_api_version = '2.4' DimensionData.connectionCls.conn_class = DimensionDataMockHttp DimensionDataMockHttp.type = None self.driver = DimensionData(*DIMENSIONDATA_PARAMS) def test_invalid_region(self): with self.assertRaises(ValueError): self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah') def test_invalid_creds(self): DimensionDataMockHttp.type = 'UNAUTHORIZED' with self.assertRaises(InvalidCredsError): self.driver.list_targets() def test_list_targets(self): targets = self.driver.list_targets() self.assertEqual(len(targets), 2) self.assertEqual(targets[0].id, '5579f3a7-4c32-4cf5-8a7e-b45c36a35c10') self.assertEqual(targets[0].address, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(targets[0].extra['servicePlan'], 'Enterprise') def test_create_target(self): target = self.driver.create_target( 'name', 'e75ead52-692f-4314-8725-c8a4f4d13a87', extra={'servicePlan': 'Enterprise'}) self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f') self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(target.extra['servicePlan'], 'Enterprise') def test_create_target_DEFAULT(self): DimensionDataMockHttp.type = 'DEFAULT' target = self.driver.create_target( 'name', 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f') self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87') def test_create_target_EXISTS(self): DimensionDataMockHttp.type = 'EXISTS' with self.assertRaises(DimensionDataAPIException) as context: self.driver.create_target( 'name', 'e75ead52-692f-4314-8725-c8a4f4d13a87', extra={'servicePlan': 'Enterprise'}) self.assertEqual(context.exception.code, 'ERROR') self.assertEqual(context.exception.msg, 'Cloud backup for this server is already enabled or being enabled (state: NORMAL).') def test_update_target(self): target = self.driver.list_targets()[0] extra = {'servicePlan': 'Essentials'} new_target = self.driver.update_target(target, extra=extra) self.assertEqual(new_target.extra['servicePlan'], 'Essentials') def test_update_target_DEFAULT(self): DimensionDataMockHttp.type = 'DEFAULT' target = 'e75ead52-692f-4314-8725-c8a4f4d13a87' self.driver.update_target(target) def test_update_target_STR(self): target = 'e75ead52-692f-4314-8725-c8a4f4d13a87' extra = {'servicePlan': 'Essentials'} new_target = self.driver.update_target(target, extra=extra) self.assertEqual(new_target.extra['servicePlan'], 'Essentials') def test_delete_target(self): target = self.driver.list_targets()[0] self.assertTrue(self.driver.delete_target(target)) def test_ex_add_client_to_target(self): target = self.driver.list_targets()[0] client = self.driver.ex_list_available_client_types(target)[0] storage_policy = self.driver.ex_list_available_storage_policies(target)[0] schedule_policy = self.driver.ex_list_available_schedule_policies(target)[0] self.assertTrue( self.driver.ex_add_client_to_target(target, client, storage_policy, schedule_policy, 'ON_FAILURE', 'nobody@example.com') ) def test_ex_add_client_to_target_STR(self): self.assertTrue( self.driver.ex_add_client_to_target('e75ead52-692f-4314-8725-c8a4f4d13a87', 'FA.Linux', '14 Day Storage Policy', '12AM - 6AM', 'ON_FAILURE', 'nobody@example.com') ) def test_ex_get_backup_details_for_target(self): target = self.driver.list_targets()[0] response = self.driver.ex_get_backup_details_for_target(target) self.assertEqual(response.service_plan, 'Enterprise') client = response.clients[0] self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8') self.assertEqual(client.type.type, 'FA.Linux') self.assertEqual(client.running_job.progress, 5) self.assertTrue(isinstance(client.running_job, BackupTargetJob)) self.assertEqual(len(client.alert.notify_list), 2) self.assertTrue(isinstance(client.alert.notify_list, list)) def test_ex_get_backup_details_for_target_NOBACKUP(self): target = self.driver.list_targets()[0].address DimensionDataMockHttp.type = 'NOBACKUP' response = self.driver.ex_get_backup_details_for_target(target) self.assertTrue(response is None) def test_ex_cancel_target_job(self): target = self.driver.list_targets()[0] response = self.driver.ex_get_backup_details_for_target(target) client = response.clients[0] self.assertTrue(isinstance(client.running_job, BackupTargetJob)) success = client.running_job.cancel() self.assertTrue(success) def test_ex_cancel_target_job_with_extras(self): success = self.driver.cancel_target_job( None, ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8', ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87' ) self.assertTrue(success) def test_ex_cancel_target_job_FAIL(self): DimensionDataMockHttp.type = 'FAIL' with self.assertRaises(DimensionDataAPIException) as context: self.driver.cancel_target_job( None, ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8', ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87' ) self.assertEqual(context.exception.code, 'ERROR') """Test a backup info for a target that does not have a client""" def test_ex_get_backup_details_for_target_NO_CLIENT(self): DimensionDataMockHttp.type = 'NOCLIENT' response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(response.service_plan, 'Essentials') self.assertEqual(len(response.clients), 0) """Test a backup details that has a client, but no alerting or running jobs""" def test_ex_get_backup_details_for_target_NO_JOB_OR_ALERT(self): DimensionDataMockHttp.type = 'NOJOB' response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314_8725-c8a4f4d13a87') self.assertEqual(response.service_plan, 'Enterprise') self.assertTrue(isinstance(response.clients, list)) self.assertEqual(len(response.clients), 1) client = response.clients[0] self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8') self.assertEqual(client.type.type, 'FA.Linux') self.assertIsNone(client.running_job) self.assertIsNone(client.alert) """Test getting backup info for a server that doesn't exist""" def test_ex_get_backup_details_for_target_DISABLED(self): DimensionDataMockHttp.type = 'DISABLED' with self.assertRaises(DimensionDataAPIException) as context: self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(context.exception.code, 'ERROR') self.assertEqual(context.exception.msg, 'Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup') def test_ex_list_available_client_types(self): target = self.driver.list_targets()[0] answer = self.driver.ex_list_available_client_types(target) self.assertEqual(len(answer), 1) self.assertEqual(answer[0].type, 'FA.Linux') self.assertEqual(answer[0].is_file_system, True) self.assertEqual(answer[0].description, 'Linux File system') def test_ex_list_available_storage_policies(self): target = self.driver.list_targets()[0] answer = self.driver.ex_list_available_storage_policies(target) self.assertEqual(len(answer), 1) self.assertEqual(answer[0].name, '30 Day Storage Policy + Secondary Copy') self.assertEqual(answer[0].retention_period, 30) self.assertEqual(answer[0].secondary_location, 'Primary') def test_ex_list_available_schedule_policies(self): target = self.driver.list_targets()[0] answer = self.driver.ex_list_available_schedule_policies(target) self.assertEqual(len(answer), 1) self.assertEqual(answer[0].name, '12AM - 6AM') self.assertEqual(answer[0].description, 'Daily backup will start between 12AM - 6AM') def test_ex_remove_client_from_target(self): target = self.driver.list_targets()[0] client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0] self.assertTrue(self.driver.ex_remove_client_from_target(target, client)) def test_ex_remove_client_from_target_STR(self): self.assertTrue( self.driver.ex_remove_client_from_target( 'e75ead52-692f-4314-8725-c8a4f4d13a87', '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) ) def test_ex_remove_client_from_target_FAIL(self): DimensionDataMockHttp.type = 'FAIL' with self.assertRaises(DimensionDataAPIException) as context: self.driver.ex_remove_client_from_target( 'e75ead52-692f-4314-8725-c8a4f4d13a87', '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) self.assertEqual(context.exception.code, 'ERROR') self.assertTrue('Backup Client is currently performing another operation' in context.exception.msg) def test_priv_target_to_target_address(self): target = self.driver.list_targets()[0] self.assertEqual( self.driver._target_to_target_address(target), 'e75ead52-692f-4314-8725-c8a4f4d13a87' ) def test_priv_target_to_target_address_STR(self): self.assertEqual( self.driver._target_to_target_address('e75ead52-692f-4314-8725-c8a4f4d13a87'), 'e75ead52-692f-4314-8725-c8a4f4d13a87' ) def test_priv_target_to_target_address_TYPEERROR(self): with self.assertRaises(TypeError): self.driver._target_to_target_address([1, 2, 3]) def test_priv_client_to_client_id(self): client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0] self.assertEqual( self.driver._client_to_client_id(client), '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) def test_priv_client_to_client_id_STR(self): self.assertEqual( self.driver._client_to_client_id('30b1ff76-c76d-4d7c-b39d-3b72be0384c8'), '30b1ff76-c76d-4d7c-b39d-3b72be0384c8' ) def test_priv_client_to_client_id_TYPEERROR(self): with self.assertRaises(TypeError): self.driver._client_to_client_id([1, 2, 3]) class InvalidRequestError(Exception): def __init__(self, tag): super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag) class DimensionDataMockHttp(MockHttp): fixtures = BackupFileFixtures('dimensiondata') def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_EXISTS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_DEFAULT(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_FAIL(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_NOCLIENT(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_DISABLED(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_NOJOB(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers): body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type(self, method, url, body, headers): body = self.fixtures.load( '_backup_client_type.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy( self, method, url, body, headers): body = self.fixtures.load( '_backup_client_storagePolicy.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy( self, method, url, body, headers): body = self.fixtures.load( '_backup_client_schedulePolicy.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client( self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( '_backup_client_SUCCESS_PUT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: raise ValueError("Unknown Method {0}".format(method)) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOCLIENT( self, method, url, body, headers): # only gets here are implemented # If we get any other method something has gone wrong assert(method == 'GET') body = self.fixtures.load( '_backup_INFO_NOCLIENT.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLED( self, method, url, body, headers): # only gets here are implemented # If we get any other method something has gone wrong assert(method == 'GET') body = self.fixtures.load( '_backup_INFO_DISABLED.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOJOB( self, method, url, body, headers): # only gets here are implemented # If we get any other method something has gone wrong assert(method == 'GET') body = self.fixtures.load( '_backup_INFO_NOJOB.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DEFAULT( self, method, url, body, headers): if method != 'POST': raise InvalidRequestError('Only POST is accepted for this test') request = ET.fromstring(body) service_plan = request.get('servicePlan') if service_plan != DEFAULT_BACKUP_PLAN: raise InvalidRequestError('The default plan %s should have been passed in. Not %s' % (DEFAULT_BACKUP_PLAN, service_plan)) body = self.fixtures.load( '_backup_ENABLE.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup( self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( '_backup_ENABLE.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'GET': if url.endswith('disable'): body = self.fixtures.load( '_backup_DISABLE.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( '_backup_INFO.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: raise ValueError("Unknown Method {0}".format(method)) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP( self, method, url, body, headers): assert(method == 'GET') body = self.fixtures.load('server_server_NOBACKUP.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS( self, method, url, body, headers): # only POSTs are implemented # If we get any other method something has gone wrong assert(method == 'POST') body = self.fixtures.load( '_backup_EXISTS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify( self, method, url, body, headers): request = ET.fromstring(body) service_plan = request.get('servicePlan') if service_plan != 'Essentials': raise InvalidRequestError("Expected Essentials backup plan in request") body = self.fixtures.load('_backup_modify.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify_DEFAULT( self, method, url, body, headers): request = ET.fromstring(body) service_plan = request.get('servicePlan') if service_plan != DEFAULT_BACKUP_PLAN: raise InvalidRequestError("Expected % backup plan in test" % DEFAULT_BACKUP_PLAN) body = self.fixtures.load('_backup_modify.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8( self, method, url, body, headers): if url.endswith('disable'): body = self.fixtures.load( ('_remove_backup_client.xml') ) elif url.endswith('cancelJob'): body = self.fixtures.load( ('' '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml') ) else: raise ValueError("Unknown URL: %s" % url) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_FAIL( self, method, url, body, headers): if url.endswith('disable'): body = self.fixtures.load( ('_remove_backup_client_FAIL.xml') ) elif url.endswith('cancelJob'): body = self.fixtures.load( ('' '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml') ) else: raise ValueError("Unknown URL: %s" % url) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/0000775000175000017500000000000013600223624020465 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/common/__init__.py0000664000175000017500000000141513535474530022612 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. apache-libcloud-2.8.0/libcloud/test/common/fixtures/0000775000175000017500000000000013600223624022336 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/0000775000175000017500000000000013600223624024761 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670.json0000664000175000017500000000017113535474530030732 0ustar kamikami00000000000000{"status":"OK","event":{"id":12345670,"event_type_id":1,"percentage":"100","droplet_id":1234560,"action_status":"done"}} ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670_UNAUTHORIZED.jsonapache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670_UNAUTHORIZED.js0000664000175000017500000000011513535474530032374 0ustar kamikami00000000000000{"status":"ERROR","error_message":"Access Denied","message":"Access Denied"} apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v2_account.json0000664000175000017500000000020213535474530030063 0ustar kamikami00000000000000{"account":{"droplet_limit":10,"email":"user@domain.tld","uuid":"a1234567890b1234567890c1234567890d12345","email_verified":true}} apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v2_account_UNAUTHORIZED.json0000664000175000017500000000007613535474530032075 0ustar kamikami00000000000000{"id":"unauthorized","message":"Unable to authenticate you."} apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v2_actions.json0000664000175000017500000000005513535474530030075 0ustar kamikami00000000000000{"actions":[],"links":{},"meta":{"total":0}} apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v2_actions_12345670.json0000664000175000017500000000063413535474530031073 0ustar kamikami00000000000000{"action":{"id":12345670,"status":"completed","type":"power_on","started_at":"2015-03-28T10:57:40Z","completed_at":"2015-03-28T10:57:42Z","resource_id":1234560,"resource_type":"droplet","region":{"name":"New York 3","slug":"nyc3","sizes":["512mb","1gb","2gb","4gb","8gb","16gb","32gb","48gb","64gb"],"features":["virtio","private_networking","backups","ipv6","metadata"],"available":true},"region_slug":"nyc3"}} apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_1.json0000664000175000017500000000106713535474530031315 0ustar kamikami00000000000000{"actions":[{"id":12345671,"status":"completed","type":"create","started_at":"2015-04-10T14:09:37Z","completed_at":"2015-04-10T14:10:03Z","resource_id":1234561,"resource_type":"droplet","region":{"name":"Frankfurt 1","slug":"fra1","sizes":["512mb","1gb","2gb","4gb","8gb","16gb","32gb","48gb","64gb"],"features":["virtio","private_networking","backups","ipv6","metadata"],"available":true},"region_slug":"fra1"}],"links":{"pages":{"last":"https://api.digitalocean.com/v2/actions/?page=2","next":"https://api.digitalocean.com/v2/actions/?page=2"}},"meta":{"total":2}} apache-libcloud-2.8.0/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_2.json0000664000175000017500000000107013535474530031310 0ustar kamikami00000000000000{"actions":[{"id":12345670,"status":"completed","type":"create","started_at":"2015-04-10T14:09:12Z","completed_at":"2015-04-10T14:09:38Z","resource_id":1234560,"resource_type":"droplet","region":{"name":"Frankfurt 1","slug":"fra1","sizes":["512mb","1gb","2gb","4gb","8gb","16gb","32gb","48gb","64gb"],"features":["virtio","private_networking","backups","ipv6","metadata"],"available":true},"region_slug":"fra1"}],"links":{"pages":{"first":"https://api.digitalocean.com/v2/actions/?page=1","prev":"https://api.digitalocean.com/v2/actions/?page=1"}},"meta":{"total":2}} apache-libcloud-2.8.0/libcloud/test/common/fixtures/google/0000775000175000017500000000000013600223624023612 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/common/fixtures/google/pkey.json0000664000175000017500000000220613535474530025470 0ustar kamikami00000000000000{ "private_key_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "private_key": "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n", "client_email": "foo@developer.gserviceaccount.com", "client_id": "foo.apps.googleusercontent.com", "type": "service_account" } apache-libcloud-2.8.0/libcloud/test/common/fixtures/google/pkey.pem0000664000175000017500000000156713535474530025311 0ustar kamikami00000000000000-----BEGIN RSA PRIVATE KEY----- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -----END RSA PRIVATE KEY----- apache-libcloud-2.8.0/libcloud/test/common/test_aliyun.py0000664000175000017500000000415513535474530023417 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.common import aliyun from libcloud.common.aliyun import AliyunRequestSignerAlgorithmV1_0 from libcloud.test import LibcloudTestCase class AliyunRequestSignerAlgorithmV1_0TestCase(LibcloudTestCase): def setUp(self): self.signer = AliyunRequestSignerAlgorithmV1_0('testid', 'testsecret', '1.0') def test_sign_request(self): params = {'TimeStamp': '2012-12-26T10:33:56Z', 'Format': 'XML', 'AccessKeyId': 'testid', 'Action': 'DescribeRegions', 'SignatureMethod': 'HMAC-SHA1', 'RegionId': 'region1', 'SignatureNonce': 'NwDAxvLU6tFE0DVb', 'Version': '2014-05-26', 'SignatureVersion': '1.0'} method = 'GET' path = '/' expected = 'K9fCVP6Jrklpd3rLYKh1pfrrFNo=' self.assertEqual(expected, self.signer._sign_request(params, method, path)) class AliyunCommonTestCase(LibcloudTestCase): def test_percent_encode(self): data = { 'abc': 'abc', ' *~': '%20%2A~' } for key in data: self.assertEqual(data[key], aliyun._percent_encode(key)) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_aws.py0000664000175000017500000003222613535474530022710 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from datetime import datetime import mock from libcloud.common.aws import AWSRequestSignerAlgorithmV4 from libcloud.common.aws import SignedAWSConnection from libcloud.common.aws import UNSIGNED_PAYLOAD from libcloud.test import LibcloudTestCase class EC2MockDriver(object): region_name = 'my_region' class AWSRequestSignerAlgorithmV4TestCase(LibcloudTestCase): def setUp(self): SignedAWSConnection.driver = EC2MockDriver() SignedAWSConnection.service_name = 'my_service' SignedAWSConnection.version = '2013-10-15' self.connection = SignedAWSConnection('my_key', 'my_secret') self.signer = AWSRequestSignerAlgorithmV4(access_key='my_key', access_secret='my_secret', version='2013-10-15', connection=self.connection) SignedAWSConnection.action = '/my_action/' SignedAWSConnection.driver = EC2MockDriver() self.now = datetime(2015, 3, 4, hour=17, minute=34, second=52) def test_v4_signature(self): params = { 'Action': 'DescribeInstances', 'Version': '2013-10-15' } headers = { 'Host': 'ec2.eu-west-1.amazonaws.com', 'Accept-Encoding': 'gzip,deflate', 'X-AMZ-Date': '20150304T173452Z', 'User-Agent': 'libcloud/0.17.0 (Amazon EC2 (eu-central-1)) ' } dt = self.now sig = self.signer._get_authorization_v4_header(params=params, headers=headers, dt=dt, method='GET', path='/my_action/') self.assertEqual(sig, 'AWS4-HMAC-SHA256 ' 'Credential=my_key/20150304/my_region/my_service/aws4_request, ' 'SignedHeaders=accept-encoding;host;user-agent;x-amz-date, ' 'Signature=f9868f8414b3c3f856c7955019cc1691265541f5162b9b772d26044280d39bd3') def test_v4_signature_contains_user_id(self): sig = self.signer._get_authorization_v4_header(params={}, headers={}, dt=self.now) self.assertIn('Credential=my_key/', sig) def test_v4_signature_contains_credential_scope(self): with mock.patch('libcloud.common.aws.AWSRequestSignerAlgorithmV4._get_credential_scope') as mock_get_creds: mock_get_creds.return_value = 'my_credential_scope' sig = self.signer._get_authorization_v4_header(params={}, headers={}, dt=self.now) self.assertIn('Credential=my_key/my_credential_scope, ', sig) def test_v4_signature_contains_signed_headers(self): with mock.patch('libcloud.common.aws.AWSRequestSignerAlgorithmV4._get_signed_headers') as mock_get_headers: mock_get_headers.return_value = 'my_signed_headers' sig = self.signer._get_authorization_v4_header({}, {}, self.now, method='GET', path='/') self.assertIn('SignedHeaders=my_signed_headers, ', sig) def test_v4_signature_contains_signature(self): with mock.patch('libcloud.common.aws.AWSRequestSignerAlgorithmV4._get_signature') as mock_get_signature: mock_get_signature.return_value = 'my_signature' sig = self.signer._get_authorization_v4_header({}, {}, self.now) self.assertIn('Signature=my_signature', sig) def test_get_signature_(self): def _sign(key, msg, hex=False): if hex: return 'H|%s|%s' % (key, msg) else: return '%s|%s' % (key, msg) with mock.patch('libcloud.common.aws.AWSRequestSignerAlgorithmV4._get_key_to_sign_with') as mock_get_key: with mock.patch('libcloud.common.aws.AWSRequestSignerAlgorithmV4._get_string_to_sign') as mock_get_string: with mock.patch('libcloud.common.aws._sign', new=_sign): mock_get_key.return_value = 'my_signing_key' mock_get_string.return_value = 'my_string_to_sign' sig = self.signer._get_signature({}, {}, self.now, method='GET', path='/', data=None) self.assertEqual(sig, 'H|my_signing_key|my_string_to_sign') def test_get_string_to_sign(self): with mock.patch('hashlib.sha256') as mock_sha256: mock_sha256.return_value.hexdigest.return_value = 'chksum_of_canonical_request' to_sign = self.signer._get_string_to_sign({}, {}, self.now, method='GET', path='/', data=None) self.assertEqual(to_sign, 'AWS4-HMAC-SHA256\n' '20150304T173452Z\n' '20150304/my_region/my_service/aws4_request\n' 'chksum_of_canonical_request') def test_get_key_to_sign_with(self): def _sign(key, msg, hex=False): return '%s|%s' % (key, msg) with mock.patch('libcloud.common.aws._sign', new=_sign): key = self.signer._get_key_to_sign_with(self.now) self.assertEqual(key, 'AWS4my_secret|20150304|my_region|my_service|aws4_request') def test_get_signed_headers_contains_all_headers_lowercased(self): headers = {'Content-Type': 'text/plain', 'Host': 'my_host', 'X-Special-Header': ''} signed_headers = self.signer._get_signed_headers(headers) self.assertIn('content-type', signed_headers) self.assertIn('host', signed_headers) self.assertIn('x-special-header', signed_headers) def test_get_signed_headers_concats_headers_sorted_lexically(self): headers = {'Host': 'my_host', 'X-Special-Header': '', '1St-Header': '2', 'Content-Type': 'text/plain'} signed_headers = self.signer._get_signed_headers(headers) self.assertEqual(signed_headers, '1st-header;content-type;host;x-special-header') def test_get_credential_scope(self): scope = self.signer._get_credential_scope(self.now) self.assertEqual(scope, '20150304/my_region/my_service/aws4_request') def test_get_canonical_headers_joins_all_headers(self): headers = { 'accept-encoding': 'gzip,deflate', 'host': 'my_host', } self.assertEqual(self.signer._get_canonical_headers(headers), 'accept-encoding:gzip,deflate\n' 'host:my_host\n') def test_get_canonical_headers_sorts_headers_lexically(self): headers = { 'accept-encoding': 'gzip,deflate', 'host': 'my_host', '1st-header': '2', 'x-amz-date': '20150304T173452Z', 'user-agent': 'my-ua' } self.assertEqual(self.signer._get_canonical_headers(headers), '1st-header:2\n' 'accept-encoding:gzip,deflate\n' 'host:my_host\n' 'user-agent:my-ua\n' 'x-amz-date:20150304T173452Z\n') def test_get_canonical_headers_lowercases_headers_names(self): headers = { 'Accept-Encoding': 'GZIP,DEFLATE', 'User-Agent': 'My-UA' } self.assertEqual(self.signer._get_canonical_headers(headers), 'accept-encoding:GZIP,DEFLATE\n' 'user-agent:My-UA\n') def test_get_canonical_headers_trims_header_values(self): # TODO: according to AWS spec (and RFC 2616 Section 4.2.) excess whitespace # from inside non-quoted strings should be stripped. Now we only strip the # start and end of the string. See # http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html headers = { 'accept-encoding': ' gzip,deflate', 'user-agent': 'libcloud/0.17.0 ' } self.assertEqual(self.signer._get_canonical_headers(headers), 'accept-encoding:gzip,deflate\n' 'user-agent:libcloud/0.17.0\n') def test_get_request_params_joins_params_sorted_lexically(self): self.assertEqual(self.signer._get_request_params({ 'Action': 'DescribeInstances', 'Filter.1.Name': 'state', 'Version': '2013-10-15' }), 'Action=DescribeInstances&Filter.1.Name=state&Version=2013-10-15') def test_get_canonical_headers_allow_numeric_header_value(self): headers = { 'Accept-Encoding': 'gzip,deflate', 'Content-Length': 314 } self.assertEqual(self.signer._get_canonical_headers(headers), 'accept-encoding:gzip,deflate\n' 'content-length:314\n') def test_get_request_params_allows_integers_as_value(self): self.assertEqual(self.signer._get_request_params({'Action': 'DescribeInstances', 'Port': 22}), 'Action=DescribeInstances&Port=22') def test_get_request_params_urlquotes_params_keys(self): self.assertEqual(self.signer._get_request_params({'Action+Reaction': 'DescribeInstances'}), 'Action%2BReaction=DescribeInstances') def test_get_request_params_urlquotes_params_values(self): self.assertEqual(self.signer._get_request_params({ 'Action': 'DescribeInstances&Addresses', 'Port-Range': '2000 3000' }), 'Action=DescribeInstances%26Addresses&Port-Range=2000%203000') def test_get_request_params_urlquotes_params_values_allows_safe_chars_in_value(self): # http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html self.assertEqual('Action=a~b.c_d-e', self.signer._get_request_params({'Action': 'a~b.c_d-e'})) def test_get_payload_hash_returns_digest_of_empty_string_for_GET_requests(self): SignedAWSConnection.method = 'GET' self.assertEqual(self.signer._get_payload_hash(method='GET'), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') def test_get_payload_hash_with_data_for_PUT_requests(self): SignedAWSConnection.method = 'PUT' self.assertEqual(self.signer._get_payload_hash(method='PUT', data='DUMMY'), 'ceec12762e66397b56dad64fd270bb3d694c78fb9cd665354383c0626dbab013') def test_get_payload_hash_with_empty_data_for_POST_requests(self): SignedAWSConnection.method = 'POST' self.assertEqual(self.signer._get_payload_hash(method='POST'), UNSIGNED_PAYLOAD) def test_get_canonical_request(self): req = self.signer._get_canonical_request( {'Action': 'DescribeInstances', 'Version': '2013-10-15'}, {'Accept-Encoding': 'gzip,deflate', 'User-Agent': 'My-UA'}, method='GET', path='/my_action/', data=None ) self.assertEqual(req, 'GET\n' '/my_action/\n' 'Action=DescribeInstances&Version=2013-10-15\n' 'accept-encoding:gzip,deflate\n' 'user-agent:My-UA\n' '\n' 'accept-encoding;user-agent\n' 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') def test_post_canonical_request(self): req = self.signer._get_canonical_request( {'Action': 'DescribeInstances', 'Version': '2013-10-15'}, {'Accept-Encoding': 'gzip,deflate', 'User-Agent': 'My-UA'}, method='POST', path='/my_action/', data='{}' ) self.assertEqual(req, 'POST\n' '/my_action/\n' 'Action=DescribeInstances&Version=2013-10-15\n' 'accept-encoding:gzip,deflate\n' 'user-agent:My-UA\n' '\n' 'accept-encoding;user-agent\n' '44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_azure.py0000664000175000017500000000414413570310635023234 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.common.azure import AzureConnection from libcloud.test import LibcloudTestCase class AzureConnectionTestCase(LibcloudTestCase): def setUp(self): self.conn = AzureConnection('user', 'key') def test_content_length_is_used_if_set(self): headers = {'content-length': '123'} method = 'PUT' values = self.conn._format_special_header_values(headers, method) self.assertEqual(values[2], '123') def test_content_length_is_blank_if_new_api_version(self): headers = {} method = 'PUT' self.conn.API_VERSION = '2018-11-09' values = self.conn._format_special_header_values(headers, method) self.assertEqual(values[2], '') def test_content_length_is_zero_if_write_and_old_api_version(self): headers = {} method = 'PUT' self.conn.API_VERSION = '2011-08-18' values = self.conn._format_special_header_values(headers, method) self.assertEqual(values[2], '0') def test_content_length_is_blank_if_read_and_old_api_version(self): headers = {} method = 'GET' self.conn.API_VERSION = '2011-08-18' values = self.conn._format_special_header_values(headers, method) self.assertEqual(values[2], '') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_base.py0000664000175000017500000001021513535474530023022 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import sys import mock from libcloud.common.base import LazyObject, Response from libcloud.common.exceptions import BaseHTTPError, RateLimitReachedError from libcloud.test import LibcloudTestCase class LazyObjectTest(LibcloudTestCase): class A(LazyObject): def __init__(self, x, y=None): self.x = x self.y = y def test_lazy_init(self): # Test normal init a = self.A(1, y=2) self.assertTrue(isinstance(a, self.A)) # Test lazy init with mock.patch.object(self.A, '__init__', return_value=None) as mock_init: a = self.A.lazy(3, y=4) self.assertTrue(isinstance(a, self.A)) # Proxy is a subclass of A mock_init.assert_not_called() # Since we have a mock init, an A object doesn't actually get # created. But, we can still call __dict__ on the proxy, which will # init the lazy object. self.assertEqual(a.__dict__, {}) mock_init.assert_called_once_with(3, y=4) def test_setattr(self): a = self.A.lazy('foo', y='bar') a.z = 'baz' wrapped_lazy_obj = object.__getattribute__(a, '_lazy_obj') self.assertEqual(a.z, 'baz') self.assertEqual(wrapped_lazy_obj.z, 'baz') class ErrorResponseTest(LibcloudTestCase): def mock_response(self, code, headers={}): m = mock.MagicMock() m.request = mock.Mock() m.headers = headers m.status_code = code m.text = None return m def test_rate_limit_response(self): resp_mock = self.mock_response(429, {'Retry-After': '120'}) try: Response(resp_mock, mock.MagicMock()) except RateLimitReachedError as e: self.assertEqual(e.retry_after, 120) except Exception: # We should have got a RateLimitReachedError self.fail("Catched exception should have been RateLimitReachedError") else: # We should have got an exception self.fail("HTTP Status 429 response didn't raised an exception") def test_error_with_retry_after(self): # 503 Service Unavailable may include Retry-After header resp_mock = self.mock_response(503, {'Retry-After': '300'}) try: Response(resp_mock, mock.MagicMock()) except BaseHTTPError as e: self.assertIn('retry-after', e.headers) self.assertEqual(e.headers['retry-after'], '300') else: # We should have got an exception self.fail("HTTP Status 503 response didn't raised an exception") @mock.patch('time.time', return_value=1231006505) def test_error_with_retry_after_http_date_format(self, time_mock): retry_after = 'Sat, 03 Jan 2009 18:20:05 -0000' # 503 Service Unavailable may include Retry-After header resp_mock = self.mock_response(503, {'Retry-After': retry_after}) try: Response(resp_mock, mock.MagicMock()) except BaseHTTPError as e: self.assertIn('retry-after', e.headers) # HTTP-date got translated to delay-secs self.assertEqual(e.headers['retry-after'], '300') else: # We should have got an exception self.fail("HTTP Status 503 response didn't raised an exception") if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_base_driver.py0000664000175000017500000000500013535474530024371 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from mock import Mock from libcloud.common.base import BaseDriver from libcloud.test import unittest class BaseDriverTestCase(unittest.TestCase): def test_timeout_argument_propagation_and_preservation(self): class DummyDriver1(BaseDriver): pass # 1. No timeout provided DummyDriver1.connectionCls = Mock() DummyDriver1(key='foo') call_kwargs = DummyDriver1.connectionCls.call_args[1] self.assertIsNone(call_kwargs['timeout']) self.assertIsNone(call_kwargs['retry_delay']) # 2. Timeout provided as constructor argument class DummyDriver1(BaseDriver): pass DummyDriver1.connectionCls = Mock() DummyDriver1(key='foo', timeout=12) call_kwargs = DummyDriver1.connectionCls.call_args[1] self.assertEqual(call_kwargs['timeout'], 12) self.assertIsNone(call_kwargs['retry_delay']) # 3. timeout provided via "_ex_connection_class_kwargs" method class DummyDriver2(BaseDriver): def _ex_connection_class_kwargs(self): result = {} result['timeout'] = 13 return result DummyDriver2.connectionCls = Mock() DummyDriver2(key='foo') call_kwargs = DummyDriver2.connectionCls.call_args[1] # 4. Value provided via "_ex_connection_class_kwargs" and constructor, # constructor should win DummyDriver2.connectionCls = Mock() DummyDriver2(key='foo', timeout=14, retry_delay=10) call_kwargs = DummyDriver2.connectionCls.call_args[1] self.assertEqual(call_kwargs['timeout'], 14) self.assertEqual(call_kwargs['retry_delay'], 10) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_cloudstack.py0000664000175000017500000001610213570310635024237 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import b from libcloud.utils.py3 import parse_qsl from libcloud.common.cloudstack import CloudStackConnection from libcloud.common.types import MalformedResponseError from libcloud.test import MockHttp async_delay = 0 class CloudStackMockDriver(object): host = 'nonexistent.' path = '/path' async_poll_frequency = 0 name = 'fake' async_delay = 0 class CloudStackCommonTest(unittest.TestCase): def setUp(self): CloudStackConnection.conn_class = CloudStackMockHttp self.connection = CloudStackConnection('apikey', 'secret', host=CloudStackMockDriver.host) self.connection.poll_interval = 0.0 self.driver = self.connection.driver = CloudStackMockDriver() def test_sync_request_bad_response(self): self.driver.path = '/bad/response' try: self.connection._sync_request('fake') except Exception as e: self.assertTrue(isinstance(e, MalformedResponseError)) return self.assertTrue(False) def test_sync_request(self): self.driver.path = '/sync' self.connection._sync_request('fake') def test_async_request_successful(self): self.driver.path = '/async/success' result = self.connection._async_request('fake') self.assertEqual(result, {'fake': 'result'}) def test_async_request_unsuccessful(self): self.driver.path = '/async/fail' try: self.connection._async_request('fake') except Exception as e: self.assertEqual(CloudStackMockHttp.ERROR_TEXT, str(e)) return self.assertFalse(True) def test_async_request_delayed(self): global async_delay self.driver.path = '/async/delayed' async_delay = 2 self.connection._async_request('fake') self.assertEqual(async_delay, 0) def test_signature_algorithm(self): cases = [ ( { 'command': 'listVirtualMachines' }, 'z/a9Y7J52u48VpqIgiwaGUMCso0=' ), ( { 'command': 'deployVirtualMachine', 'name': 'fred', 'displayname': 'George', 'serviceofferingid': 5, 'templateid': 17, 'zoneid': 23, 'networkids': 42 }, 'gHTo7mYmadZ+zluKHzlEKb1i/QU=' ), ( { 'command': 'deployVirtualMachine', 'name': 'fred', 'displayname': 'George+Ringo', 'serviceofferingid': 5, 'templateid': 17, 'zoneid': 23, 'networkids': 42 }, 'tAgfrreI1ZvWlWLClD3gu4+aKv4=' ) ] connection = CloudStackConnection('fnord', 'abracadabra') for case in cases: params = connection.add_default_params(case[0]) self.assertEqual(connection._make_signature(params), b(case[1])) class CloudStackMockHttp(MockHttp, unittest.TestCase): ERROR_TEXT = 'ERROR TEXT' def _response(self, status, result, response): return (status, json.dumps(result), {}, response) def _check_request(self, url): url = urlparse.urlparse(url) query = dict(parse_qsl(url.query)) self.assertTrue('apiKey' in query) self.assertTrue('command' in query) self.assertTrue('response' in query) self.assertTrue('signature' in query) self.assertTrue(query['response'] == 'json') return query def _bad_response(self, method, url, body, headers): self._check_request(url) result = {'success': True} return self._response(httplib.OK, result, httplib.responses[httplib.OK]) def _sync(self, method, url, body, headers): query = self._check_request(url) result = {query['command'].lower() + 'response': {}} return self._response(httplib.OK, result, httplib.responses[httplib.OK]) def _async_success(self, method, url, body, headers): query = self._check_request(url) if query['command'].lower() == 'queryasyncjobresult': self.assertEqual(query['jobid'], '42') result = { query['command'].lower() + 'response': { 'jobstatus': 1, 'jobresult': {'fake': 'result'} } } else: result = {query['command'].lower() + 'response': {'jobid': '42'}} return self._response(httplib.OK, result, httplib.responses[httplib.OK]) def _async_fail(self, method, url, body, headers): query = self._check_request(url) if query['command'].lower() == 'queryasyncjobresult': self.assertEqual(query['jobid'], '42') result = { query['command'].lower() + 'response': { 'jobstatus': 2, 'jobresult': {'errortext': self.ERROR_TEXT} } } else: result = {query['command'].lower() + 'response': {'jobid': '42'}} return self._response(httplib.OK, result, httplib.responses[httplib.OK]) def _async_delayed(self, method, url, body, headers): global async_delay query = self._check_request(url) if query['command'].lower() == 'queryasyncjobresult': self.assertEqual(query['jobid'], '42') if async_delay == 0: result = { query['command'].lower() + 'response': { 'jobstatus': 1, 'jobresult': {'fake': 'result'} } } else: result = { query['command'].lower() + 'response': { 'jobstatus': 0, } } async_delay -= 1 else: result = {query['command'].lower() + 'response': {'jobid': '42'}} return self._response(httplib.OK, result, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_digitalocean_v2.py0000664000175000017500000001004313535474530025141 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and import sys import unittest from libcloud.common.types import InvalidCredsError from libcloud.common.digitalocean import DigitalOceanBaseDriver from libcloud.test import LibcloudTestCase, MockHttp from libcloud.test.file_fixtures import FileFixtures from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS from libcloud.utils.py3 import httplib class DigitalOceanTests(LibcloudTestCase): def setUp(self): DigitalOceanBaseDriver.connectionCls.conn_class = \ DigitalOceanMockHttp DigitalOceanMockHttp.type = None self.driver = DigitalOceanBaseDriver(*DIGITALOCEAN_v2_PARAMS) def test_authentication(self): DigitalOceanMockHttp.type = 'UNAUTHORIZED' self.assertRaises(InvalidCredsError, self.driver.ex_account_info) def test_ex_account_info(self): account_info = self.driver.ex_account_info() self.assertEqual(account_info['uuid'], 'a1234567890b1234567890c1234567890d12345') self.assertTrue(account_info['email_verified']) self.assertEqual(account_info['email'], 'user@domain.tld') self.assertEqual(account_info['droplet_limit'], 10) def test_ex_list_events(self): events = self.driver.ex_list_events() self.assertEqual(events, []) def test_ex_get_event(self): action = self.driver.ex_get_event('12345670') self.assertEqual(action["id"], 12345670) self.assertEqual(action["status"], "completed") self.assertEqual(action["type"], "power_on") def test__paginated_request(self): DigitalOceanMockHttp.type = 'page_1' actions = self.driver._paginated_request('/v2/actions', 'actions') self.assertEqual(actions[0]['id'], 12345671) self.assertEqual(actions[0]['status'], 'completed') class DigitalOceanMockHttp(MockHttp): fixtures = FileFixtures('common', 'digitalocean') response = { None: httplib.OK, 'CREATE': httplib.CREATED, 'DELETE': httplib.NO_CONTENT, 'EMPTY': httplib.OK, 'NOT_FOUND': httplib.NOT_FOUND, 'UNAUTHORIZED': httplib.UNAUTHORIZED, 'UPDATE': httplib.OK } def _v2_account(self, method, url, body, headers): body = self.fixtures.load('_v2_account.json') return (self.response[self.type], body, {}, httplib.responses[self.response[self.type]]) def _v2_account_UNAUTHORIZED(self, method, url, body, headers): body = self.fixtures.load( '_v2_account_UNAUTHORIZED.json') return (self.response[self.type], body, {}, httplib.responses[self.response[self.type]]) def _v2_actions(self, method, url, body, headers): body = self.fixtures.load('_v2_actions.json') return (self.response[self.type], body, {}, httplib.responses[self.response[self.type]]) def _v2_actions_12345670(self, method, url, body, headers): body = self.fixtures.load('_v2_actions_12345670.json') return (self.response[self.type], body, {}, httplib.responses[self.response[self.type]]) def _v2_actions_page_1(self, method, url, body, headers): body = self.fixtures.load('_v2_actions_page_1.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_gandi.py0000664000175000017500000000241513535474530023175 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import xmlrpclib from libcloud.test import MockHttp class BaseGandiMockHttp(MockHttp): def _get_method_name(self, type, use_param, qs, path): return "_xmlrpc" def _xmlrpc(self, method, url, body, headers): params, methodName = xmlrpclib.loads(body) meth_name = '_xmlrpc__' + methodName.replace('.', '_') if self.type: meth_name = '%s_%s' % (meth_name, self.type) return getattr(self, meth_name)(method, url, body, headers) apache-libcloud-2.8.0/libcloud/test/common/test_gandi_live.py0000664000175000017500000000224013570310635024202 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re from libcloud.test import MockHttp FORMAT_URL = re.compile(r'[./?=-]') class BaseGandiLiveMockHttp(MockHttp): def _get_method_name(self, type, use_param, qs, path): return "_json" def _json(self, method, url, body, headers): meth_name = '_json%s_%s' % (FORMAT_URL.sub('_', url), method.lower()) return getattr(self, meth_name)(method, url, body, headers) apache-libcloud-2.8.0/libcloud/test/common/test_google.py0000664000175000017500000003740513535474530023376 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Tests for Google Connection classes. """ import datetime import mock import os import sys import unittest try: import simplejson as json except ImportError: import json from libcloud.common.google import (GoogleAuthError, GoogleAuthType, GoogleBaseAuthConnection, GoogleInstalledAppAuthConnection, GoogleServiceAcctAuthConnection, GoogleGCEServiceAcctAuthConnection, GoogleOAuth2Credential, GoogleBaseConnection, _utcnow, _utc_timestamp) from libcloud.test import MockHttp, LibcloudTestCase from libcloud.utils.py3 import httplib # Skip some tests if cryptography is unavailable try: from cryptography.hazmat.primitives.hashes import SHA256 except ImportError: SHA256 = None SCRIPT_PATH = os.path.dirname(os.path.realpath(__file__)) PEM_KEY = os.path.join(SCRIPT_PATH, 'fixtures', 'google', 'pkey.pem') JSON_KEY = os.path.join(SCRIPT_PATH, 'fixtures', 'google', 'pkey.json') with open(JSON_KEY, 'r') as f: KEY_STR = json.loads(f.read())['private_key'] GCE_PARAMS = ('email@developer.gserviceaccount.com', 'key') GCE_PARAMS_PEM_KEY = ('email@developer.gserviceaccount.com', PEM_KEY) GCE_PARAMS_JSON_KEY = ('email@developer.gserviceaccount.com', JSON_KEY) GCE_PARAMS_KEY = ('email@developer.gserviceaccount.com', KEY_STR) GCE_PARAMS_IA = ('client_id', 'client_secret') GCE_PARAMS_GCE = ('foo', 'bar') GCS_S3_PARAMS_20 = ('GOOG0123456789ABCXYZ', # GOOG + 16 alphanumeric chars '0102030405060708091011121314151617181920') # 40 base64 chars GCS_S3_PARAMS_24 = ('GOOGDF5OVRRGU4APFNSTVCXI', # GOOG + 20 alphanumeric chars '0102030405060708091011121314151617181920') # 40 base64 chars STUB_UTCNOW = _utcnow() STUB_TOKEN = { 'access_token': 'tokentoken', 'token_type': 'Bearer', 'expires_in': 3600 } STUB_IA_TOKEN = { 'access_token': 'installedapp', 'token_type': 'Bearer', 'expires_in': 3600, 'refresh_token': 'refreshrefresh' } STUB_REFRESH_TOKEN = { 'access_token': 'refreshrefresh', 'token_type': 'Bearer', 'expires_in': 3600 } STUB_TOKEN_FROM_FILE = { 'access_token': 'token_from_file', 'token_type': 'Bearer', 'expire_time': _utc_timestamp(STUB_UTCNOW + datetime.timedelta(seconds=3600)), 'expires_in': 3600 } class MockJsonResponse(object): def __init__(self, body): self.object = body class GoogleTestCase(LibcloudTestCase): """ Assists in making Google tests hermetic and deterministic. Add anything that needs to be mocked here. Create a patcher with the suffix '_patcher'. e.g. _foo_patcher = mock.patch('module.submodule.class.foo', ...) Patchers are started at setUpClass and stopped at tearDownClass. Ideally, you should make a note in the thing being mocked, for clarity. """ PATCHER_SUFFIX = '_patcher' _utcnow_patcher = mock.patch( 'libcloud.common.google._utcnow', return_value=STUB_UTCNOW) _authtype_is_gce_patcher = mock.patch( 'libcloud.common.google.GoogleAuthType._is_gce', return_value=False) _read_token_file_patcher = mock.patch( 'libcloud.common.google.GoogleOAuth2Credential._get_token_from_file', return_value=STUB_TOKEN_FROM_FILE ) _write_token_file_patcher = mock.patch( 'libcloud.common.google.GoogleOAuth2Credential._write_token_to_file') _ia_get_code_patcher = mock.patch( 'libcloud.common.google.GoogleInstalledAppAuthConnection.get_code', return_value=1234 ) @classmethod def setUpClass(cls): super(GoogleTestCase, cls).setUpClass() for patcher in [a for a in dir(cls) if a.endswith(cls.PATCHER_SUFFIX)]: getattr(cls, patcher).start() @classmethod def tearDownClass(cls): super(GoogleTestCase, cls).tearDownClass() for patcher in [a for a in dir(cls) if a.endswith(cls.PATCHER_SUFFIX)]: getattr(cls, patcher).stop() class GoogleBaseAuthConnectionTest(GoogleTestCase): """ Tests for GoogleBaseAuthConnection """ def setUp(self): GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp self.mock_scopes = ['foo', 'bar'] kwargs = {'scopes': self.mock_scopes} self.conn = GoogleInstalledAppAuthConnection(*GCE_PARAMS, **kwargs) def test_scopes(self): self.assertEqual(self.conn.scopes, 'foo bar') def test_add_default_headers(self): old_headers = {} expected_headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'accounts.google.com'} new_headers = self.conn.add_default_headers(old_headers) self.assertEqual(new_headers, expected_headers) def test_token_request(self): request_body = {'code': 'asdf', 'client_id': self.conn.user_id, 'client_secret': self.conn.key, 'redirect_uri': self.conn.redirect_uri, 'grant_type': 'authorization_code'} new_token = self.conn._token_request(request_body) self.assertEqual(new_token['access_token'], STUB_IA_TOKEN['access_token']) exp = STUB_UTCNOW + datetime.timedelta( seconds=STUB_IA_TOKEN['expires_in']) self.assertEqual(new_token['expire_time'], _utc_timestamp(exp)) class GoogleInstalledAppAuthConnectionTest(GoogleTestCase): """ Tests for GoogleInstalledAppAuthConnection """ def setUp(self): GoogleInstalledAppAuthConnection.conn_class = GoogleAuthMockHttp self.mock_scopes = ['https://www.googleapis.com/auth/foo'] kwargs = {'scopes': self.mock_scopes} self.conn = GoogleInstalledAppAuthConnection(*GCE_PARAMS, **kwargs) def test_refresh_token(self): # This token info doesn't have a refresh token, so a new token will be # requested token_info1 = {'access_token': 'tokentoken', 'token_type': 'Bearer', 'expires_in': 3600} new_token1 = self.conn.refresh_token(token_info1) self.assertEqual(new_token1['access_token'], STUB_IA_TOKEN['access_token']) # This token info has a refresh token, so it will be able to be # refreshed. token_info2 = {'access_token': 'tokentoken', 'token_type': 'Bearer', 'expires_in': 3600, 'refresh_token': 'refreshrefresh'} new_token2 = self.conn.refresh_token(token_info2) self.assertEqual(new_token2['access_token'], STUB_REFRESH_TOKEN['access_token']) # Both sets should have refresh info self.assertTrue('refresh_token' in new_token1) self.assertTrue('refresh_token' in new_token2) class GoogleAuthTypeTest(GoogleTestCase): def test_guess(self): self.assertEqual(GoogleAuthType.guess_type(GCE_PARAMS_IA[0]), GoogleAuthType.IA) with mock.patch.object(GoogleAuthType, '_is_gce', return_value=True): # Since _is_gce currently depends on the environment, not on # parameters, other auths should override GCE. It does not make # sense for IA auth to happen on GCE, which is why it's left out. self.assertEqual(GoogleAuthType.guess_type(GCE_PARAMS[0]), GoogleAuthType.SA) self.assertEqual( GoogleAuthType.guess_type(GCS_S3_PARAMS_20[0]), GoogleAuthType.GCS_S3) self.assertEqual( GoogleAuthType.guess_type(GCS_S3_PARAMS_24[0]), GoogleAuthType.GCS_S3) self.assertEqual(GoogleAuthType.guess_type(GCE_PARAMS_GCE[0]), GoogleAuthType.GCE) class GoogleOAuth2CredentialTest(GoogleTestCase): def test_init_oauth2(self): kwargs = {'auth_type': GoogleAuthType.IA} cred = GoogleOAuth2Credential(*GCE_PARAMS, **kwargs) # If there is a viable token file, this gets used first self.assertEqual(cred.token, STUB_TOKEN_FROM_FILE) # No token file, get a new token. Check that it gets written to file. with mock.patch.object(GoogleOAuth2Credential, '_get_token_from_file', return_value=None): cred = GoogleOAuth2Credential(*GCE_PARAMS, **kwargs) expected = STUB_IA_TOKEN expected['expire_time'] = cred.token['expire_time'] self.assertEqual(cred.token, expected) cred._write_token_to_file.assert_called_once_with() def test_refresh(self): args = list(GCE_PARAMS) + [GoogleAuthType.GCE] cred = GoogleOAuth2Credential(*args) cred._refresh_token = mock.Mock() # Test getting an unexpired access token. tomorrow = datetime.datetime.now() + datetime.timedelta(days=1) cred.token = {'access_token': 'Access Token!', 'expire_time': _utc_timestamp(tomorrow)} cred.access_token self.assertFalse(cred._refresh_token.called) # Test getting an expired access token. yesterday = datetime.datetime.now() - datetime.timedelta(days=1) cred.token = {'access_token': 'Access Token!', 'expire_time': _utc_timestamp(yesterday)} cred.access_token self.assertTrue(cred._refresh_token.called) def test_auth_connection(self): # Test a bogus auth type self.assertRaises(GoogleAuthError, GoogleOAuth2Credential, *GCE_PARAMS, **{'auth_type': 'XX'}) # Try to create an OAuth2 credential when dealing with a GCS S3 # interoperability auth type. self.assertRaises(GoogleAuthError, GoogleOAuth2Credential, *GCE_PARAMS, **{'auth_type': GoogleAuthType.GCS_S3}) kwargs = {} if SHA256: kwargs['auth_type'] = GoogleAuthType.SA cred1 = GoogleOAuth2Credential(*GCE_PARAMS_PEM_KEY, **kwargs) self.assertTrue(isinstance(cred1.oauth2_conn, GoogleServiceAcctAuthConnection)) cred1 = GoogleOAuth2Credential(*GCE_PARAMS_JSON_KEY, **kwargs) self.assertTrue(isinstance(cred1.oauth2_conn, GoogleServiceAcctAuthConnection)) cred1 = GoogleOAuth2Credential(*GCE_PARAMS_KEY, **kwargs) self.assertTrue(isinstance(cred1.oauth2_conn, GoogleServiceAcctAuthConnection)) kwargs['auth_type'] = GoogleAuthType.IA cred2 = GoogleOAuth2Credential(*GCE_PARAMS_IA, **kwargs) self.assertTrue(isinstance(cred2.oauth2_conn, GoogleInstalledAppAuthConnection)) kwargs['auth_type'] = GoogleAuthType.GCE cred3 = GoogleOAuth2Credential(*GCE_PARAMS_GCE, **kwargs) self.assertTrue(isinstance(cred3.oauth2_conn, GoogleGCEServiceAcctAuthConnection)) class GoogleBaseConnectionTest(GoogleTestCase): """ Tests for GoogleBaseConnection """ def setUp(self): GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp self.mock_scopes = ['https://www.googleapis.com/auth/foo'] kwargs = {'scopes': self.mock_scopes, 'auth_type': GoogleAuthType.IA} self.conn = GoogleBaseConnection(*GCE_PARAMS, **kwargs) def test_add_default_headers(self): old_headers = {} new_expected_headers = {'Content-Type': 'application/json', 'Host': 'www.googleapis.com'} new_headers = self.conn.add_default_headers(old_headers) self.assertEqual(new_headers, new_expected_headers) def test_pre_connect_hook(self): old_params = {} old_headers = {} auth_str = '%s %s' % (STUB_TOKEN_FROM_FILE['token_type'], STUB_TOKEN_FROM_FILE['access_token']) new_expected_params = {} new_expected_headers = {'Authorization': auth_str} new_params, new_headers = self.conn.pre_connect_hook(old_params, old_headers) self.assertEqual(new_params, new_expected_params) self.assertEqual(new_headers, new_expected_headers) def test_encode_data(self): data = {'key': 'value'} json_data = '{"key": "value"}' encoded_data = self.conn.encode_data(data) self.assertEqual(encoded_data, json_data) def test_has_completed(self): body1 = {"endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "kind": "compute#operation", "status": "DONE", "targetId": "16211908079305042870"} body2 = {"endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "kind": "compute#operation", "status": "RUNNING", "targetId": "16211908079305042870"} response1 = MockJsonResponse(body1) response2 = MockJsonResponse(body2) self.assertTrue(self.conn.has_completed(response1)) self.assertFalse(self.conn.has_completed(response2)) def test_get_poll_request_kwargs(self): body = {"endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "kind": "compute#operation", "selfLink": "https://www.googleapis.com/operations-test"} response = MockJsonResponse(body) expected_kwargs = {'action': 'https://www.googleapis.com/operations-test'} kwargs = self.conn.get_poll_request_kwargs(response, None, {}) self.assertEqual(kwargs, expected_kwargs) def test_morph_action_hook(self): self.conn.request_path = '/compute/apiver/project/project-name' action1 = ('https://www.googleapis.com/compute/apiver/project' '/project-name/instances') action2 = '/instances' expected_request = '/compute/apiver/project/project-name/instances' request1 = self.conn.morph_action_hook(action1) request2 = self.conn.morph_action_hook(action2) self.assertEqual(request1, expected_request) self.assertEqual(request2, expected_request) class GoogleAuthMockHttp(MockHttp): """ Mock HTTP Class for Google Auth Connections. """ json_hdr = {'content-type': 'application/json; charset=UTF-8'} def _o_oauth2_token(self, method, url, body, headers): if 'code' in body: body = json.dumps(STUB_IA_TOKEN) elif 'refresh_token' in body: body = json.dumps(STUB_REFRESH_TOKEN) else: body = json.dumps(STUB_TOKEN) return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_nfsn.py0000664000175000017500000000527013535474530023061 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import string import sys import unittest from mock import Mock, patch from libcloud.common.nfsn import NFSNConnection from libcloud.test import LibcloudTestCase, MockHttp from libcloud.utils.py3 import httplib mock_time = Mock() mock_time.return_value = 1000000 mock_salt = Mock() mock_salt.return_value = 'yumsalty1234' mock_header = 'testid;1000000;yumsalty1234;66dfb282a9532e5b8e6a9517764d5fbc001a4a2e' class NFSNConnectionTestCase(LibcloudTestCase): def setUp(self): NFSNConnection.conn_class = NFSNMockHttp NFSNMockHttp.type = None self.driver = NFSNConnection('testid', 'testsecret') def test_salt_length(self): self.assertEqual(16, len(self.driver._salt())) def test_salt_is_unique(self): s1 = self.driver._salt() s2 = self.driver._salt() self.assertNotEqual(s1, s2) def test_salt_characters(self): """ salt must be alphanumeric """ salt_characters = string.ascii_letters + string.digits for c in self.driver._salt(): self.assertIn(c, salt_characters) @patch('time.time', mock_time) def test_timestamp(self): """ Check that timestamp uses time.time """ self.assertEqual('1000000', self.driver._timestamp()) @patch('time.time', mock_time) @patch('libcloud.common.nfsn.NFSNConnection._salt', mock_salt) def test_auth_header(self): """ Check that X-NFSN-Authentication is set """ response = self.driver.request(action='/testing') self.assertEqual(httplib.OK, response.status) class NFSNMockHttp(MockHttp): def _testing(self, method, url, body, headers): if headers['X-NFSN-Authentication'] == mock_header: return (httplib.OK, '', {}, httplib.responses[httplib.OK]) else: return (httplib.UNAUTHORIZED, '', {}, httplib.responses[httplib.UNAUTHORIZED]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_openstack.py0000664000175000017500000000344613535474530024107 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from mock import Mock from libcloud.common.base import LibcloudConnection from libcloud.common.openstack import OpenStackBaseConnection class OpenStackBaseConnectionTest(unittest.TestCase): def setUp(self): self.timeout = 10 OpenStackBaseConnection.conn_class = Mock() self.connection = OpenStackBaseConnection('foo', 'bar', timeout=self.timeout, ex_force_auth_url='https://127.0.0.1') self.connection.driver = Mock() self.connection.driver.name = 'OpenStackDriver' def tearDown(self): OpenStackBaseConnection.conn_class = LibcloudConnection def test_base_connection_timeout(self): self.connection.connect() self.assertEqual(self.connection.timeout, self.timeout) self.connection.conn_class.assert_called_with( host='127.0.0.1', secure=1, port=443, timeout=10) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_openstack_identity.py0000664000175000017500000011331513576514553026022 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import datetime try: import simplejson as json except ImportError: import json from mock import Mock from libcloud.utils.py3 import httplib from libcloud.utils.py3 import assertRaisesRegex from libcloud.common.openstack import OpenStackBaseConnection from libcloud.common.openstack_identity import AUTH_TOKEN_EXPIRES_GRACE_SECONDS from libcloud.common.openstack_identity import get_class_for_auth_version from libcloud.common.openstack_identity import OpenStackServiceCatalog from libcloud.common.openstack_identity import OpenStackIdentity_2_0_Connection from libcloud.common.openstack_identity import OpenStackIdentity_3_0_Connection from libcloud.common.openstack_identity import OpenStackIdentity_3_0_Connection_OIDC_access_token from libcloud.common.openstack_identity import OpenStackIdentityUser from libcloud.compute.drivers.openstack import OpenStack_1_0_NodeDriver from libcloud.common.openstack_identity import OpenStackIdentity_2_0_Connection_VOMS from libcloud.test import unittest from libcloud.test import MockHttp from libcloud.test.secrets import OPENSTACK_PARAMS from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.compute.test_openstack import OpenStackMockHttp from libcloud.test.compute.test_openstack import OpenStack_2_0_MockHttp class OpenStackIdentityConnectionTestCase(unittest.TestCase): def setUp(self): OpenStackBaseConnection.auth_url = None OpenStackBaseConnection.conn_class = OpenStackMockHttp def test_auth_url_is_correctly_assembled(self): tuples = [ ('1.0', OpenStackMockHttp), ('1.1', OpenStackMockHttp), ('2.0', OpenStack_2_0_MockHttp), ('2.0_apikey', OpenStack_2_0_MockHttp), ('2.0_password', OpenStack_2_0_MockHttp) ] APPEND = 0 NOTAPPEND = 1 auth_urls = [ ('https://auth.api.example.com', APPEND, ''), ('https://auth.api.example.com/', NOTAPPEND, '/'), ('https://auth.api.example.com/foo/bar', NOTAPPEND, '/foo/bar'), ('https://auth.api.example.com/foo/bar/', NOTAPPEND, '/foo/bar/') ] actions = { '1.0': '/v1.0', '1.1': '/v1.1/auth', '2.0': '/v2.0/tokens', '2.0_apikey': '/v2.0/tokens', '2.0_password': '/v2.0/tokens' } user_id = OPENSTACK_PARAMS[0] key = OPENSTACK_PARAMS[1] for (auth_version, mock_http_class) in tuples: for (url, should_append_default_path, expected_path) in auth_urls: connection = \ self._get_mock_connection(mock_http_class=mock_http_class, auth_url=url) auth_url = connection.auth_url cls = get_class_for_auth_version(auth_version=auth_version) osa = cls(auth_url=auth_url, user_id=user_id, key=key, parent_conn=connection) try: osa = osa.authenticate() except Exception: pass if (should_append_default_path == APPEND): expected_path = actions[auth_version] self.assertEqual(osa.action, expected_path) def test_basic_authentication(self): tuples = [ ('1.0', OpenStackMockHttp), ('1.1', OpenStackMockHttp), ('2.0', OpenStack_2_0_MockHttp), ('2.0_apikey', OpenStack_2_0_MockHttp), ('2.0_password', OpenStack_2_0_MockHttp) ] user_id = OPENSTACK_PARAMS[0] key = OPENSTACK_PARAMS[1] for (auth_version, mock_http_class) in tuples: connection = \ self._get_mock_connection(mock_http_class=mock_http_class) auth_url = connection.auth_url cls = get_class_for_auth_version(auth_version=auth_version) osa = cls(auth_url=auth_url, user_id=user_id, key=key, parent_conn=connection) self.assertEqual(osa.urls, {}) self.assertIsNone(osa.auth_token) self.assertIsNone(osa.auth_user_info) osa = osa.authenticate() self.assertTrue(len(osa.urls) >= 1) self.assertTrue(osa.auth_token is not None) if auth_version in ['1.1', '2.0', '2.0_apikey', '2.0_password']: self.assertTrue(osa.auth_token_expires is not None) if auth_version in ['2.0', '2.0_apikey', '2.0_password']: self.assertTrue(osa.auth_user_info is not None) def test_token_expiration_and_force_reauthentication(self): user_id = OPENSTACK_PARAMS[0] key = OPENSTACK_PARAMS[1] connection = self._get_mock_connection(OpenStack_2_0_MockHttp) auth_url = connection.auth_url yesterday = datetime.datetime.today() - datetime.timedelta(1) tomorrow = datetime.datetime.today() + datetime.timedelta(1) osa = OpenStackIdentity_2_0_Connection(auth_url=auth_url, user_id=user_id, key=key, parent_conn=connection) mocked_auth_method = Mock(wraps=osa._authenticate_2_0_with_body) osa._authenticate_2_0_with_body = mocked_auth_method # Force re-auth, expired token osa.auth_token = None osa.auth_token_expires = yesterday count = 5 for i in range(0, count): osa.authenticate(force=True) self.assertEqual(mocked_auth_method.call_count, count) # No force reauth, expired token osa.auth_token = None osa.auth_token_expires = yesterday mocked_auth_method.call_count = 0 self.assertEqual(mocked_auth_method.call_count, 0) for i in range(0, count): osa.authenticate(force=False) self.assertEqual(mocked_auth_method.call_count, 1) # No force reauth, valid / non-expired token osa.auth_token = None mocked_auth_method.call_count = 0 self.assertEqual(mocked_auth_method.call_count, 0) for i in range(0, count): osa.authenticate(force=False) if i == 0: osa.auth_token_expires = tomorrow self.assertEqual(mocked_auth_method.call_count, 1) # No force reauth, valid / non-expired token which is about to expire in # less than AUTH_TOKEN_EXPIRES_GRACE_SECONDS soon = datetime.datetime.utcnow() + \ datetime.timedelta(seconds=AUTH_TOKEN_EXPIRES_GRACE_SECONDS - 1) osa.auth_token = None mocked_auth_method.call_count = 0 self.assertEqual(mocked_auth_method.call_count, 0) for i in range(0, count): if i == 0: osa.auth_token_expires = soon osa.authenticate(force=False) self.assertEqual(mocked_auth_method.call_count, 1) def _get_mock_connection(self, mock_http_class, auth_url=None): OpenStackBaseConnection.conn_class = mock_http_class if auth_url is None: auth_url = "https://auth.api.example.com" OpenStackBaseConnection.auth_url = auth_url connection = OpenStackBaseConnection(*OPENSTACK_PARAMS) connection._ex_force_base_url = "https://www.foo.com" connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS) return connection class OpenStackIdentity_2_0_ConnectionTests(unittest.TestCase): def setUp(self): mock_cls = OpenStackIdentity_2_0_MockHttp mock_cls.type = None OpenStackIdentity_2_0_Connection.conn_class = mock_cls self.auth_instance = OpenStackIdentity_2_0_Connection(auth_url='http://none', user_id='test', key='test', tenant_name='test', proxy_url='http://proxy:8080', timeout=10) self.auth_instance.auth_token = 'mock' self.assertEqual(self.auth_instance.proxy_url, 'http://proxy:8080') def test_list_projects(self): result = self.auth_instance.list_projects() self.assertEqual(len(result), 2) self.assertEqual(result[0].id, 'a') self.assertEqual(result[0].name, 'test') self.assertEqual(result[0].description, 'test project') self.assertTrue(result[0].enabled) class OpenStackIdentity_3_0_ConnectionTests(unittest.TestCase): def setUp(self): mock_cls = OpenStackIdentity_3_0_MockHttp mock_cls.type = None OpenStackIdentity_3_0_Connection.conn_class = mock_cls self.auth_instance = OpenStackIdentity_3_0_Connection(auth_url='http://none', user_id='test', key='test', tenant_name='test', proxy_url='http://proxy:8080', timeout=10) self.auth_instance.auth_token = 'mock' self.assertEqual(self.auth_instance.proxy_url, 'http://proxy:8080') def test_token_scope_argument(self): # Invalid token_scope value expected_msg = 'Invalid value for "token_scope" argument: foo' assertRaisesRegex(self, ValueError, expected_msg, OpenStackIdentity_3_0_Connection, auth_url='http://none', user_id='test', key='test', token_scope='foo') # Missing tenant_name expected_msg = 'Must provide tenant_name and domain_name argument' assertRaisesRegex(self, ValueError, expected_msg, OpenStackIdentity_3_0_Connection, auth_url='http://none', user_id='test', key='test', token_scope='project') # Missing domain_name expected_msg = 'Must provide domain_name argument' assertRaisesRegex(self, ValueError, expected_msg, OpenStackIdentity_3_0_Connection, auth_url='http://none', user_id='test', key='test', token_scope='domain', domain_name=None) # Scope to project all ok OpenStackIdentity_3_0_Connection(auth_url='http://none', user_id='test', key='test', token_scope='project', tenant_name='test', domain_name='Default') # Scope to domain OpenStackIdentity_3_0_Connection(auth_url='http://none', user_id='test', key='test', token_scope='domain', tenant_name=None, domain_name='Default') def test_authenticate(self): auth = OpenStackIdentity_3_0_Connection(auth_url='http://none', user_id='test_user_id', key='test_key', token_scope='project', tenant_name="test_tenant", tenant_domain_id="test_tenant_domain_id", domain_name='test_domain', proxy_url='http://proxy:8080', timeout=10) auth.authenticate() self.assertEqual(auth.proxy_url, 'http://proxy:8080') def test_list_supported_versions(self): OpenStackIdentity_3_0_MockHttp.type = 'v3' versions = self.auth_instance.list_supported_versions() self.assertEqual(len(versions), 2) self.assertEqual(versions[0].version, 'v2.0') self.assertEqual(versions[0].url, 'http://192.168.18.100:5000/v2.0/') self.assertEqual(versions[1].version, 'v3.0') self.assertEqual(versions[1].url, 'http://192.168.18.100:5000/v3/') def test_list_domains(self): domains = self.auth_instance.list_domains() self.assertEqual(len(domains), 1) self.assertEqual(domains[0].id, 'default') self.assertEqual(domains[0].name, 'Default') self.assertTrue(domains[0].enabled) def test_list_projects(self): projects = self.auth_instance.list_projects() self.assertEqual(len(projects), 4) self.assertEqual(projects[0].id, 'a') self.assertEqual(projects[0].domain_id, 'default') self.assertTrue(projects[0].enabled) self.assertEqual(projects[0].description, 'Test project') def test_list_users(self): users = self.auth_instance.list_users() self.assertEqual(len(users), 12) self.assertEqual(users[0].id, 'a') self.assertEqual(users[0].domain_id, 'default') self.assertEqual(users[0].enabled, True) self.assertEqual(users[0].email, 'openstack-test@localhost') def test_list_roles(self): roles = self.auth_instance.list_roles() self.assertEqual(len(roles), 2) self.assertEqual(roles[1].id, 'b') self.assertEqual(roles[1].name, 'admin') def test_list_user_projects(self): user = self.auth_instance.list_users()[0] projects = self.auth_instance.list_user_projects(user=user) self.assertEqual(len(projects), 0) def test_list_user_domain_roles(self): user = self.auth_instance.list_users()[0] domain = self.auth_instance.list_domains()[0] roles = self.auth_instance.list_user_domain_roles(domain=domain, user=user) self.assertEqual(len(roles), 1) self.assertEqual(roles[0].name, 'admin') def test_get_domain(self): domain = self.auth_instance.get_domain(domain_id='default') self.assertEqual(domain.name, 'Default') def test_get_user(self): user = self.auth_instance.get_user(user_id='a') self.assertEqual(user.id, 'a') self.assertEqual(user.domain_id, 'default') self.assertEqual(user.enabled, True) self.assertEqual(user.email, 'openstack-test@localhost') def test_get_user_without_email(self): user = self.auth_instance.get_user(user_id='b') self.assertEqual(user.id, 'b') self.assertEqual(user.name, 'userwithoutemail') self.assertIsNone(user.email) def test_get_user_without_enabled(self): user = self.auth_instance.get_user(user_id='c') self.assertEqual(user.id, 'c') self.assertEqual(user.name, 'userwithoutenabled') self.assertIsNone(user.enabled) def test_create_user(self): user = self.auth_instance.create_user(email='test2@localhost', password='test1', name='test2', domain_id='default') self.assertEqual(user.id, 'c') self.assertEqual(user.name, 'test2') def test_enable_user(self): user = self.auth_instance.list_users()[0] result = self.auth_instance.enable_user(user=user) self.assertTrue(isinstance(result, OpenStackIdentityUser)) def test_disable_user(self): user = self.auth_instance.list_users()[0] result = self.auth_instance.disable_user(user=user) self.assertTrue(isinstance(result, OpenStackIdentityUser)) def test_grant_domain_role_to_user(self): domain = self.auth_instance.list_domains()[0] role = self.auth_instance.list_roles()[0] user = self.auth_instance.list_users()[0] result = self.auth_instance.grant_domain_role_to_user(domain=domain, role=role, user=user) self.assertTrue(result) def test_revoke_domain_role_from_user(self): domain = self.auth_instance.list_domains()[0] role = self.auth_instance.list_roles()[0] user = self.auth_instance.list_users()[0] result = self.auth_instance.revoke_domain_role_from_user(domain=domain, role=role, user=user) self.assertTrue(result) def test_grant_project_role_to_user(self): project = self.auth_instance.list_projects()[0] role = self.auth_instance.list_roles()[0] user = self.auth_instance.list_users()[0] result = self.auth_instance.grant_project_role_to_user(project=project, role=role, user=user) self.assertTrue(result) def test_revoke_project_role_from_user(self): project = self.auth_instance.list_projects()[0] role = self.auth_instance.list_roles()[0] user = self.auth_instance.list_users()[0] result = self.auth_instance.revoke_project_role_from_user(project=project, role=role, user=user) self.assertTrue(result) class OpenStackIdentity_3_0_Connection_OIDC_access_token_federation_projectsTests( unittest.TestCase): def setUp(self): mock_cls = OpenStackIdentity_3_0_federation_projects_MockHttp mock_cls.type = None OpenStackIdentity_3_0_Connection_OIDC_access_token.conn_class = mock_cls self.auth_instance = OpenStackIdentity_3_0_Connection_OIDC_access_token(auth_url='http://none', user_id='idp', key='token', tenant_name='oidc', proxy_url='http://proxy:8080', timeout=10) self.auth_instance.auth_token = 'mock' def test_authenticate(self): auth = OpenStackIdentity_3_0_Connection_OIDC_access_token(auth_url='http://none', user_id='idp', key='token', token_scope='project', tenant_name="oidc", proxy_url='http://proxy:8080', timeout=10) auth.authenticate() class OpenStackIdentity_3_0_Connection_OIDC_access_tokenTests( unittest.TestCase): def setUp(self): mock_cls = OpenStackIdentity_3_0_MockHttp mock_cls.type = None OpenStackIdentity_3_0_Connection_OIDC_access_token.conn_class = mock_cls self.auth_instance = OpenStackIdentity_3_0_Connection_OIDC_access_token(auth_url='http://none', user_id='idp', key='token', tenant_name='oidc', domain_name='project_name2') self.auth_instance.auth_token = 'mock' def test_authenticate(self): auth = OpenStackIdentity_3_0_Connection_OIDC_access_token(auth_url='http://none', user_id='idp', key='token', token_scope='project', tenant_name="oidc", domain_name='project_name2') auth.authenticate() class OpenStackIdentity_2_0_Connection_VOMSTests(unittest.TestCase): def setUp(self): mock_cls = OpenStackIdentity_2_0_Connection_VOMSMockHttp mock_cls.type = None OpenStackIdentity_2_0_Connection_VOMS.conn_class = mock_cls self.auth_instance = OpenStackIdentity_2_0_Connection_VOMS(auth_url='http://none', user_id=None, key='/tmp/proxy.pem', tenant_name='VO') self.auth_instance.auth_token = 'mock' def test_authenticate(self): auth = OpenStackIdentity_2_0_Connection_VOMS(auth_url='http://none', user_id=None, key='/tmp/proxy.pem', token_scope='test', tenant_name="VO") auth.authenticate() class OpenStackServiceCatalogTestCase(unittest.TestCase): fixtures = ComputeFileFixtures('openstack') def test_parsing_auth_v1_1(self): data = self.fixtures.load('_v1_1__auth.json') data = json.loads(data) service_catalog = data['auth']['serviceCatalog'] catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version='1.0') entries = catalog.get_entries() self.assertEqual(len(entries), 3) entry = [e for e in entries if e.service_type == 'cloudFilesCDN'][0] self.assertEqual(entry.service_type, 'cloudFilesCDN') self.assertIsNone(entry.service_name) self.assertEqual(len(entry.endpoints), 2) self.assertEqual(entry.endpoints[0].region, 'ORD') self.assertEqual(entry.endpoints[0].url, 'https://cdn2.clouddrive.com/v1/MossoCloudFS') self.assertEqual(entry.endpoints[0].endpoint_type, 'external') self.assertEqual(entry.endpoints[1].region, 'LON') self.assertEqual(entry.endpoints[1].endpoint_type, 'external') def test_parsing_auth_v2(self): data = self.fixtures.load('_v2_0__auth.json') data = json.loads(data) service_catalog = data['access']['serviceCatalog'] catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version='2.0') entries = catalog.get_entries() self.assertEqual(len(entries), 9) entry = [e for e in entries if e.service_name == 'cloudServers'][0] self.assertEqual(entry.service_type, 'compute') self.assertEqual(entry.service_name, 'cloudServers') self.assertEqual(len(entry.endpoints), 1) self.assertIsNone(entry.endpoints[0].region) self.assertEqual(entry.endpoints[0].url, 'https://servers.api.rackspacecloud.com/v1.0/1337') self.assertEqual(entry.endpoints[0].endpoint_type, 'external') def test_parsing_auth_v3(self): data = self.fixtures.load('_v3__auth.json') data = json.loads(data) service_catalog = data['token']['catalog'] catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version='3.x') entries = catalog.get_entries() self.assertEqual(len(entries), 6) entry = [e for e in entries if e.service_type == 'volume'][0] self.assertEqual(entry.service_type, 'volume') self.assertIsNone(entry.service_name) self.assertEqual(len(entry.endpoints), 3) self.assertEqual(entry.endpoints[0].region, 'regionOne') self.assertEqual(entry.endpoints[0].endpoint_type, 'external') self.assertEqual(entry.endpoints[1].region, 'regionOne') self.assertEqual(entry.endpoints[1].endpoint_type, 'admin') self.assertEqual(entry.endpoints[2].region, 'regionOne') self.assertEqual(entry.endpoints[2].endpoint_type, 'internal') def test_get_public_urls(self): data = self.fixtures.load('_v2_0__auth.json') data = json.loads(data) service_catalog = data['access']['serviceCatalog'] catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version='2.0') public_urls = catalog.get_public_urls(service_type='object-store') expected_urls = ['https://storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111', 'https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111'] self.assertEqual(public_urls, expected_urls) def test_get_regions(self): data = self.fixtures.load('_v2_0__auth.json') data = json.loads(data) service_catalog = data['access']['serviceCatalog'] catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version='2.0') regions = catalog.get_regions(service_type='object-store') self.assertEqual(regions, ['LON', 'ORD']) regions = catalog.get_regions(service_type='invalid') self.assertEqual(regions, []) def test_get_service_types(self): data = self.fixtures.load('_v2_0__auth.json') data = json.loads(data) service_catalog = data['access']['serviceCatalog'] catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version='2.0') service_types = catalog.get_service_types() self.assertEqual(service_types, ['compute', 'image', 'network', 'object-store', 'rax:object-cdn', 'volumev2']) service_types = catalog.get_service_types(region='ORD') self.assertEqual(service_types, ['rax:object-cdn']) def test_get_service_names(self): data = self.fixtures.load('_v2_0__auth.json') data = json.loads(data) service_catalog = data['access']['serviceCatalog'] catalog = OpenStackServiceCatalog(service_catalog=service_catalog, auth_version='2.0') service_names = catalog.get_service_names() self.assertEqual(service_names, ['cinderv2', 'cloudFiles', 'cloudFilesCDN', 'cloudServers', 'cloudServersOpenStack', 'cloudServersPreprod', 'glance', 'neutron', 'nova']) service_names = catalog.get_service_names(service_type='compute') self.assertEqual(service_names, ['cloudServers', 'cloudServersOpenStack', 'cloudServersPreprod', 'nova']) class OpenStackIdentity_2_0_MockHttp(MockHttp): fixtures = ComputeFileFixtures('openstack_identity/v2') json_content_headers = {'content-type': 'application/json; charset=UTF-8'} def _v2_0_tenants(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v2_0_tenants.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() class OpenStackIdentity_3_0_MockHttp(MockHttp): fixtures = ComputeFileFixtures('openstack_identity/v3') json_content_headers = {'content-type': 'application/json; charset=UTF-8'} def _v3(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v3_versions.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_domains(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v3_domains.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_projects(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v3_projects.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_auth_tokens(self, method, url, body, headers): if method == 'POST': status = httplib.OK data = json.loads(body) if 'password' in data['auth']['identity']: if data['auth']['identity']['password']['user']['domain']['name'] != 'test_domain' or \ data['auth']['scope']['project']['domain']['id'] != 'test_tenant_domain_id': status = httplib.UNAUTHORIZED body = ComputeFileFixtures('openstack').load('_v3__auth.json') headers = self.json_content_headers.copy() headers['x-subject-token'] = '00000000000000000000000000000000' return (status, body, headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_users(self, method, url, body, headers): if method == 'GET': # list users body = self.fixtures.load('v3_users.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == 'POST': # create user body = self.fixtures.load('v3_create_user.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.CREATED]) raise NotImplementedError() def _v3_users_a(self, method, url, body, headers): if method == 'GET': # look up a user body = self.fixtures.load('v3_users_a.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'PATCH': # enable / disable user body = self.fixtures.load('v3_users_a.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_users_b(self, method, url, body, headers): if method == 'GET': # look up a user body = self.fixtures.load('v3_users_b.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_users_c(self, method, url, body, headers): if method == 'GET': # look up a user body = self.fixtures.load('v3_users_c.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_roles(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v3_roles.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_domains_default_users_a_roles_a(self, method, url, body, headers): if method == 'PUT': # grant domain role body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.NO_CONTENT]) elif method == 'DELETE': # revoke domain role body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.NO_CONTENT]) raise NotImplementedError() def _v3_projects_a_users_a_roles_a(self, method, url, body, headers): if method == 'PUT': # grant project role body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.NO_CONTENT]) elif method == 'DELETE': # revoke project role body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.NO_CONTENT]) raise NotImplementedError() def _v3_domains_default(self, method, url, body, headers): if method == 'GET': # get domain body = self.fixtures.load('v3_domains_default.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_users_a_projects(self, method, url, body, headers): if method == 'GET': # get user projects body = self.fixtures.load('v3_users_a_projects.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_domains_default_users_a_roles(self, method, url, body, headers): if method == 'GET': # get user domain roles body = self.fixtures.load('v3_domains_default_users_a_roles.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_OS_FEDERATION_identity_providers_idp_protocols_oidc_auth(self, method, url, body, headers): if method == 'GET': headers = self.json_content_headers.copy() headers['x-subject-token'] = '00000000000000000000000000000000' return (httplib.OK, body, headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_OS_FEDERATION_projects(self, method, url, body, headers): if method == 'GET': # get user projects body = json.dumps({"projects": [{"id": "project_id", "name": "project_name"}, {"id": "project_id2", "name": "project_name2"}]}) return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_auth_projects(self, method, url, body, headers): if method == 'GET': # get user projects body = json.dumps({"projects": [{"id": "project_id", "name": "project_name"}, {"id": "project_id2", "name": "project_name2"}]}) return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() class OpenStackIdentity_3_0_federation_projects_MockHttp(OpenStackIdentity_3_0_MockHttp): fixtures = ComputeFileFixtures('openstack_identity/v3') json_content_headers = {'content-type': 'application/json; charset=UTF-8'} def _v3_OS_FEDERATION_projects(self, method, url, body, headers): if method == 'GET': # get user projects body = json.dumps({"projects": [{"id": "project_id"}]}) return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v3_auth_projects(self, method, url, body, headers): return (httplib.INTERNAL_SERVER_ERROR, body, self.json_content_headers, httplib.responses[httplib.INTERNAL_SERVER_ERROR]) class OpenStackIdentity_2_0_Connection_VOMSMockHttp(MockHttp): fixtures = ComputeFileFixtures('openstack_identity/v2') json_content_headers = {'content-type': 'application/json; charset=UTF-8'} def _v2_0_tokens(self, method, url, body, headers): if method == 'POST': status = httplib.UNAUTHORIZED data = json.loads(body) if 'voms' in data['auth'] and data['auth']['voms'] is True: status = httplib.OK body = ComputeFileFixtures('openstack').load('_v2_0__auth.json') headers = self.json_content_headers.copy() headers['x-subject-token'] = '00000000000000000000000000000000' return (status, body, headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v2_0_tenants(self, method, url, body, headers): if method == 'GET': # get user projects body = json.dumps({"tenant": [{"name": "tenant_name"}]}) return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/common/test_ovh.py0000664000175000017500000000223213535474530022704 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re from libcloud.test import MockHttp FORMAT_URL = re.compile(r'[./?=-]') class BaseOvhMockHttp(MockHttp): def _get_method_name(self, type, use_param, qs, path): return "_json" def _json(self, method, url, body, headers): meth_name = '_json%s_%s' % (FORMAT_URL.sub('_', url), method.lower()) return getattr(self, meth_name)(method, url, body, headers) apache-libcloud-2.8.0/libcloud/test/common/test_retry_limit.py0000664000175000017500000000435013535474530024456 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import socket import ssl from mock import Mock, patch, MagicMock from libcloud.utils.misc import TRANSIENT_SSL_ERROR from libcloud.common.base import Connection from libcloud.test import unittest CONFLICT_RESPONSE_STATUS = [ ('status', '429'), ('reason', 'CONFLICT'), ('retry_after', '3'), ('content-type', 'application/json')] SIMPLE_RESPONSE_STATUS = ('HTTP/1.1', 429, 'CONFLICT') @patch('os.environ', {'LIBCLOUD_RETRY_FAILED_HTTP_REQUESTS': True}) class FailedRequestRetryTestCase(unittest.TestCase): def test_retry_connection(self): con = Connection(timeout=0.2, retry_delay=0.1) con.connection = Mock() connect_method = 'libcloud.common.base.Connection.request' with patch(connect_method) as mock_connect: try: mock_connect.side_effect = socket.gaierror('') con.request('/') except socket.gaierror: pass def test_retry_connection_ssl_error(self): conn = Connection(timeout=0.2, retry_delay=0.1) with patch.object(conn, 'connect', Mock()): with patch.object(conn, 'connection') as connection: connection.request = MagicMock( __name__='request', side_effect=ssl.SSLError(TRANSIENT_SSL_ERROR)) self.assertRaises(ssl.SSLError, conn.request, '/') self.assertGreater(connection.request.call_count, 1) if __name__ == '__main__': unittest.main() apache-libcloud-2.8.0/libcloud/test/common/test_upcloud.py0000664000175000017500000002747513535474530023603 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import json from mock import Mock, call from libcloud.common.upcloud import UpcloudCreateNodeRequestBody, UpcloudNodeDestroyer, UpcloudNodeOperations from libcloud.common.upcloud import _StorageDevice from libcloud.common.upcloud import UpcloudTimeoutException from libcloud.common.upcloud import PlanPrice from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, NodeAuthSSHKey from libcloud.test import unittest class TestUpcloudCreateNodeRequestBody(unittest.TestCase): def setUp(self): self.image = NodeImage(id='01000000-0000-4000-8000-000030060200', name='Ubuntu Server 16.04 LTS (Xenial Xerus)', driver='', extra={'type': 'template'}) self.location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver='') self.size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048, extra={'core_number': 1, 'storage_tier': 'maxiops'}, price=None, driver='') def test_creating_node_from_template_image(self): body = UpcloudCreateNodeRequestBody(name='ts', image=self.image, location=self.location, size=self.size) json_body = body.to_json() dict_body = json.loads(json_body) expected_body = { 'server': { 'title': 'ts', 'hostname': 'localhost', 'plan': '1xCPU-1GB', 'zone': 'fi-hel1', 'login_user': {'username': 'root', 'create_password': 'yes'}, 'storage_devices': { 'storage_device': [{ 'action': 'clone', 'title': 'Ubuntu Server 16.04 LTS (Xenial Xerus)', 'storage': '01000000-0000-4000-8000-000030060200', 'size': 30, 'tier': 'maxiops', }] }, } } self.assertDictEqual(expected_body, dict_body) def test_creating_node_from_cdrom_image(self): image = NodeImage(id='01000000-0000-4000-8000-000030060200', name='Ubuntu Server 16.04 LTS (Xenial Xerus)', driver='', extra={'type': 'cdrom'}) body = UpcloudCreateNodeRequestBody(name='ts', image=image, location=self.location, size=self.size) json_body = body.to_json() dict_body = json.loads(json_body) expected_body = { 'server': { 'title': 'ts', 'hostname': 'localhost', 'plan': '1xCPU-1GB', 'zone': 'fi-hel1', 'login_user': {'username': 'root', 'create_password': 'yes'}, 'storage_devices': { 'storage_device': [ { 'action': 'create', 'size': 30, 'tier': 'maxiops', 'title': 'Ubuntu Server 16.04 LTS (Xenial Xerus)', }, { 'action': 'attach', 'storage': '01000000-0000-4000-8000-000030060200', 'type': 'cdrom' } ] } } } self.assertDictEqual(expected_body, dict_body) def test_creating_node_using_ssh_keys(self): auth = NodeAuthSSHKey('sshkey') body = UpcloudCreateNodeRequestBody(name='ts', image=self.image, location=self.location, size=self.size, auth=auth) json_body = body.to_json() dict_body = json.loads(json_body) expected_body = { 'server': { 'title': 'ts', 'hostname': 'localhost', 'plan': '1xCPU-1GB', 'zone': 'fi-hel1', 'login_user': { 'username': 'root', 'ssh_keys': { 'ssh_key': [ 'sshkey' ] }, }, 'storage_devices': { 'storage_device': [{ 'action': 'clone', 'size': 30, 'title': 'Ubuntu Server 16.04 LTS (Xenial Xerus)', 'tier': 'maxiops', 'storage': '01000000-0000-4000-8000-000030060200' }] }, } } self.assertDictEqual(expected_body, dict_body) def test_creating_node_using_hostname(self): body = UpcloudCreateNodeRequestBody(name='ts', image=self.image, location=self.location, size=self.size, ex_hostname='myhost.upcloud.com') json_body = body.to_json() dict_body = json.loads(json_body) expected_body = { 'server': { 'title': 'ts', 'hostname': 'myhost.upcloud.com', 'plan': '1xCPU-1GB', 'zone': 'fi-hel1', 'login_user': {'username': 'root', 'create_password': 'yes'}, 'storage_devices': { 'storage_device': [{ 'action': 'clone', 'title': 'Ubuntu Server 16.04 LTS (Xenial Xerus)', 'storage': '01000000-0000-4000-8000-000030060200', 'tier': 'maxiops', 'size': 30 }] }, } } self.assertDictEqual(expected_body, dict_body) def test_creating_node_with_non_default_username(self): body = UpcloudCreateNodeRequestBody(name='ts', image=self.image, location=self.location, size=self.size, ex_username='someone') json_body = body.to_json() dict_body = json.loads(json_body) login_user = dict_body['server']['login_user'] self.assertDictEqual({'username': 'someone', 'create_password': 'yes'}, login_user) class TestStorageDevice(unittest.TestCase): def setUp(self): self.image = NodeImage(id='01000000-0000-4000-8000-000030060200', name='Ubuntu Server 16.04 LTS (Xenial Xerus)', driver='', extra={'type': 'template'}) self.size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048, extra={'core_number': 1}, price=None, driver='') def test_storage_tier_default_value(self): storagedevice = _StorageDevice(self.image, self.size) d = storagedevice.to_dict() self.assertEqual(d['storage_device'][0]['tier'], 'maxiops') def test_storage_tier_given(self): self.size.extra['storage_tier'] = 'hdd' storagedevice = _StorageDevice(self.image, self.size) d = storagedevice.to_dict() self.assertEqual(d['storage_device'][0]['tier'], 'hdd') class TestUpcloudNodeDestroyer(unittest.TestCase): def setUp(self): self.mock_sleep = Mock() self.mock_operations = Mock(spec=UpcloudNodeOperations) self.destroyer = UpcloudNodeDestroyer(self.mock_operations, sleep_func=self.mock_sleep) def test_node_already_in_stopped_state(self): self.mock_operations.get_node_state.side_effect = ['stopped'] self.assertTrue(self.destroyer.destroy_node(1)) self.assertTrue(self.mock_operations.stop_node.call_count == 0) self.mock_operations.destroy_node.assert_called_once_with(1) def test_node_in_error_state(self): self.mock_operations.get_node_state.side_effect = ['error'] self.assertFalse(self.destroyer.destroy_node(1)) self.assertTrue(self.mock_operations.stop_node.call_count == 0) self.assertTrue(self.mock_operations.destroy_node.call_count == 0) def test_node_in_started_state(self): self.mock_operations.get_node_state.side_effect = ['started', 'stopped'] self.assertTrue(self.destroyer.destroy_node(1)) self.mock_operations.stop_node.assert_called_once_with(1) self.mock_operations.destroy_node.assert_called_once_with(1) def test_node_in_maintenace_state(self): self.mock_operations.get_node_state.side_effect = ['maintenance', 'maintenance', None] self.assertTrue(self.destroyer.destroy_node(1)) self.mock_sleep.assert_has_calls([call(self.destroyer.WAIT_AMOUNT), call(self.destroyer.WAIT_AMOUNT)]) self.assertTrue(self.mock_operations.stop_node.call_count == 0) self.assertTrue(self.mock_operations.destroy_node.call_count == 0) def test_node_statys_in_started_state_for_awhile(self): self.mock_operations.get_node_state.side_effect = ['started', 'started', 'stopped'] self.assertTrue(self.destroyer.destroy_node(1)) # Only one all for stop should be done self.mock_operations.stop_node.assert_called_once_with(1) self.mock_sleep.assert_has_calls([call(self.destroyer.WAIT_AMOUNT)]) self.mock_operations.destroy_node.assert_called_once_with(1) def test_reuse(self): """Verify that internal flag self.destroyer._stop_node is handled properly""" self.mock_operations.get_node_state.side_effect = ['started', 'stopped', 'started', 'stopped'] self.assertTrue(self.destroyer.destroy_node(1)) self.assertTrue(self.destroyer.destroy_node(1)) self.assertEqual(self.mock_sleep.call_count, 0) self.assertEqual(self.mock_operations.stop_node.call_count, 2) def test_timeout(self): self.mock_operations.get_node_state.side_effect = ['maintenance'] * 50 self.assertRaises(UpcloudTimeoutException, self.destroyer.destroy_node, 1) def test_timeout_reuse(self): """Verify sleep count is handled properly""" self.mock_operations.get_node_state.side_effect = ['maintenance'] * 50 self.assertRaises(UpcloudTimeoutException, self.destroyer.destroy_node, 1) self.mock_operations.get_node_state.side_effect = ['maintenance', None] self.assertTrue(self.destroyer.destroy_node(1)) class TestPlanPrice(unittest.TestCase): def setUp(self): prices = [{'name': 'uk-lon1', 'server_plan_1xCPU-1GB': {'amount': 1, 'price': 1.488}}, {'name': 'fi-hel1', 'server_plan_1xCPU-1GB': {'amount': 1, 'price': 1.588}}] self.pp = PlanPrice(prices) def test_zone_prices(self): location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver=None) self.assertEqual(self.pp.get_price('1xCPU-1GB', location), 1.588) def test_plan_not_found_in_zone(self): location = NodeLocation(id='no_such_location', name='', country='', driver=None) self.assertIsNone(self.pp.get_price('1xCPU-1GB', location)) def test_no_location_given(self): self.assertIsNone(self.pp.get_price('1xCPU-1GB')) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/0000775000175000017500000000000013600223624020651 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/__init__.py0000664000175000017500000000775513535474530023013 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.compute.base import Node, NodeImage, NodeLocation, StorageVolume from libcloud.pricing import get_pricing class TestCaseMixin(): should_list_locations = True should_have_pricing = False should_list_volumes = False def test_list_nodes_response(self): nodes = self.driver.list_nodes() self.assertTrue(isinstance(nodes, list)) for node in nodes: self.assertTrue(isinstance(node, Node)) def test_list_sizes_response(self): sizes = self.driver.list_sizes() size = sizes[0] self.assertTrue(isinstance(sizes, list)) # Check that size values are ints or None self.assertTrue(size.ram is None or isinstance(size.ram, int)) self.assertTrue(size.disk is None or isinstance(size.disk, int)) self.assertTrue(size.bandwidth is None or isinstance(size.bandwidth, int)) # Check that price values are ints, floats, or None. self.assertTrue(size.price is None or isinstance(size.price, float) or isinstance(size.price, int)) def test_list_images_response(self): images = self.driver.list_images() self.assertTrue(isinstance(images, list)) for image in images: self.assertTrue(isinstance(image, NodeImage)) def test_list_volumes_response(self): if not self.should_list_volumes: return None volumes = self.driver.list_volumes() self.assertTrue(isinstance(volumes, list)) for volume in volumes: self.assertTrue(isinstance(volume, StorageVolume)) def test_list_locations_response(self): if not self.should_list_locations: return None locations = self.driver.list_locations() self.assertTrue(isinstance(locations, list)) for dc in locations: self.assertTrue(isinstance(dc, NodeLocation)) def test_create_node_response(self): # should return a node object size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node(name='node-name', image=image, size=size) self.assertTrue(isinstance(node, Node)) def test_destroy_node_response(self): # should return a node object node = self.driver.list_nodes()[0] ret = self.driver.destroy_node(node) self.assertTrue(isinstance(ret, bool)) def test_reboot_node_response(self): # should return a node object node = self.driver.list_nodes()[0] ret = self.driver.reboot_node(node) self.assertTrue(isinstance(ret, bool)) def test_get_pricing_success(self): if not self.should_have_pricing: return None driver_type = 'compute' try: get_pricing(driver_type=driver_type, driver_name=self.driver.api_name) except KeyError: self.fail("No {driver_type!r} pricing info for {driver}.".format( driver=self.driver.__class__.__name__, driver_type=driver_type, )) if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/test/compute/fixtures/0000775000175000017500000000000013600223624022522 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/0000775000175000017500000000000013600223624024002 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/dcs.xml0000664000175000017500000001247113535474530025315 0ustar kamikami00000000000000 2 barcelona barcelona 3 1 VIRTUAL_FACTORY http://10.60.12.7:80/virtualfactory 4 1 VIRTUAL_SYSTEM_MONITOR http://10.60.12.7:80/vsm 5 1 APPLIANCE_MANAGER http://10.60.12.7:80/am 6 1 NODE_COLLECTOR http://10.60.12.7:80/nodecollector 7 1 STORAGE_SYSTEM_MONITOR http://10.60.12.7:80/ssm 8 1 DHCP_SERVICE omapi://10.60.12.7:7911 9 1 BPM_SERVICE http://10.60.12.7:80/bpm-async Abiquo apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/ent_1.xml0000664000175000017500000000474113535474530025553 0ustar kamikami00000000000000 0 0 0 0 0 0 0 0 0 0 0 0 1 false Abiquo 0 0 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2.xml0000664000175000017500000000216013535474530027142 0ustar kamikami00000000000000 2virtual image repo010.60.1.72:/opt/vm_repository0 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_template_11.xml0000664000175000017500000000405213535474530031340 0ustar kamikami00000000000000 11 m0n0wall-vhd m0n0wall image in VHD format ready for XenServer and HyperV 1/rs/abiport9000/ovf/269/m0n0wall-1.3b18-i386-flat.vmdk-VHD_SPARSE.vhd VHD_SPARSE 10490880 1 128 27262976 false 0 2013-01-10T20:25:12-05:00 SYSTEM false http://icons.abiquo.com/monowall.jpg apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/ent_1_dcrep_2_templates.xml0000664000175000017500000001016513535474530031224 0ustar kamikami00000000000000 11m0n0wall-vhdm0n0wall image in VHD format ready for XenServer and HyperV1/rs/abiport9000/ovf/269/m0n0wall-1.3b18-i386-flat.vmdk-VHD_SPARSE.vhdVHD_SPARSE10490880112827262976false02013-01-10T20:25:12-05:00SYSTEMfalsehttp://icons.abiquo.com/monowall.jpg 19 RHEL6 Build Bot RHEL6 Build Bot 1/rs/abiport9000/ovf/73/build-bot-rhel6-disk1.vmdk VMDK_STREAM_OPTIMIZED 351064576 1 1024 4294967296 false 0 2013-01-10T20:25:12-05:00 SYSTEM false http://rs.bcn.abiquo.com:9000/public/icons/q.png apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/ent_1_dcreps.xml0000664000175000017500000000227713535474530027115 0ustar kamikami00000000000000 2virtual image repo010.60.1.72:/opt/vm_repository0 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/login.xml0000664000175000017500000000157513535474530025657 0ustar kamikami00000000000000 true ABIQUO Standard user 2 en_US Standard user c69a39bd64ffb77ea7ee3369dce742f3 User apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/not_found_error.xml0000664000175000017500000000030113535474530027735 0ustar kamikami00000000000000 DC-0 The requested datacenter does not exist apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/privilege_errors.html0000664000175000017500000000237713535474530030276 0ustar kamikami00000000000000 Apache Tomcat/6.0.35 - Error report

HTTP Status 403 - Access is denied


type Status report

message Access is denied

description Access to the specified resource (Access is denied) has been forbidden.


Apache Tomcat/6.0.35

apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/unauthorized_user.html0000664000175000017500000000236213535474530030465 0ustar kamikami00000000000000 Apache Tomcat/6.0.35 - Error report

HTTP Status 401 - Bad credentials


type Status report

message Bad credentials

description This request requires HTTP authentication (Bad credentials).


Apache Tomcat/6.0.35

apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4.xml0000664000175000017500000000631313535474530025541 0ustar kamikami00000000000000 0 0 0 0 0 0 0 0 0 0 0 0 KVM 4 vdc_kvm
192.168.0.0
192.168.0.1 2 24 default_private_network INTERNAL
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5.xml0000664000175000017500000000320313535474530027006 0ustar kamikami00000000000000 0 0 5 libcloud_test_group 0 NOT_DEPLOYED apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_needs_sync.xml0000664000175000017500000000320113535474530031216 0ustar kamikami00000000000000 0 0 5 libcloud_test_group 0 NEEDS_SYNC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vm_3_not_allocated.xml0000664000175000017500000000762113535474530032632 0ustar kamikami00000000000000 1 0 3 1 1 ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614 128 NOT_ALLOCATED 914f8125-33d3-4fe3-a162-5d6f5bf32614 0 3 0 0 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_5_vms.xml0000664000175000017500000000744613535474530027710 0ustar kamikami00000000000000 10311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf326140300 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6.xml0000664000175000017500000000326013535474530027012 0ustar kamikami00000000000000 0 0 6 libcloud <connections/> 0 DEPLOYED apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy.xml0000664000175000017500000000052613535474530030733 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task.xml0000664000175000017500000000276413535474530031763 0ustar kamikami00000000000000 Undeploy task's power off on virtual machine with id 3 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.103a1a6b-4de2-48d8-9a38-8698561020b8 1da8c8b6-86f6-49ef-9d29-57dcc73b875a UNKNOWN DONE 1358012669 POWER_OFF Undeploy task's deconfigure on virtual machine with id 3 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.e4250ca9-505d-4640-9ad2-fb101f9e9978 1da8c8b6-86f6-49ef-9d29-57dcc73b875a UNKNOWN DONE 1358012669 DECONFIGURE 3 FINISHED_SUCCESSFULLY 1da8c8b6-86f6-49ef-9d29-57dcc73b875a 1358012669 UNDEPLOY admin apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_undeploy_task_failed.xml0000664000175000017500000000276613535474530033271 0ustar kamikami00000000000000 Undeploy task's power off on virtual machine with id 3 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.103a1a6b-4de2-48d8-9a38-8698561020b8 1da8c8b6-86f6-49ef-9d29-57dcc73b875a UNKNOWN DONE 1358012669 POWER_OFF Undeploy task's deconfigure on virtual machine with id 3 1da8c8b6-86f6-49ef-9d29-57dcc73b875a.e4250ca9-505d-4640-9ad2-fb101f9e9978 1da8c8b6-86f6-49ef-9d29-57dcc73b875a UNKNOWN DONE 1358012669 DECONFIGURE 3 FINISHED_UNSUCCESSFULLY 1da8c8b6-86f6-49ef-9d29-57dcc73b875a 1358012669 UNDEPLOY admin apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3.xml0000664000175000017500000000755113535474530027745 0ustar kamikami00000000000000 10311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf32614590130080.12.23.43 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_allocated.xml0000664000175000017500000000754513535474530031760 0ustar kamikami00000000000000 10311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf32614590130080.12.23.43 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy.xml0000664000175000017500000000066513535474530031320 0ustar kamikami00000000000000 You can keep track of the progress in the link apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task.xml0000664000175000017500000000274713535474530032345 0ustar kamikami00000000000000 Deploy task's configure on virtual machine with id 3 b44fe278-6b0f-4dfb-be81-7c03006a93cb.a04623bd-7b2c-4c23-9441-aeaa39dd4893 b44fe278-6b0f-4dfb-be81-7c03006a93cb UNKNOWN DONE 1357872859 CONFIGURE Deploy task's power on on virtual machine with id 3 b44fe278-6b0f-4dfb-be81-7c03006a93cb.2fdee19a-4fad-4040-bc94-7acfd6fedc48 b44fe278-6b0f-4dfb-be81-7c03006a93cb UNKNOWN DONE 1357872859 POWER_ON 3 FINISHED_SUCCESSFULLY b44fe278-6b0f-4dfb-be81-7c03006a93cb 1357872859 DEPLOY user apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deploy_task_failed.xml0000664000175000017500000000273113535474530033642 0ustar kamikami00000000000000 Deploy task's configure on virtual machine with id 3 b44fe278-6b0f-4dfb-be81-7c03006a93cb.a04623bd-7b2c-4c23-9441-aeaa39dd4893 b44fe278-6b0f-4dfb-be81-7c03006a93cb UNKNOWN DONE 1357872859 CONFIGURE Deploy task's power on on virtual machine with id 3 b44fe278-6b0f-4dfb-be81-7c03006a93cb.2fdee19a-4fad-4040-bc94-7acfd6fedc48 b44fe278-6b0f-4dfb-be81-7c03006a93cb UNKNOWN DONE 1357872859 POWER_ON 3 ABORTED b44fe278-6b0f-4dfb-be81-7c03006a93cb 1357872859 DEPLOY user apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_deployed.xml0000664000175000017500000000753613535474530031635 0ustar kamikami00000000000000 10311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128ON914f8125-33d3-4fe3-a162-5d6f5bf32614590130080.12.23.43 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_nics.xml0000664000175000017500000000165713535474530030762 0ustar kamikami00000000000000 64192.168.0.252:54:00:b7:f7:850 36434.34.34.552:54:00:b7:f7:880 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset.xml0000664000175000017500000000067713535474530031151 0ustar kamikami00000000000000 You can keep track of the progress in the link apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_reset_task.xml0000664000175000017500000000203513535474530032161 0ustar kamikami00000000000000 Reset task's reset on virtual machine with id 3 a8c9818e-f389-45b7-be2c-3db3a9689940.5f42a7fc-82f3-4121-be26-da62eb8b9b92 a8c9818e-f389-45b7-be2c-3db3a9689940 ROLLBACK_DONE FAILED 1357873142 RESET 3 FINISHED_SUCCESSFULLY a8c9818e-f389-45b7-be2c-3db3a9689940 1357873142 RESET user apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy.xml0000664000175000017500000000067713535474530031666 0ustar kamikami00000000000000 You can keep track of the progress in the link apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task.xml0000664000175000017500000000203513535474530032676 0ustar kamikami00000000000000 Reset task's reset on virtual machine with id 3 a8c9818e-f389-45b7-be2c-3db3a9689940.5f42a7fc-82f3-4121-be26-da62eb8b9b92 a8c9818e-f389-45b7-be2c-3db3a9689940 ROLLBACK_DONE FAILED 1357873142 RESET 3 FINISHED_SUCCESSFULLY a8c9818e-f389-45b7-be2c-3db3a9689940 1357873142 RESET user ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task_failed.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_3_undeploy_task_failed.x0000664000175000017500000000203713535474530033653 0ustar kamikami00000000000000 Reset task's reset on virtual machine with id 3 a8c9818e-f389-45b7-be2c-3db3a9689940.5f42a7fc-82f3-4121-be26-da62eb8b9b92 a8c9818e-f389-45b7-be2c-3db3a9689940 ROLLBACK_DONE FAILED 1357873142 RESET 3 FINISHED_UNSUCCESSFULLY a8c9818e-f389-45b7-be2c-3db3a9689940 1357873142 RESET user apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vm_creation_ok.xml0000664000175000017500000000675513535474530032105 0ustar kamikami00000000000000 10311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf326140 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms.xml0000664000175000017500000000744613535474530027711 0ustar kamikami00000000000000 10311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128NOT_ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf326140300 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_6_vms_allocated.xml0000664000175000017500000000744213535474530031715 0ustar kamikami00000000000000 10311ABQ_914f8125-33d3-4fe3-a162-5d6f5bf32614128ALLOCATED914f8125-33d3-4fe3-a162-5d6f5bf326140300 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapp_creation_ok.xml0000664000175000017500000000320313535474530031137 0ustar kamikami00000000000000 0 0 5 libcloud_test_group 0 NOT_DEPLOYED apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdc_4_vapps.xml0000664000175000017500000000673713535474530026764 0ustar kamikami00000000000000 2 006libcloud0DEPLOYED 005libcloud_test_group0NOT_DEPLOYED apache-libcloud-2.8.0/libcloud/test/compute/fixtures/abiquo/vdcs.xml0000664000175000017500000000665613535474530025513 0ustar kamikami00000000000000 0 0 0 0 0 0 0 0 0 0 0 0 KVM 4 vdc_kvm
192.168.0.0
192.168.0.1 2 24 default_private_network INTERNAL
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/0000775000175000017500000000000013600223624023650 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_locations.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_loc0000664000175000017500000001676313535474530031700 0ustar kamikami00000000000000East AsiaEast AsiaComputeStoragePersistentVMRoleHighMemoryA5A6A7ExtraLargeExtraSmallLargeMediumSmallA5A6A7Basic_A0Basic_A1Basic_A2Basic_A3Basic_A4ExtraLargeExtraSmallLargeMediumSmallSoutheast AsiaSoutheast AsiaComputeStoragePersistentVMRoleHighMemoryA5A6A7ExtraLargeExtraSmallLargeMediumSmallA5A6A7Basic_A0Basic_A1Basic_A2Basic_A3Basic_A4ExtraLargeExtraSmallLargeMediumSmallNorth EuropeNorth EuropeComputeStoragePersistentVMRoleHighMemoryA5A6A7A8A9ExtraLargeExtraSmallLargeMediumSmallA5A6A7A8A9Basic_A0Basic_A1Basic_A2Basic_A3Basic_A4ExtraLargeExtraSmallLargeMediumSmallWest EuropeWest EuropeComputeStoragePersistentVMRoleHighMemoryA5A6A7A8A9ExtraLargeExtraSmallLargeMediumSmallA5A6A7A8A9Basic_A0Basic_A1Basic_A2Basic_A3Basic_A4ExtraLargeExtraSmallLargeMediumSmallEast USEast USComputeStoragePersistentVMRoleHighMemoryA5A6A7A8A9ExtraLargeExtraSmallLargeMediumSmallA5A6A7A8A9Basic_A0Basic_A1Basic_A2Basic_A3Basic_A4ExtraLargeExtraSmallLargeMediumSmallNorth Central USNorth Central USComputeStoragePersistentVMRoleHighMemoryA5A6A7A8A9ExtraLargeExtraSmallLargeMediumSmallA5A6A7A8A9Basic_A0Basic_A1Basic_A2Basic_A3Basic_A4ExtraLargeExtraSmallLargeMediumSmallWest USWest USComputeStoragePersistentVMRoleHighMemoryA5A6A7A8A9ExtraLargeExtraSmallLargeMediumSmallA5A6A7A8A9Basic_A0Basic_A1Basic_A2Basic_A3Basic_A4ExtraLargeExtraSmallLargeMediumSmall././@LongLink0000000000000000000000000000022100000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_operations_acc33f6756cda6fd96826394fce4c9f3.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ope0000664000175000017500000000030413535474530031666 0ustar kamikami00000000000000fbd6fd8f-9e3e-acad-8524-92f64e1050b6Succeeded././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000001374713535474530031713 0ustar kamikami00000000000000https://management.core.windows.net/5191b16a-673d-426c-8c55-fdd912858e4e/services/hostedservices/dcoddkinztest01dcoddkinztest01North EuropeCreated2014-05-23T12:32:51Z2014-05-27T15:30:15Zdc03Productionf1f3169a845a4a2c9b76101934d84d72Runninghttp://dcoddkinztest01.cloudapp.net/PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJkYzAzIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQogIDxSb2xlIG5hbWU9Im9kZGtpbnoyIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQo8L1NlcnZpY2VDb25maWd1cmF0aW9uPg==dc03dc03ReadyRole00Small100.92.66.69SSH191.235.135.622222tcpStarteddc03685099736b68f503fdbcb0164369b2471.02014-05-28T10:09:42ZUnknownNotReadyen-USVM Agent is unresponsive. Status was last reported at 2014-05-27T15:30:08Z.oddkinz2oddkinz2ReadyRole00Small100.92.60.107SSH191.235.135.625770622tcpStartedoddkinz20c2115da20a7293aedf34bfe4dca9db21.02014-05-28T10:09:42ZUnknownNotReadyen-USVM Agent is unresponsive. Status was last reported at 2014-05-27T15:49:58Z.1dc03PersistentVMRoleNetworkConfiguration22SSH22tcp191.235.135.62falseReadWritedc03-dc03-0-201405271530050398http://mtlytics.blob.core.windows.net/vhds/dcoddkinztest01-dc03-2014-05-27.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxSmalltrueoddkinz2PersistentVMRoleNetworkConfiguration22SSH57706tcp191.235.135.62falseReadWritedc03-oddkinz2-0-201405271549530290http://mtlytics.blob.core.windows.net/vhds/dcoddkinztest01-oddkinz2-2014-05-27.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxSmalltruefalsefalse2014-05-27T15:30:01Z2014-05-28T10:09:41Z2014-04-01T23:49:45Z2014-04-03T23:49:45ZPersistentVMUpdateCompleted
191.235.135.62
truedc03ContractContract
dcoddkinztest01.f5.internal.cloudapp.net
././@LongLink0000000000000000000000000000026100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deployments_dc03_roleinstances_dc13.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000030513535474530031675 0ustar kamikami00000000000000ResourceNotFoundRole instance name is not valid.././@LongLink0000000000000000000000000000025000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deploymentslots_Production.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000001274113535474530031704 0ustar kamikami00000000000000dc03Productionf1f3169a845a4a2c9b76101934d84d72Runninghttp://dcoddkinztest01.cloudapp.net/PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJkYzAzIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQogIDxSb2xlIG5hbWU9Im9kZGtpbnoyIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQo8L1NlcnZpY2VDb25maWd1cmF0aW9uPg==dc03dc03ReadyRole00Small100.92.66.69SSH191.235.135.622222tcpStarteddc03685099736b68f503fdbcb0164369b2471.02014-05-28T09:20:27ZUnknownNotReadyen-USVM Agent is unresponsive. Status was last reported at 2014-05-27T15:30:08Z.oddkinz2oddkinz2ReadyRole00Small100.92.60.107SSH191.235.135.625770622tcpStartedoddkinz20c2115da20a7293aedf34bfe4dca9db21.02014-05-28T09:20:27ZUnknownNotReadyen-USVM Agent is unresponsive. Status was last reported at 2014-05-27T15:49:58Z.1dc03PersistentVMRoleNetworkConfiguration22SSH22tcp191.235.135.62falseReadWritedc03-dc03-0-201405271530050398http://mtlytics.blob.core.windows.net/vhds/dcoddkinztest01-dc03-2014-05-27.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxSmalltrueoddkinz2PersistentVMRoleNetworkConfiguration22SSH57706tcp191.235.135.62falseReadWritedc03-oddkinz2-0-201405271549530290http://mtlytics.blob.core.windows.net/vhds/dcoddkinztest01-oddkinz2-2014-05-27.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxSmalltruefalsefalse2014-05-27T15:30:01Z2014-05-28T09:20:26Z2014-04-01T23:49:45Z2014-04-03T23:49:45ZPersistentVMUpdateCompleted
191.235.135.62
truedc03ContractContract
dcoddkinztest01.f5.internal.cloudapp.net
././@LongLink0000000000000000000000000000025000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest02_deploymentslots_Production.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000027713535474530031705 0ustar kamikami00000000000000ResourceNotFoundNo deployments were found.././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000030713535474530031677 0ustar kamikami00000000000000ResourceNotFoundThe hosted service does not exist.././@LongLink0000000000000000000000000000025000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03_deploymentslots_Production.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000027713535474530031705 0ustar kamikami00000000000000ResourceNotFoundNo deployments were found.././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest04.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000030713535474530031677 0ustar kamikami00000000000000ResourceNotFoundThe hosted service does not exist.././@LongLink0000000000000000000000000000024100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz1_deploymentslots_Production.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000662213535474530031705 0ustar kamikami00000000000000dc01Production5a62b73e8a2e448398e3485a112c5232Runninghttp://dcoddkinztest01.cloudapp.net/PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJkYzAxIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQo8L1NlcnZpY2VDb25maWd1cmF0aW9uPg==dc01dc01ReadyRole00Small10.77.46.71SSH168.63.66.2042222tcpStarteddc017e1eac23032be4029fc02f676c866ddf1.02014-05-27T15:12:29ZUnknownNotReadyen-USVM Agent is unresponsive. Status was last reported at 2014-05-27T14:59:30Z.1dc01PersistentVMRoleNetworkConfiguration22SSH22tcp168.63.66.204falseReadWritedc01-dc01-0-201405271459270089http://mtlytics.blob.core.windows.net/vhds/dcoddkinztest01-dc01-2014-05-27.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxSmalltruefalsefalse2014-05-27T14:59:23Z2014-05-27T15:12:27Z2014-04-11T18:28:18Z2014-04-13T18:28:18ZPersistentVMUpdateCompleted
168.63.66.204
truedc01ContractContract
dcoddkinztest01.f3.internal.cloudapp.net
././@LongLink0000000000000000000000000000024100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz2_deploymentslots_Production.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000001257013535474530031704 0ustar kamikami00000000000000dc03Productionf1f3169a845a4a2c9b76101934d84d72Runninghttp://oddkinz2.cloudapp.net/PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJkYzAzIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQogIDxSb2xlIG5hbWU9Im9kZGtpbnoxIj4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQo8L1NlcnZpY2VDb25maWd1cmF0aW9uPg==dc03dc03ReadyRole00Small100.92.66.69SSH191.235.135.622222tcpStarteddc03685099736b68f503fdbcb0164369b2471.02014-05-27T15:38:47ZUnknownNotReadyen-USStatus not available for role dc03.oddkinz1oddkinz1ReadyRole00Small100.92.60.91SSH191.235.135.626331322tcpStartedoddkinz10318c2b4abba6f83e3e24185c36f876e1.02014-05-27T15:38:47ZUnknownNotReadyen-USStatus not available for role oddkinz1.1dc03PersistentVMRoleNetworkConfiguration22SSH22tcp191.235.135.62falseReadWritedc03-dc03-0-201405271530050398http://mtlytics.blob.core.windows.net/vhds/oddkinz2-dc03-2014-05-27.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxSmalltrueoddkinz1PersistentVMRoleNetworkConfiguration22SSH63313tcp191.235.135.62falseReadWritedc03-oddkinz1-0-201405271534090109http://mtlytics.blob.core.windows.net/vhds/oddkinz2-oddkinz1-2014-05-27.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxSmalltruefalsefalse2014-05-27T15:30:01Z2014-05-27T15:38:45Z2014-04-01T23:49:45Z2014-04-03T23:49:45ZPersistentVMUpdateCompleted
191.235.135.62
truedc03ContractContract
oddkinz2.f5.internal.cloudapp.net
././@LongLink0000000000000000000000000000024100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz5_deploymentslots_Production.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000027713535474530031705 0ustar kamikami00000000000000ResourceNotFoundNo deployments were found.././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdc1234.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000030713535474530031677 0ustar kamikami00000000000000ResourceNotFoundThe hosted service does not exist.././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000111313535474530031673 0ustar kamikami00000000000000https://management.core.windows.net/5191b16a-673d-426c-8c55-fdd912858e4e/services/hostedservices/testdc123testdc123North EuropeCreated2014-05-29T12:04:22Z2014-05-29T12:04:23Z././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000001236113535474530031702 0ustar kamikami00000000000000https://management.core.windows.net/5191b16a-673d-426c-8c55-fdd912858e4e/services/hostedservices/testdc123testdc123North EuropeCreated2014-05-29T12:04:22Z2014-05-29T12:05:06Zdcoddkinztest02Productionf18bf4439e6848138d9692cdcfa08769Runninghttp://testdc123.cloudapp.net/PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJkYzE0Ij4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQogIDxSb2xlIG5hbWU9ImRjb2Rka2luenRlc3QwMyI+DQogICAgPEluc3RhbmNlcyBjb3VudD0iMSIgLz4NCiAgPC9Sb2xlPg0KPC9TZXJ2aWNlQ29uZmlndXJhdGlvbj4=dc14dc14ReadyRole00ExtraSmall100.86.126.44SSH137.116.228.1094581022tcpStarteddc148bd92d2a2bd27182427a02ba38dcd16ddcoddkinztest03dcoddkinztest03ReadyRole00ExtraSmall100.86.132.14SSH137.116.228.1092222tcpStarteddcoddkinztest031332d4b5da308f258b37facbe92457bd1dc14PersistentVMRoleNetworkConfiguration22SSH45810tcp137.116.228.109falseReadWritedcoddkinztest02-dc14-0-201405291222150139http://mtlytics.blob.core.windows.net/vhds/testdc123-dc14-2014-05-29.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxExtraSmalldcoddkinztest03PersistentVMRoleNetworkConfiguration22SSH22tcp137.116.228.109falseReadWritedcoddkinztest02-dcoddkinztest03-0-201405291204550075http://mtlytics.blob.core.windows.net/vhds/testdc123-dcoddkinztest03-2014-05-29.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxExtraSmallfalsefalse2014-05-29T12:04:51Z2014-05-29T12:29:34Z2014-04-11T18:28:14Z2014-04-13T18:28:14ZPersistentVMUpdateCompleted
137.116.228.109
truedcoddkinztest02ContractContract
testdc123.f2.internal.cloudapp.net
././@LongLink0000000000000000000000000000022400000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deployments.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000107513535474530031702 0ustar kamikami00000000000000https://management.core.windows.net/5191b16a-673d-426c-8c55-fdd912858e4e/services/hostedservices/testdc123testdc123North EuropeCreated2014-05-29T12:04:22Z2014-05-29T12:05:06Z././@LongLink0000000000000000000000000000024300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deploymentslots_Production.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000001137713535474530031710 0ustar kamikami00000000000000dcoddkinztest02Productionf18bf4439e6848138d9692cdcfa08769Runninghttp://testdc123.cloudapp.net/PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJkYzE0Ij4NCiAgICA8SW5zdGFuY2VzIGNvdW50PSIxIiAvPg0KICA8L1JvbGU+DQogIDxSb2xlIG5hbWU9ImRjb2Rka2luenRlc3QwMyI+DQogICAgPEluc3RhbmNlcyBjb3VudD0iMSIgLz4NCiAgPC9Sb2xlPg0KPC9TZXJ2aWNlQ29uZmlndXJhdGlvbj4=dc14dc14ReadyRole00ExtraSmall100.86.126.44SSH137.116.228.1094581022tcpStarteddc148bd92d2a2bd27182427a02ba38dcd16ddcoddkinztest03dcoddkinztest03ReadyRole00ExtraSmall100.86.132.14SSH137.116.228.1092222tcpStarteddcoddkinztest031332d4b5da308f258b37facbe92457bd1dc14PersistentVMRoleNetworkConfiguration22SSH45810tcp137.116.228.109falseReadWritedcoddkinztest02-dc14-0-201405291222150139http://mtlytics.blob.core.windows.net/vhds/testdc123-dc14-2014-05-29.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxExtraSmalldcoddkinztest03PersistentVMRoleNetworkConfiguration22SSH22tcp137.116.228.109falseReadWritedcoddkinztest02-dcoddkinztest03-0-201405291204550075http://mtlytics.blob.core.windows.net/vhds/testdc123-dcoddkinztest03-2014-05-29.vhd5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415LinuxExtraSmallfalsefalse2014-05-29T12:04:51Z2014-05-29T12:29:34Z2014-04-11T18:28:14Z2014-04-13T18:28:14ZPersistentVMUpdateCompleted
137.116.228.109
truedcoddkinztest02ContractContract
testdc123.f2.internal.cloudapp.net
././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc_deployments.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000107513535474530031702 0ustar kamikami00000000000000https://management.core.windows.net/5191b16a-673d-426c-8c55-fdd912858e4e/services/hostedservices/testdc123testdc123North EuropeCreated2014-05-29T12:04:22Z2014-05-29T12:04:23Z././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_images.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000073165613535474530031721 0ustar kamikami00000000000000PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.2-x64-v5.8.8.1Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.3 with RightLink 5.8.RightScale Linux v13false2012-08-28T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.3-x64-v5.8.8Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.2 with RightLink 5.8.RightScale Linux v13false2012-08-28T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.3-x64-v5.8.8.5Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.3 with RightLink 5.8.RightScale Linux v13false2012-10-12T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.3-x64-v5.8.8.6Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.3 with RightLink 5.8.RightScale Linux v13false2012-11-12T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.3-x64-v5.8.8.7Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.3 with RightLink 5.8.RightScale Linux v13false2012-01-15T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.3-x64-v5.8.8.8Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.3 with RightLink 5.8.RightScale Linux v13false2012-01-25T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.3-x64-v5.8.8.9Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.3 with RightLink 5.8.RightScale Linux v13false2013-03-01T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.4-x64-v13.4Linuxfalse2013-04-19T00:00:00ZfalseRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.4-x64-v13.5.0.1Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.4 with RightLink 5.8.RightScale Linux v13false2013-07-11T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.4-x64-v13.5.0.2Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.4 with RightLink 5.8.RightScale Linux v13false2013-07-22T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.5-x64-v13.5.2Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.5 with RightLink 5.8.RightScale Linux v13false2013-12-26T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US100b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.5-x64-v13.5.3Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementCentOS 6.5 with RightLink 5.8.RightScale Linux v13false2014-04-17T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v13.4Linuxfalse2013-04-19T00:00:00ZfalseRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v13.5.0.1Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementUbuntu 12.04 with RightLink 5.8.RightScale Linux v13false2013-07-11T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v13.5.2Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementUbuntu 12.04 with RightLink 5.8.RightScale Linux v13false2013-12-26T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v13.5.3Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementUbuntu 12.04 with RightLink 5.8.RightScale Linux v13false2014-04-17T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v5.8.8Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementUbuntu 12.04 with RightLink 5.8.RightScale Linux v13false2012-08-28T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v5.8.8.5Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementUbuntu 12.04 with RightLink 5.8.RightScale Linux v13false2012-10-12T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v5.8.8.7Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementUbuntu 12.04 with RightLink 5.8.RightScale Linux v13false2013-01-15T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US100b11de9248dd4d87b18621318e037d37__RightImage-Ubuntu-12.04-x64-v5.8.8.8Linuxhttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementUbuntu 12.04 with RightLink 5.8.RightScale Linux v13false2013-01-25T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with LinuxPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__JDK-1.6.0_71-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321312[Java Platform|http://www.oracle.com/java|_blank], Standard Edition 6 (update 71) enables development of secure, portable, high-performance applications and includes a Java Development Kit (JDK), Java Runtime Environment (JRE), and tools for developing, debugging, and monitoring Java applications. WARNING: These older versions of the JRE and JDK are provided to help developers debug issues in older systems. They are not recommended for use in production. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://www.windowsazure.com/en-us/documentation/articles/virtual-machines-java-run-tomcat-application-server/|_blank]JDK 6 on Windows Server 20122014-05-01T07:00:00ZtrueJava6_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321694SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386544Java6_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321310[Java Platform|http://www.oracle.com/java|_blank], Standard Edition 7 (update 51) enables development of secure, portable, high-performance applications and includes a Java Development Kit (JDK), Java Runtime Environment (JRE), and tools for developing, debugging, and monitoring Java applications. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://www.windowsazure.com/en-us/documentation/articles/virtual-machines-java-run-tomcat-application-server|_blank]JDK 7 on Windows Server 20122014-05-01T07:00:00ZtrueJava7_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321701SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkID=386543Java7_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__JDK-1.8.0-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321310[Java Platform|http://www.oracle.com/java|_blank], Standard Edition 8 enables development of secure, portable, high-performance applications and includes a Java Development Kit (JDK), Java Runtime Environment (JRE), and tools for developing, debugging, and monitoring Java applications. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank].JDK 8 on Windows Server 2012 R22014-05-01T07:00:00ZtrueJava7_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321701SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkID=386543Java7_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-11.2.0.4.0-EE-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321683[Oracle Database|http://www.oracle.com/database|_blank] 11g R2 Enterprise Edition (11.2.0.4.0) provides comprehensive features to easily manage the most demanding transaction processing, business intelligence, and content management applications. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank].Oracle Database 11g R2 Enterprise Edition on Windows Server 2008 R22014-05-01T07:00:00ZtrueOracleDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321692SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386538OracleDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-11.2.0.4.0-EE-WebLogic-10.3.6-EE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321684[Oracle Database|http://www.oracle.com/database|_blank] 11g R2 Enterprise Edition (11.2.0.4.0) provides comprehensive features to easily manage the most demanding transaction processing, business intelligence, and content management applications. [Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 11g Enterprise Edition (10.3.6) is a leading Java application server for modern data centers. It takes full advantage of the latest hardware architectures including 64-bit addressable memory, multi-core computing systems and high-speed networks. Minimum recommended virtual machine size for this image is [Medium|http://go.microsoft.com/fwlink/?LinkID=309169|_blank].Oracle Database 11g R2 and WebLogic Server 11g Enterprise Edition on Windows Server 2008 R22014-05-01T07:00:00ZtrueOracleWeblogicDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321691MediumMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386541OracleWeblogicDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-11.2.0.4.0-SE-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321686[Oracle Database|http://www.oracle.com/database|_blank] 11g R2 Standard Edition (11.2.0.4.0) is an affordable, full-featured data management solution that is ideal for midsize companies. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank].Oracle Database 11g R2 Standard Edition on Windows Server 2008 R22014-05-01T07:00:00ZtrueOracleDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321689SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386537OracleDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-11.2.0.4.0-SE-WebLogic-10.3.6-SE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321687[Oracle Database|http://www.oracle.com/database|_blank] 11g R2 Standard Edition (11.2.0.4.0) is an affordable, full-featured data management solution that is ideal for midsize companies. [Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 11g Standard Edition (10.3.6) is a leading Java application server for enterprises of all sizes, providing developers with the tools and technologies to write enterprise applications and services quickly and operations teams with the administration capabilities to keep them up and running. Minimum recommended virtual machine size for this image is [Medium|http://go.microsoft.com/fwlink/?LinkID=309169|_blank].Oracle Database 11g R2 and WebLogic Server 11g Standard Edition on Windows Server 2008 R22014-05-01T07:00:00ZtrueOracleWeblogicDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321688MediumMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386542OracleWeblogicDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-12.1.0.1.0-0514-EE-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321314[Oracle Database|http://www.oracle.com/database|_blank] 12c Enterprise Edition (12.1.0.1.0) is a next-generation database designed for the cloud, providing a new multitenant architecture on top of a fast, scalable, reliable, and secure database platform. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn439775.aspx|_blank]Oracle Database 12c Enterprise Edition on Windows Server 20122014-05-01T07:00:00ZtrueOracleDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321699SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386538OracleDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-12.1.0.1.0-0514-SE-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321317[Oracle Database|http://www.oracle.com/database|_blank] 12c Standard Edition (12.1.0.1.0) is an affordable, full-featured data management solution that is ideal for midsize companies. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn439775.aspx|_blank]Oracle Database 12c Standard Edition on Windows Server 20122014-05-01T07:00:00ZtrueOracleDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321696SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386537OracleDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-12.1.0.1.0-EE-WebLogic-12.1.2.0-EE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321315[Oracle Database|http://www.oracle.com/database|_blank] 12c Enterprise Edition (12.1.0.1.0) is a next-generation database designed for the cloud, providing a new multitenant architecture on top of a fast, scalable, reliable, and secure database platform. [Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 12c Enterprise Edition (12.1.2.0) is a leading Java EE application server. Minimum recommended virtual machine size for this image is [Medium|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn466427.aspx|_blank]Oracle Database 12c and WebLogic Server 12c Enterprise Edition on Windows Server 20122014-05-01T07:00:00ZtrueOracleWeblogicDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321698MediumMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386541OracleWeblogicDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Oracle-Database-12.1.0.1.0-SE-WebLogic-12.1.2.0-SE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321318[Oracle Database|http://www.oracle.com/database|_blank] 12c Standard Edition (12.1.0.1.0) is an affordable, full-featured data management solution that is ideal for midsize companies. [Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 12c Standard Edition (12.1.2.0) is a leading Java EE application server. Minimum recommended virtual machine size for this image is [Medium|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn466427.aspx|_blank]Oracle Database 12c and WebLogic Server 12c Standard Edition on Windows Server 20122014-05-01T07:00:00ZtrueOracleWeblogicDatabase12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321695MediumMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386542OracleWeblogicDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__WebLogic-12.1.2.0-EE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321313[Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 12c Enterprise Edition (12.1.2.0) is a leading Java EE application server, delivering next-generation applications on a mission-critical cloud platform, with native cloud management, and integrated tools. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn439774.aspx|_blank]Oracle WebLogic Server 12c Enterprise Edition on Windows Server 20122014-05-01T07:00:00ZtrueOracleWeblogic12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321700SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386540OracleWeblogic12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__WebLogic-12.1.2.0-SE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321316[Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 12c Standard Edition (12.1.2.0) is a leading Java EE application server, delivering next-generation applications on a mission-critical cloud platform, with native cloud management, and integrated tools. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn439774.aspx|_blank]Oracle WebLogic Server 12c Standard Edition on Windows Server 20122014-05-01T07:00:00ZtrueOracleWeblogic12_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321697SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386539OracleWeblogic12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Weblogic-10.3.6-EE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkID=321682[Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 11g Enterprise Edition (10.3.6) is a leading Java application server for modern data centers. It takes full advantage of the latest hardware architectures including 64-bit addressable memory, multi-core computing systems and high-speed networks. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn466428.aspx|_blank]Oracle WebLogic Server 11g Enterprise Edition on Windows Server 2008 R22014-05-01T07:00:00ZtrueOracleWeblogic11_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321693SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386540OracleWeblogic11_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1280c0083a6d9a24f2d91800e52cad83950__Weblogic-10.3.6-SE-JDK-1.7.0_51-0514-Win-GAWindowshttp://go.microsoft.com/fwlink/?LinkId=321685[Oracle WebLogic Server|http://www.oracle.com/weblogicserver|_blank] 11g Standard Edition (10.3.6) is a leading Java application server for enterprises of all sizes, providing developers with the tools and technologies to write enterprise applications and services quickly and operations teams with the administration capabilities to keep them up and running. Minimum recommended virtual machine size for this image is [Small|http://go.microsoft.com/fwlink/?LinkID=309169|_blank]. [Learn More|http://msdn.microsoft.com/en-us/library/dn466428.aspx|_blank]Oracle WebLogic Server 11g Standard Edition on Windows Server 2008 R22014-05-01T07:00:00ZtrueOracleWeblogic11_100.pnghttp://go.microsoft.com/fwlink/?LinkId=321690SmallMicrosoft Open Technologies, Inc.http://go.microsoft.com/fwlink/?LinkId=386539OracleWeblogic11_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1272cdc6229df6344129ee553dd3499f0d3__BizTalk-Server-2013-EnterpriseWindowshttp://go.microsoft.com/fwlink/?LinkID=296354;http://go.microsoft.com/fwlink/?LinkID=131004This image contains the Enterprise edition of BizTalk Server 2013. Some BizTalk Server components like accelerators require additional setup before use. Medium is the recommended size for this image.trueBizTalkServer2013_100.pnghttp://go.microsoft.com/fwlink/?LinkID=131004MediumMicrosoft BizTalk Server Grouphttp://go.microsoft.com/fwlink/?LinkID=280328BizTalkServer2013_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1272cdc6229df6344129ee553dd3499f0d3__BizTalk-Server-2013-StandardWindowshttp://go.microsoft.com/fwlink/?LinkID=296355;http://go.microsoft.com/fwlink/?LinkID=131004This image contains the Standard edition of BizTalk Server 2013. Some BizTalk Server components like accelerators require additional setup before use. Medium is the recommended size for this image.trueBizTalkServer2013_100.pnghttp://go.microsoft.com/fwlink/?LinkID=131004MediumMicrosoft BizTalk Server Grouphttp://go.microsoft.com/fwlink/?LinkID=280327BizTalkServer2013_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1273a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20131018-enusWindowsThis image contains the Windows Server 2012 R2 Datacenter operating system with the Windows Server Essentials Experience role installed. The new Windows Server Essentials Experience server role on Windows Server 2012 R2 Datacenter includes features, such as Remote Web Access, that were previously available only in Windows Server Essentials. Before creating a virtual machine, you must configure a valid virtual network to use VPN connections. For more information about how to set up Windows Server Essentials Experience, see [here|http://go.microsoft.com/fwlink/?LinkId=322143].Windows Server Essentials Experience on Windows Server 2012 R22013-10-18T00:00:00ZfalseWindowsServer2012R2_100.pngMediumMicrosoft Windows Server Essentials GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1273a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20131127-enusWindowsThis image contains the Windows Server 2012 R2 Datacenter operating system with the Windows Server Essentials Experience role installed. The new Windows Server Essentials Experience server role on Windows Server 2012 R2 Datacenter includes features, such as Remote Web Access, that were previously available only in Windows Server Essentials. Before creating a virtual machine, you must configure a valid virtual network to use VPN connections. For more information about how to set up Windows Server Essentials Experience, see [here|http://go.microsoft.com/fwlink/?LinkId=322143].Windows Server Essentials Experience on Windows Server 2012 R22013-11-29T00:00:00ZfalseWindowsServer2012R2_100.pngMediumMicrosoft Windows Server Essentials GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1273a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20131217-enusWindowsThis image contains the Windows Server 2012 R2 Datacenter operating system with the Windows Server Essentials Experience role installed. The new Windows Server Essentials Experience server role on Windows Server 2012 R2 Datacenter includes features, such as Remote Web Access, that were previously available only in Windows Server Essentials. Before creating a virtual machine, you must configure a valid virtual network to use VPN connections. For more information about how to set up Windows Server Essentials Experience, see [here|http://go.microsoft.com/fwlink/?LinkId=322143].Windows Server Essentials Experience on Windows Server 2012 R22013-12-23T00:00:00ZfalseWindowsServer2012R2_100.pngMediumMicrosoft Windows Server Essentials GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1273a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20140213-enusWindowsThis image contains the Windows Server 2012 R2 Datacenter operating system with the Windows Server Essentials Experience role installed. The new Windows Server Essentials Experience server role on Windows Server 2012 R2 Datacenter includes features, such as Remote Web Access, that were previously available only in Windows Server Essentials. Before creating a virtual machine, you must configure a valid virtual network to use VPN connections. For more information about how to set up Windows Server Essentials Experience, see [here|http://go.microsoft.com/fwlink/?LinkId=322143].Windows Server Essentials Experience on Windows Server 2012 R22014-01-23T00:00:00ZfalseWindowsServer2012R2_100.pngMediumMicrosoft Windows Server Essentials GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1273a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20140306-enusWindowsThis image contains the Windows Server 2012 R2 Datacenter operating system with the Windows Server Essentials Experience role installed. The new Windows Server Essentials Experience server role on Windows Server 2012 R2 Datacenter includes features, such as Remote Web Access, that were previously available only in Windows Server Essentials. Before creating a virtual machine, you must configure a valid virtual network to use VPN connections. For more information about how to set up Windows Server Essentials Experience, see [here|http://go.microsoft.com/fwlink/?LinkId=322143].Windows Server Essentials Experience on Windows Server 2012 R22014-03-05T16:00:00ZfalseWindowsServer2012R2_100.pngMediumMicrosoft Windows Server Essentials GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US1273a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20140327-enusWindowsThis image contains the Windows Server 2012 R2 Datacenter operating system with the Windows Server Essentials Experience role installed. The new Windows Server Essentials Experience server role on Windows Server 2012 R2 Datacenter includes features, such as Remote Web Access, that were previously available only in Windows Server Essentials. Before creating a virtual machine, you must configure a valid virtual network to use VPN connections. For more information about how to set up Windows Server Essentials Experience, see [here|http://go.microsoft.com/fwlink/?LinkId=322143].Windows Server Essentials Experience on Windows Server 2012 R22014-03-26T16:00:00ZfalseWindowsServer2012R2_100.pngMediumMicrosoft Windows Server Essentials GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US305112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415Linuxhttp://www.openlogic.com/azure/service-agreement/This distribution of Linux is based on CentOS version 6.5 and is provided by OpenLogic. It contains an installation of the Basic Server packages.2014-04-15T00:00:00ZfalseCentOS6_100.pngOpenLogicCentOS6_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128a699494373c04fc0bc8f2bb1389d6106__Win2K8R2SP1-Datacenter-201403.01-en.us-127GB.vhdWindowsWindows Server 2008 R2 is a multi-purpose server designed to increase the reliability and flexibility of your server or private cloud infrastructure, helping you to save time and reduce costs. It provides you with powerful tools to react to business needs with greater control and confidence.Windows Server 2008 R2 SP12014-03-17T00:00:00ZfalseWindowsServer2008R2_100.pngMicrosoft Windows Server GroupWindowsServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128a699494373c04fc0bc8f2bb1389d6106__Win2K8R2SP1-Datacenter-201404.01-en.us-127GB.vhdWindowsWindows Server 2008 R2 is a multi-purpose server designed to increase the reliability and flexibility of your server or private cloud infrastructure, helping you to save time and reduce costs. It provides you with powerful tools to react to business needs with greater control and confidence.Windows Server 2008 R2 SP12014-04-17T00:00:00ZfalseWindowsServer2008R2_100.pngMicrosoft Windows Server GroupWindowsServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-Datacenter-201403.01-en.us-127GB.vhdWindowsWindows Server 2012 incorporates Microsoft's experience building and operating public clouds, resulting in a dynamic, highly available server platform. It offers a scalable, dynamic and multi-tenant-aware infrastructure that helps securely connect across premises.Windows Server 2012 Datacenter2014-03-17T00:00:00ZfalseWindowsServer2012_100.pngMicrosoft Windows Server GroupWindowsServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-Datacenter-201404.01-en.us-127GB.vhdWindowsWindows Server 2012 incorporates Microsoft's experience building and operating public clouds, resulting in a dynamic, highly available server platform. It offers a scalable, dynamic and multi-tenant-aware infrastructure that helps securely connect across premises.Windows Server 2012 Datacenter2014-04-17T00:00:00ZfalseWindowsServer2012_100.pngMicrosoft Windows Server GroupWindowsServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201403.01-en.us-127GB.vhdWindowsAt the heart of the Microsoft Cloud OS vision, Windows Server 2012 R2 brings Microsoft's experience delivering global-scale cloud services into your infrastructure. It offers enterprise-class performance, flexibility for your applications and excellent economics for your datacenter and hybrid cloud environment.Windows Server 2012 R2 Datacenter2014-03-17T00:00:00ZfalseWindowsServer2012R2_100.pngMicrosoft Windows Server GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201404.01-en.us-127GB.vhdWindowsAt the heart of the Microsoft Cloud OS vision, Windows Server 2012 R2 brings Microsoft's experience delivering global-scale cloud services into your infrastructure. It offers enterprise-class performance, flexibility for your applications and excellent economics for your datacenter and hybrid cloud environment. This image includes Windows Server 2012 R2 Update.Windows Server 2012 R2 Datacenter2014-04-17T00:00:00ZfalseWindowsServer2012R2_100.pngMicrosoft Windows Server GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127ad072bd3082149369c449ba5832401ae__RdshOnWindowsServer2012R2.20140305.127GB.vhdWindowsThis image contains the Windows Server 2012 R2 operating system with the Remote Desktop Session Host (RD Session Host) role installed. This image has been pre-configured for Windows Azure. RD Session Host enables a server to host RemoteApp programs or session-based desktops.Windows Server Remote Desktop Session Host on Windows Server 2012 R2false2014-03-05T23:38:03.7394082ZfalseWindowsServer2012R2_100.pngLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127ad072bd3082149369c449ba5832401ae__Windows-Server-RDSHwO13P-on-Windows-Server-2012-R2-20140421-1748WindowsThis image can be used by authorized Microsoft Service Providers only.Windows Server RDSHwO13P on Windows Server 2012 R2false2014-04-21T19:09:55.3775121ZfalseWindowsServer2012R2_100.pnghttp://www.windowsazure.com/en-us/support/legal/privacy-statementLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127ad072bd3082149369c449ba5832401ae__Windows-Server-RDSHwO13P-on-Windows-Server-2012-R2-20140502-1817WindowsThis image can be used by authorized Microsoft Service Providers only.Windows Server RDSHwO13P on Windows Server 2012 R2false2014-05-02T19:00:47.4740507ZfalseWindowsServer2012R2_100.pnghttp://www.windowsazure.com/en-us/support/legal/privacy-statementLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127ad072bd3082149369c449ba5832401ae__Windows-Server-RDSHwO13P-on-Windows-Server-2012-R2-20140509-1817WindowsThis image can be used by authorized Microsoft Service Providers only.Windows Server RDSHwO13P on Windows Server 2012 R2false2014-05-09T19:06:56.874678ZfalseWindowsServer2012R2_100.pnghttp://www.windowsazure.com/en-us/support/legal/privacy-statementLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127ad072bd3082149369c449ba5832401ae__Windows-Server-RDSHwO13P-on-Windows-Server-2012-R2-20140512-2037WindowsThis image can be used by authorized Microsoft Service Providers only.Windows Server RDSHwO13P on Windows Server 2012 R2false2014-05-12T21:28:12.4214603ZfalseWindowsServer2012R2_100.pnghttp://www.windowsazure.com/en-us/support/legal/privacy-statementLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127ad072bd3082149369c449ba5832401ae__Windows-Server-RDSHwO13P-on-Windows-Server-2012-R2-20140514-1702WindowsThis image can be used by authorized Microsoft Service Providers only.Windows Server RDSHwO13P on Windows Server 2012 R2false2014-05-14T17:59:34.290158ZfalseWindowsServer2012R2_100.pnghttp://www.windowsazure.com/en-us/support/legal/privacy-statementLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128ad072bd3082149369c449ba5832401ae__Windows-Server-Remote-Desktop-Session-Host-on-Windows-Server-2012-R2-20140514-1852WindowsThis image contains the Windows Server 2012 R2 operating system with the Remote Desktop Session Host (RD Session Host) role installed. This image has been pre-configured for Windows Azure. RD Session Host enables a server to host RemoteApp programs or session-based desktops.Windows Server Remote Desktop Session Host on Windows Server 2012 R2false2014-05-14T19:33:36.5822032ZfalseWindowsServer2012R2_100.pngLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20121218-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.10 (amd64 20121218) for Windows Azure. This image is DEPRECATED and was reached its END OF LIFE on 2014-04-18. This image is provided for archival purposes only. Please see [Ubuntu Release Wiki|https://wiki.ubuntu.com/Releases|_blank] for information about successor releases and the Ubuntu life-cycle.Ubuntu Server 12.10false2012-12-18T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20130225-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130225) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-02-25T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20130325-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130325) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTSfalse2013-03-25T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20130415-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130415) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTSfalse2013-04-15T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20130516-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130516) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-05-17T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20130527-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130527) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-05-27T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20130603-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130603) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-06-03T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_2-LTS-amd64-server-20130624-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130624) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-06-24T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20130827-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130827) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-08-27T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20130909-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130909) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-09-09T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20130916.1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20130916.1) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-09-16T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20131003-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20131003) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-10-03T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20131024-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20131024) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 12.04 LTStrue2013-10-24T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20131111-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20131111) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2013-11-11T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20131114-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20131114) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2013-11-14T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20131205-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20131205) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2013-12-05T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20140127-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20140127) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2014-01-27T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20140130-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.3 LTS (amd64 20140130) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.3 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2014-01-30T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_4-LTS-amd64-server-20140227-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.4 LTS (amd64 20140227) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.4 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2014-02-27T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_4-LTS-amd64-server-20140408-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.4 LTS (amd64 20140408) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.4 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2014-04-08T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_4-LTS-amd64-server-20140428-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.4 LTS (amd64 20140428) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.4 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2014-04-28T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_4-LTS-amd64-server-20140514-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 12.04.4 LTS (amd64 20140514) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 12.04.4 LTS will be available until 2017-04-26. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 12.04 LTStrue2014-05-15T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20130808-alpha3-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20130808) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 13.10false2013-08-08T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20130905-beta1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20130905) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 13.10false2013-09-05T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20130925-beta2-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20130925) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 13.10false2013-09-26T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20131015-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20131015) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see http://www.ubuntu.com/cloud and http://juju.ubuntu.com.Ubuntu Server 13.10true2013-10-15T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20131113-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20131113) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2013-11-13T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20131204-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20131204) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2013-12-04T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20131215-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20131215) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2013-12-15T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140108-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140108) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-01-08T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140112-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140112) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-01-12T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140119-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140119) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-01-19T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140129-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140129) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-01-29T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140202-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140202) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-02-02T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140212-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140212) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-02-12T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140226-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140226) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-02-27T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140409.1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140409.1) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-04-10T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140427-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140427) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-04-27T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-20140507-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 13.10 (amd64 20140507) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 13.10 will be available until 2014-07-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 13.10true2014-05-07T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140122.1-alpha2-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyMILESTONE RELEASE: This is a milestone release and is considered experimental. This build is unsupported and is for development and preview reference only. Ubuntu Server 14.04 LTS (amd64 20140122.1) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 14.04 LTS will be available until 2019-04-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 14.04 LTStrue2014-01-23T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140226.1-beta1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyMILESTONE RELEASE: This is a milestone release and is considered experimental. This build is unsupported and is for development and preview reference only. Ubuntu Server 14.04 LTS (amd64 20140226.1) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 14.04 LTS will be available until 2019-04-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 14.04 LTStrue2014-02-28T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140326-beta2-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyMILESTONE RELEASE: This is a milestone release and is considered experimental. This build is unsupported and is for development and preview reference only. Ubuntu Server 14.04 LTS (amd64 20140326) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 14.04 LTS will be available until 2019-04-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 14.04 LTSfalse2014-03-27T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140414-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 14.04 LTS (amd64 20140414) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 14.04 LTS will be available until 2019-04-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 14.04 LTStrue2014-04-14T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140416.1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyUbuntu Server 14.04 LTS (amd64 20140416.1) for Windows Azure. Ubuntu Server is the world's most popular Linux for cloud environments. Updates and patches for Ubuntu 14.04 LTS will be available until 2019-04-17. Ubuntu Server is the perfect platform for all workloads from web applications to NoSQL databases and Hadoop. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank].Ubuntu Server 14.04 LTStrue2014-04-17T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_3-LTS-amd64-server-20131125-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20131125 of Ubuntu Server 12.04.3 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 12.04 LTS DAILYfalse2013-11-25T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_4-LTS-amd64-server-20140514-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140514 of Ubuntu Server 12.04.4 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 12.04 LTS DAILYfalse2014-05-15T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_4-LTS-amd64-server-20140515-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140515 of Ubuntu Server 12.04.4 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 12.04 LTS DAILYfalse2014-05-15T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_4-LTS-amd64-server-20140519-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140519 of Ubuntu Server 12.04.4 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 12.04 LTS DAILYfalse2014-05-19T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-precise-12_04_4-LTS-amd64-server-20140526-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140526 of Ubuntu Server 12.04.4 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 12.04 LTS DAILYfalse2014-05-26T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-saucy-13_10-amd64-server-20140507-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140507 of Ubuntu Server 13.10 DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 13.10 DAILYfalse2014-05-07T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-saucy-13_10-amd64-server-20140511-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140511 of Ubuntu Server 13.10 DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 13.10 DAILYfalse2014-05-11T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-saucy-13_10-amd64-server-20140514-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140514 of Ubuntu Server 13.10 DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 13.10 DAILYfalse2014-05-14T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-saucy-13_10-amd64-server-20140518-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140518 of Ubuntu Server 13.10 DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 13.10 DAILYfalse2014-05-18T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-saucy-13_10-amd64-server-20140521-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140521 of Ubuntu Server 13.10 DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 13.10 DAILYfalse2014-05-21T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-trusty-14_04-LTS-amd64-server-20140517.1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140517.1 of Ubuntu Server 14.04 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 14.04 LTS DAILYfalse2014-05-17T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-trusty-14_04-LTS-amd64-server-20140519.1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140519.1 of Ubuntu Server 14.04 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 14.04 LTS DAILYfalse2014-05-19T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-trusty-14_04-LTS-amd64-server-20140521.1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140521.1 of Ubuntu Server 14.04 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 14.04 LTS DAILYfalse2014-05-21T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-trusty-14_04-LTS-amd64-server-20140524.1-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140524.1 of Ubuntu Server 14.04 LTS DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 14.04 LTS DAILYfalse2014-05-24T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu_DAILY_BUILD-utopic-14_10-amd64-server-20140521-en-us-30GBLinuxhttp://www.ubuntu.com/project/about-ubuntu/licensing;http://www.ubuntu.com/aboutus/privacypolicyDAILY BUILD 20140521 of Ubuntu Server 14.10 DAILY (amd64) for Windows Azure. Daily builds are up-to-date builds of the regular release images for Ubuntu Server. While every effort is made to make sure that these are production quality, these images come with no warranty. In the event of a support issue, you may be asked to update to an official released build. For more information see [Ubuntu Cloud|http://www.ubuntu.com/cloud|_blank] and [using Juju to deploy your workloads|http://juju.ubuntu.com|_blank]. Ubuntu Server 14.10 DAILYfalse2014-05-21T00:00:00ZfalseUbuntu-cof-100.pnghttp://www.ubuntu.com/aboutus/privacypolicyCanonicalUbuntu-cof-45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b4590d9e3ed742e4a1d46e5424aa335e__SUSE-Linux-Enterprise-Server-11-SP3-Prio-v202Linuxhttp://www.novell.com/licensing/eula/SUSE Linux Enterprise Server Premium Image with PRIORITY Support: SUSE Linux Enterprise Server is a highly reliable, scalable and secure server operating system, built to power physical, virtual and cloud-based mission-critical workloads. With this affordable, interoperable and manageable open source foundation, enterprises can cost-effectively deliver core business services, enable secure networks and easily manage their heterogeneous IT resources, maximizing efficiency and value. Customization of images can be done at [http://susestudio.com|http://susestudio.com]. The Premium Image with PRIORITY support includes updates, patches, and support through 24x7 web, email, chat and phone from SUSE. VMs created from this image incur per-hour support fees, in addition to Azure platform fees. An Azure support plan is required (developer or above). Support incidents are initiated through Azure.SUSE Linux Enterprise Server 11 SP3 (Premium Image)2014-05-08T00:00:00ZtrueSuse11_100.pngSUSEhttp://go.microsoft.com/fwlink/?LinkId=299677Suse11_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b4590d9e3ed742e4a1d46e5424aa335e__SUSE-Linux-Enterprise-Server-11-SP3-SAP-CAL-v101Linuxhttp://www.novell.com/licensing/eula/The SUSE Linux Enterprise Server 11 SP3 for SAP Cloud Appliance Library image is the base image for SAP's Cloud Appliance Library. It will be used automatically when deploying an SAP Cloud Appliance Library instance and has the same features as the native SLES image, however customized to fit SAP's CAL needs. For further description and usage guide lines please refer to the description of the SUSE Linux Enterprise image. Customization of images can be done at [http://susestudio.com|http://susestudio.com].SUSE Linux Enterprise Server 11 SP3 for SAP Cloud Appliance Library2014-05-14T00:00:00ZfalseSuse11_100.pngSUSESuse11_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b4590d9e3ed742e4a1d46e5424aa335e__SUSE-Linux-Enterprise-Server-11-SP3-v202Linuxhttp://www.novell.com/licensing/eula/SUSE Linux Enterprise Server is a highly reliable, scalable and secure server operating system, built to power physical, virtual and cloud-based mission-critical workloads. With this affordable, interoperable and manageable open source foundation, enterprises can cost-effectively deliver core business services, enable secure networks and easily manage their heterogeneous IT resources, maximizing efficiency and value. Customization of images can be done at [http://susestudio.com|http://susestudio.com].SUSE Linux Enterprise Server 11 SP32014-01-16T00:00:00ZfalseSuse11_100.pngSUSESuse11_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30b4590d9e3ed742e4a1d46e5424aa335e__openSUSE-13.1-v101LinuxopenSUSE 13.1 brings updated desktop environments and software, lot of polishing, a brand new KDE theme, complete systemd integration and many other features. Customization of these images can be done at http://susestudio.comopenSUSE 13.12014-04-15T00:00:00ZfalseOpenSuse12_100.pngSUSEOpenSuse12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-iis75-v5.8.8Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with IIS 7.5 and RightLink 5.8.RightScale Windows v13false2012-08-28T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-iis75-v5.8.8.11Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with IIS 7.5 and RightLink 5.8.RightScale Windows v13false2012-12-07T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-sqlsvr2012-v5.8.8Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with MS SQL Server 2012 Standard and RightLink 5.8.RightScale Windows v13false2012-08-28T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-sqlsvr2012-v5.8.8.1Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with MS SQL Server 2012 Standard and RightLink 5.8.RightScale Windows v13false2012-08-28T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-sqlsvr2012-v5.8.8.12Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with MS SQL Server 2012 Standard and RightLink 5.8.RightScale Windows v13false2012-12-12T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-sqlsvr2012-v5.8.8.15Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with MS SQL Server 2012 Standard and RightLink 5.8.RightScale Windows v13false2013-01-05T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-v5.8.8Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.8.RightScale Windows v13false2012-08-28T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-SP1-x64-v5.8.8.11Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.8.RightScale Windows v13false2012-12-07T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US31bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-iis7.5-v13.4.12.2Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with IIS 7.5 and RightLink 5.8RightScale Windows v13false2013-05-30T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-iis7.5-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with IIS 7.5 and RightLink v5.8RightScale Windows v13false2013-08-16T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-iis7.5-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2012-v13.4.3.1Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with MS SQL Server 2012 Standard and RightLink v5.8RightScale Windows v13false2013-06-06T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271257PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2012-v13.5.1Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with MS SQL Server 2012 Standard and RightLink v5.8RightScale Windows v13false2013-08-19T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271257PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2012-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271257PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2012ent-v13.4.3.1Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with MS SQL Server 2012 Enterprise and RightLink v5.8RightScale Windows v13false2013-06-06T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271259PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2012ent-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with MS SQL Server 2012 Enterprise and RightLink v5.8RightScale Windows v13false2013-08-16T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271259PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2012ent-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271259PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2k8r2-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with MS SQL Server 2008R2 and RightLink v5.8RightScale Windows v13false2013-08-16T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271257PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2k8r2-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271257PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2k8r2ent-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with MS SQL Server 2008R2 Enterprise and RightLink v5.8RightScale Windows v13false2013-08-15T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271259PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-sqlsvr2k8r2ent-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271259PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US31bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-v13.4.12.2Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink 5.8RightScale Windows v13false2013-05-30T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink v5.8RightScale Windows v13false2013-08-15T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2008R2-x64-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2008R2 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US31bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-iis8-v13.4.12.2Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with IIS 8 and RightLink 5.8RightScale Windows v13false2013-05-30T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-iis8-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with IIS 8 and RightLink v5.8RightScale Windows v13false2013-08-15T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-iis8-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-iis8-v5.8.8.12Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with IIS 8 and RightLink 5.8.RightScale Windows v13false2012-12-12T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-sqlsvr2012-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with MS SQL Server 2012 Standard and RightLink v5.8RightScale Windows v13false2013-08-15T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271257PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-sqlsvr2012-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271257PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-sqlsvr2012ent-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with MS SQL Server 2012 Enterprise and RightLink v5.8RightScale Windows v13false2013-08-15T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271259PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-sqlsvr2012ent-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Ztruehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows Serverhttp://go.microsoft.com/fwlink/?LinkId=271259PublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US31bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-v13.4.12.2Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.8RightScale Windows v13false2013-05-30T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-v13.5Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink v5.8RightScale Windows v13false2013-08-15T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-v14Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.9RightScale Windows v14false2014-03-24T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-v5.8.8.12Windowshttp://support.rightscale.com/12-Guides/RightLink/RightLink_End_User_License_AgreeementWindows 2012 with RightLink 5.8.RightScale Windows v13false2012-12-12T00:00:00Zfalsehttp://www.rightscale.com/privacy_policy.phpRightScale with Windows ServerPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US40c290a6b031d841e09f2da759bbabe71f__Oracle-Database-121010.v1-EE-LnxLinuxhttp://www.oracle.com/technetwork/licenses/oracle-license-2016066.htmlOracle Database 12c Enterprise Edition is a next-generation database designed for the cloud, providing a new multitenant architecture on top of a fast, scalable, reliable, and secure database platform. [Learn more|http://www.oracle.com/database|_blank]Oracle DatabasefalseOracleDatabase12_100.pnghttp://www.oracle.com/us/legal/privacy/privacy-policy-078584.htmlOracleOracleDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US40c290a6b031d841e09f2da759bbabe71f__Oracle-Database-121010.v3-SE-LnxLinuxhttp://www.oracle.com/technetwork/licenses/oracle-license-2016066.htmlOracle Database 12c Standard Edition is an affordable, full-featured data management solution that is ideal for midsize companies. [Learn more|http://www.oracle.com/database|_blank]Oracle Database StandardfalseOracleDatabase12_100.pnghttp://www.oracle.com/us/legal/privacy/privacy-policy-078584.htmlOracleOracleDatabase12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US10c290a6b031d841e09f2da759bbabe71f__Oracle-Linux-6Linuxhttp://www.oracle.com/technetwork/licenses/oracle-license-2016066.htmlOracle Linux 6 brings the latest Linux innovations to market, delivering extreme performance, advanced scalability, and reliability for enterprise applications and systems. [Learn more|http://www.oracle.com/linux|_blank]Oracle LinuxfalseOracleLinux6_100.pnghttp://www.oracle.com/us/legal/privacy/privacy-policy-078584.htmlOracleOracleLinux6_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30c290a6b031d841e09f2da759bbabe71f__WebLogic-Server-12c.v1-LnxLinuxhttp://www.oracle.com/technetwork/licenses/oracle-license-2016066.htmlOracle WebLogic Server 12c Enterprise Edition is a leading Java EE application server, delivering next-generation applications on a mission-critical cloud platform, with native cloud management, and integrated tools. [Learn more|http://www.oracle.com/weblogicserver|_blank]Oracle WeblogicfalseOracleWeblogic12_100.pnghttp://www.oracle.com/us/legal/privacy/privacy-policy-078584.htmlOracleOracleWeblogic12_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US128c6e0f177abd8496e934234bd27f46c5d__SharePoint-2013-Trial-1-7-2014Windowshttp://www.microsoft.com/en-us/download/details.aspx?id=38417Microsoft SharePoint Server 2013 Trial on Windows Server 2012 Datacenter. Virtual Machines created with this trial image will expire on July 6, 2014. This image includes a complete installation of SharePoint Server 2013. Some SharePoint Server 2013 components require additional setup and configuration. You can set-up Active Directory and SQL Server required for your SharePoint farm by provisioning additional virtual machines. Minimum recommended virtual machine size for this image is Large. To evaluate the advanced capabilities of SharePoint Server 2013, we recommend that you use a virtual machine size of Extra Large.SharePoint Server 2013 Trial2014-01-07T00:00:00ZfalseSharePoint2013_100.pnghttp://www.windowsazure.com/en-us/support/legal/privacy-statement/ExtraLargeMicrosoft SharePoint GroupSharePoint2013_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;West US30de89c2ed05c748f5aded3ddc75fdcce4__PuppetEnterpriseMaster-3_2_1-amd64-server-20140408-en-us-30GBLinuxhttp://puppetlabs.com/solutions/microsoft#EulaThis image includes a pre-configured Puppet Master with the Ubuntu Linux distribution for easy deployment of Puppet Enterprise. The evaluation will end on May 31, 2014 per Puppet Labs' End User License Agreement (EULA). To set up a Puppet Enterprise environment, please refer to the Getting Started Guide for Deploying a Puppet Master with Windows Azure at http://puppetlabs.com/solutions/microsoftPuppet Enterprise 3.22014-04-10T17:33:44.796315ZfalsePuppetLabs_100x100.pnghttp://puppetlabs.com/solutions/microsoftMediumPuppet LabsPuppetLabs_45x45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US30de89c2ed05c748f5aded3ddc75fdcce4__PuppetEnterpriseMaster-3_2_2-amd64-server-20140408-en-us-30GBLinuxhttp://puppetlabs.com/solutions/microsoft#EulaThis image includes a pre-configured Puppet Master with the Ubuntu Linux distribution for easy deployment of Puppet Enterprise. The evaluation will end on May 31, 2014 per Puppet Labs' End User License Agreement (EULA). To set up a Puppet Enterprise environment, please refer to the Getting Started Guide for Deploying a Puppet Master with Windows Azure at http://puppetlabs.com/solutions/microsoftPuppet Enterprise 3.22014-04-16T20:41:05.3700261ZfalsePuppetLabs_100x100.pnghttp://puppetlabs.com/solutions/microsoftMediumPuppet LabsPuppetLabs_45x45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2008R2SP2-Enterprise-CY13SU04-SQL2008-SP2-10.50.4021.0Windowshttp://go.microsoft.com/fwlink/?LinkID=285681This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2008 R2 SP2 Enterprise on Windows Server 2008 R22013-04-16T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxLargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2008R2SP2-Standard-CY13SU04-SQL2008-SP2-10.50.4021.0Windowshttp://go.microsoft.com/fwlink/?LinkID=285685This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2008 R2 SP2 Standard on Windows Server 2008 R22013-04-16T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxMediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-CU4-11.0.3368.0-Enterprise-ENU-Win2012Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Enterprise on Windows Server 20122013-06-26T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067LargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-CU4-11.0.3368.0-Enterprise-ENU-Win2K8R2Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Enterprise on Windows Server 2008 R22013-07-10T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067LargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-CU4-11.0.3368.0-Standard-ENU-Win2012Windowshttp://go.microsoft.com/fwlink/?LinkID=285691Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Standard on Windows Server 20122013-07-15T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-Enterprise-CY13SU04-SQL11-SP1-CU3-11.0.3350.0-BWindowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server 2012 components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Enterprise on Windows Server 2008 R22013-04-16T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067LargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-Enterprise-CY13SU04-SQL2012-SP1-11.0.3350.0-Win2012Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Enterprise on Windows Server 20122013-04-16T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067LargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-Standard-CY13SU04-SQL11-SP1-CU3-11.0.3350.0-BWindowshttp://go.microsoft.com/fwlink/?LinkID=285691Some SQL Server 2012 components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Standard on Windows Server 2008 R22013-04-16T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-Standard-CY13SU04-SQL2012-SP1-11.0.3350.0-Win2012Windowshttp://go.microsoft.com/fwlink/?LinkID=285685Some SQL Server 2012 components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Standard on Windows Server 20122013-04-16T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__Microsoft-SQL-Server-2012SP1-Web-CY13SU04-SQL11-SP1-CU3-11.0.3350.0Windowshttp://go.microsoft.com/fwlink/?LinkID=286424Some SQL Server 2012 components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Web on Windows Server 2008 R22013-04-16T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Enterprise-ENU-Win2K8R2-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=285681This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2008 R2 SP2 Enterprise on Windows Server 2008 R22013-10-22T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxLargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Enterprise-ENU-Win2K8R2-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285681We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2008 R2 SP2 Enterprise on Windows Server 2008 R22013-12-23T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxLargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Enterprise-ENU-Win2K8R2-CY14SU02Windowshttp://go.microsoft.com/fwlink/?LinkID=285681We recommend that you use a virtual machine size of A3 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2008 R2 SP2 Enterprise on Windows Server 2008 R22014-02-21T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxA3Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Standard-ENU-Win2K8R2-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=285685Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2008 R2 SP2 Standard on Windows Server 2008 R22013-10-22T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxMediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Standard-ENU-Win2K8R2-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285685We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2008 R2 SP2 Standard on Windows Server 2008 R22013-12-23T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxMediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Standard-ENU-Win2K8R2-CY14SU02Windowshttp://go.microsoft.com/fwlink/?LinkID=285685We recommend that you use a virtual machine size of A2 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2008 R2 SP2 Standard on Windows Server 2008 R22014-02-21T00:00:00ZtrueSqlserver2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxA2Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Web-ENU-Win2K8R2Windowshttp://go.microsoft.com/fwlink/?LinkID=285686Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2008 R2 SP2 Web on Windows Server 2008 R22013-07-29T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxMediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Web-ENU-Win2K8R2-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=285686Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2008 R2 SP2 Web on Windows Server 2008 R22013-10-22T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxMediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Web-ENU-Win2K8R2-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285686We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2008 R2 SP2 Web on Windows Server 2008 R22013-12-23T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxMediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2008R2SP2-GDR-10.50.4021.0-Web-ENU-Win2K8R2-CY14SU02Windowshttp://go.microsoft.com/fwlink/?LinkID=285686We recommend that you use a virtual machine size of A2 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2008 R2 SP2 Web on Windows Server 2008 R22014-02-21T00:00:00ZtrueSqlServer2008R2_100.pnghttp://msdn.microsoft.com/library/ms143384(v=sql.105).aspxA2Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2008R2_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-DataWarehousing-ENU-WS2012Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This Enterprise Edition image uses Fast Track optimization rated for 400 GB data warehousing workloads. After the portal deployment completes, you need to attach the disks. To do this, connect to the VM and then follow the on-screen instructions. Before using the VM, review the recommendations at http://go.microsoft.com/fwlink/p/?LinkId=320441. For best performance, we recommend the A6 VM size. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 for Data Warehousing on Windows Server 20122013-09-30T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A6Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-DataWarehousing-ENU-WS2012-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This Enterprise Edition image uses Fast Track optimization rated for 400 GB data warehousing workloads. After the portal deployment completes, you need to attach the disks. To do this, connect to the VM and then follow the on-screen instructions. Before using the VM, review the recommendations [here|http://go.microsoft.com/fwlink/p/?LinkId=320441|_blank]. For best performance, we recommend the A6 VM size. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 for Data Warehousing on Windows Server 20122013-12-23T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A6Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-DataWarehousing-ENU-WS2012-CY14SU02Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This Enterprise Edition image uses Fast Track optimization rated for 400 GB data warehousing workloads. After the portal deployment completes, you need to attach the disks. To do this, connect to the VM and then follow the on-screen instructions. Before using the VM, review the recommendations [here|http://go.microsoft.com/fwlink/p/?LinkId=320441|_blank]. For best performance, we recommend the A6 VM size. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 for Data Warehousing on Windows Server 20122014-02-21T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A6Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Enterprise-ENU-WS2008R2-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Enterprise on Windows Server 2008 R22013-10-21T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067LargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Enterprise-ENU-Win2012Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Enterprise on Windows Server 20122013-08-06T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067LargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Enterprise-ENU-Win2012-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of large or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Enterprise on Windows Server 20122013-10-21T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067LargeMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Enterprise-ENU-Win2012-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image contains the full version of SQL Server. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of A3 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 Enterprise on Windows Server 20122013-12-23T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A3Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Enterprise-ENU-Win2K8R2-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285687This image will be removed on 5/30/2014. We recommend that you use a virtual machine size of A3 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 Enterprise on Windows Server 2008 R22013-12-23T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A3Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Standard-ENU-WS2008R2Windowshttp://go.microsoft.com/fwlink/?LinkID=285687Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Standard on Windows Server 2008 R22013-09-04T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Standard-ENU-Win2012-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=285691Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Standard on Windows Server 20122013-10-21T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Standard-ENU-Win2012-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285691Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of A2 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 Standard on Windows Server 20122013-12-23T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A2Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Standard-ENU-Win2K8R2-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=285691Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Standard on Windows Server 2008 R22013-10-21T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Standard-ENU-Win2K8R2-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=285691We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 Standard on Windows Server 2008 R22013-12-23T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Standard-ENU-Win2K8R2-CY14SU02Windowshttp://go.microsoft.com/fwlink/?LinkID=285691This image will be removed on 5/30/2014. We recommend that you use a virtual machine size of A2 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 Standard on Windows Server 2008 R22014-02-21T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A2Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Web-ENU-WS2008R2Windowshttp://go.microsoft.com/fwlink/?LinkID=286424Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Web on Windows Server 2008 R22013-09-04T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Web-ENU-WS2008R2-CY13SU10Windowshttp://go.microsoft.com/fwlink/?LinkID=286424Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database.SQL Server 2012 SP1 Web on Windows Server 2008 R22013-10-24T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Web-ENU-Win2K8R2-CY13SU12Windowshttp://go.microsoft.com/fwlink/?LinkID=286424Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of medium or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 Web on Windows Server 2008 R22013-12-23T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067MediumMicrosoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2012SP1-CU5-11.0.3373.0-Web-ENU-Win2K8R2-CY14SU02Windowshttp://go.microsoft.com/fwlink/?LinkID=286424This image will be removed on 5/30/2014. Some SQL Server components require additional setup and configuration before use. We recommend that you use a virtual machine size of A2 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2012 SP1 Web on Windows Server 2008 R22014-02-21T00:00:00ZtrueSqlServer2012_100.pnghttp://www.microsoft.com/en-us/download/details.aspx?id=29067A2Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2012_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2014RTM-12.0.2000.8-DataWarehousing-ENU-WS2012R2-AprilGAWindowshttp://go.microsoft.com/fwlink/?LinkID=298186This image is optimized for data warehousing workloads with data sizes up to 1TB using clustered columnstore indexes. After the portal deployment completes, you need to attach disks to the virtual machine. To do this, connect to the VM and follow the on-screen instructions. Before using the VM, review the recommendations [here|http://msdn.microsoft.com/library/dn387396.aspx|_blank]. For best performance, we recommend using a VM size of A7. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2014 RTM DataWarehousing on Windows Server 2012 R22014-04-01T07:00:00ZtrueSQLServer2014_100.pnghttp://go.microsoft.com/fwlink/?LinkID=282418A7Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2014_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2014RTM-12.0.2000.8-ENTCORE-ENU-WS2012R2-AprilGAWindowshttp://go.microsoft.com/fwlink/?LinkID=298186This image contains the full version of SQL Server. We recommend that you use a virtual machine size of A3 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2014 RTM Enterprise on Windows Server 2012 R22014-04-01T07:00:00ZtrueSqlServer2014_100.pnghttp://go.microsoft.com/fwlink/?LinkID=282418A3Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271259SqlServer2014_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2014RTM-12.0.2000.8-Standard-ENU-WS2012R2-AprilGAWindowshttp://go.microsoft.com/fwlink/?LinkID=298186This image contains the full version of SQL Server. We recommend that you use a virtual machine size of A2 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2014 RTM Standard on Windows Server 2012 R22014-04-01T07:00:00ZtrueSqlServer2014_100.pnghttp://go.microsoft.com/fwlink/?LinkID=282418A2Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271257SqlServer2014_45.pngPublicEast Asia;Southeast Asia;North Europe;West Europe;East US;North Central US;West US127fb83b3509582419d99629ce476bcb5c8__SQL-Server-2014RTM-12.0.2000.8-Web-ENU-WS2012R2-AprilGAWindowshttp://go.microsoft.com/fwlink/?LinkID=298186This image contains the full version of SQL Server. We recommend that you use a virtual machine size of A2 or higher. This image has been pre-configured for Windows Azure, including enabling CEIP which can be disabled, for more info see [here|http://msdn.microsoft.com/en-us/library/windowsazure/dn133151.aspx#database|_blank].SQL Server 2014 RTM Web on Windows Server 2012 R22014-04-01T07:00:00ZtrueSqlServer2014_100.pnghttp://go.microsoft.com/fwlink/?LinkID=282418A2Microsoft SQL Server Grouphttp://go.microsoft.com/fwlink/?LinkId=271258SqlServer2014_45.pngPublicEast US;West US127ad072bd3082149369c449ba5832401ae__Windows-Server-RDSHwO13P-on-Windows-Server-2012-R2-20140417-1824WindowsThis image can be used by authorized Microsoft Service Providers only.Windows Server RDSHwO13P on Windows Server 2012 R2false2014-04-17T19:21:27.3838648ZfalseWindowsServer2012R2_100.pnghttp://www.windowsazure.com/en-us/support/legal/privacy-statementLargeMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngPublicEast US;West US127ad072bd3082149369c449ba5832401ae__Windows-Server-Remote-Desktop-Session-Host-on-Windows-Server-2012-R2-20140403-2126WindowsThis image contains the Windows Server 2012 R2 operating system with the Remote Desktop Session Host (RD Session Host) role installed. This image has been pre-configured for Windows Azure. RD Session Host enables a server to host RemoteApp programs or session-based desktops.Windows Server Remote Desktop Session Host on Windows Server 2012 R2false2014-04-03T22:17:28.0548753ZfalseWindowsServer2012R2_100.pngMediumMicrosoft Windows Server Remote Desktop GroupWindowsServer2012R2_45.pngUserNorth Europe30http://mtlytics.blob.core.windows.net/vhds/eqowwq2s.a51201312281344410973.vhdambaribaseLinuxThe base Ambari InstancefalseUserNorth Europe30http://mtlytics.blob.core.windows.net/communityimages/community-271-bcee18c0-e6f5-4595-a9ae-b64ebb9cb8a9-2.vhdAzure-Data-AnalysisLinuxhttp://spark.elastacloud.com{"description":"Includes R, openmpi and loads of packages. Include Spark 0.8, Shark 0.7 and Storm and Kafka. Also includes iPython notebook + a whole heap of libraries.","publisherUrl":"https://vmdepot.msopentech.com/User/Show?user=271","publisher":"elastacloud","imageUrl":"https://vmdepot.msopentech.com/Vhd/Show?VhdID=8689&version=10769","icons":{"Small":"https://vmdepotwestus.blob.core.windows.net/images/271/6c415744-cfed-4ed5-8493-361f47716623_45x45.png","Large":"https://vmdepotwestus.blob.core.windows.net/images/271/6c415744-cfed-4ed5-8493-361f47716623_100x100.png","ExtraLarge":"https://vmdepotwestus.blob.core.windows.net/images/271/6c415744-cfed-4ed5-8493-361f47716623_215x215.png"}}CommunityfalseUserNorth Europe30https://neelasta5191b16a673d426c.blob.core.windows.net/elastaimage/elastaspark0.vhdelastaspark0Linux2014-04-14T13:40:06ZfalseGeneralizedUserNorth Europe30https://neelasta5191b16a673d426c.blob.core.windows.net/elastaimage/neelastaspark0.vhdneelastaspark0Linux2014-05-27T12:10:18ZfalseGeneralizedUserNorth Europe30https://neelasta5191b16a673d426c.blob.core.windows.net/elastaimage/neelastaspark1.vhdneelastaspark1Linux2014-05-27T11:24:59ZfalseGeneralizedUserWest Europe30https://portalvhdsj5170kkqq0ftq.blob.core.windows.net/elastaimage/sparkius1.vhdsparkius1Linux2014-02-04T11:36:22ZfalseUserNorth Europe30http://mtlytics.blob.core.windows.net/vhds/m15pycz2.ync201403171254370011.vhdstorm.elactacloud.baseLinuxfalseUserNorth Europe30http://portalvhds3c3c6cj9bpgwh.blob.core.windows.net/vhds/hqbn1y3e.gya201404221049490886.vhdzk-drill-src-0LinuxfalseGeneralized././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_storageservices_dss123.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000032213535474530031674 0ustar kamikami00000000000000ResourceNotFoundThe storage account \'dss123\' was not found.././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_services_vmimages.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/_3761b98b_673d_526c_8d55_fee918758e6e_ser0000664000175000017500000000205413535474530031700 0ustar kamikami00000000000000 test-vm-20140926-782617 User test-vm-20140926-782617-os-2014-09-26 ReadWrite Generalized Linux https://portal.blob.core.windows.net/vhds/test-vm-20140926-782617-os-2014-09-26.vhd 30 test-service test-deployment test-role Central US 2014-09-26T17:39:34.5199416Z 2014-09-26T17:39:34.5199416Z false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure/libcloud.pem0000664000175000017500000000000013535474530026151 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/0000775000175000017500000000000013600223624024507 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_77777777_7777_7777_7777_777777777777_oauth2_token.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_77777777_7777_7777_7777_7777777777770000664000175000017500000000033313535474530031016 0ustar kamikami00000000000000{"expires_in":"3600","token_type":"Bearer","expires_on":"1111111111","not_before":"1111111111","resource":"https://management.core.windows.net/","access_token":"3333333333333333333333333333333333333333333333333333333"} ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Commerce_RateCard.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500001321321413535474530033456 0ustar kamikami00000000000000{ "Currency": "USD", "IsTaxIncluded": false, "Locale": "en-US", "Meters": [ { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "9a6cb708-ad98-4a61-bdc7-16360e3b50ad", "MeterName": "Unlimited Data - 1 Gbps", "MeterRates": { "0": 8700.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "02ef3dbe-1b98-4ee0-81bb-6133f5b3ad51", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "67d2ce10-48c6-4834-a7a1-c7b4a19803c4", "MeterName": "Data Transfer In (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "42093d75-9418-4b6c-9c29-fa8bb83ef0cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "892c73e6-4782-408c-aee2-e88c3cd6fb9c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.245 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "417cd99a-dd90-4e0f-8df5-532f17c1c4f6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e687a2a0-483d-4641-906f-500dbe35febf", "MeterName": "Compute Hours", "MeterRates": { "0": 7.782 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0becd1d4-71e7-4395-a785-47ff2db3d6d4", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.142 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5f77822d-d647-45ca-b985-2186b0810c89", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f6fa3fdf-cbec-442b-b98d-4fc132be16eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1b6197e5-7112-4b20-b569-ab2b30df61fe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.65 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "31ca06b2-a234-478b-82af-e33f8ddaf21d", "MeterName": "MSFT Peering Unlimited Data 5 Gbps", "MeterRates": { "0": 41000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "339544eb-d636-48dc-b1b6-2a45228ce8ad", "MeterName": "Compute Hours", "MeterRates": { "0": 0.262 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aa905571-5d7f-4b6d-a1e6-406a281250a5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.974 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "28cea04e-3479-41d5-bcec-97c3f51d356b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.983 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8fcd80c1-24cf-46c7-a7c6-511f275b6a39", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 250.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a118854d-af9d-470a-9441-a50253580cb4", "MeterName": "Compute Hours", "MeterRates": { "0": 2.815 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7cb2e14f-ff57-436b-b155-3d3787649979", "MeterName": "Compute Hours", "MeterRates": { "0": 0.121 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d57528b4-2110-4cc5-8750-b2d730fd3166", "MeterName": "Compute Hours", "MeterRates": { "0": 1.263 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0e416802-fb06-4e3a-813c-b0ed4c202850", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (24 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6ae899af-3ee2-4213-82d3-9d91c233cc9c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.904 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "365a457f-78b3-4c98-8199-2c0459ed3e39", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4cd39a06-0803-4f70-a970-02bdf31124e3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.730125 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "846cf1cb-4cf6-4f04-9e69-8b5493c3dc19", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "61c94f93-033b-4b1e-843e-87a3bde1ec16", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 516.128 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c35c15df-4d8c-4992-b970-8903e537a4b8", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "16c5f661-64d1-4a81-8279-0164bb823597", "MeterName": "Compute Hours", "MeterRates": { "0": 0.462 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e819f9d8-4ce1-4c33-b793-78011e7348c9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.707 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "228d22b2-c814-473a-acfc-3f8644c950ff", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a58368b4-e6cd-436b-bfab-a85ae0e25301", "MeterName": "Compute Hours", "MeterRates": { "0": 8.102 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ea94e351-beb5-421a-92f9-84b1d4d41235", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f65c4174-b990-4bc2-beca-052741dda5be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.051 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ad0cb59e-47aa-42b0-9f4a-451c9f9af4c9", "MeterName": "Compute Hours", "MeterRates": { "0": 2.664 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4817d00a-40ed-44c1-9963-d70e32499efb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "14494683-5d41-4dbf-a960-e10b204b10b2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6f69f6b3-34c2-4a40-8bcb-bb5aa8268553", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "27d7c4a2-5743-4d71-9741-9a8bb074cd34", "MeterName": "MSFT Peering Metered Data 10 Gbps", "MeterRates": { "0": 5000.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-05-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3dfa2dd0-43d8-4445-90a9-3803eaf10ed2", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "761abab8-259d-4206-a6ae-707ed03fc540", "MeterName": "Standard IO - File Read Operation Units (in 10,000s)", "MeterRates": { "0": 0.0015 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "80aed687-40ca-4467-8a4f-99b9c446456a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.759 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "04bf8db0-4f5d-45cb-8c5a-d8d8116c29d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.143 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "b90f8b65-6c3e-43fc-9149-bdfc73b6a5b9", "MeterName": "Paid Data per App", "MeterRates": { "0": 2.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1 GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc8fac33-6774-4005-a3db-efc784cfa66c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.246 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f598ae38-36f3-47a5-8fe4-1f655c9e8ac8", "MeterName": "Compute Hours", "MeterRates": { "0": 4.88 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2e0c0f5f-d41d-45ec-b1ce-1fc2434c1aca", "MeterName": "Compute Hours", "MeterRates": { "0": 2.13 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0fdede62-7f19-4b2a-941b-468037da8f9d", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 66.43 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "27749c62-4f47-4cf6-8e94-7be023958baa", "MeterName": "Compute Hours", "MeterRates": { "0": 1.6 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV6 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a59a85a3-d040-4dd4-8dbf-b0f64717e019", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "95250052-9980-4739-951e-60acbad79507", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4bfdf677-7be2-4a9e-8533-6513c69a151c", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 51.48 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f35b599d-b770-4341-9e52-eee2510f3d8a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.92 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d888ed83-b181-4f95-92ed-1bf6991cef5d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.632 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "58adcdac-6704-4871-a583-30f0426e98e5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.556 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4a64934a-3f91-4202-b920-e14cc88a5b5d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.042 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "e753e8a5-24de-40e1-9c0f-4438951bd077", "MeterName": "Standard CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.17 }, "MeterRegion": "Zone 5", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fda30072-8627-4b14-a283-69cd00bfc880", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 25.42 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "0f2d27dc-6004-4e1c-84c3-1b229913e5c1", "MeterName": "Face Storage Included (in 1,000s)", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1K Faces" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c15c48c4-1c1f-4945-9be5-08224d795402", "MeterName": "Compute Hours", "MeterRates": { "0": 0.119 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b5f839bb-aba7-489b-9e8c-25c480c264bb", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9d81c74d-7a64-4601-b45c-0008a1054cd3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ca22ba8e-b675-4388-8b67-b2e3ebde6d73", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "7e4cc87b-7937-4939-b4b2-12fe83fe092c", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "bd4a9ff3-f831-4b3d-a7da-8ea4112ff213", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b91f630e-7dcf-4871-aed0-df6c00fd3784", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "84030b12-74d4-4695-86fb-e371784d3bfd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72aaf753-f9bc-448f-9612-c85dc956e6d6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "62f20455-d83a-45d1-a0f6-e0adf240c024", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.0963 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8375a86c-cc34-458a-aaf1-c8e2caf3ea71", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "62ec4bf2-15b9-4c37-a753-872978bc0dee", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.1661 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "56b248d8-543e-4290-ae47-fd8674f5c97f", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.3569 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "982ff28e-09d8-40f3-8379-f2bab7488ea6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "45026268-b020-40a7-b840-06a9c720c1be", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c57b2ab1-8a46-4746-bbd0-df1d79c957f8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "de8b5688-21a0-4bb2-812f-8962b0f63e12", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "RemoteApp", "MeterId": "0ad45537-5207-4535-9f21-3b8e80e73b7d", "MeterName": "Basic Users", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Named User", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1e85030c-67b9-4302-b5eb-85be0c021eaa", "MeterName": "Compute Hours", "MeterRates": { "0": 4.336 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "33f52b64-9b91-4e51-a087-a41ab5818b6f", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 205.82 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "86fe555a-88fc-4f0f-8c4a-0d414519b701", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "705ac022-f360-4a96-9f32-a2a982d7b70e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6a8123f0-241c-45fc-aa2c-614fa24b08d1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.066 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d0d60c11-d96e-4fae-a3df-1e39f822d2a9", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 102.96 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "aeeee065-765c-4ce3-8c74-21861409c30d", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.142 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cortana Intelligence", "MeterId": "9e8f4c7c-3482-4e98-953d-186f3e1172c8", "MeterName": "Basic (Daily Unit)", "MeterRates": { "0": 8.064516 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Customer Insights", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7968aef1-8e33-4597-8917-6eb4dbb57979", "MeterName": "Compute Hours", "MeterRates": { "0": 1.481 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a54f6f40-6ef5-46c7-99e5-33124bfcf2b1", "MeterName": "Compute Hours", "MeterRates": { "0": 2.815 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "af4334e4-7547-49da-9017-6f710540309d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6a6a7719-7350-4178-8f96-e1033895b6a5", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "83175033-13ee-4c95-835d-5087c5eb5423", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "80562bbc-3761-40ea-bed9-de87c154ebd5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9263a2e8-a7c0-4765-ab07-f2b267a841ef", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "2f4ac5a8-7f72-4878-a22b-50749e033fc8", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "S Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d0ae028c-44d0-4689-a24f-e729cad573c6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.058 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ef18c0af-c644-465a-9a76-9cf1e3cf54f5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.766 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "31281e3f-641c-4d4d-9b70-3a27437a9aa9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.644 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "83944f00-e218-4cca-974a-c0d01dafd2bf", "MeterName": "Compute Hours", "MeterRates": { "0": 2.617 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "06ee940c-273f-447f-9ca0-ba54218a9722", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 23.848 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fd826c3d-0cda-4969-b028-b3afcd2991cc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.329 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "500de1f7-1bea-4481-89ba-cf400bf13abf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.332 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e40a96fa-4939-4857-a296-7118e0ca74dc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.88 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "7cbfdd49-706c-43d8-9ff2-251f08cd9c36", "MeterName": "Standard S1 Overage (in 1,000s)", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "af4c7b6e-9fa1-4207-ae06-6625f30994ae", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.0083 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "14238d16-80ad-42a4-9656-b7e1261fbccb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a97bb631-35bd-47a7-ac4e-0c1ea52f1719", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.201 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "187e023f-9a0c-4615-8212-3ccd964aa745", "MeterName": "MSFT Peering Metered Data 200 Mbps", "MeterRates": { "0": 145.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b766ad35-2929-48dc-81aa-e1f5a2d5bfd5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.84 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dcc0c382-24d4-4bf3-9b32-2d727b072d65", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 49.5 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ac1c269f-595a-4936-92b2-a40b936bab7e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.86 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "33462701-5dda-4102-b1f8-e1eca737ff6e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.071 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b0400d79-68d7-48a4-8f39-5c867d108ebd", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.0805 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "95f391bf-dd5a-47eb-8f08-d17ccb9ed370", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.246 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XL OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f89269ee-ef2b-4269-9aba-9308de89cb68", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "e06dd150-870d-4fd8-a78a-a811b0d22b37", "MeterName": "Standard Overage (in 100,000s)", "MeterRates": { "0": 50.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Speller API", "MeterTags": [], "Unit": "100K Transactions" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12a23053-8007-4387-b1b5-720140dfa00e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0f0157d1-ff48-49ba-9653-eba004a1a10d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Recovery Services", "MeterId": "6c1ae29e-ea4c-43f3-a25d-55c78b8db13e", "MeterName": "VM replicated to System Center", "MeterRates": { "0": 16.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Site Recovery", "MeterTags": [], "Unit": "VM" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c01a1eed-b19a-4aad-bb83-8d62cdc29778", "MeterName": "Standard IO - Page Blob Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c4de179c-c9ed-4e2e-b77c-392655fc62b5", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.1252 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e869673a-1901-4af5-8788-58b668f7a8b6", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "885308fc-3438-4ea1-a9f0-356ac1806722", "MeterName": "Compute Hours", "MeterRates": { "0": 1.169 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0e61c836-8150-406a-bab5-4242c6914f97", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0b02555-e025-4b46-813d-9fc9c59f4838", "MeterName": "Compute Hours", "MeterRates": { "0": 2.954 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1e96d878-3362-4400-8488-e4b200098e1a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.098 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "620c9c91-4e48-4f35-8085-8e6b620e2154", "MeterName": "Compute Hours", "MeterRates": { "0": 0.131 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5d4be54d-908b-4a00-bf85-83644882619f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96a067eb-479a-487b-9fbe-f64199af0205", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5dc94800-2d4b-4f71-9a72-e867bae0876f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.121 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1dc72c6d-2ca8-404b-b5f3-dd64eca27ce2", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 72.0 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "146f3877-a621-4b5a-80bb-ecc2279ae2ff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4bdf6b62-85a8-4241-9b92-ce226b2c5f23", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "50bbe40a-7656-40c5-b799-591fd6ee4227", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.5855 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "ff7c3059-02f0-437d-a6b8-a16f1a37a101", "MeterName": "Standard S4 Overage (in 1,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1127b2c7-502e-4e6c-88b8-61a94b4f423b", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.1993 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "66260cb7-608e-40a1-bb09-34e9645b2c53", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6f49b921-b7b3-4fe9-aa4b-0699944bbdb7", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.21 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "854ec580-2f31-4916-9851-accdbde5194a", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 499.982 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "b7eccac8-e584-47d9-9368-90bc9782f562", "MeterName": "S3 (Units)", "MeterRates": { "0": 10000.0 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c596b592-e7d1-4f7a-8d11-9aac6048f87d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.315 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "96b4003d-adb9-453c-b024-a810ffddc21d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.148 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "acc81779-f782-4e9b-b837-90e9538a091d", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0055 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c24f70bc-1665-4d57-96dd-6e56038e2e00", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e407bc64-9bf3-4ee1-b6d6-145a590703a6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "4f1fa8fe-ffed-48fa-9969-26a150775b60", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.15 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 5.0, "MeterCategory": "Business Analytics", "MeterId": "1d35a882-0e55-447a-8482-3e49221b18bd", "MeterName": "Low Frequency Cloud Activity", "MeterRates": { "0": 0.6 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Factory", "MeterTags": [], "Unit": "Activities" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7cafdacd-f6b7-4991-ade6-cca146bea157", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.143 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a4f190ad-91b9-42a5-a9e7-858e84d0956c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.37 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "75f53448-65fd-4333-b0d4-ae2dda1db5f5", "MeterName": "Metered Data - 10 Gbps", "MeterRates": { "0": 5000.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a4407cfc-ba27-47c6-b53b-2c8cac94f316", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7bb27309-e491-4288-b180-d6e7112edc34", "MeterName": "Compute Hours", "MeterRates": { "0": 0.186 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96812953-bc3b-4b96-bdf5-051d8c4a534f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A10 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12029fdf-d31a-4d82-81b5-bac12e9f3649", "MeterName": "Compute Hours", "MeterRates": { "0": 0.047 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3f7390fa-1879-4310-871a-95a0a0c26ec2", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 6.048 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "77f439fd-d80d-49c0-9ce1-262a5211d0eb", "MeterName": "Compute Hours", "MeterRates": { "0": 3.059 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8dc92ab8-91b0-407c-a5cd-f484e3653db7", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0044 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "b40291f6-f450-429b-a21f-0bc6711787ac", "MeterName": "Build and Release Hosted Pipelines", "MeterRates": { "0": 40.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Team Services", "MeterTags": [], "Unit": "Pipeline" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "245bfc87-0f93-4ae2-b7bc-3f567b10e520", "MeterName": "Compute Hours", "MeterRates": { "0": 0.458 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6b3b540c-c0b2-4d98-9abc-aa26087f38e9", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c6aef3cf-44df-4155-947c-64f444e3dc5c", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 101.71 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "8fc71fea-8c59-4c40-b16e-d8946d7cc130", "MeterName": "Free Apps", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "Apps" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "327be05e-b61d-4e57-aba3-5b9e1a767213", "MeterName": "MSFT Peering Unlimited Data 100 Mbps", "MeterRates": { "0": 1300.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9af22c27-8e81-40a0-8973-f442ba923911", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9d57c036-8bb9-4ef3-b81e-c90c0727b08d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "47655184-5a06-4122-a7db-a0ae297e3a6c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "510bac5f-4aa6-4c16-82e7-8cf12f2e6adb", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.656 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A8 OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "05f39632-0947-4cda-8833-2172163d0134", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "132e16fb-665a-4ed8-a9b4-1995e8fa73c6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.937 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b14a5b7f-417c-4b16-b719-5f4b057d560b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.54 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "07b2433f-f09e-45a3-834a-a7743d60bd28", "MeterName": "Compute Hours", "MeterRates": { "0": 0.127 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e4ce293f-b27e-407a-a20b-b3498718006b", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "14d7b1f9-2825-495f-bd8f-eac5943a57f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.152 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "cdd01af8-9c0b-4952-ab2b-ddbeb16e1ac1", "MeterName": "Compute Hours", "MeterRates": { "0": 2.13 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0f99ffe3-9c01-4093-9f43-e5542cde52c2", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.4 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "576fc19c-9ed8-4e74-9164-86ffc1ccb429", "MeterName": "Compute Hours", "MeterRates": { "0": 0.092 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "30f61715-f06d-4f84-969d-e63087d22472", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "ca610afb-d685-4cb9-acbf-2278a934112f", "MeterName": "Standard CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.138 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f741839d-9c12-4b40-8985-c397bfd1e4d5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.808 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "46b7049d-2f0a-4153-96b9-78fea3f83029", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0048 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "68a31453-4e2b-4410-962c-14fe90fb3252", "MeterName": "Compute Hours", "MeterRates": { "0": 3.227 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "275b0d22-68f3-4196-bf3b-702247d9f6bb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6b95aaaa-e6e4-41a3-a2a6-90dea894c272", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.225 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "450c65cd-de2a-4639-affd-fc9e85105bbb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2ef71e5b-5da5-4a4d-b492-5277f79b30ea", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Identity", "MeterId": "945bbf0f-0272-4ccb-ad3a-23798e584380", "MeterName": "Users", "MeterRates": { "0": 1.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Multi-Factor Authentication", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0c1492a2-8db8-44c6-b0ed-cc6188c72b34", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1a002948-ff5d-4047-8fce-d284852ae52b", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.145 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4320563a-74fd-4fa2-a3e7-e163c0189719", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "9d9c75c7-6002-4a16-9258-c909a9565e9a", "MeterName": "Standard Medium Azure App Service Hours", "MeterRates": { "0": 0.22 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c089fd5b-4dc8-4422-be54-7103c08e21ba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.773 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0a29368a-01ba-48d8-b033-7f40b551d443", "MeterName": "Compute Hours", "MeterRates": { "0": 1.172 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0b26ac36-5ac3-450d-a942-0fd60e4192c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "b137c303-c66a-4b0e-84e6-1f92f444d91e", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "36055b6a-ccb4-40ff-b2b8-34b855fb4aaf", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.2825 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "aa1d3b6c-a906-4731-af7a-a3299b0a8c34", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "079430b3-16fc-4f1c-89da-080cdc2bf35f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f1249c5d-dca1-45e8-b42b-726dc9da0b94", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 122.88 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cb5fb216-7c56-4f37-a553-a448e7e53ff7", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.904 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f3c5ed3-a187-4fb8-9d8b-02e36641e27b", "MeterName": "Compute Hours", "MeterRates": { "0": 11.339 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ad1be467-1a36-4e0b-b3de-e7b0cb0f6f9e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.202 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4e1cf28e-c997-43ef-93be-5f3febc60f40", "MeterName": "Compute Hours", "MeterRates": { "0": 0.883 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "07821c60-1222-41db-b35f-59d169cd2c49", "MeterName": "Compute Hours", "MeterRates": { "0": 1.168 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5435d17e-896a-4d1f-aabc-8b74183f6e9e", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.034 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "299db139-4526-4af9-86e8-53240278b2b1", "MeterName": "Compute Hours", "MeterRates": { "0": 7.076 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2d636ecf-35a5-4c5e-8a87-6ee81d71bd81", "MeterName": "Compute Hours", "MeterRates": { "0": 0.992 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7008e60c-6d9c-400a-8d4b-6b050aa28e29", "MeterName": "Compute Hours", "MeterRates": { "0": 0.079 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "976544bb-a6c1-4a04-879b-2d95dec07732", "MeterName": "Compute Hours", "MeterRates": { "0": 0.203 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8e9af6db-7104-4f1a-830e-93eabb955444", "MeterName": "Compute Hours", "MeterRates": { "0": 0.032 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (up to 4 cores)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c9ed8e37-ac21-4027-a060-3eb0eb5e8a0c", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 155.44 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a821a90b-2a56-4c1c-812d-0446190249fe", "MeterName": "Compute Hours", "MeterRates": { "0": 9.064 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bcc8a6d2-f176-4e6a-b033-f5bc8cebb68e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.378 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "02ee2eec-2705-421e-ac2c-cdebf2e537d9", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.06 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a10d37fa-4928-426f-9ebe-e2d8ce3cca06", "MeterName": "Compute Hours", "MeterRates": { "0": 1.738 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cd3d7d79-e60b-457e-aa9e-3adad73fb10b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "feb04742-34f8-4ad9-b883-d912810b39cd", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3c44e152-1ea5-415e-99c4-e73c00eac715", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 250.0 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "39efd5e7-cc49-4425-bb58-a7b78f56333c", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0375 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c9846bec-80e3-4900-9e38-5060835d44d4", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 99.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "5c935199-99d3-490d-9342-703ceebe392c", "MeterName": "Metered Data - 100 Mbps", "MeterRates": { "0": 100.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "197eeb00-f40e-4d31-bf6d-8ef8d54ff342", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "944f6253-f198-4f72-ba6f-d3b8ee4d4768", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "132d57f9-3761-4035-9a0e-a087c44cba20", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "af68cdc4-8795-4b3d-a360-5fdde7241f05", "MeterName": "Compute Hours", "MeterRates": { "0": 1.22 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "26828661-e674-4f0d-8e1b-6ad70e1615c4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7873159d-ebeb-47cf-9bbb-b2933bee9f2a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.265 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d9701908-80f2-42c3-baf2-b7972e43a2c4", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 148.68 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "73292260-ef3f-4583-8fef-199625b783ae", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d92b8278-b72c-4b6a-8b57-606806ec1d23", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 34.05 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e733dc13-8522-4050-8987-8db7125856b6", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "cc143740-dafd-4586-b1cf-f07c5665a1be", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "99762400-c6ee-4f87-91ba-0508f1638e21", "MeterName": "Standard Data Analyzed (GB)", "MeterRates": { "0": 2.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Log Analytics", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7af6950b-29e5-45a9-8584-5d3bd8f0a618", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a6a35bd0-b360-46cd-9433-3f6cee8551eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1b962c90-79f4-4c53-96a4-d69db802e0a2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.243 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b285dada-cd22-4275-b73a-f559579fffe4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.959 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ff2a610d-bb62-4440-90d5-02266ff4ffb0", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.68 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "d5034e45-00c1-48c6-8c00-c866f788e033", "MeterName": "Base Unit", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Messaging", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "40f0e9b6-6760-431b-9a48-0693ec372d44", "MeterName": "Compute Hours", "MeterRates": { "0": 0.662 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a135fea2-6c76-44e2-ad54-3b6313f0844f", "MeterName": "Standard S2 Search Hour", "MeterRates": { "0": 1.613 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2abb385b-e987-4155-ba96-23a34f3bb7df", "MeterName": "Compute Hours", "MeterRates": { "0": 0.67 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "89c117f6-6100-485c-b0b2-c33c8b63e18a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a84406ff-d8dc-43cb-be4c-286e8266bc29", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9f1c506-6e89-475c-a74b-bfdc39fec60d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.521 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "e8862232-6131-4dbe-bde4-e2ae383afc6f", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SLES (6 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ae557946-5cd9-4047-843e-cb33489feed2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c72a3185-ea40-4d10-aaa5-d99405c74cf8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.894 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60477f1e-08ae-4588-8c69-e7775816132e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.026 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a362614a-506d-4c5b-82f3-b408efc4fd8a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.888 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "61f839aa-bbd5-4270-821b-07904e18cfa0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A10 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5b1f1e2d-5c19-43ea-bbfb-d5378301858e", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.011 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a2639ce-ae47-4413-9837-6b4f4b78be3d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "632d368f-6336-47eb-a1ee-b063ec39eb1f", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.0645 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a8dd9ff-0e5f-4ce9-92f8-0bfbb1091e42", "MeterName": "Compute Hours", "MeterRates": { "0": 0.313 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e5d08ee7-4d8a-49dc-8e46-f818d0499298", "MeterName": "Unlimited Data - 500 Mbps", "MeterRates": { "0": 2750.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "584a0f53-5caa-4dde-9586-d62ab46d388f", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.151 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "fe8170f4-b698-4d4d-ba84-d6ee6ff74c97", "MeterName": "Standard Live Encoder Input Hours", "MeterRates": { "0": 5.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8e56f69a-3211-4cb6-b73f-f629cfeeb34e", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 33.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8b227a6-d291-423a-8dbf-423c9dd94a94", "MeterName": "Compute Hours", "MeterRates": { "0": 0.044 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0f254a75-3036-4ae6-af7d-eb9cd4b7167a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b74c1bd6-c0ea-4248-b00a-dfe2afce7af0", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6bd28d13-48d9-442d-8501-a1f59507b135", "MeterName": "Compute Hours", "MeterRates": { "0": 0.22 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ea6dc3b9-a9ee-4d30-a059-8edf46dfc478", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ec97b317-5e42-46ee-81ee-0dc4396aa2f4", "MeterName": "Standard S3 Overage API Transactions (in 1,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f3fa81b2-281d-4750-ab7d-f91fa7ede967", "MeterName": "Compute Hours", "MeterRates": { "0": 0.368 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0b64d111-1850-4091-b27f-763e35f67215", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5468 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "54c40026-ffc2-4da4-888d-481a0ef44704", "MeterName": "Compute Hours", "MeterRates": { "0": 2.026 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "07e398a1-409c-42a2-bbfc-390f6d099709", "MeterName": "MSFT Peering Unlimited Data 50 Mbps", "MeterRates": { "0": 610.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fbbd1796-402b-46b1-b7cb-5a729a6e1c69", "MeterName": "Compute Hours", "MeterRates": { "0": 0.291 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b5e31c9d-98f4-47c6-af4d-e22a4be844ea", "MeterName": "Compute Hours", "MeterRates": { "0": 1.706 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5d16be88-bfc0-4f33-bb0a-826eb941c13f", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.017 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bb8a035f-5ff5-44bf-aeb6-77b2fc1de144", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "f622d0e3-d20d-4fa4-85f3-5e8010b3d421", "MeterName": "Basic C5 (Hours)", "MeterRates": { "0": 0.42 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d33be181-a577-4f8e-9e3a-6d650e620b02", "MeterName": "Compute Hours", "MeterRates": { "0": 0.513 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "21b293cd-60dc-418f-9b98-2b452ed0de09", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.059 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f438a8b0-a0a8-4633-8cb1-21daba7270a0", "MeterName": "Compute Hours", "MeterRates": { "0": 7.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (20 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "97a052f2-dbc4-4271-8f00-dbfa0a37e079", "MeterName": "Compute Hours", "MeterRates": { "0": 1.56 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c33ad113-990e-4e2f-bb6c-54d61ff4f8fa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "701c1cfc-bae6-4655-85a1-4949d634c7aa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1289d3d9-2c7a-491b-ab7f-c3c5cf6dd7e7", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.067 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9f98bcd9-2523-4212-b153-315e6aee3c20", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 80.54 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2dd2239e-ed74-49ad-8077-500d8a6653cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.62 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8b767c7b-3c71-42d2-821b-b6b072e181c3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.482 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "83961fe3-e796-4275-8699-e0f13ea9185d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.132 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "41804069-17cf-45dc-9bf8-a672686ccc51", "MeterName": "Compute Hours", "MeterRates": { "0": 0.475 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b2433c8a-f094-4e89-84b2-123d6ee29ca3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.036 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "20b2cac7-36fa-4c48-bf67-c4d43d7a9f40", "MeterName": "Premium P4 (Hours)", "MeterRates": { "0": 5.772 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "67d2bbb3-964e-446b-888b-0e8f0c586f21", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "42df9574-8a63-476d-bcb7-acf476d3a2fd", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.8064 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a6e82a0a-80c9-4d64-a816-212e27c97b10", "MeterName": "Compute Hours", "MeterRates": { "0": 1.133 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "554675b5-d546-4f54-8828-c10c03d38a9a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.333 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2e6e6d84-12e9-4ddd-a33b-301d391df510", "MeterName": "Compute Hours", "MeterRates": { "0": 2.854 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "433f8899-8f34-4120-a266-39649d1ef24e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03994b5a-a7ce-4d12-9d61-0f6cf58d6778", "MeterName": "Compute Hours", "MeterRates": { "0": 0.273 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "9fff85ca-d247-4c0c-b841-9e8dc6dbaad3", "MeterName": "S1 Media Reserved Units", "MeterRates": { "0": 69.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d793e346-94f3-4e3b-ae43-666913a4b7da", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7a11aa0a-27ba-4ab8-be1b-1906db4b2efb", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dfac5a0f-6f3a-45b5-bbd5-b28336d57cc2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.496 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bf8eeccc-0b61-4645-98fd-bf20411f2d6d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.508 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4a70b10f-0790-4026-8a75-d8363d5f83f8", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.032 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "c6119456-9b69-4ffb-9dfd-9e1cea4d0621", "MeterName": "Basic C5 (Hours)", "MeterRates": { "0": 0.525 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f10a94cc-a898-4d73-9411-821009720c15", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "00a95b36-8625-4555-bea6-5288c7ce8f50", "MeterName": "Compute Hours", "MeterRates": { "0": 0.588 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "712c80a9-91af-452a-b3d9-de0361c8de7e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82cef088-c0ae-41c7-a7e3-93c83254a24e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.264 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82194f40-08e3-4d64-9b08-11fb9934ffdb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.021 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4801f383-ed00-4597-a879-da967f7739f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.39 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "437025b7-d995-4efe-8b98-b48d0875d72e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.155 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a6b58cdd-8455-4ff0-9c09-4a81f6c5df90", "MeterName": "MSFT Peering Metered Data 50 Mbps", "MeterRates": { "0": 55.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0a82aed6-2937-4cc0-a1f6-71fc3a9e4f7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4148a391-4010-4d8f-aba4-e4e4d5599899", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6d6122d8-47dc-42cb-a910-1d6726abc07f", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 34.32 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0caea3e3-b9d1-4219-a3ec-fc4cf8142a6b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "079eda81-1004-4bd3-aba3-4a970cb6bbd8", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.0935 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "3d7aa86c-0e9d-4139-b59f-cc5bad92b873", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57e8f0ea-b5ea-4bc8-9bd0-a9ddce256025", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "26c98145-3131-4e0a-8c2b-bed1246c8adc", "MeterName": "Encoding Data Processed (GB)", "MeterRates": { "0": 1.39 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ba80c965-1c31-4f45-a7cd-22c78ced9e86", "MeterName": "Metered Data - 10 Gbps", "MeterRates": { "0": 4350.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e0d57bc5-e150-4955-b95c-fb2fadab34d9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.316 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "330cfeab-55fc-4c95-a422-f0f09428ef53", "MeterName": "Compute Hours", "MeterRates": { "0": 0.119 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "757e2aa1-9d5a-447e-be83-64d99dc51f2f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.291 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "069007d7-2cd2-4779-88c6-b43d264b498b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7b1a43ea-b0e8-4ee6-a4c8-219433bda935", "MeterName": "Compute Hours", "MeterRates": { "0": 0.296 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "716cfdf0-dbcf-4c84-bdc3-43130dde78e5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.051 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "80177185-c995-432e-bd37-09a3faed72fe", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f4e6a4cc-2e80-452c-853c-71bf9b8a6d12", "MeterName": "Compute Hours", "MeterRates": { "0": 0.297 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d83fa551-8030-416a-b443-306aef06a5d2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "27d42441-b91e-4491-89fd-388c48477246", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c66bea2-94be-4740-9a4e-006919770975", "MeterName": "Compute Hours", "MeterRates": { "0": 0.65 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e59e3380-bea3-4f6f-90ef-0846822dbf36", "MeterName": "Compute Hours", "MeterRates": { "0": 2.68 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "fef1105b-7705-4f29-890c-2e1cc9cfa9a4", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.4 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f88737c3-4061-458c-87e3-619ccacd6913", "MeterName": "Compute Hours", "MeterRates": { "0": 0.516 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5261a49e-27cc-4b42-b264-15e332882525", "MeterName": "Compute Hours", "MeterRates": { "0": 0.153 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "32c3ebec-1646-49e3-8127-2cafbd3a04d8", "MeterName": "Data Transfer In (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "c647ba7a-af71-451d-9971-c7d7e611f622", "MeterName": "Premium P1 (Hours)", "MeterRates": { "0": 0.722 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "495caadd-0d44-43b2-b25b-46e922f2f806", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 4.8387 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ceec0284-39ba-4ec8-98ed-09630ba1b1e2", "MeterName": "Compute Hours", "MeterRates": { "0": 8.602 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f0550a41-a422-4a7a-adb3-538e35514db8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f8c187bb-5a47-46ae-b874-f186d207fff4", "MeterName": "Standard IO - Block Blob List Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "0287df59-e0c6-40a9-b91a-68a2f16bc215", "MeterName": "Speaker Identification APIs (in 1,000s)", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000 APIs" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a6123fe9-eef6-40b3-907b-ea1ba52684cb", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6512d69f-3960-4574-bb3b-f5732e130459", "MeterName": "Compute Hours", "MeterRates": { "0": 1.176 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5ca8088c-26ba-41c6-a704-f7557fe0fc50", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5d97dd1f-b0f2-4387-b9cf-da849209d530", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "eeada8b8-8ce8-402b-b4a1-554f7ebc8e96", "MeterName": "Standard S3 (Units)", "MeterRates": { "0": 80.65 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "baf90f4b-64ee-49aa-b386-0b712ef78234", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "22e690b0-183e-4266-bbeb-0c8ccf98f160", "MeterName": "DWU", "MeterRates": { "0": 1.5121 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b45771fd-b60a-443d-9be7-2ec851484000", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.07 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "173e1c1b-b46e-4e95-acf6-01eb80033084", "MeterName": "Compute Hours", "MeterRates": { "0": 0.154 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "26fb83ae-317e-49ab-8ebe-4a986e4a47eb", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.1 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3d22f164-f13b-48c1-9c5a-e528bd62213f", "MeterName": "Metered Data - 1 Gbps", "MeterRates": { "0": 436.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7d04ca17-6ace-45b2-bf21-4edf16445747", "MeterName": "Compute Hours", "MeterRates": { "0": 4.034 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "dea7a453-5935-40f1-886f-55f6e9966d21", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0fb61242-a7bb-47a5-916f-f4e55b1f6bf1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "84801b67-0e31-47c3-8730-7c73b304406e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.016 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0ad39c38-f2c3-43cc-a26d-d26bdd69b3e5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1039fc03-7378-4357-94c6-f83a1d9e42c7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "28bd4017-f91c-4023-a580-2279ec2b7f5a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.941 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8a89df43-bc6b-407b-beae-8fa839ce0eb8", "MeterName": "Compute Hours", "MeterRates": { "0": 2.294 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4d6302b1-a3cd-49c7-96bb-09bc268b59ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.759 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5884da61-d1d1-4ae7-8114-f1f86da79259", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d7f3e9ce-c9a8-4f35-b3b9-de8f77a1ae72", "MeterName": "MSFT Peering Unlimited Data 200 Mbps", "MeterRates": { "0": 2300.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d513de91-7c61-4933-9af0-616ac638a464", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "572f570a-de2f-4407-aef6-f6c8a5e992b3", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.2875 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1859ba35-77e1-449e-b1f3-e490781d9988", "MeterName": "Compute Hours", "MeterRates": { "0": 0.383 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e30738b9-0928-42f5-ba74-949bcac756fd", "MeterName": "Free Database (Hours)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MySQL Database on Azure", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "41f6335d-be86-4c70-8f05-57adc898cb24", "MeterName": "Compute Hours", "MeterRates": { "0": 0.337 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3789a039-9a1e-43c7-a228-8df0e6b648d9", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e7d6c5fc-84f2-4fa0-8111-e8da312db6d7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c8f6b01f-78b9-40b0-bad8-80f0641f5a02", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "36fcf8a0-48d7-4037-99b0-9839138a1cd4", "MeterName": "Standard C1 (Hours)", "MeterRates": { "0": 0.173 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1cd3b30f-7ba4-4181-bcd1-e41063749146", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6f73be4c-f475-4698-b673-80e0daf18e90", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5625 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "30c0ff35-bdc0-4eb8-84c6-57dabf875c41", "MeterName": "Compute Hours", "MeterRates": { "0": 0.673 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f256212b-6c29-413d-b7e1-4d2eaf898ebe", "MeterName": "Compute Hours", "MeterRates": { "0": 1.208 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "28bbcbe2-049c-4f6e-b5d8-f6639672fdbc", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a8ec343f-bb99-4489-83e9-3e3e3a8212a5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.56 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7fbb6997-1165-4148-b611-82e89f28a401", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c63de514-dabd-4a85-a414-2b7094627d78", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c4dacb04-bcd1-4726-8062-cb9c7ba0b4f6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.58 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d2b483e-8fce-453c-8d9e-6ad67b93175c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "011d5795-7609-4c28-8084-cd26374a1d0e", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.122 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c35e681-ab07-4484-8a18-1df63da194ab", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c584c76-714c-490f-949d-9d85a0e0669a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.895 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5d281697-2039-4cfc-9a83-c8a67af384d3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d554ea87-a187-418f-a591-b951c5e09c04", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.016 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b6ce5147-8a54-43b2-b17f-1188cb63cf5c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.203 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6393c4ce-a679-4158-a99d-beca6a1c9776", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d6eb6e09-ee00-4672-aa66-ed1219c1113d", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "20905866-28a8-451c-836b-3b75a3f90971", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c4899873-0de9-4783-88f9-62968847f0e7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "5e539fca-af70-4f32-a45a-9a277e0a82fa", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A8 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f06a5bb7-a75c-47f0-9203-1177f5d407ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.048 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (6 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "db489e69-ca33-4dc8-98bf-4285b24b9ca5", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 17.16 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c466cf23-472d-40b7-a468-e909db972adf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.857 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "be6bd2fc-0be3-4dcf-b054-a518c4c1fc82", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f3e04e3e-3793-4659-9ebc-2d95394dc1fd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c1c70ef4-920c-4f3b-b370-1c4e99767543", "MeterName": "Compute Hours", "MeterRates": { "0": 0.296 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f96d035-3bac-46d6-b2bc-c6daa0938536", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0963ca7a-d6bf-405b-bbfe-bb7fc7820dd4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.42 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6fe32f7d-0f47-468a-9822-b7031a87d181", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "65249eea-64ec-45b7-b79e-e587786ead80", "MeterName": "Compute Hours", "MeterRates": { "0": 0.975 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "04a96859-eb95-4f16-a6fa-4b6805a709ed", "MeterName": "Compute Hours", "MeterRates": { "0": 9.064 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "f7ff655f-c6b7-4e23-88a0-34adb1f4d72e", "MeterName": "Basic C6 (Hours)", "MeterRates": { "0": 1.05 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "6f29f045-f330-49fc-bb92-aacd0186f819", "MeterName": "Standard CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.14 }, "MeterRegion": "Zone 4", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cb2b1bb7-1ed1-421d-bb81-7f8b5e872710", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 8.2155 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "11f88600-1818-4539-ada5-0bd306a13dfa", "MeterName": "Premium CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7669960c-6891-4f31-8fa0-73ab6240b00c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "15b74273-453f-47d0-8b63-a4a7fa4e8d9c", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 571.408 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b11c3146-9d8d-42b6-ad94-1d0234bbde8a", "MeterName": "Premium Unlimited Data - 100 Mbps", "MeterRates": { "0": 675.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8a481051-9bc9-486e-aeb0-8dbd0a1d89a4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.197 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "724638cb-e35a-4b8d-9ca6-6cd62c1ef85a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "309ff4b5-4810-4bca-a4e3-5767e2e344fa", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "7fadaaec-3afd-4afb-89a7-cdb1e3cb702b", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "bf5b0de6-a5f1-45d6-aaab-d4f0b74dfe77", "MeterName": "Standard IO - Disk List Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c7e1cc89-b081-4af0-a4ad-0a24ea844b30", "MeterName": "Compute Hours", "MeterRates": { "0": 0.625 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4bf8a987-48e0-49b2-908e-7b0255a0e608", "MeterName": "Compute Hours", "MeterRates": { "0": 0.15 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5b4df5ce-0604-4779-aca3-f09e6a623526", "MeterName": "Basic Search Hour", "MeterRates": { "0": 0.12 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1cde2c10-a3ab-496d-b881-0fa56034bcb6", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.636 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7b1da18d-2412-401f-ab90-8f92d4bd5a98", "MeterName": "Compute Hours", "MeterRates": { "0": 3.95 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a9f475c6-54e5-4a54-9d5e-1e538bbf0881", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f1b96c2-2fa6-4f77-91ae-a3adf5dd3cd2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "ab1b55bd-4dcd-4c21-8648-faa589d929b2", "MeterName": "Standard C1 (Hours)", "MeterRates": { "0": 0.173 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1e451c33-1810-4a8b-b78e-047341ca84bb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "129ace17-bf34-4a1c-bc64-06a68bf18247", "MeterName": "Compute Hours", "MeterRates": { "0": 1.17 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "678ddeab-b53d-4987-a8e2-94aa245399df", "MeterName": "Standard S2 Overage (in 1,000s)", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "45c7b5bb-d542-4341-84be-db69b4cda513", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0de24925-fea5-4424-af40-e91b866f974c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "6f9f59dc-58dd-4553-be88-22792ecc13ee", "MeterName": "Bing Speech Long Form APIs (Mins)", "MeterRates": { "0": 0.15 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b4d6b97c-0802-41b0-a0a8-57a2b9bab531", "MeterName": "Compute Hours", "MeterRates": { "0": 0.036 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8601bc01-ce91-4283-b445-d91084bdb86f", "MeterName": "Compute Hours", "MeterRates": { "0": 3.075 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "41e8048a-2cf8-4ae0-abe9-df16b2d8643f", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.0645 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0a7ac46a-f068-4da0-b497-d551898515e3", "MeterName": "Compute Hours", "MeterRates": { "0": 5.36 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "774941f3-ee15-4ce2-b8f2-fd6ed2760e14", "MeterName": "Compute Hours", "MeterRates": { "0": 4.88 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "ec96198d-ac23-488d-811f-47bcc1440e24", "MeterName": "Standard CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7b88068a-a50e-4420-a661-1d0de1381069", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d86bdc3f-486d-48e2-8bb8-6d0697656ebf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.356 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "545b66e2-8d15-46b2-8bb5-0fa3bb73cee5", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0275 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "30242e11-c74f-4af3-a972-d5ba472bd1f2", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0288 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9eef0166-d2d6-4dd8-ae46-df8691b63b64", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "RemoteApp", "MeterId": "9a049cee-7b9c-48ff-9bea-3f7eb0f39374", "MeterName": "Basic Overage Session Hours", "MeterRates": { "0": 0.175 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Named User", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "173429b7-e66b-4ccb-96c9-97a6650df06f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.611 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "11e08152-731b-4eb3-b580-680a6b6a60b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.44 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a09d8362-a45a-40df-b4f2-fa9ecfa230f9", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 483.88 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f4fdacd6-0159-4efa-9a71-5cfbcfaaefc1", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "495c9a53-cafe-4b01-b17e-d7ee2abc3379", "MeterName": "Compute Hours", "MeterRates": { "0": 0.101 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "817948c5-969f-4529-a58e-55ba7f06813f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.488 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a1d3d1f4-2d2d-42e0-8514-37df19cd9f8d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1b33abd0-f6e2-43dd-9810-51c0dd9df087", "MeterName": "Compute Hours", "MeterRates": { "0": 0.61 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "da46314c-5be6-4d7f-919e-4a33b7467c21", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "716242bb-9c68-4140-ab19-21a468ddbb74", "MeterName": "Compute Hours", "MeterRates": { "0": 0.038 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7f483922-d12a-4723-a457-1d93ada4da1a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.351 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6baa8ec4-a588-4e40-a516-67f6914a3a17", "MeterName": "Compute Hours", "MeterRates": { "0": 0.096 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "52cb44d4-f0ae-400a-9bca-1745f14f3ece", "MeterName": "Compute Hours", "MeterRates": { "0": 1.74 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "7214c3f4-aa3d-4ade-b075-be92533ed9a8", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "06fe658c-e98e-472e-bda4-ba962dcafbd8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.315 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "19985828-412c-4eff-8714-9c242b214dc9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.106 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "94600900-14cc-4eaa-b478-f5729db4faf2", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.68 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb25747d-ddd3-4a0b-aae5-52ee0deb4ccf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.115 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4a4646f2-60c6-413e-a489-559627683c49", "MeterName": "Premium Metered Data - 5 Gbps", "MeterRates": { "0": 5180.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6ecded8f-3f77-48d7-9fbe-001df000546f", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8a7cac3-260d-4a23-a913-bb0c3d010621", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Enterprise (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3d506f0c-344a-4e3f-a7bb-a9f5b71d2aed", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.063 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9fdf4e62-d5b3-40c4-a653-87b600555d36", "MeterName": "Compute Hours", "MeterRates": { "0": 0.154 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a4d4f647-f54e-400b-a11a-dcf256afa091", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8ab06071-5c92-4d9d-a5bb-bd438c6c39f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.894 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "afa3348f-504d-406d-8331-6bcda01a8698", "MeterName": "Compute Hours", "MeterRates": { "0": 0.166 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "52a3bcd4-2abc-47e5-8361-7d03b71deadc", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 150.0 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7723a342-2802-4415-b9bd-07ccd123e94e", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a5c72a95-7226-401c-bc1b-d9a50c5afb64", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 16.95 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "55a41eda-5924-486f-9e9d-2f8aae4cc812", "MeterName": "Compute Hours", "MeterRates": { "0": 1.208 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "30106574-06d9-4c74-a112-0aed422b7133", "MeterName": "Compute Hours", "MeterRates": { "0": 1.95 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A9 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "85016b5d-4693-492f-b2af-cdb3a56e8a24", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "632836ce-f431-4f04-a290-4cb47f2f19e3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "65bf40a1-9471-4b05-acc3-d4aa9e419cc2", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 3.025 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "552764bc-e985-44b8-a15c-82d2cf280ef1", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1948 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "36a471d0-6947-4766-8fcf-bcc5bbc98076", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 645.16 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5806ac75-4d74-4d81-b90f-81a434a09917", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "cdd937d6-47df-41f7-87ce-d55f7fa4a208", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3502ec6e-9d34-4770-8e20-b702ea9a59cc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a63a874c-01c4-4596-b12a-4979045f1a2e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.592 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a575220c-735c-463b-83c9-8b6c6b340691", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.88 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ce83be4-1d7f-4f30-afc4-b35d3797db8e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.081 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c5bea5ff-8d40-4a98-831d-7d0aefc471bb", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 23.848 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "10164352-daf6-4c7a-abf0-1e02c7f9e026", "MeterName": "Compute Hours", "MeterRates": { "0": 3.411 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "455f5f4b-ec0f-44e3-8108-71104622b1f0", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.091 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cc09ac2c-be1f-4e35-827a-96dcd05b90ad", "MeterName": "Compute Hours", "MeterRates": { "0": 0.917 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "496f6a33-2a05-4598-9b9b-3ee7ecc9b75f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "052a9e03-6b5f-452e-92f5-3eddef816ca0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "04bf956c-6f30-4b04-8b1b-8618253e7ba2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.318 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5200cf98-a3b2-4db9-b548-2282819b9f2e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.553 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7deb8496-2550-4037-842a-6481140f32ad", "MeterName": "Compute Hours", "MeterRates": { "0": 10.1568 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f30fe3a2-a2de-40a5-aec4-fe17ef06aac2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "825bdd8a-9501-4f95-ada0-0e4948420152", "MeterName": "Compute Hours", "MeterRates": { "0": 1.482 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0affea74-afb7-48a1-951d-ae7e33baaf17", "MeterName": "Inter VNET Data Transfer Out (GB)", "MeterRates": { "0": 0.09 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "39960ae8-4e8c-4721-a256-5613bfeb209c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.264 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "84d6454d-0608-424f-aaaa-2bb3ef8c5729", "MeterName": "Compute Hours", "MeterRates": { "0": 0.398 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "4d555982-7f9a-4884-a128-780030263ab5", "MeterName": "Premium CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.17 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "612d7338-3940-442b-bcf3-97cfef3d8719", "MeterName": "S4 (Daily Units)", "MeterRates": { "0": 1129.032258 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2c92d701-9775-4be6-b5be-73f4fedb337b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.814 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8dd19c05-21f6-4a09-99ca-c82fc6faa225", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6c1463e2-dd5c-4e14-8f74-da3eac607c01", "MeterName": "Compute Hours", "MeterRates": { "0": 0.059 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d2da929c-6b2c-4313-8ef3-65319f885e9a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cbda89dc-3b80-4757-b045-f26f7d157342", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0ac27380-2479-4928-8cb4-26b745b00579", "MeterName": "Compute Hours", "MeterRates": { "0": 0.204 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "70145075-bf82-49f2-a3b5-11760c0f4bcb", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "64a57c24-8cb9-4ddf-a953-c1872a37ef7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a59540c-88f4-4ea3-aced-5a476baa3836", "MeterName": "Compute Hours", "MeterRates": { "0": 0.616 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b4db8aa1-a229-425a-b682-a7a33d9f316f", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.1287 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9092305a-5da2-49b4-8726-3230bf59487d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.536 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a53642e-10c1-402a-a499-fede1744b5ae", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66375 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f58bb04-d4fe-4afc-9086-97846ba0daff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.947 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1f2df07f-6cee-41bf-bdaf-ba2e65f30f8a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.55 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f7aa4a89-a94b-4521-863e-4a328ccd4735", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "14fc9a21-4919-4cb1-b495-5666966556bc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7caeb614-05c2-4546-b069-6228f1d1b49f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "63bb6bad-6b13-4765-8960-1443f27edd99", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "becfbc59-4b04-422b-9308-0062f1e236b0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.786 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "88300ab6-0e31-45bd-af34-50fd487cb801", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "eb556891-ba58-46dc-906a-f0019d90b752", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 8.0355 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "84a4ea60-17b4-4590-86d7-d89a1b92c7e8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "508aa363-1ca3-495a-a261-33cef5178438", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.44 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "61aa7dea-7160-43f4-a389-80f1ec35aa89", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A10 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "61be8307-999a-4933-abc3-42f3acd50dd0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ddd6acf9-0d0b-4b82-af5b-f54840a4271d", "MeterName": "Premium Unlimited Data - 50 Mbps", "MeterRates": { "0": 710.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "edd7ca3e-21e6-47e4-8112-8186d3e3dc04", "MeterName": "Compute Hours", "MeterRates": { "0": 1.505 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "8494083f-ed4b-4903-b253-ef80454860b4", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.44 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b48383d6-630e-4ac5-b6dd-aed7d9b1f9bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5e1befca-128b-4ea4-9337-94c32fbf1775", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.3548 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03c4e3ff-4852-4eb9-bdb4-d753e579b779", "MeterName": "Compute Hours", "MeterRates": { "0": 0.822 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "905664b1-fb2f-4d36-9503-a3239e01c732", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "L Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c31edca2-bc00-417c-a08f-60874859075d", "MeterName": "Compute Hours", "MeterRates": { "0": 3.505 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A9 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9487dd3a-1550-4fcd-9f9f-b458470d2dd9", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 5.0, "MeterCategory": "Networking", "MeterId": "9995d93a-7d35-4d3f-9c69-7a7fea447ef4", "MeterName": "Data Transfer Out (GB)", "MeterRates": { "0": 0.087 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d32b5169-e4ab-48c1-b424-633c106d4a62", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise and Weblogic Server Enterprise (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1c42f6a7-82a6-470f-b205-dc61a5d667aa", "MeterName": "Compute Hours", "MeterRates": { "0": 1.125 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4f6d2505-e8b5-4d98-a89f-605ce3b5382d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.342 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "34c47e1d-7a41-409b-8e9c-5ff475f69b57", "MeterName": "Compute Hours", "MeterRates": { "0": 0.696 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ba185525-e728-4310-b40d-69ce2adb6a5d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "607fba6a-151a-4fec-b008-86475a70eed9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.917 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d310c7b1-6cf0-4dc8-8e1a-406bebc6d50b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "3107feb4-cfd2-4be9-ad64-f555a522c460", "MeterName": "10TB Commitment Tier", "MeterRates": { "0": 10.33 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c4160b2c-d66b-4b5a-9b6b-0e21b7d6c90a", "MeterName": "Compute Hours", "MeterRates": { "0": 10.54 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bba78a10-6f7f-4971-92f4-352e0ffb4d9c", "MeterName": "Compute Hours", "MeterRates": { "0": 3.135 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "G3 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9ea2b61d-0bea-4416-a533-3741a833c2ed", "MeterName": "Compute Hours", "MeterRates": { "0": 1.875 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0e9d0c9b-ab6d-4312-9c7e-3794e22af9c4", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "de3b79d6-f52a-49e7-9fd3-4acf364484a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.372 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7399033d-a82f-4c50-af92-d369ab38e5fe", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "24daa89f-2d98-4349-ba5a-8a80589eddba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a042e19-44c7-4943-aca4-c9c198e4cc0e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Standard (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4ec733e8-c70b-45ec-9cba-471a9439d08b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e8572e17-4f5f-45b2-8f77-f1d0ba856790", "MeterName": "Compute Hours", "MeterRates": { "0": 0.365 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "179ac5fc-99bb-454f-a1f7-80eaf7259a84", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "04d45c09-006c-4222-81ef-0dfbac3f798a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "38d1a005-1f82-458c-a63b-499a01fc8fb1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1598bb07-82b6-4d80-82e4-145913675ad9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.379 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "724c09d9-8982-45d7-8141-416541713a0c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "02de2ad3-57a5-4700-87b1-29c845b1333a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.264 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "824ba5d0-a4d8-44c3-b589-01a9064f1017", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 66.56 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "1921bf17-aa45-49ee-84e8-95c6381ad0fc", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "17dc5e9c-c71e-46f8-9e9b-895adf6e779d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.322 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "06574cbd-a711-4eee-a835-2b92a501f2f1", "MeterName": "Compute Hours", "MeterRates": { "0": 3.891 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ce6f075-d216-4f1e-a698-d34dccf0012f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.114 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce92577e-4209-4248-a16c-ecc92abff1d3", "MeterName": "Compute Hours", "MeterRates": { "0": 4.77 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24r VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "a56e7e95-3e76-4730-bbde-3bcba7f59b92", "MeterName": "Premium Overage Data Points (1M)", "MeterRates": { "0": 2.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1M Data Points" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d99b5c72-4cdd-4898-b093-f089c5eaed46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b5d2552e-2184-4a9d-acbf-ecec7cb13631", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 234.84 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3c6a0492-2004-4e59-9dcf-d60c681a9b60", "MeterName": "Compute Hours", "MeterRates": { "0": 10.8 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5a766580-08a5-4e24-8177-851660e45c16", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 374.99 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "baf8991c-b7a2-42f5-b058-5f6d3eae2652", "MeterName": "Data Transfer In (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ff705a8d-5eb0-4327-9d2f-6df6a097dcea", "MeterName": "Premium Unlimited Data - 200 Mbps", "MeterRates": { "0": 1300.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "92567832-8613-47c4-9e8a-b2b9461a4875", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8bd8c303-7ff0-429f-afc7-7baef7134cbf", "MeterName": "Compute Hours", "MeterRates": { "0": 2.2 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7b32f9cc-adea-4a5b-9543-af9bc424db96", "MeterName": "Compute Hours", "MeterRates": { "0": 1.405 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "af2b2778-848c-4402-9363-e673ef62aa25", "MeterName": "Compute Hours", "MeterRates": { "0": 0.079 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "f3870da0-d9f7-4afc-9fc1-322ca46fb308", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.118 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a0288c3e-6174-4520-b867-c57df0068db9", "MeterName": "Compute Hours", "MeterRates": { "0": 2.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (upto 4c)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "42abbc74-9dcd-46f9-a9ad-6d1883adebf9", "MeterName": "Compute Hours", "MeterRates": { "0": 9.348 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c376e76f-1886-4c5c-86ed-d70467cdfeb9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.54 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a46b01ea-f43f-4c41-af8c-e8b0a81d05c6", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6cf115f0-8f01-4064-9c0f-e9cd8a13c210", "MeterName": "Compute Hours", "MeterRates": { "0": 0.238 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aed1b84c-9d7b-4dda-8af3-41effd68944c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "d394a1c6-43bb-43e8-a5dc-9fcf98bf82c6", "MeterName": "Standard CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.087 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "2c51ccb1-5e73-40b0-b491-5917eb35413c", "MeterName": "Premium P1 (Hours)", "MeterRates": { "0": 0.666 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "464fea94-ddd6-4ce7-9523-e32113a366ba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ebf88dfe-e397-4979-82f4-34ec95b1e3ef", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 9.6774 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dca9ea38-177d-42c3-8aa3-43875743b549", "MeterName": "Compute Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f6fce07e-0b4a-42d8-af6d-169b25e2369e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "964c283a-83a3-4dd4-8baf-59511998fe8b", "MeterName": "Storage Transactions (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f6d02be-a7f9-4918-96d1-c291793047e6", "MeterName": "Compute Hours", "MeterRates": { "0": 6.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (16 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b8b9adcd-ab9d-4a0a-af03-8c24150dd027", "MeterName": "DWU", "MeterRates": { "0": 1.2097 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "02bdbbe3-fe07-46fc-a6dd-2528064f028a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7180c163-b174-4312-bafd-98af0b0f4c6b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A10 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "1ad36bbb-89d3-45fb-b158-2c63187c1514", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fce5434d-919d-448e-9bac-334f6224da59", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 234.84 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8ff981a1-40b8-4292-aa18-c1af57836008", "MeterName": "Compute Hours", "MeterRates": { "0": 0.169 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "62fceb21-b01c-497e-bcdb-1e9c442c5549", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 31.2 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "01fd67ab-085a-4902-a7d4-bc77a17e6f5b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard and Weblogic Server Standard (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1609ec1a-662e-4038-975f-33f9d3561fe9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "365445cc-94a2-4b1c-ac2e-5a1c3819d026", "MeterName": "Compute Hours", "MeterRates": { "0": 1.35 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "587413c5-b379-44ca-9d7f-bdf1f7761f7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "45a39d7f-67b0-47e3-984b-31f016d17efd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "508422d7-d4c4-48bd-8299-976be7567c17", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "57d3a18f-ce3b-42c8-870d-9171cb2b3eba", "MeterName": "Compute Hours", "MeterRates": { "0": 2.346 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dc466506-c5d1-4342-8fe8-e2f6dcc44963", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12f33a96-529d-4d37-9d63-f1c3ca7b7ff8", "MeterName": "Compute Hours", "MeterRates": { "0": 9.0024 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4b83a4b7-cfd2-4695-9553-4613eb548028", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1a32f82a-9df2-4a6c-a80a-a5c50d973e36", "MeterName": "Compute Hours", "MeterRates": { "0": 0.808 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "700973cb-edf8-4ff1-abc1-03a40938bf79", "MeterName": "Compute Hours", "MeterRates": { "0": 1.466 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f89fad18-7dc5-46aa-9f05-7167ae5b8b2b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7ccc62c9-ad67-40a8-8f53-086670077511", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0967 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b586fc31-dc5e-488e-bbc9-85c73a945eb4", "MeterName": "Compute Hours", "MeterRates": { "0": 3.24 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e3600abc-da0a-45bb-8ae5-b101d6b29680", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.053 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "772b97d7-d0db-4c7c-ac8d-38d803b5d5cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.322 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d5d9555e-fdc8-4f16-a51e-a9bcafc7d178", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 68.64 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "53c64fd5-9d6d-4ac8-9daa-cffaf391a88a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.079 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d3ae7dc5-be77-4daf-813c-87d7eaccb869", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.152 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5709be3-2b12-44b9-acc7-a124a08f5291", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a0df826d-744f-4f97-9fa9-98e9f8139444", "MeterName": "Compute Hours", "MeterRates": { "0": 0.029 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "23dbb0e2-3f3b-48c3-85dd-d25732f5c17c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.025 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b2631b5-c9a4-41e5-aac6-415b558555c1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.84 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2e9d1961-f4d3-4abc-ae40-9589d6160e6c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.037 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ebef8043-7ee9-4c4e-aa01-eedd271d4f8b", "MeterName": "Inter VNET Data Transfer Out (GB)", "MeterRates": { "0": 0.16 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "00b540ce-1a81-4462-9a6a-f76f8aaba69b", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9546a336-9961-44f6-af0c-ea2dda4be24c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.46 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "21c04ef6-9fa3-42ad-898c-0dd240dca24c", "MeterName": "Unlimited Data - 2 Gbps", "MeterRates": { "0": 17400.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8482b9d1-8fe9-4daa-9296-e5c93a9c0da6", "MeterName": "DWU", "MeterRates": { "0": 1.5121 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ebd14d28-564a-49c3-b914-380d86dac592", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A10 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c7108a85-74e0-47a4-bd95-e5a65ffd3fd8", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.04 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "653c8017-f340-4c18-8b58-6a14ee202e80", "MeterName": "Unlimited Data - 200 Mbps", "MeterRates": { "0": 2300.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "807a90ec-f1bc-4212-af64-76aede95a646", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A9 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "cd1bc846-87c1-4ddb-ac31-79336f425990", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "09aa689d-f5d0-42b4-9d42-699d33614d4d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.492 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ec92c06-a8b9-4999-9dba-d6db2a71c9f9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3d2bf71-0a63-4b93-90a3-8e2acd001363", "MeterName": "Compute Hours", "MeterRates": { "0": 2.601 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "145e0950-caa8-476f-a917-53c5a28d30dd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.154 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b35e4827-5326-45a4-a778-30ecc6de4394", "MeterName": "Compute Hours", "MeterRates": { "0": 0.568 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b321b90f-70b3-4a9a-b2cc-2190853a8894", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d5a8971b-009f-4adb-8c79-071c501c1234", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c3b5ed45-bebd-480f-b19a-6e37a0ce9e05", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 122.88 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "538e08d3-d404-4ae1-9ed7-f6349d11d4e8", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7bce5d0e-07d2-4c2f-bcf3-43d695673d90", "MeterName": "Compute Hours", "MeterRates": { "0": 1.044 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "67cce584-456c-46cd-99c1-c50ad01efbe5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e186a616-4bcf-4719-a255-bea710b8af96", "MeterName": "Compute Hours", "MeterRates": { "0": 1.466 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5defb250-5ee7-46d9-81ce-b45d72fe02d0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.105 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9341ff9a-3bc3-46fc-9d4b-b43bcd46e80f", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7323fb19-0bd2-43ae-832e-51704271c8b4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.111 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "6691a6aa-73bf-4d66-91fb-356bf4b894ed", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.183 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8771fb57-295b-4766-9d6f-b729c922af17", "MeterName": "Streaming Units (Hours)", "MeterRates": { "0": 0.031 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Stream Analytics", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b4c9ee83-616e-4a6e-9de2-800db3d5778a", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.143 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "964d267d-40cd-49fc-806e-5504d43e6567", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fa17bf92-ddfb-40fe-910d-5c42e5a8ce61", "MeterName": "Compute Hours", "MeterRates": { "0": 1.35 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b6243603-b03b-4f0d-95cb-e511e67fd730", "MeterName": "Compute Hours", "MeterRates": { "0": 0.224 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "8839858f-ba33-470f-a1a4-f742bdb63342", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0304 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0cba612e-f9d6-46f5-b4ea-4f4cb0b3ef96", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.477 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "221a60b9-c27b-4522-ab9d-1f0d9ff18faf", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.136 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "242ead45-9acf-4745-992e-6c7bc804a5e8", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "45ff39f6-c7a6-40fb-a124-cf5b280ba092", "MeterName": "Standard IO - Block Blob Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "272492b3-1c92-4a5f-bee9-52a8e10ca514", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a543af92-d76e-4d22-83fd-dd775ea4ab08", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c7e6773b-4d5f-4d63-b22b-bf7db01afcb1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.232 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "061710cf-1114-4164-8f6d-54b1b4a52eb5", "MeterName": "DWU", "MeterRates": { "0": 1.5121 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd70e961-d2be-44c8-9768-291c82c6b6d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.208 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8a63da00-62a2-4db2-bad3-989dc1de6773", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.201 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3c948bb6-3345-49a8-9f91-88d2d63279af", "MeterName": "Compute Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0703a687-2907-45a1-bfaf-d59c91497313", "MeterName": "Compute Hours", "MeterRates": { "0": 0.42 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f0876270-a519-4c34-b8d6-12cf8cb86fea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "817e731d-c1f0-454d-ae5e-c243c498d9d5", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 425.8144 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7fb8c093-812f-4319-afc6-2b307755e7d0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3fb8d49e-54ba-447b-a860-c03bebe5b27a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.68 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "02f4525d-e44e-433d-b8ac-bc0c4e4048fa", "MeterName": "Free Automation Minutes", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Automation", "MeterTags": [], "Unit": "Minutes" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f41287d7-e9ae-458e-8701-5708529b1b25", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 28.125 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5cab3a1d-f211-42ff-925b-108c935b39a5", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.378 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dec9098e-cece-4148-a376-166b4d0ea1bf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "98875161-56c4-400f-888c-57ea8d5c9200", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "70879643-c28c-4317-8b9f-ffacd10d6f65", "MeterName": "Compute Hours", "MeterRates": { "0": 0.141 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9ba0e2a-2c8d-4191-a17f-6c3adba33b49", "MeterName": "Compute Hours", "MeterRates": { "0": 7.782 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d54d315-63da-47e3-aaba-7c386025b2a6", "MeterName": "Compute Hours", "MeterRates": { "0": 2.343 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fbd0e8e2-a150-43c7-b34b-2352c0daa4d2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.186 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "c9e287dc-2557-494e-9be3-40de4e85ae82", "MeterName": "Live Channel Hours", "MeterRates": { "0": 0.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cb850c5b-e213-440b-a074-315ea34e6cb4", "MeterName": "API Service Prediction Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "4607eff7-1a97-4080-a705-67d0a7525864", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SLES (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "92b9e427-1ca5-4464-9dc6-85dbb7ac7e86", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8e88ecd8-08be-4a61-a58d-6740db64eb31", "MeterName": "Compute Hours", "MeterRates": { "0": 1.596 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9c26b409-f661-49ed-8f9a-661e56751e12", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f431c85b-7443-48a1-97d9-6932e1c050c4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b3348f9d-20e1-45e3-a20b-aab4f275505a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.528 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "5abbc7c0-6e12-4950-94ec-41f50f4544a8", "MeterName": "MSFT Peering Unlimited Data 50 Mbps", "MeterRates": { "0": 300.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e71287b7-5b9e-4291-9715-7d209bdc39a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.784 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6676f64e-ad33-4c27-b7f5-2086a3de0a28", "MeterName": "Compute Hours", "MeterRates": { "0": 0.418 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "d4b33bc0-adc7-46e0-9d88-6e2099604b52", "MeterName": "Premium CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.34 }, "MeterRegion": "Zone 5", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "50966b82-429e-4fb6-9075-8ff1908fbc71", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "463a9c40-ba9f-4cba-b238-1353af4486b7", "MeterName": "Unlimited Data - 50 Mbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cc83e0ac-437b-44f9-ad5b-9982c3241899", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2696 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8778022c-ce89-4ebf-8f3a-646bff3faf28", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c53a5ff2-fc5a-4e37-a087-271a5ada2554", "MeterName": "Unlimited Data - 1 Gbps", "MeterRates": { "0": 5700.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8ced5a85-695d-473b-b0fa-e71cfc6860da", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4e449232-725e-47c4-ab33-158751518423", "MeterName": "Compute Hours", "MeterRates": { "0": 0.748 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9d6eed9b-b42d-421b-974c-2802edb6db90", "MeterName": "Compute Hours", "MeterRates": { "0": 0.916 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "385a6b7c-bf3c-4787-a9b0-f97c0180537a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.254 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "59a70c09-d509-48e2-8789-fb410ecd9dab", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.17 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "67710900-e9c1-421e-8aa8-32de76f1b91d", "MeterName": "Standard CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.087 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8fc68c4c-2c37-4079-8493-fea12df31298", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "82b0f0f1-bc4d-4be6-a829-2963661454af", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4fd98994-9320-40e6-9aed-303abf506bb7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.343 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9c6a0e21-61fe-42db-80be-a05863ceb840", "MeterName": "Compute Hours", "MeterRates": { "0": 0.178 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "58152f9a-64ae-436d-99a9-94bd9846c9e4", "MeterName": "Standard Small Azure App Service Hours", "MeterRates": { "0": 0.1 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "41f7de4c-9efd-4b91-8538-549ee2bb4f3c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.632 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0008ac09-705a-431e-b9c7-026746cb920a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.112 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d2c80cb7-431e-4022-bd1f-3e7e8e0ffbb5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb244f0b-a749-40ce-a97a-28ab7f4ffd03", "MeterName": "Compute Hours", "MeterRates": { "0": 0.509 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7701caf0-43b4-4e12-beae-b90236128c46", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.076 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0e08de02-4dcb-49ba-81b7-3456af4377cf", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 12.71 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "283363fa-24b6-4384-8390-81ff35d26cc2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8481cae4-6889-4bd7-8124-11a462a15a9a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.043 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "56b10f1b-64ad-4278-a67f-50e6973ca379", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "0a30477e-9b02-4768-9163-ff663b5fa669", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "M Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "18a8a0d6-1d4a-4405-b431-31e7f899fb19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0fa5e8c0-96ef-4dff-8b02-1c99485fec2f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.513 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "620bde26-937a-411b-b835-4b2a95d735eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.349 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2a76ff8-c25d-4136-a931-a7071392c5c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "08443a97-e0d0-4e23-80e9-f7fea7ea871f", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 627.264 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "777906a6-44a3-48ed-8dae-fccce59b59bc", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.0935 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a12520d4-4bdb-4561-9e8a-a5d9fda5b5c7", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ea8aeb7-58ab-4ee0-a16b-69853ce7202c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (6 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d6842e1b-34e2-409f-b6ee-0e45f7d912d0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.202 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6f07483a-ff01-40b1-baac-ce7768104392", "MeterName": "Compute Hours", "MeterRates": { "0": 0.968 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "65a00353-376c-49f9-920c-f36712acb3c5", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "29a89311-86f0-4cb0-8865-9eab7a989e71", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.68 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8837935d-68e4-45b9-986e-4f737d283b6e", "MeterName": "Compute Hours", "MeterRates": { "0": 4.742 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-01-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "f14abb17-cb70-4fc0-8a22-a985b9c4eb8d", "MeterName": "Enterprise Integration Pack", "MeterRates": { "0": 999.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Packs" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bbed5eb4-5f11-4a2a-bb02-9c3f1b2d2ac2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.44 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6514601e-b368-455c-830a-4188486815ed", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "83bf8b50-01cc-45f5-9589-d64b0cf66317", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.68 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cd779ac8-48fa-4fe5-a90c-18ad2cfe7e08", "MeterName": "Overage Storage (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MySQL Database on Azure", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a9e2e628-8f76-4c81-8292-3b7203ca8a76", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d1e043cd-4b29-4546-b5e2-5a1ab0ba301b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.81 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "SQL Gen 4 Compute (24 cores)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "63749803-1cbe-4c1c-babe-31f9685822c1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.798 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e4ad1fd5-6d02-4120-995e-54f773cff8f8", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.049 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8776da1f-f73e-4c5d-a766-8ccbc365330f", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 3.7742 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "33aed8dc-e2e7-4bdd-bc22-ac8a21bb9950", "MeterName": "Basic C4 (Hours)", "MeterRates": { "0": 0.263 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f5fbff1d-6ffa-4130-8638-a2636acfdfd4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e698786f-a423-49c0-8e60-6756a19d2527", "MeterName": "500-AU-hours Commitment Tier", "MeterRates": { "0": 14.52 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "818ff3c6-6655-4180-8da7-c0c79aa00c79", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0445 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "15bbf8a2-3ed0-49e2-8e09-65063d9ed14e", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "M Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d619a803-dff1-4e17-917d-f2e68137356e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.633 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5114dbae-3c14-4b73-8b6b-2633ea0bc343", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a373e2eb-e1f9-4f93-895b-e31d547ff8ed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.281 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2d222980-4bc4-437f-9cc4-f66891810cc9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "24c6cbe2-7202-4167-b882-ad2c400eb399", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 37.5 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "458fb98f-9987-417f-8c95-5ffe6101c0ad", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0238 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6c56768f-ee88-4b44-b40e-6c97f9982260", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.171 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b7635939-ec60-4bf1-89d1-e0a0c9a119e8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ceb8e318-0ef5-4b92-9431-ab5f48363646", "MeterName": "Compute Hours", "MeterRates": { "0": 0.163 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9a8fcc65-d42a-4a8b-b6e7-13c88cc80344", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7f017af4-4d79-4351-8168-e388096a7d13", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bfa84f91-4d88-4ca7-bb5e-56eaf7035f66", "MeterName": "Compute Hours", "MeterRates": { "0": 1.46 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8cc7429a-3b60-4cee-af6f-6f0823aa739b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.093 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e52330dc-6af8-4607-a779-fedaa080032b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.946 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ea9d7922-1bb3-4aaf-912b-a28fd2ae328d", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95ac54ed-4c19-4d0d-8922-48de0ac92a9d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ece75ef1-5152-4df5-90c7-1b0b574c560a", "MeterName": "Compute Hours", "MeterRates": { "0": 3.218 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "68688293-afb1-4e64-9d81-c178af2d3556", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "cb5e3343-3f87-467c-abff-eaffe4aeac70", "MeterName": "Compute Hours", "MeterRates": { "0": 0.766 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "561564c7-48fd-4fa5-b25f-d61a4131fbac", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3fd455c8-e35b-4a2c-95a1-a0afd782a77c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.662 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd21e1fe-b418-4295-bae6-df0c773237c0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.966 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb7f2382-4eb3-4711-9e5f-7f29f9174187", "MeterName": "Compute Hours", "MeterRates": { "0": 2.88 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (24 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "55382455-ba6b-4f92-9c65-92b9194f3ef3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "14e83449-bb46-45f0-b4d9-644fdd5575dc", "MeterName": "Metered Data - 500 Mbps", "MeterRates": { "0": 290.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ad86bfd6-3f66-4201-b0c5-9ffc077af445", "MeterName": "Compute Hours", "MeterRates": { "0": 1.596 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9b1fb262-0ef5-4fda-9f72-77d8858f6ab8", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 5.3569 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "eed642ff-ddaf-49f6-9b8e-d734308a77fb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.644 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b17ee794-9c81-499f-9a76-789152fa3f39", "MeterName": "Compute Hours", "MeterRates": { "0": 0.149 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "daf52501-330a-4a7a-a88a-cf85ed40988f", "MeterName": "Users", "MeterRates": { "0": 6.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Team Services", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "02362ee4-a7d1-41af-8ddd-c72d8791a67e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.169 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9abab23a-5b84-4beb-8cae-cd1d782da641", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fd2bf4f6-fc0e-4083-8ddf-e0227ce8adf5", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 5.3569 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8ea2c421-4813-433a-926f-b9ead5f8b54a", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 590.4457 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c7a0c9f2-b08a-4f54-955f-c2ba8c7b0837", "MeterName": "DNS Queries (1M)", "MeterRates": { "0": 0.54 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Traffic Manager", "MeterTags": [], "Unit": "1M Queries" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3e8f4449-337c-4aaf-b574-1ff7d82edcf4", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 10.7139 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "92e2eef3-ee88-40ff-a961-29de352857ba", "MeterName": "Compute Hours", "MeterRates": { "0": 1.505 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c2188b1-f379-45b9-9e9c-5cbc0e564f58", "MeterName": "Compute Hours", "MeterRates": { "0": 0.69 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "f86ca981-9678-4601-9a36-608519eab106", "MeterName": "Premium P3 (Hours)", "MeterRates": { "0": 2.885 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0f190e0f-7121-49ca-b4e0-5198dbc6bb20", "MeterName": "Standard Managed Disk/S20 (Units)", "MeterRates": { "0": 11.968 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a9be7552-6ff5-4957-a4eb-c9b0fbcedd41", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "63efeb72-d133-4dbb-b245-03920d0cdf38", "MeterName": "Compute Hours", "MeterRates": { "0": 1.482 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "b9ec9d15-e4b3-4e4b-9403-54a13394c367", "MeterName": "Premium P1 (Hours)", "MeterRates": { "0": 0.666 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "aaacf121-9c4c-4d64-a8c9-a9b4a71f650f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.62 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b0ea14fc-7462-48d3-9a69-00d612e14c3c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9d9cbb89-b1a5-41d8-b998-72c750a05de8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.342 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7558d537-4fbd-40e6-ad58-dea0dc0fd45a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4bd1a54c-a1ad-4de1-a5f6-7f700f6d04fa", "MeterName": "Compute Hours", "MeterRates": { "0": 6.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (12 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "08f25d5b-967e-4c02-b178-b82e98612470", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 619.3536 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "33be92a3-8f1d-4078-a0a9-d4691e6d3da6", "MeterName": "Compute Hours", "MeterRates": { "0": 11.59 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12699064-6912-437d-8cf7-9a50364cfb1d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (up to 4c)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c26b4887-a3ec-4ae1-a449-881e0ba32bab", "MeterName": "Data Transfer Out - to China (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "35f3c7e7-10ab-49db-ac73-44d936470ca5", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 3.025 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "47cee240-ba75-4389-958d-3db0c26d202e", "MeterName": "Standard S4 (Units)", "MeterRates": { "0": 80.65 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "86dc9c21-8721-4084-9586-2953507e3fd5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "2073b0aa-c836-4642-9d97-0635f52e3520", "MeterName": "Free Data Analyzed (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Log Analytics", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "707e2bd6-063a-4ba7-a245-d25ac9935c3d", "MeterName": "Inactive Pipelines", "MeterRates": { "0": 0.8 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Factory", "MeterTags": [], "Unit": "Pipelines" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "773b6822-15e5-4cd1-bd56-205319f97a76", "MeterName": "Unlimited Data - 5 Gbps", "MeterRates": { "0": 41000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "afb5c1d0-10c6-4580-a6a3-5da2b7cf41d8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6881ea97-3bc8-435d-8e4a-d798ed9374f6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.42 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c5e3505f-1cc6-4253-a275-ad5a2a6a2264", "MeterName": "Compute Hours", "MeterRates": { "0": 0.797 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aa7039ea-f973-4adf-a642-898fb6fcf81a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "33d27e51-c8d9-4f82-b897-5cfa23d6923e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.897 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "178c6e36-9b57-4074-88ee-be5d47816f0d", "MeterName": "Compute Hours", "MeterRates": { "0": 8.14 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "c46eb634-c020-454e-9073-b381ecc04d02", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b625b9bc-3082-465b-bc81-25fd89cd24f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.698 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2073dab8-6491-429a-bb8b-32fd566c0b4a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.776 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Automation and Control", "MeterId": "ffb38d30-ebbb-4d2d-bfc0-adeb056db796", "MeterName": "Included per Node (Minute)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "OMS Automation and Control", "MeterTags": [], "Unit": "1 Minute" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "27485d03-df4e-42b8-9651-c0a0b436cc19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "96328029-e3da-49d7-bba1-48ef64f13ff1", "MeterName": "Standard S2 Overage API Transactions (in 1,000s)", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cfa45c60-93c6-468d-944e-b5b633191c77", "MeterName": "Compute Hours", "MeterRates": { "0": 0.292 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "19779bfa-01e0-4e38-9ea2-6a697d78434f", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b6207704-0157-45cb-a101-e4ce9dc22442", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0047 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "309f895a-26d2-46c8-a46b-c2e9db459ece", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "945b8bdc-4942-45f4-bb2d-65b849304aff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "99c83182-0ebc-4eba-99a6-80e0c0fa572b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.622 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8c2fa0c0-5c8d-477f-9e8b-7fc0c88fe974", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bdf5b6e5-6d0d-4b87-b82f-2ebd3a1beeaf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.549 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e129d70a-be93-44d0-a4e7-b5e157f2e429", "MeterName": "Compute Hours", "MeterRates": { "0": 0.104 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4afcdfe0-4c53-47ed-b966-815b7e8f0e3e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.86 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "29cec9c7-cbe1-4b5d-ae75-d5ee7b2f4061", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.06 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "aa21c415-c101-4554-8919-e309853e9f1e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.336 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5dd7adaf-6c8a-4f08-99aa-09a13cb20fa0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "390ffa62-8fef-426d-9812-bb515d27934a", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 28.125 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cdce56fa-76eb-43c2-b613-160095b4aa13", "MeterName": "Compute Hours", "MeterRates": { "0": 0.112 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1bb2f28b-9b13-4a5f-85d6-cf6211c8c668", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5c54154b-efc5-44d3-b55c-51cd4b08d710", "MeterName": "Compute Hours", "MeterRates": { "0": 0.225 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96967cf3-a8ae-4189-9e81-8cc329c9b704", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cea84742-b76f-47e8-b854-02aa86fc275f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.789 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "cc7a7284-897d-49e3-b737-af53983ebadc", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "05649c84-73d2-440e-8cf9-6b13639bd019", "MeterName": "Basic Emotion APIs (in 1,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f9c724c0-117a-4574-94c2-57d410deb181", "MeterName": "Compute Hours", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (up to 4 c)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "83acc60c-599a-4df3-af7e-53a2c9af9073", "MeterName": "Compute Hours", "MeterRates": { "0": 0.345 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "40bf9efc-dc8d-4f11-8afb-3e37b45bd581", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "564ac91a-61ac-4f2a-a530-35612b37ced2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2054a513-86e0-4ff2-869e-58747bc5180b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0f4978b4-2620-4624-9793-b39e97e6777a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c94eb30-7c88-40d4-b439-9f1afd8a8a27", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7a772e60-7449-4b3b-ba34-db60e8316a0e", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0028 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2aec6f70-b1fe-42a6-8142-b879c955603d", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ab7b25a5-88da-40f8-9634-3a2b2bddecd9", "MeterName": "Standard S2 Search Hour", "MeterRates": { "0": 1.597 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "55a35243-c285-43ed-801e-2c9b7becb616", "MeterName": "Compute Hours", "MeterRates": { "0": 1.52 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "b79e0928-54a8-4744-91c1-4ede04bcbfc4", "MeterName": "Premium P3 (Hours)", "MeterRates": { "0": 2.774 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d7ebd709-2374-4152-8839-6c39d70e74c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.82 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "16b1d653-1719-4f3f-8a23-4d232a4b8cf7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9cc63cf8-6593-410a-b0e7-26a4ef71e8b3", "MeterName": "Standard IO - Disk Delete Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "647d3d48-03b8-4942-98da-5cac31483ae5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.95 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A9 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "b1b1c400-243d-4449-a1d1-db76519eb2ab", "MeterName": "Standard S2 (Units)", "MeterRates": { "0": 16.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "002b5895-34c1-47ee-9828-b8a8312de15b", "MeterName": "MSFT Peering Unlimited Data 10 Gbps", "MeterRates": { "0": 82000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "65bed0bc-772d-4674-8c59-fb2408c05d22", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7f4afbf4-59ed-43d3-9884-9b4f5893ae76", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.008 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2032cff5-03dd-4363-9ff5-a149d59bed3a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.82 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "635ebce7-ba7e-489d-97f3-3b555b75e0d6", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.0163 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "316feed9-2528-478b-bc4b-0383bb429422", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "6d631ddb-1e2a-43fb-b466-7f7d70f7e532", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.5 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "46a4598f-bd08-4614-b2a3-75b147499c7d", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.034 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Analysis Services", "MeterId": "fa22ebb4-a4dd-4407-a476-8ba85b72688f", "MeterName": "Standard S1 (Hours)", "MeterRates": { "0": 1.015 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Tabular", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "85a398f0-b6ad-4d2d-bb05-1d95337a5255", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9247b5d2-8660-4d3d-adbf-084b329effec", "MeterName": "Compute Hours", "MeterRates": { "0": 0.232 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2f7e6be6-c801-4b28-bfbf-148f7a61bffc", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 76.54 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2013-12-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "a6eebb9d-d376-4864-9abb-023b81026acc", "MeterName": "S3 Media Reserved Units", "MeterRates": { "0": 399.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a646be2d-e3ec-460e-895b-3ab467bff38d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a4103861-18b7-4eab-b66f-d39c911743ad", "MeterName": "Compute Hours", "MeterRates": { "0": 0.255 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "14bd8294-0eb7-4eba-a383-39bf8d000caa", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1fd0df97-f57c-458c-8fb6-59a425b8c615", "MeterName": "Compute Hours", "MeterRates": { "0": 0.261 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d6775764-05f3-4ab6-9424-088f1934cda3", "MeterName": "Unlimited Data - 200 Mbps", "MeterRates": { "0": 1150.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d138e4f8-ef93-4387-af83-8296a1f4a226", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cae64797-9ecf-4906-b517-6238c80c045f", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.161 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9772b374-943a-476c-8039-ca451f1cfae1", "MeterName": "Compute Hours", "MeterRates": { "0": 6.185 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "G4 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "43636e6b-432f-4fa6-81c2-570325eceaf2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ae650aa5-7740-4159-a443-e1f33349d3ea", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 438.176 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a4b8ea37-87dc-45c2-9fc2-b7e56dc8239d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5e4f7678-cdd0-4ddc-b367-0db324fe2688", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.076 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0138eeb5-295f-4de2-972b-439f08dcf964", "MeterName": "Throughput Unit Hours", "MeterRates": { "0": 0.15 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "59f4215a-8925-4ae2-b8ff-3633b818cc35", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.03 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9e05d9c8-8936-48ef-b98e-f019e9d64978", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2168d000-4a4f-4479-8a88-3a832e658ec5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.308 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b86e86ea-ec87-4ae8-9022-17c5825fcb09", "MeterName": "Compute Hours", "MeterRates": { "0": 0.498 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "62472b82-91e2-47c0-9650-9835b5259fe3", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.09 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "405cd96b-f74e-4089-b564-1bacf8867e4d", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.656 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d0ab06d5-71d6-4b8b-8507-41b72af59f4b", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5eb93b2d-565b-4a8d-adfe-a9af9e0d6ade", "MeterName": "Unit Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "303e8e3b-649f-42f5-ad47-44bf47e4da1e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.54 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bbdcc7cb-8933-4655-8111-a0f519b6c717", "MeterName": "Compute Hours", "MeterRates": { "0": 0.161 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "13b6f9ac-0250-4024-9b45-dff0ac955e0c", "MeterName": "Data Movement On Premises", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Factory", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 10.0, "MeterCategory": "Notification Hubs", "MeterId": "5d392d84-c8d6-45d4-a758-790ed34f49c7", "MeterName": "Pushes (in 1,000,000s)", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Notification Hubs", "MeterTags": [], "Unit": "1,000,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a55dee14-c633-4b4b-b2e0-51182b7720a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8fc8af7f-3909-4aae-9682-43f76a019101", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.3569 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "951409c3-50d2-4a9d-aeb2-eca9b89e8e5b", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9b4e644-fd53-4132-9563-64c07b5e4f4e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cc3b405f-1778-49f9-86c9-54779c8cd45b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.36 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "45d50770-f8f9-4225-a392-5c675296e095", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "100e40ce-2ab9-47e6-bf59-500d17602826", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "393252bb-c4a3-46e2-b7b1-ddd53e4af57a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.087 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1e8f6d9f-8b40-4c97-80cc-cff87a290a93", "MeterName": "Compute Hours", "MeterRates": { "0": 4.674 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4f2b28da-0425-47eb-9b14-7c121ad16b6c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c5d206b6-b977-438a-a4f7-6ae12482323b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.349 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cee722d6-ac16-4ec7-8810-1a5f715d08e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e2c5e3dc-180e-42fe-aea0-7949eb0f40c6", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.1108 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8920a12c-c242-4fec-93c9-97ffd4797e96", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2202b900-92d8-4d6d-bbef-1f2118894b06", "MeterName": "Compute Hours", "MeterRates": { "0": 0.615 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9d1d6262-6d0d-4b4f-bfeb-54d80e611efb", "MeterName": "Compute Hours", "MeterRates": { "0": 3.24 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d25fc970-d2ca-403f-9d42-1a6ebf8f3d94", "MeterName": "Compute Hours", "MeterRates": { "0": 1.22 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "04234260-6e2d-41ca-a84e-d177d2e6d026", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.036 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "bedf6c71-d8d8-4564-a569-4f68fdfc5477", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "0b33c255-383a-4fe3-b42f-f20672895345", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5965f6d3-2ac7-499e-9498-744177a02998", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1a8ebeb4-98d1-4568-833e-6924033ec224", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0475 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "5717909a-0a40-49d5-8459-9d9dce6353d7", "MeterName": "Private Agents - Azure", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Build and Deployment", "MeterTags": [], "Unit": "Agents" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b2756b34-6dfe-4952-9ed8-24de5d06e8eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "faaaf232-94e4-4068-ae01-b854c46b94c2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.793 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6368dbf8-dafb-46df-948a-58c3df992ba1", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5dae9203-a8b1-455e-b81d-9f3cbbb091e7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "49a3e78b-fa72-4d46-beeb-3bb9032ea524", "MeterName": "Premium Unlimited Data - 500 Mbps", "MeterRates": { "0": 3150.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ce369276-0a11-4712-b1ec-28d9eaa07515", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6182e588-176b-433d-a131-b13820c7ee26", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "73c297a4-0244-4e14-9097-3986331ab667", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3c7d0253-8add-4d1c-93bb-3a64165d2468", "MeterName": "Compute Hours", "MeterRates": { "0": 0.444 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e4768566-1551-4e61-ae41-3ea37746eb1a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.336 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8690a7d9-dc11-42c9-b9fe-4de90efdf6d4", "MeterName": "Compute Hours", "MeterRates": { "0": 2.814 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6efd0914-c5c7-4c12-935b-a1b1d1858478", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.171 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5b0fc766-2ba8-4947-8d27-5f2988a24ef1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.64 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "cb78426a-53d6-4033-b6f6-c59a04c66903", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XS OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "db82e20c-830a-44d4-a1e4-c86a54b75b89", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "4ceae6f9-ec3f-46ed-8587-f27a65eb9edf", "MeterName": "Standard CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.138 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9425e4b3-8cfe-4fec-8193-a8b4cf706bfd", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 191.7 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "14f8a4b5-8926-48b2-9972-78feab72c978", "MeterName": "Compute Hours", "MeterRates": { "0": 0.125 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c9c9186d-b393-406f-a14f-fe04641eed01", "MeterName": "Compute Hours", "MeterRates": { "0": 1.853 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "145a6173-898f-4b98-be19-51f693f0c15b", "MeterName": "Premium Elastic Database Existence", "MeterRates": { "0": 0.2016 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "4e38119e-b416-4bc5-992c-95120a689104", "MeterName": "Standard C4 (Hours)", "MeterRates": { "0": 0.525 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "fa3849ff-c59b-4098-83ce-19d2b7951cbe", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e1517b3a-f462-4937-87b7-2ee7f7cc143b", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "0bc4d87d-34ce-48dd-befd-78e789a154e7", "MeterName": "Premium P4 (Hours)", "MeterRates": { "0": 5.328 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7ec34f4c-ee1e-4395-9090-ff818baadf30", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b76ab750-b3ae-48c0-91cf-b1253df59c40", "MeterName": "Compute Hours", "MeterRates": { "0": 0.232 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "365c9dda-c9f6-4213-b87b-0cfa21158af9", "MeterName": "Metered Data - 100 Mbps", "MeterRates": { "0": 110.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cfc25816-35ce-411e-9b62-a181b3f84653", "MeterName": "Compute Hours", "MeterRates": { "0": 0.444 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "68c289e1-85e6-462a-bd59-aa359fe314f8", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f3ffc04c-ba8d-45d0-aaf1-6baab8669279", "MeterName": "Metered Data - 200 Mbps", "MeterRates": { "0": 145.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5c94fa93-eb86-4951-a960-6525398ba98c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "19c6b5e3-4162-4be1-9911-fba6f27991c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "531ba0bc-b317-4b20-ad74-a86f323cf8d2", "MeterName": "Premium P4 (Hours)", "MeterRates": { "0": 5.55 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a103733a-0fc9-4c8c-b49c-5024f2441d8e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.75 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A9 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cd40e526-ccd9-4ec5-a96c-7995b77b21c4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.366 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5f23989a-ceff-45f6-9fb3-d8e306cf531d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "bf8870a0-ab78-4b28-be9e-cb142df24f44", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 88.594 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c721b73c-fdba-4dac-8b07-b3f47cdd7a09", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dd5fcf13-7031-48b0-b736-8ca7da3a6a92", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "24d04c62-6a53-4da1-ac64-8d71a4a8b8f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.464 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5a81ebd-6435-4b0f-9ab1-6c0d0dd6eed0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fcd9fc54-3503-49f1-b40c-d3f8587badc3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.665 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "878bced4-6856-46c1-a3df-15641b31057a", "MeterName": "SNI SSL", "MeterRates": { "0": 9.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Sites" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2d6af38f-0f68-4004-9014-1e3213172915", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "476d2ca6-250d-43bd-81df-d0c8776dc343", "MeterName": "Compute Hours", "MeterRates": { "0": 3.299 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "32a184d1-b0fa-4e6f-bcf5-273e806c298a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.34 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b6d46ef1-b7ec-4c83-bcdc-cc80c3770aa3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.537 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "505283ff-c0ef-44f1-b16e-6d826d8a9e0e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bcf06b41-75d0-4c10-8dee-c8eca7a99e8f", "MeterName": "Compute Hours", "MeterRates": { "0": 3.54 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b07baa29-b855-414a-8532-fc85e9cf5e80", "MeterName": "Compute Hours", "MeterRates": { "0": 0.616 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0d21c63f-67c2-4e58-a68b-3157271b7e1a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.84 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a0e53d7-8d30-4b3d-b9c3-5369543d7367", "MeterName": "Compute Hours", "MeterRates": { "0": 4.88 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "7245f503-495e-4e21-9009-901f562bd21b", "MeterName": "S1 (Units)", "MeterRates": { "0": 80.0 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "708bb9ce-e2d0-4851-91e7-956fea11381a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2a42f457-d6a6-4418-b986-364b6641ef3b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4f662f3d-3e36-469b-9b05-d58edb773d6a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "94819513-7e2a-4a19-af01-ca7af9ea11cf", "MeterName": "Compute Hours", "MeterRates": { "0": 1.097 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6fea4f21-ab0f-4fcd-a1c6-30498bc6f3c4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.677 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4c35170a-4731-4072-841d-c20793007168", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4ce4e22f-fab9-44e3-8373-4aec088195fc", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.1252 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c95d3e05-b0cb-4ff7-bf07-57f89f9331ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.467 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e5134ccb-47b0-470a-9267-bbd4333e68c2", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 8.2155 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "953fe2ae-f932-4f3d-b34d-b5d1f950fa25", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fc9243a0-f593-4d7d-877c-7fec64b647ce", "MeterName": "Compute Hours", "MeterRates": { "0": 1.032 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "79fe2eab-cd87-43bb-9e51-3e30e40c8f6e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "48310a23-bc87-46c0-af2d-30bb7c6cb293", "MeterName": "Compute Hours", "MeterRates": { "0": 0.354 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c5ace7f6-f89d-4975-897c-f105a92c54db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.85 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7fadae88-cf47-4565-ad69-1e923511d070", "MeterName": "Compute Hours", "MeterRates": { "0": 0.594 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f69b71b2-4d12-406d-82f7-11903f972e6c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.473 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ab6bc6cf-8911-4155-b4ef-f218adbf7dc3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.292 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d4337f7a-5463-42e8-b28f-5da34915a48c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "908741b0-34e3-4946-bdd5-8b36a5ae278a", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.16 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8d0901c1-87c3-43ab-80af-bdbaedd77838", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f6aeea19-4ead-4a3d-b3a8-030aca2f65de", "MeterName": "Compute Hours", "MeterRates": { "0": 0.584 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e91c1a32-29da-4b4c-969e-3fa3ec93d86e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.059 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c1635534-1c1d-4fc4-b090-88fc2672ef87", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "eec9ca61-da82-4336-a1de-a0684da9ccbd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "39706f5b-224c-4dda-a804-fa6e733b15b6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.662 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b91d1bf5-26bd-405c-abcb-639780bf1b0f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "831bc3d3-78d6-4713-8262-4415317dfb43", "MeterName": "DWU", "MeterRates": { "0": 1.6936 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4063a9cc-77ed-4ffe-ac92-a4b6178dca3a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.39 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d79fa9df-f2bf-48f9-90ef-9e04a442cff7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "02b4d5e6-b772-4bd3-964b-7f5798fa9628", "MeterName": "Compute Hours", "MeterRates": { "0": 0.373 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2c23b2c1-8094-4a07-a7d2-39ad6204e792", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "45259a84-3419-4d3b-835e-78e1ecfebaf6", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5745cdaf-9afb-4771-ab1e-ac407b7c9777", "MeterName": "Compute Hours", "MeterRates": { "0": 2.252 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "b38a9048-adc6-4b0e-b3a1-a05737d2f34e", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SLES (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bda9aae0-a721-4e5e-879d-c52beb0cfd52", "MeterName": "Compute Hours", "MeterRates": { "0": 0.366 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "32c5021d-a34c-4bcb-b993-9b822e17ced9", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.083 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-01-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "103e4fe8-3efe-4046-b713-13bad55a29bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM Low Priority (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dbc2f35e-e9fb-4e31-88ef-04863e7a34c4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A10 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "382fd7ca-1517-4bc7-b22e-bf01be17eecc", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b9c339dd-811b-4960-8f8e-ab67c0a3a14c", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.084 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ea0c73f1-eb11-4ebe-865f-e0197987b8ec", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.4 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "daa010ef-6dfd-4e1f-b6b1-145d71268c5d", "MeterName": "MSFT Peering Unlimited Data 5 Gbps", "MeterRates": { "0": 41000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c3d11efb-d78a-453d-bd69-1e2811aa5edf", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 66.0 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0c6206c1-0315-42b5-9dfe-5a97cc653f9a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e3f81bab-5147-49fc-a7e5-f61f069bfc33", "MeterName": "Compute Hours", "MeterRates": { "0": 0.583 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3be2846-7569-4352-95d9-38c7a14bed05", "MeterName": "Compute Hours", "MeterRates": { "0": 0.349 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "db2ae25a-4469-4fa3-9c27-63ac21da6b30", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "19018383-8b5b-45cf-8bca-d4146b124786", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "56a12414-9659-4186-bf38-02cdfdf4dc63", "MeterName": "Unlimited Data - 100 Mbps", "MeterRates": { "0": 1230.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a178a1c1-7245-4296-abc5-4adc4e09528f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.308 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "a5afd00d-d3ef-4bcd-8b42-f158b2799782", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SLES (12 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3d292628-2790-481e-9435-cf62ff10331d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fa6ff965-8782-439d-920b-81bd3fb7c877", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6b355dbb-33b9-402e-bd6c-e54c14684fe9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.642 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72cbc933-fe63-4de0-a60d-f37c66dc7d4f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.611 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6acd3da4-3a69-44b4-90b1-cbded1f3729a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ee58c1ec-2358-4208-bd89-842083fa832b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31152 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "658e7924-b9c8-48dd-bf72-ee7fa989dec3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "daa2596f-4d24-47e4-a7c2-d5ab5128b17b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.68 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6ec21e9f-fc68-4f94-a02e-a6f5c66bb50e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.781 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2b5a7bf3-e866-4eae-8a5b-4cafec12a59f", "MeterName": "Compute Hours", "MeterRates": { "0": 9.65 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3a55145e-62f0-4bb4-8159-e41443f56b9c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.08 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b076df03-5463-45f2-a4ed-179377663e5f", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0756 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "837830bd-b8f1-454d-a085-c5c6bdcc4bf9", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 282.263 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "412d6928-652a-44ec-8bbb-d1dea652b7a6", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.336 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d8617238-d7b7-4eb3-ab46-8ea14cf88c6b", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.1136 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "0aa0e0e9-3f58-4dcf-9bb0-9db7ae1d5954", "MeterName": "Multi-step Web Test", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1 Test" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4fae75c3-3a6a-4803-bf68-84315c2222fd", "MeterName": "Compute Hours", "MeterRates": { "0": 1.481 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "de906888-5097-4b18-80e0-56d8aba038b1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.584 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4c3ddd68-400d-4f2a-94be-b62aa44091cc", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 16.5 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b6e36faf-e19d-44e5-81ca-3d0d6e81d653", "MeterName": "Compute Hours", "MeterRates": { "0": 2.309 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e35b8f7f-eaa2-42b1-be4b-e54f41ddfb14", "MeterName": "Compute Hours", "MeterRates": { "0": 4.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (12 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "23c97f6a-0554-42d1-a754-02618756c9ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.589 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e4b34039-5e6d-4be8-ae2e-4a63cd935af8", "MeterName": "Compute Hours", "MeterRates": { "0": 2.664 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2f448a94-8147-4294-881b-84d616ba6119", "MeterName": "Compute Hours", "MeterRates": { "0": 1.159 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "1937c943-e424-4b28-a84e-4e8f916a0ec5", "MeterName": "Metered Data - 100 Mbps", "MeterRates": { "0": 100.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "62577447-ac4f-4f37-a303-cfae8be6aa5d", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c12cae93-ac6a-4295-8c74-88f4342b8e6b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "4a7c53f0-7521-4f5b-9fe8-7d37ca58835c", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e4da13cd-e9ec-4e45-9518-1d2bd04ddac2", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 37.5 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3da168a6-d35d-46c1-8eb6-0ba6c4affec9", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 270.97 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "babfda65-9bc3-4415-8223-16d4ce761328", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "817457f7-0ab7-445b-ad6a-9d682b457ade", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A8 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "45bb30fc-e60f-4d61-8a92-f30c26fb633e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.61 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a6f4e40d-4dc4-4415-a93c-9dfcf913f7ed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b194ea06-90ab-4406-aa81-293cbfe2aece", "MeterName": "Compute Hours", "MeterRates": { "0": 0.214 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f5fdbf6d-ce2d-4026-97cc-250e1b3d3460", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2a429862-8f20-4e1b-befe-152aee05d626", "MeterName": "Compute Hours", "MeterRates": { "0": 0.282 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5b4c9731-0db5-421e-b5f4-fc82d81c4290", "MeterName": "Compute Hours", "MeterRates": { "0": 1.177 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e6ea4199-b8f8-43a0-8328-b7501db904cd", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.5354 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "237deb5e-619a-45b6-af87-1a12990dccb1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.375 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0fce87c2-1eb6-4f6c-90bf-60aa0e40576b", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0486f41c-e942-40ab-940b-07b059d312ed", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "f822b803-6235-451c-9c89-28b2247b0dac", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "S Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "3e74682b-d8d1-4e69-9077-79fefb279365", "MeterName": "S3 Overage (Hours)", "MeterRates": { "0": 7.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "967317b3-e56a-43e8-a6c0-94e9cc3132fc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "154d76a9-c8cc-466e-b8a1-4bfb0a7b0cb2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.288 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f5be9354-8006-4643-bb6c-6ab91b182043", "MeterName": "Compute Hours", "MeterRates": { "0": 0.698 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "68e4f398-381b-4fd1-a77f-02d238d1c8e4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.999 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a81c334b-927e-479e-acec-71b1987439e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.056 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "579ee866-7f95-4e13-8cd0-333e83e78fdb", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ec5cddbb-fbb1-4baa-8219-f19ef8cf7786", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "99ce0a26-4339-426b-9f80-10d697f0f191", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "66eb8ea0-fcad-4c64-8a00-2d82e130562a", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f5e981aa-4b62-4c26-8d7a-7eccb04546bb", "MeterName": "Monthly Fee", "MeterRates": { "0": 9.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Seats" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2a87c94a-471c-46e5-931a-f7310f143322", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "a7dacaba-81f7-4e7a-a54d-71424e600227", "MeterName": "Basic C4 (Hours)", "MeterRates": { "0": 0.263 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "048f06b9-9d71-4d2b-940e-bd4b32d55d0b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.704 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "046e62a7-0e90-4564-b269-0b993ec6226f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.025 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3ffa649c-d4c4-4686-abf2-30b4b965eaf9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "1c851764-16fd-4a27-b542-5f6bc931fae9", "MeterName": "Standard S4 (Units)", "MeterRates": { "0": 161.29 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "61448f94-e6e2-4acf-a179-0a37484c599a", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 464.5248 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "efb98702-34fc-4acb-80bd-dce84208c00f", "MeterName": "Basic Small Azure App Service Hours", "MeterRates": { "0": 0.083 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8595db1e-afcb-4ac6-8175-166dcd17f5fc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.786 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a438d19c-6aab-4fc0-b0d1-35b49a12317e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.342 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "76bbe46a-19f4-4c9f-bf3b-dc6618416b65", "MeterName": "Compute Hours", "MeterRates": { "0": 0.204 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1092c5f4-51bc-49be-9773-34cc253c6f1d", "MeterName": "Premium Storage - Page Blob/P6 (Units)", "MeterRates": { "0": 11.1361 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c3601923-b8db-4243-9600-5a746d39961d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "81c518cc-715a-4867-942f-2f0453f26045", "MeterName": "Compute Hours", "MeterRates": { "0": 0.836 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "131b3a0e-fd33-4213-94dd-1d1171ce4385", "MeterName": "Compute Hours", "MeterRates": { "0": 3.752 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b1979b96-5a24-46e7-9c60-d78cf81beee5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.975 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "84c854ea-5a9a-4af1-965d-ed87d16eda92", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.8 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Security Center", "MeterId": "dcd983ef-db32-4340-bf23-13f7e9f5f48a", "MeterName": "Standard Nodes", "MeterRates": { "0": 15.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Nodes" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "e43ed5d2-fb13-41f7-90e0-668e105987b1", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XL Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 10.0, "MeterCategory": "Notification Hubs", "MeterId": "2be0cde9-a26f-41ec-8682-b0b9c3c37012", "MeterName": "Pushes (in 1,000,000s)", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Notification Hubs", "MeterTags": [], "Unit": "1,000,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b5c9582-a8fd-4dc8-a494-f7ef82317065", "MeterName": "Compute Hours", "MeterRates": { "0": 0.594 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5d2ce9e0-3e31-4726-93fe-9f7ce4d04d99", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72cb2719-ced3-4a98-b4e9-51d8b0869fb8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3f3ca9cb-3ccd-4e0e-a619-c796c1b9edff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "88e0794e-588c-4cdf-9603-ae69bfaffc8e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.644 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c01dd06c-7dc9-4534-934c-dff44042aeb0", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e3ba6ef4-8da7-4781-b3f9-34c966e06ce0", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7de65d21-12d3-4904-8632-cbe9c481efac", "MeterName": "Compute Hours", "MeterRates": { "0": 1.367 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "2a5336a7-5168-4959-994c-f56df612d151", "MeterName": "Standard S4 Overage (in 1,000s)", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4cfb867b-2167-49dd-b89a-024719061a09", "MeterName": "Compute Hours", "MeterRates": { "0": 0.111 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3999d18d-3a2f-4230-948a-52296b7f378a", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 5.8806 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5ebb1769-35d6-481a-b69a-3207e48f1e5f", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7657247b-86ab-4ed1-a170-185f360138d8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.542 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a9f53a13-21fc-45c6-aade-c42e2accf259", "MeterName": "DWU", "MeterRates": { "0": 1.5121 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a7aa8fcb-42f3-4311-9c3b-4ec6647f46e0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.234 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a8f591d-b01b-4c42-bcb7-3ef8c7d6ca1c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.86 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "54e4a052-cd51-475c-b7df-d4772343fb3d", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.252 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9426e695-7bb4-4bc7-9899-a51b5bdbe3f7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.504 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "295f29b5-64ff-42fc-b942-d5f2ea2a0cf7", "MeterName": "Compute Hours", "MeterRates": { "0": 2.577 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "de2a4d92-c50f-47cc-9eda-9fcd1e7361de", "MeterName": "Compute Hours", "MeterRates": { "0": 0.897 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A10 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7f258707-ef67-41bd-9469-9ffc2b61a932", "MeterName": "Compute Hours", "MeterRates": { "0": 0.145 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "025cc6ab-6db3-492d-8a66-ed3e8c10144b", "MeterName": "Basic C3 (Hours)", "MeterRates": { "0": 0.225 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0ca118e2-2601-4829-a2f3-33f9ab7d051a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.528 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b80056b5-6af6-443c-9ce5-fe2e577d1521", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8a18372f-182c-45ef-bdc5-b89965bfc92c", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 584.208 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "278c095f-cd23-48ae-9081-8cdf49767428", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "acf575e3-9a0e-4471-9ddb-48ae53ea80d3", "MeterName": "Basic Medium Azure App Service Hours", "MeterRates": { "0": 0.165 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a55b03b5-3098-4141-ae72-d6f5643c6171", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.008 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ab463704-d90b-491c-9587-59a998835ef5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ab81f8f5-dd6a-4e9e-b2ae-fceb79c58f2f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95383be9-bc60-4903-948c-e33437dafda1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.278 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4afe8ef6-63c8-4741-8a8d-b06234b67ad9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c366aead-ff21-4e26-bb1b-e01b2d04199f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "750d52f8-b415-48de-b41d-56199cc4ca91", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ea107df3-ed81-43a4-93ca-85dc6734ad54", "MeterName": "Compute Hours", "MeterRates": { "0": 9.65 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "86ef543d-fef7-4d10-bb82-49840b1c3355", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0f901b9d-6fa9-426a-9590-d2924413c8e5", "MeterName": "Compute Hours", "MeterRates": { "0": 2.24 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1f666157-d311-4ea5-96b4-b7d4b9311704", "MeterName": "Compute Hours", "MeterRates": { "0": 0.594 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7963fa2c-11ef-45c8-b003-aca4d1e4961b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.46 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a88905e-84ba-4cdc-8f84-be4b0f4ffd89", "MeterName": "Compute Hours", "MeterRates": { "0": 0.904 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f11f905e-ea54-4f25-8547-46e0e8cd9575", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.913 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0350c6c6-6c31-4eed-aa53-a35993f89f36", "MeterName": "Compute Hours", "MeterRates": { "0": 1.35 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1f7726f2-0ab5-4a46-b4bf-24d0b0bd6c8a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.684 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "ee6736cf-57fd-443b-9a89-9b9810953c65", "MeterName": "Build and Release Private Pipelines", "MeterRates": { "0": 15.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Team Services", "MeterTags": [], "Unit": "Pipeline" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "47fea96d-d300-43d0-ab31-e6ff39c1f440", "MeterName": "Compute Hours", "MeterRates": { "0": 9.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (24 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "732e96a2-d15f-44fa-a205-a5b7396630c3", "MeterName": "DWU", "MeterRates": { "0": 1.2097 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aaa99b30-673d-45e3-b860-f0624f371d5e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.44 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "658a22b4-f07e-46d5-93fa-ba67f56c3377", "MeterName": "Compute Hours", "MeterRates": { "0": 0.698 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d4a1726f-2b95-4355-9907-b6b2123f8a37", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.73 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b2f312fa-a3de-4a4a-96c7-0c1cf4fde580", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "51aa477a-14ab-41f3-8721-1af6d5d9f1e6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.187 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2416f288-46fa-49f3-944d-bef5d19b0d3f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "893f0c95-434d-4f9b-8c26-5f88cd3aa703", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72c52807-1e01-4905-b609-42df4c90d935", "MeterName": "Compute Hours", "MeterRates": { "0": 0.592 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "53a0922e-fb31-452c-937f-eddb28332602", "MeterName": "Compute Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3f35ddf8-022e-4f88-ac8d-97adf188b12b", "MeterName": "Compute Hours", "MeterRates": { "0": 7.076 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "47b01664-7b82-4abc-b160-df2a38793258", "MeterName": "Compute Hours", "MeterRates": { "0": 9.064 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a0c8e7ce-7ed6-4acc-a1c7-9dfeb7a62ce9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.041 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4e3d4f06-9cf5-4cb0-bb82-10c1013c0413", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5807 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e4fa4193-078d-4720-b328-aeadf1703dd9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bfca4552-5529-4b01-98f9-b7a42ca4d69f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "47c3ea37-8f9e-4d0f-a3e4-c1351de4408b", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3f5c6b82-f791-4f30-a506-2570de10e79c", "MeterName": "BGP Routes Add-on Units", "MeterRates": { "0": 3000.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0a6c7eb6-0290-4e92-a112-4de73442b6ae", "MeterName": "Compute Hours", "MeterRates": { "0": 0.035 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "20d81067-af7c-48d9-acf7-d17d2e5ffe31", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0652 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1bf80982-509f-4353-811a-b50357600ec1", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.0158 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c2682b49-0379-463f-822c-9e486104ef9a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.4 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "14b8095c-55d1-40ff-a790-396657206a77", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.09 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c02481f5-526c-4869-8237-bbfcacaa9c14", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 60.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4c43072f-2450-4665-848d-3ae403c3bba6", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 4.8387 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a1abdf0f-f5ac-45d9-bb59-a54c58f4c600", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "233f28a1-ea62-46da-98a9-85ee0bd8e2e2", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.58 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c846e0be-b1ca-4201-b033-f532273ab35b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.056 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0c0f42d3-b620-46ab-9e09-f440e4e773cb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.39 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c59e5174-b0f7-4b9d-84f6-901b6777f387", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 46.8 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1760dd42-1206-4da9-832b-b4f47819c578", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.144 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "14f7d3f0-55fd-41ca-b92b-1543332f8347", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "eb51b970-e014-4faf-b436-4224b1e6aa73", "MeterName": "Compute Hours", "MeterRates": { "0": 2.309 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9ea14385-0aa1-47cc-afc0-f2ae4a024f41", "MeterName": "Compute Hours", "MeterRates": { "0": 2.617 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9bc6bbcb-216a-4333-a143-e08103c337b5", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "58231248-9370-44ce-9d83-9a99ad12b7d1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6285fb92-a11c-431d-8705-36239afcba6d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4d84bf3c-6f6c-4b5c-9c7b-bd34148ecdc5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.22 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "G1 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Insight and Analytics", "MeterId": "f76d1cf2-a577-409d-bb78-5e83f64bbd6f", "MeterName": "Data Retention (GB)", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Log Analytics", "MeterTags": [], "Unit": "1 GB" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "aa3a7f58-99a3-4760-8fe5-6184b0a4e14e", "MeterName": "API Service Predictions (in 1000s)", "MeterRates": { "0": 0.18 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "1000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f7d55f0c-b49e-408b-a91f-66ccfd311d1a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.804 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8e7cfcf2-abee-46f3-80fb-9fa21de35d1e", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.163 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7a1b179b-c49f-4e9a-b130-acad40ed82b0", "MeterName": "Compute Hours", "MeterRates": { "0": 2.5392 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c625d8ad-26cc-46c1-891d-0aba828a4f25", "MeterName": "Compute Hours", "MeterRates": { "0": 1.35 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e490b7ca-7d10-4b35-8b4d-81336dd54bfe", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "24062590-f2b5-4dd3-8073-e07dd42fa4e6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2c25e126-bca1-44a7-bd50-1a9fb70d58fb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5ad08c62-8af3-4458-868a-d3faa2518049", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 483.88 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d0dfe87-dd20-4c48-87a2-8e3f4f2b3650", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "46cce6a1-234c-40a6-862c-ec372b7803a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.292 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d1b60c4a-516d-444f-8519-2cd3d27147bc", "MeterName": "Compute Hours", "MeterRates": { "0": 2.16 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "687f0c7a-8a70-4575-9084-ab94abb22831", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 645.16 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "63836cf4-f142-4702-875d-0423839defb4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a48f58e1-fa30-44ff-8312-d3af67e18f32", "MeterName": "Compute Hours", "MeterRates": { "0": 1.243 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "66394b4e-5393-4ab9-aa3c-f15965cb2a6c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.568 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "728f3206-5e3c-4f02-ba31-669d04054659", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "4d10df20-7dd5-4f8a-8ff9-2bb0a2b252fc", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "96c86a67-1c24-4dc7-bac7-925f97a5f83e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.593 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cbd9afac-80a8-442c-afcb-8c3c64b410a1", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 108.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "50545028-8a65-4a48-b7e2-1883331450a8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.642 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "413bd863-a535-4e68-b041-1ee74bb62452", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4a5e21b1-9fba-45ac-b374-f3c5ce690b41", "MeterName": "Compute Hours", "MeterRates": { "0": 0.904 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7d154811-9adf-410f-a44f-264b2c0bb928", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e9549cbe-02d9-4213-b4be-22d6dfe8a3af", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0784154a-97be-40b5-80d9-7d60f73735d5", "MeterName": "MSFT Peering Unlimited Data 500 Mbps", "MeterRates": { "0": 5200.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b28ec8f7-c86f-48c8-95cf-0b147a25c41f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.497 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2f968df1-9a17-4398-bcfb-ad8bf7922321", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0264 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "66866def-3e1c-4db2-a0ee-075bad42dee2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.126 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b126a96f-6045-4fb6-9ef8-483b34c1a47b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8a72cc18-f690-438e-b77d-51195de7a551", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "287d9432-4499-4a9a-a53a-274fbb259dd6", "MeterName": "Compute Hours", "MeterRates": { "0": 2.059 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4be10750-f3ba-4314-a572-c93f6d03b541", "MeterName": "Compute Hours", "MeterRates": { "0": 0.096 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cfc45eb6-a396-4e89-b97f-48a417c64af5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ef9a7eca-060b-446c-8870-99716edd5912", "MeterName": "Standard Large Azure App Service Hours", "MeterRates": { "0": 0.44 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "702248f2-87a3-41fd-bb1b-996d11587a54", "MeterName": "Compute Hours", "MeterRates": { "0": 4.311 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "65e1a547-ca1f-42a8-b9dd-e290c579976e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.786 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3b31b19d-61ed-4016-9e96-641a30f29004", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9dfd9e6e-652b-4630-994e-cf521e7754fd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.122 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7908e336-4148-4888-acde-854d853e1b81", "MeterName": "Compute Hours", "MeterRates": { "0": 0.103 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 100.0, "MeterCategory": "Networking", "MeterId": "b1e1e5b4-4bde-428c-a22e-9e94faeec6d2", "MeterName": "Remaps", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Reserved IP", "MeterTags": [], "Unit": "Remaps" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e5773d67-c426-498e-a991-8ed469df9bc0", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "83e8b916-0a6c-452c-9c1b-85836f5a133f", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "L OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0aaf975b-8e33-404b-93f7-de7d69774ca1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c619e80-c14d-4051-be0f-e87163be7078", "MeterName": "Compute Hours", "MeterRates": { "0": 0.888 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99645d6f-b5d9-43ae-9004-554b501796eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "6633d915-7f8d-4ac9-a7b3-a0d52037340d", "MeterName": "MSFT Peering Metered Data 100 Mbps", "MeterRates": { "0": 100.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "af4fbe86-4f1e-40b1-9b18-b6bd21d52a73", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "58f7423c-4bf9-465f-93e1-9c0006297c2d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.284 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "40a3b3c1-a48a-4a66-a7e7-b300cffac4ab", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ccb656a-df40-46fe-871b-4f2f9c4e7ea5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "50366d4a-43ad-4712-bf16-b0e2ab06d08e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.568 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f9985551-0928-4da0-a9b9-62972f05fe72", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6ab4b21f-3ee9-4229-85a5-9bdba2b1319b", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 45.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b6ee373a-9179-4a09-ac0e-35709d8cf1a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.122 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ef82fb76-d2bd-4470-b0fc-0c7fea2d7b2b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.111 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "87594d41-d07d-4257-be17-d4d2ee0d0132", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.06 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "df6c2e25-b152-446f-bbac-358f7f6efabf", "MeterName": "Premium CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.5 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e081f4fe-7d9b-4040-ba73-e9dfde930291", "MeterName": "Compute Hours", "MeterRates": { "0": 1.171 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0dc6943f-8742-4a62-8db2-44b61c7fe953", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9ffb9408-91da-478d-9a81-1dafff95d33b", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 54.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aae08c34-04ec-4746-9749-36b58cfa2eb8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.698 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "94e721d9-5399-4094-843f-c84eb4e2e3fd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.973 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "63710d1d-64bf-48ed-aa9f-ac07c7f6c6f6", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a2638a90-563d-472e-9d34-98fcfb71939f", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1b90c524-7e82-4db4-8c41-406874dc197f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "01d844d6-e61e-4a12-8587-18c3a457db83", "MeterName": "Compute Hours", "MeterRates": { "0": 0.378 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "50c25df0-bf26-4462-8805-ce39bdcf4475", "MeterName": "Compute Hours", "MeterRates": { "0": 0.568 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "80bfd6ca-6975-4cf4-8388-8f5b0b63704d", "MeterName": "Premium Metered Data - 50 Mbps", "MeterRates": { "0": 155.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "832190c8-deeb-4fdb-9784-5d72fc63e037", "MeterName": "Compute Hours", "MeterRates": { "0": 3.41 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "848c6294-7343-41c8-a7d2-79d81a11da0a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.611 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f0185c96-1902-44c9-b4b5-9bf534862606", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (8 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "1d997029-efe2-4491-a927-69ad45e143f2", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9fe4d0cb-6731-49ad-9358-2d8587660e91", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bf9d319e-b320-41b2-925b-c53ffedaa69e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2a490ae7-a782-482a-99cd-55429d580ad5", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 442.8343 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1664dedf-c176-413e-813c-c5489d027272", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 72.92 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "75325450-e25c-4b9b-a132-8fa43ea4cf1a", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b4f199c4-1262-45f0-9e00-f7e060cac98f", "MeterName": "Premium Metered Data - 1 Gbps", "MeterRates": { "0": 1886.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c30490b2-3656-408a-8dbc-234d5de91597", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.059 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "63664cec-1472-4c04-8b7d-497141eff456", "MeterName": "Compute Hours", "MeterRates": { "0": 0.307 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "719ad254-6b3a-4345-9508-21c1243231b6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.293 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "521ece12-5133-4e99-b661-7c5761586174", "MeterName": "Compute Hours", "MeterRates": { "0": 0.246 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b62c8e16-705f-4de9-86ab-b96b59845b00", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b1a0557b-7cb3-4822-95e5-9b3494cc4323", "MeterName": "Compute Hours", "MeterRates": { "0": 2.845 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "055313c3-6b3e-450e-8399-52bdef767120", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "76850cbe-33a1-46d4-988d-430ac234cdf5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e27e181e-9c68-4723-a831-0038fa22443f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7c925565-7add-4747-a320-f6f7c9a12914", "MeterName": "Compute Hours", "MeterRates": { "0": 0.244 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "71af610c-e39d-4910-88fe-40814469f50f", "MeterName": "MSFT Peering Unlimited Data 1 Gbps", "MeterRates": { "0": 8700.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e4a85194-81e3-47fd-ada2-fe1467b57bfe", "MeterName": "Compute Hours", "MeterRates": { "0": 2.534 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24r VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0384c995-fc14-42d1-9e2a-c51964c2d737", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.662 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "468dad9b-a8c6-4c02-a340-d3b1a7e801e2", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "21538a6f-ea3c-4bd3-8b4a-945dc9b516d3", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.0389 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2bc489d8-90c9-4f3d-b8ef-d6e49b38d9e2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3d659c2a-bd20-4574-b305-2bfd864cf816", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c4624541-6316-4fa3-8569-d8ba09eb61c3", "MeterName": "Standard IO - Block Blob Write Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cfd04c8c-986d-45ee-9330-28124fe7c460", "MeterName": "Compute Hours", "MeterRates": { "0": 0.54 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1c268ee1-0168-4fc3-bcc0-6e0edf013d4d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.616 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d67b3fc7-7f2f-4b81-a6b9-c04c830883a8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.029 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "090284c8-ffe2-4c62-9f70-e16cf79a7c8c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.345 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "14cb6eff-4841-4256-9af5-ef93ed8fb334", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "02778402-fe73-44ca-87a9-11d90554d9bf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "29d42ce5-1adb-4767-a204-009e12b27666", "MeterName": "Compute Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "af454842-91c2-406f-87a3-d719ea7ee1e0", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0326 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "bb65d6d7-6e76-4271-a92b-9afbed775d27", "MeterName": "Build Minutes", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Team Services", "MeterTags": [], "Unit": "Minutes" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "1b207df7-7922-468d-aba9-2906ef34a65d", "MeterName": "Enterprise", "MeterRates": { "0": 250.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Subscriptions" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "2a1ad802-139b-43b8-a0b5-caf8a562d6e4", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "76dfe260-5cbf-4df7-a887-3197b1c1d94c", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 225.81 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "8330ee7e-073d-45b3-912a-6a6332a541fa", "MeterName": "Professional", "MeterRates": { "0": 45.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Subscriptions" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "04509603-57ef-4919-860c-d88ea7cfbf40", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "971f0ca3-60aa-4cc8-bb98-ffad6f8c59d7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "940e92c1-bdae-44b5-807c-c1ab2d3a05b7", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 15.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "aa2f6135-a5b4-425c-b03f-dd82a19671b3", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e48918e6-299d-46f5-a5ae-5c6e528307fb", "MeterName": "Compute Hours", "MeterRates": { "0": 2.016 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3815994a-7305-4dc5-8304-7bcf289ff86c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.294 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f3051f41-8827-47c0-af02-391f346bf821", "MeterName": "Compute Hours", "MeterRates": { "0": 2.337 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "55461174-8b10-424a-af38-a7c6656ec64c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.142 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "24a55859-5294-4797-af80-820874aa6125", "MeterName": "Compute Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ed6c0830-1096-4bd8-967d-bdb50148e9bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2137cc71-7875-4d85-bd56-70c27cfbe16e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1d65f3a0-7f88-4edb-991b-ebfc48016816", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 74.34 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "063f26fe-362d-4183-9ef7-78d1263fc0f4", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 36.0 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "8498e170-ccdf-483d-b90a-578f41b05364", "MeterName": "S3 (Daily Units)", "MeterRates": { "0": 225.806452 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dcc0cff2-c425-42bd-98e2-b0d71ddc56ed", "MeterName": "Compute Hours", "MeterRates": { "0": 1.793 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f8460d15-4945-4c49-b343-b2f308f88d05", "MeterName": "Compute Hours", "MeterRates": { "0": 3.059 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6eadcddc-ec2f-4c98-a9a2-16ab1b33211e", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4c68b6b5-a4cf-469b-ae80-67736eff408e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb41c7d1-ea55-4bb2-a076-1ad8713be7f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.319 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d73422d8-e396-473c-820d-5ae98fedb5e7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ab16d6c9-b9a7-43b6-81bc-2f406a903605", "MeterName": "Compute Hours", "MeterRates": { "0": 2.659 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "569ffb9d-fa22-440a-9233-3625a5a8699e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "edd2d43c-473b-4b80-b11e-c044fcb0255d", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0044 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c13c1b49-b0ab-44f3-b56e-8521c0e42517", "MeterName": "Compute Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "0c3885bd-351d-4c28-830a-446d7bb4295c", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.013 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a779b4ae-e3ee-44cf-ad4b-c2be12f11947", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9ccde83d-b9d7-4523-bbe0-06f8e2b0984f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "af610e69-10c6-417b-9537-37944c47a686", "MeterName": "Compute Hours", "MeterRates": { "0": 4.4 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "aef827c1-ed32-4e82-b851-b917d1851ff6", "MeterName": "S2 (Units)", "MeterRates": { "0": 1000.0 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "aedf8420-cf6e-4d02-bea6-9470d4d35d86", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 451.612 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "11e70888-7dba-4ed6-94ca-5207bc3e9767", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "89d7ba29-09df-4ba0-9c78-5aa7ee2cffa2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4230fad1-d459-432b-ad6f-51dd39dda4ff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a79ff50e-8ce0-4944-8abd-dba53e60178a", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "75aa8f43-7743-4cb7-accf-18d6899502a8", "MeterName": "Studio Experiment Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "69a9f821-ee9e-490a-a42f-404ba5c19819", "MeterName": "Compute Hours", "MeterRates": { "0": 0.275 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "573d2331-2858-473d-b19a-3b0e33a9b826", "MeterName": "Compute Hours", "MeterRates": { "0": 0.61 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3ab71e8-069e-4b75-afa6-f1455adad232", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "fea0de99-4dcb-4387-82b9-fc3348238b27", "MeterName": "Basic C1 (Hours)", "MeterRates": { "0": 0.055 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0d121d82-9614-44d1-9eec-66c8e0b43930", "MeterName": "Compute Hours", "MeterRates": { "0": 2.21 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "912f9c7b-beec-42fb-a1f4-36f029343488", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "30568429-55cf-43ba-ba8f-a0c525e49f9e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.101 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "75f0db6b-5d86-4c8e-ada6-f7125a52cd3c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.22 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2e74d96f-3567-47c0-ad9a-9d58fae3a58d", "MeterName": "Compute Hours", "MeterRates": { "0": 12.731 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "19f22d59-7b1f-438a-a627-87469e71323f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "2cda0b49-7d4e-46a9-9d7f-2e8446749092", "MeterName": "MSFT Peering Unlimited Data 2 Gbps", "MeterRates": { "0": 17400.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "79af76be-b139-423d-8ddf-7b3fe8937740", "MeterName": "Standard Redactor Minutes", "MeterRates": { "0": 0.145833 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "efee451b-13f7-44e9-969c-8ee08289759b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.89 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "02e6613a-5ecb-455a-93c4-70169a699a7a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "16a7af50-d069-4426-a988-02bdf74476a1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.074 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fe876f27-eb80-4c61-bdde-39b72f5bb182", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cdbcfac1-aab0-4e3d-9dc8-8231a91c7f5e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.822 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d1166c9d-9d2d-4fb4-96c3-198e41fd358d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.177 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "12d79ab0-39f4-4db8-92dd-72eae17c295c", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d2eb6a66-5243-49a8-8eff-61d09328a429", "MeterName": "Compute Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "89ed8923-7cdb-4766-b02e-90863458fe9b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.596 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "14191e8e-4823-4535-b8cf-2379934be0d6", "MeterName": "Data Transfer Out - Metered Data (GB)", "MeterRates": { "0": 0.14 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "17b9a033-f758-4e92-b900-ad71efe48ff4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.663 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "93d53c01-f180-44d6-a5ae-00fd565bd256", "MeterName": "Free Database Days", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5d8d233d-16c9-4551-bfab-7a8a29b80635", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3eca36ab-db90-42d3-b454-a1fff0e36385", "MeterName": "Compute Hours", "MeterRates": { "0": 1.61 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "51c361ff-a826-490f-a1b3-dd41d4798ac3", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 10.7139 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f930ef5e-c409-4015-95e1-463c83a5a63c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.135 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "14854f12-8d37-4299-842a-b0f2df82a305", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b641077b-1ee1-4745-8103-4366ee2543fe", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.009 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8bf84600-37ce-42ab-a6d7-0c322aed8182", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e96ba86c-f49a-4a5a-ba06-8ed6cb6b2563", "MeterName": "Compute Hours", "MeterRates": { "0": 1.242 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6255f1e0-9143-4bf6-9302-6cbef1b06819", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "39a71e7a-f800-44da-a654-531a0838ad25", "MeterName": "Compute Hours", "MeterRates": { "0": 1.481 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Mobile Services", "MeterId": "c8e0bab1-3e3c-4814-bb8b-9df53501d690", "MeterName": "Basic Mobile Services Units", "MeterRates": { "0": 14.99 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8279dca8-8a70-4c65-adac-9d0a080f21a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6cb69b1e-dc15-4380-8134-323c26bbf4d1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8c627e43-83f7-4980-8e30-b0955f529057", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.016 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2d4d409d-9821-4057-b8b4-12499b3eec7f", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb3b45c8-7428-4181-8a37-d563d7aa2130", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c29d8624-351f-46f6-812a-b40b7bbb3853", "MeterName": "Compute Hours", "MeterRates": { "0": 0.422 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9df7e2a9-22e1-4f5c-b3e2-63d979a59692", "MeterName": "Compute Hours", "MeterRates": { "0": 0.784 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "50579338-2886-45f1-a8bb-7c4afdbebaba", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0532 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4c951c96-be04-46dd-962c-5ab4f8f96a64", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 11.7 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fac55353-c604-4165-957a-9806be61d53a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.363 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7feeaffa-2443-4f99-ac66-a0464e8a19aa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.218 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3404573-3e32-4362-9315-1d9a72e0fc6f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.681 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9a56b4f4-1d78-416e-a19b-815490ad7910", "MeterName": "Standard IO - Table Scan Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "da67782b-514b-4b3c-a7c5-103a56e6bc55", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 18.75 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "52a3285a-5924-4a3e-8f1d-af99d3454ffc", "MeterName": "5PB Commitment Tier", "MeterRates": { "0": 4096.78 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "fab075bb-b179-48e5-8715-38be9f196f27", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.177 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7dba37cc-5c5b-4ad1-8062-4d27ca4b8b59", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bee8d2d4-ec15-4a8e-9582-f146a86c19d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.307 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a711dd41-475d-42c1-b8b8-2311f0318580", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e6a69a3c-288b-4171-af54-744b271ea65a", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "cfa24dd7-3f0e-4e00-a167-2e1f0f4830ea", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "54477364-0250-4d1d-a341-382ab5f88a75", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "192f2e47-92f7-40f9-a10c-c936bc4831b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a72205d4-2c64-4ccc-89a9-7804b8a8422a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "95b38082-a0db-474c-9fca-5650c639fb9b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "181926d5-204b-464a-b9e6-4d80ea4ef552", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.1252 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d03dc942-e4bc-410f-9da4-8b6425202589", "MeterName": "Compute Hours", "MeterRates": { "0": 0.139 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5ba3f3a9-b8e5-4cc5-b2a7-9a2ab3cba406", "MeterName": "Compute Hours", "MeterRates": { "0": 0.401 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99991cc8-be03-443a-83de-4d9ede021782", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5facea72-fd89-4710-a261-10ab63daeb07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.464 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3208d7aa-8222-49f3-b363-07b68837f30c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.372 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "937d7721-8ccb-46ef-814a-dfa23d9d2b57", "MeterName": "Compute Hours", "MeterRates": { "0": 0.797 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2da459c7-3025-4ea4-9b46-23d0efa58cb1", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "424aa64e-dc25-49c4-8565-b86222279260", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.034 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6d8e5801-3e49-446f-958f-5c79bc1416ff", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.11 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2b794af0-a7ea-4290-988c-3eb887e3dbdd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "550f587d-ac2e-43dd-90de-1fab41f5ba39", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 274.43 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "93351a86-99c1-4b24-aedb-bfce45224608", "MeterName": "Premium P3 (Hours)", "MeterRates": { "0": 2.774 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2e956b65-407a-4637-8b4a-905a4756af22", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f0cfd84c-f382-4bf0-9f7b-a3a0aa980efb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle WebLogic Server Standard (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e932f3dc-b35f-42f0-b59c-d05defad0a78", "MeterName": "Compute Hours", "MeterRates": { "0": 1.342 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a7130fc0-3bc4-4e01-a47a-a7441fdec6df", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.384 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "77609be6-c110-4e07-962b-6238efbfd0d1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 100000.0, "MeterCategory": "Functions", "MeterId": "4e5cd9e2-c20f-4d7f-acbe-58931b8b49ef", "MeterName": "Compute Requests (in 10s)", "MeterRates": { "0": 1e-06 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10 Requests" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9c0e03b3-585e-406d-97a6-f4ef3fe40c7b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.463 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9081fe14-ac6f-45ca-a4d9-2b8756c500ee", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5ca9979-e9bf-4c05-a5d7-c72682d386d9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.966 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A10 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5592e36-915f-4839-aa41-295dc82a9203", "MeterName": "Compute Hours", "MeterRates": { "0": 0.074 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b67dde1-5444-4c43-9472-a94ceae8f33e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.246 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a464e4b5-404e-4be9-b016-480bf779ac73", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d70c68f-9ef2-46ba-b077-484465f471ec", "MeterName": "Compute Hours", "MeterRates": { "0": 0.315 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fcfe6f2e-4f7d-4d98-bf21-f167604ebdb2", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "27b3efd7-371a-4262-bb80-ff8a63109699", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "743df7ce-2318-440e-879c-fd0215669eaa", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5069aa0b-a93a-481e-9856-616a5e5575ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.079 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b16e83df-bad2-4a20-bfc5-9ad0d9d169b4", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.2875 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "589e46fe-4583-49ac-a10f-81e12267a127", "MeterName": "Compute Hours", "MeterRates": { "0": 0.592 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b17e33a3-6742-4e47-a50a-06b870574e65", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 145.2 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "462cd632-ec6b-4663-b79f-39715f4e8b38", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XS SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "12c6b384-7420-4809-8dea-22c75586d06e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b7b6ab06-2a5f-49a2-81b1-d8e76f012c6f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.854 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2a57b047-d1d6-4a70-a19b-4862972f10f3", "MeterName": "Compute Hours", "MeterRates": { "0": 2.016 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c785253a-41e5-4b5c-98f5-41d74e2ed6d9", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.285 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ff3e9b1b-7728-47e6-aa7e-01b852ab5cc3", "MeterName": "5,000-AU-hours Commitment Tier", "MeterRates": { "0": 116.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "923978e1-fd3f-4bd5-a798-f4b533057e46", "MeterName": "Standard IO - Block Blob Delete Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e685d428-927b-4fb1-a225-681565dec84f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2cb0396a-d3d3-4050-af45-f4c3d6f3ed32", "MeterName": "Compute Hours", "MeterRates": { "0": 1.95 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A9 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "525a1fc8-fe0b-4073-acec-4e2746d26c0c", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "57242d01-f8ce-451d-86ba-42cb6420a568", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "acc5a3fa-45f9-472b-942d-532b36f70624", "MeterName": "Compute Hours", "MeterRates": { "0": 0.768 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f830cae7-d1bd-4f19-b7af-4b2751654bd5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.293 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "15e3c6ce-261c-4db3-a8bc-f4d1de3ec183", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.101 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5d64cf92-2ca5-41a0-b5b4-537160d8b09f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4f9f1112-491c-4d37-8e06-54a1b9cbc38c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2714a45c-f880-4854-b41d-8598127d12be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "459904b3-4992-46e2-bdf1-e74810c21445", "MeterName": "Compute Hours", "MeterRates": { "0": 0.88 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "97e9da9d-caaa-4595-a6d5-66f7484142c7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.343 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a8049401-f714-419e-865a-824817f9dae1", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 571.408 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "22b100c0-8365-41be-a39d-b5cb405e9ae7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7625ba50-fbcb-4e6a-9e25-4c8354088790", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1ad497d6-14c7-465a-9cdb-5c1a3f87ff09", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b4e55536-5a69-4246-897a-2e7982be5197", "MeterName": "Compute Hours", "MeterRates": { "0": 0.279 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2012-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "SQL Reporting", "MeterId": "d4d985c9-b5fb-420b-950d-458d4c2cdb72", "MeterName": "SQL Reporting Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "37c7e193-26a7-4e2d-bf8d-f30588fbc6f8", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "432d1757-4a53-4f3b-8d0c-1643ebac6fce", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.5323 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "39b3a775-ff94-4920-ab1f-61d5dadc80c4", "MeterName": "Compute Hours", "MeterRates": { "0": 4.674 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "aaa41709-bc47-4c3f-aff7-1f8a0b228a89", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0922 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a75daa1d-ccd7-41a0-a47b-c767d0da22c7", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.163 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "339fc49d-f3cc-4c6d-83f9-44cf9c0c9d38", "MeterName": "Compute Hours", "MeterRates": { "0": 1.6 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (16 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "7ce53686-7c67-470b-ae6f-3996cbb02fbb", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bfc659da-ec05-4bfd-8065-78cd212bca35", "MeterName": "Compute Hours", "MeterRates": { "0": 0.124 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "39ef1714-a0c2-45b7-bf51-1fd8b90aba26", "MeterName": "Compute Hours", "MeterRates": { "0": 2.337 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d6ea4650-6167-4db7-b1c6-1d06df4a7885", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.263 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fb0e3314-7fa1-4ad2-8238-9c3fe64224a9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b6a1a7b1-147d-4969-b511-7b0925528a0a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.194 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "adee0345-8378-4d7e-a702-5784c368ea81", "MeterName": "Compute Hours", "MeterRates": { "0": 0.177 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e28f9980-0a1f-4006-be38-da8eec7818fa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "c139fb93-8cf6-4493-8b73-894d4d282e46", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Canonical (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d19b51a-47d8-494c-9b51-dd507ad54e99", "MeterName": "Compute Hours", "MeterRates": { "0": 0.531 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "83ecc636-598e-449b-bf69-58583c0d449b", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.4104 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d434c294-d7e6-433e-9f3a-2c6d6438d534", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.3226 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "cf13eaf2-1f43-40a8-a5d1-f7657b5461a1", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.0153 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d8889acd-5998-4f29-9be7-d6d9236810e4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.466 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f114cb19-ea64-40b5-bcd7-aee474b62853", "MeterName": "IP Address Hours", "MeterRates": { "0": 0.004 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Public IP Addresses", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7648e95e-b1c1-408f-9ab9-569fdba2b127", "MeterName": "Compute Hours", "MeterRates": { "0": 0.149 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "843d5166-3839-437d-9ebc-f82a6b2a6216", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.1394 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "356ceb86-6186-4d3c-89a8-7de605da48ce", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.22 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fd2b562b-812a-4cc2-b6b2-b20283d5c59f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4e2031cd-635d-4d54-b9df-380fdcf63c07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.029 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "60cabd47-3352-46a9-8e8b-196927217132", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "983d5164-7944-441c-8599-a516f50cf56a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.798 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0f4ff56d-127f-42d2-8c35-d6f98d1578d7", "MeterName": "Compute Hours", "MeterRates": { "0": 2.854 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d77769e8-fd22-4a77-8dfb-4aadabb25c61", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "7fd385bc-796c-45c8-b0bc-278bb675b15e", "MeterName": "Developer API Management Units", "MeterRates": { "0": 49.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "API Management", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "75320b13-bb2d-4527-9a06-8b8ffccf5237", "MeterName": "Compute Hours", "MeterRates": { "0": 2.814 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "76316769-34d9-4b32-a6ec-c89677ddad8f", "MeterName": "Premium Metered Data - 200 Mbps", "MeterRates": { "0": 445.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "c2ec93b6-fffd-473f-b03b-99ec0f014230", "MeterName": "Free Notification Hub Units", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Notification Hub", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "209fb2f9-c45c-4e6c-bf9d-954686fd3c2c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.272 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d68fab12-4fd6-4b7f-8518-b402cb9b418f", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.5168 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-03-12T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57105f32-0637-432e-ab45-76aa1956acfb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b86bf3f-9539-44e9-86cb-9961e173243a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.542 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72051996-8d8e-4921-a2da-2244d8460816", "MeterName": "Compute Hours", "MeterRates": { "0": 0.535 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "47e8ed49-fc56-41d8-a459-fbef14c92c84", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.318 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7668bf28-d39a-480d-b0cd-a432d162b20f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.916 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "26ce34b7-67b3-480d-9d1b-54a7fb80f67a", "MeterName": "IP Address Hours", "MeterRates": { "0": 0.0036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Reserved IP", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "cf857e09-a066-46e9-9f52-b6f73e70692c", "MeterName": "Standard Managed Disk/Snapshots (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b9e5e77c-a0b3-4a2c-9b8b-57fa54f31c52", "MeterName": "Standard IO - Table Batch Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "603ce07f-d881-4a8a-acb1-82bf3272fde4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a38caaf8-a8e5-4aa6-8cc9-5b5dd910d51f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.125 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "de330655-17ee-423c-8dde-a1a7ecbd7ee5", "MeterName": "Premium Elastic Database Existence", "MeterRates": { "0": 0.504 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Mobile Services", "MeterId": "090fea11-ad13-4c72-b002-c857cb161191", "MeterName": "Standard Mobile Services Units", "MeterRates": { "0": 139.99 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b704e435-6af4-4a5d-9bc3-06e4b0554f02", "MeterName": "Compute Hours", "MeterRates": { "0": 0.516 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8e5143e-bf4e-4cc1-834e-40b25a49a5b9", "MeterName": "Compute Hours", "MeterRates": { "0": 8.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (16 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "7c7b7558-7607-456d-9d8c-faf4149cb3cf", "MeterName": "Standard C4 (Hours)", "MeterRates": { "0": 0.656 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fe8719b6-301d-4f96-a11d-d0eb11d790d0", "MeterName": "Compute Hours", "MeterRates": { "0": 1.329 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "02e9eadc-810a-4abe-9ebb-b3e80009752f", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "29f6e51a-6138-4f2e-a8fe-d8df7869416d", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.143 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c0db510b-a7e8-4cb6-804d-3b965992ca1d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "222f32c5-a319-4787-b934-5fb95105b2c8", "MeterName": "Advanced APM", "MeterRates": { "0": 15.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1 Node" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "075cb6fe-fd6d-40c5-989a-40042396130d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3399fb93-fd47-4ea3-bf1a-6ded279aab72", "MeterName": "Standard Managed Disk/S10 (Units)", "MeterRates": { "0": 3.238 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e587153e-8126-4711-8d86-7e57e7148488", "MeterName": "Compute Hours", "MeterRates": { "0": 0.163 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9df35c95-f93e-4896-9a3b-5dee09059098", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.1 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e75b5ce6-8220-4efd-bf7f-e099de2efca0", "MeterName": "Compute Hours", "MeterRates": { "0": 1.387 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ac0bc029-66c4-4fe8-9dcc-140dfa46f9da", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3942 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "c1055a89-680a-4190-a2db-543e1fa71b2b", "MeterName": "Standard S2 (Units)", "MeterRates": { "0": 16.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6531567e-5972-4c52-b5c6-0fa0fae93340", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4b7af575-3c99-4ab3-84c4-b61dbfc6732d", "MeterName": "Compute Hours", "MeterRates": { "0": 2.496 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fbcb5c45-d849-4807-901c-da253442d477", "MeterName": "Compute Hours", "MeterRates": { "0": 0.797 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "80edf852-7701-45cf-aa74-67e900c190dd", "MeterName": "Compute Hours", "MeterRates": { "0": 2.845 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b29eac16-9986-42cd-890d-404a414cae83", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.0963 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "052267a2-58cb-4b75-9644-39e67df214e9", "MeterName": "Compute Hours", "MeterRates": { "0": 2.954 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "48eb1124-3c78-4278-9bc1-85d9120fab17", "MeterName": "Compute Hours", "MeterRates": { "0": 1.163 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "efb0eaa4-52c4-4850-b419-abfe35a1c96e", "MeterName": "Metered Data - 5 Gbps", "MeterRates": { "0": 2180.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7ba059a6-09f5-4081-b01b-915a2a3911bf", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.11 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "880be4a2-e038-4d1f-ad41-81864e7b278d", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "bbe2e768-80fd-44f3-b76c-dc4a13bb4e64", "MeterName": "VNET Peering Regional Egress (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "094852c3-b5da-42c0-b6c3-6c320e5301eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.37 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4f743466-7a76-422d-976b-20f2560408c8", "MeterName": "Compute Hours", "MeterRates": { "0": 8.102 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7633fab9-bc1c-4a5e-ae40-2aa80b8f15d8", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8e46e8c-181b-4f65-9936-9ed95b967609", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5a5494fe-a8ec-4c94-9d89-a18b3ea3df19", "MeterName": "Compute Hours", "MeterRates": { "0": 3.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6f6b87a3-554e-47f5-b1d7-a0e8d5311716", "MeterName": "Compute Hours", "MeterRates": { "0": 0.626 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d8eb314f-b85e-4b3a-8956-19cf69bb8c42", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.055 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "afc5f08d-34be-47b5-b394-a3211a810d5a", "MeterName": "Compute Hours", "MeterRates": { "0": 4.9 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d53819e2-6e9f-424b-ac19-a4014676dd70", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.0645 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "109063c3-f812-46be-a3e4-a62e06171fc6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6459d072-f256-49a9-ae8a-a2bc42cd5929", "MeterName": "Compute Hours", "MeterRates": { "0": 0.118 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8b698c7a-47f1-4cba-8ae1-9853d5ad562d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (24 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "606c4b3b-454e-4cdb-8033-bcac5f6b3895", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "37b7c64a-e1af-4ba0-b3a6-2f48503c14ec", "MeterName": "Standard Small Azure App Service Hours", "MeterRates": { "0": 0.11 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ab66c53e-9e98-4ad9-9044-d30942eda64d", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "123acba2-e093-4be4-bc64-508eca246fad", "MeterName": "Compute Hours", "MeterRates": { "0": 0.035 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "db25cdfd-ecd9-4893-a9af-f8858924defd", "MeterName": "Compute Hours", "MeterRates": { "0": 2.086 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "787a3dff-ac97-4b19-95d8-3e3598368d61", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a1931f21-80fc-4ba8-91d0-102d31321153", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.1612 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ccebc82a-8a1e-4e68-b226-72b4d8ef3c7a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.133 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "56044820-cfaf-462e-b198-ac435357be7d", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "56b74cb6-b4b5-4f7d-a142-392e69277781", "MeterName": "Compute Hours", "MeterRates": { "0": 0.452 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0af09a2b-acb6-4946-ac1c-9236fe1a38d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.493 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "22780443-af18-4356-8bee-9fa42dbfdaa8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "171fa11a-8ad0-4436-b758-7dcbbfec4b8c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.28 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9141ef15-470d-4392-8633-e5fcf796ceff", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7790e1b7-6fea-4ec3-8303-dffe9dad8579", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dbe2d2b7-0d35-41b4-93e0-8e5cae6b0418", "MeterName": "Compute Hours", "MeterRates": { "0": 0.123 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95d0215c-b10e-4352-925a-c9885411996d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c6ee120c-ba2b-42d6-bb3b-08d0b7c5727d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ecf3c7b-45de-487e-b7b6-4eff641a11b4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f055c9c6-a03b-41c2-b291-e60a90f36c28", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8590f1c9-8997-4cb1-b526-a5c6534f7a46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e1712dd6-f8d8-49e6-8448-4467a70a8f7a", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 75.0 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "d2e2622a-0a31-40cf-9e8b-bb2eb164614b", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.236 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f679b7f5-ead6-4474-9829-769dc819f3e2", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fb22a586-24e1-4cba-96dd-02050af5490d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.405 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "923dd535-29fa-41b9-a505-2eccc1e54d07", "MeterName": "Standard C5 (Hours)", "MeterRates": { "0": 1.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a5b0e14c-73ad-417b-9432-0d369a24667e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.255 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "babdfb96-4eb3-47e5-9add-30a06b65a7c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.163 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a1d137f-f61a-430c-bd49-0bc1cd7f6954", "MeterName": "Compute Hours", "MeterRates": { "0": 0.238 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "473a1dd1-c687-4e65-b886-f3d7332f3aa0", "MeterName": "Premium P13 Database Days", "MeterRates": { "0": 354.84 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "66ce8e33-adda-4e04-a0cb-0f1ce31849b6", "MeterName": "Standard IO - Table List Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2781f1d6-dbe4-4dbf-97c9-af5ccfd8a31b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a9275d5a-d3da-47fb-938a-69c994e810e1", "MeterName": "O365 on ER Add-On Unit", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bae7b5a8-3b51-42a9-8626-161f773b5461", "MeterName": "Compute Hours", "MeterRates": { "0": 0.096 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "eeb65ec9-9b0f-4586-a280-c1f30eae935e", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 248.39 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce655864-59d7-4ddf-9fd2-b683d467ee64", "MeterName": "Compute Hours", "MeterRates": { "0": 0.396 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ba501f8b-0892-4e26-9abe-1f3d6e1bbe2f", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0028 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c4721d3f-e7d3-4b5c-8f86-c5b533b8936b", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 33.9 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7478abb1-2639-4530-8d20-4de16c10b22b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.691 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "79cd9ab4-6623-4245-ad35-96337eafa05d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "58448cde-9a5d-44e9-9379-eb46c209649c", "MeterName": "Standard S2 Search Hour", "MeterRates": { "0": 1.774 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "963858e4-b3ba-46bd-90cc-b509518302d5", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.16 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Stretch Database", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8b585da3-4286-4870-9af7-c6f627789344", "MeterName": "Compute Hours", "MeterRates": { "0": 0.206 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "91ca2643-d874-4da6-a684-bbc95c756bc8", "MeterName": "Standard Encoder (Output GB)", "MeterRates": { "0": 1.99 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "01778ecd-15f6-434a-96c2-07fd540d312d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.486 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1b8ee1c5-63ee-4235-b273-74d94fbc561c", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.1077 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "32f0a970-4107-40a9-9cae-f529a3622c90", "MeterName": "Compute Hours", "MeterRates": { "0": 0.276 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c106c992-da17-4880-b2af-93691cb1ee2e", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.1932 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "0108f28e-6117-49c0-91cc-d446196a369e", "MeterName": "Premium P1 (Hours)", "MeterRates": { "0": 0.722 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3dc1a5ab-164e-4d57-bd3e-10d6164ecfce", "MeterName": "Compute Hours", "MeterRates": { "0": 0.127 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4005571d-fc07-48d3-98f5-86e27a41808e", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.375 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "309791ed-430a-4013-9b05-8e8854ec0e01", "MeterName": "Premium P13 Secondary Active Geo Database Days", "MeterRates": { "0": 369.03 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "15adff7b-0dab-4c00-889d-caa6d4fb31bb", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.054 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6a1bd106-333c-4dfa-a71f-2722fdf518e0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd3fb07a-872c-4e22-b154-7ca4ead5f9b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "00bce34f-cde7-4bd5-8f14-b0b7d6b21e40", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3206138-e211-4bff-9f16-fed7f6ea9db3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.25 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "45778e44-99e9-4a44-96cf-a8f629094ec1", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 25.42 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8be55a12-6a8c-47b8-a3d8-6dec90290312", "MeterName": "Compute Hours", "MeterRates": { "0": 0.383 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "91e3e03f-973f-4594-8a5d-b2a26d712a7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "4eea396d-b680-47c7-a1f5-3d9f5cd4d998", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "390384db-82bc-48a6-a5ab-25323805a0fe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.418 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12f622c3-619b-4b39-955d-2bce51cefe61", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "105f1ebd-5829-468a-98b1-36019e2670e4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "40a11b2c-ce1b-43c1-8da6-b3ff083ce540", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 126.46 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "65f8af30-924d-4dab-8aad-94168563caec", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "91dabf9e-0400-47cb-9c9d-08903b1d9e3a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.175 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "db694303-aa9d-44d0-b059-1bb26ab4abd3", "MeterName": "Compute Hours", "MeterRates": { "0": 2.156 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b05cb24b-e950-4f32-93fc-bc4381ba05af", "MeterName": "Compute Hours", "MeterRates": { "0": 1.466 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cae13303-88d7-4113-be86-6e1aaaa4c4e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d848378a-fb17-425c-8126-0f22525ccbed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.699 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "fb7392a3-f693-4e3c-9de0-01ba98ddb948", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "38529ded-5b8e-4b49-b078-ce81794a3543", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.008 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "696e01fd-b4de-4584-a321-ba40f0af038a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b939c7c4-6cd5-4c4b-95a9-ebb04712363c", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0741ca2d-09c7-4c55-94a2-c0b6c0d30bff", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 233.47 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "23e1ac7a-73e3-48fe-80d4-27e129d74e5d", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e315c24e-2f54-4668-95ae-5aef18f93125", "MeterName": "Data Transfer In (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4dd4e1de-c11d-4208-a892-b4d7fe4aa6c1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.175 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "661029d0-f3d1-41a4-8f27-f85785363906", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "360b544c-fa6b-4a07-a5a8-48a1ca2cb074", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dadc6f05-6975-4db1-8dae-cf6d802ce15e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.083 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b57c4278-68bf-45a0-a4ab-1586eaf63904", "MeterName": "Compute Hours", "MeterRates": { "0": 0.237 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "47df7bbe-4be6-4409-bab9-2ddf50fc690c", "MeterName": "Standard IO - Disk Read Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7005237e-58cc-4800-9432-5cbaf104d124", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0edfd79-e322-4833-bff8-778e609c26ec", "MeterName": "Compute Hours", "MeterRates": { "0": 0.379 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "36010ef7-9201-422c-b3e2-033ffeb8b28d", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 132.0 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "7d169ef9-f902-456d-994a-747929e8f497", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5071d41d-d567-4b8c-b8a4-f185692c299c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fe0c1675-39b5-4d4e-95c9-1b3b9d0e654b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.032 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "72a91179-cc9e-4a79-98ef-2708a9a8b2a6", "MeterName": "Premium Video Face Detection APIs (Minutes)", "MeterRates": { "0": 0.1667 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bbdee837-3c2c-4da9-bad8-3f4dd2df45ea", "MeterName": "Premium P13 Database Days", "MeterRates": { "0": 335.48 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3db40165-e9f2-457c-955f-c159c58302f2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.916 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "40af2e4f-b9c2-4484-b034-a1064c6f82c3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a35c5774-1850-41f2-8368-e388e7f106b3", "MeterName": "Compute Hours", "MeterRates": { "0": 5.194 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4ee3e365-90f9-4630-b38f-ed6986135acd", "MeterName": "Compute Hours", "MeterRates": { "0": 3.218 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3f2b1e1c-c886-4ec6-ad6f-dd0ef38819c9", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.07 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5841b9c4-4195-4e6a-8088-4fd40062813d", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.5 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7d879c93-49bb-47b5-9a5a-e978129e7ff8", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 99.0 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "89ec5da9-baa5-44c1-8622-085e52553989", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 77.72 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "42d79216-1330-48fe-b1c8-b07445df2e45", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ccde4ff5-1516-4120-a220-9e982301b810", "MeterName": "Compute Hours", "MeterRates": { "0": 0.316 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7b0c2c83-f956-4c5f-b822-93bb157ad5db", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 61.44 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "37bb912c-9d9c-485b-8e88-f0e57dc367cd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4f47ebee-5501-4e95-be52-0e923987ed83", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "97e620a4-f295-48ef-b3aa-834378a8cf9f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "20b08e25-1f62-4d96-9c4e-7ba404db36f7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.936 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "72bb7aa1-e3a0-4363-a4af-953b80d220ac", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0264 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d340fdcf-27c6-4389-8e22-51c9a83adaf2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "64d48263-32ab-4359-b05b-8626b0974e17", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1601ff38-6a99-42ba-b3bb-1eb132081dae", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b9ef3036-86bd-4682-9a13-1cc3e80b3d58", "MeterName": "Compute Hours", "MeterRates": { "0": 0.171 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b20317e6-d6be-48ad-b7b8-86714f5debd0", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7e20a7ed-96c3-4774-a333-bac48bf0de6d", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 62.4 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d422f5f7-2394-4171-ba60-27e90e182c51", "MeterName": "Compute Hours", "MeterRates": { "0": 1.168 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4eca9863-1928-4f14-8770-56332a7b8dae", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 571.408 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c71c2203-0303-422d-b362-fe5145fc4bee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e2d0a93f-8d8e-4de8-a457-c86351239e52", "MeterName": "Compute Hours", "MeterRates": { "0": 6.38 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "39f65a7d-ccca-4eb5-9718-2f8d3712323e", "MeterName": "Compute Hours", "MeterRates": { "0": 4.9 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "e8ded5da-820f-4012-b68a-a0ebc82f7045", "MeterName": "Standard S3 Overage (in 1,000s)", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6e6fcacb-5f0d-4d19-afdc-9ff9931a6c40", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 30.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "eb1a5a41-fddf-4744-b23f-ca4f905a3422", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 66.43 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e53c5205-28aa-4750-ac82-4e7e6039786c", "MeterName": "Compute Hours", "MeterRates": { "0": 3.271 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "1a2bbbcf-4313-43fb-95c7-11d95b45cd24", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "978ec393-2954-41ad-bd64-1aec2566b910", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2f252a64-b5b9-4af7-be23-736debec89d5", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.22 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "a43cd070-5629-4b2e-a742-67755ce6b962", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.756 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "9c1e1960-41f1-43c0-b98e-c4ad9cc72fa5", "MeterName": "Standard C6 (Hours)", "MeterRates": { "0": 2.625 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cf9be5f2-0ca0-4bcb-8773-93ce0448640a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "223c2a69-e19f-4dc1-a7c5-8118b16c5dca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.038 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12c113f6-61d5-4f4f-8e05-d51e85221d7d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.616 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8b51cc3f-cf27-4249-af00-cdea5f8e45bf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a40bdff-6f45-4172-b974-6b0ff58329df", "MeterName": "Compute Hours", "MeterRates": { "0": 0.205 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "27ea9e39-5e13-4d2b-9a16-ea6a269c6e62", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5060c012-6a58-4cdd-87b8-653dde025599", "MeterName": "Compute Hours", "MeterRates": { "0": 0.308 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b5d831b5-bec6-4361-924a-5e9a6d9d8e49", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0d0014c-8ebe-4838-829c-efec05dd79a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.232 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "328e19f9-37e5-4fee-8b98-d896a49a0d33", "MeterName": "Compute Hours", "MeterRates": { "0": 0.087 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Recovery Services", "MeterId": "82a2e983-9683-4842-82b4-bb634c60c8be", "MeterName": "VM replicated to Azure", "MeterRates": { "0": 25.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Site Recovery", "MeterTags": [], "Unit": "1 VM" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ee15eae5-95b1-420f-a06b-86a2069baf67", "MeterName": "Compute Hours", "MeterRates": { "0": 0.21 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c49be935-2bef-464d-a39d-e91a1dbc66a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.464 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "22eff9c9-8b81-4c26-87fc-0301d0ace3f4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.121 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "74e45d17-1efa-4520-93b6-ab248adceb07", "MeterName": "Standard C3 (Hours)", "MeterRates": { "0": 0.563 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "758b46f1-1579-4490-a54a-9829ff267c51", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.026 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e40c606b-e16c-4803-aac4-1e47666f4609", "MeterName": "DWU", "MeterRates": { "0": 1.5121 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99694622-7772-4b82-b9cc-733fea3bb1c6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "572914d6-90b7-4bcb-ab74-37a940185788", "MeterName": "Compute Hours", "MeterRates": { "0": 2.46 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "00f4a440-7d4d-4f36-8069-86bd74df79c0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.893 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "74f3cc80-52e6-4f9c-a7e4-44c29e838f04", "MeterName": "Compute Hours", "MeterRates": { "0": 2.351 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cac456f9-3814-47c9-98bf-bcc73f824acf", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.0177 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6ae71335-b4fa-4612-b67f-0e5091192d9f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "81d4cb7f-5f28-4c6f-84f9-1c422ca73adc", "MeterName": "MSFT Peering Unlimited Data 5 Gbps", "MeterRates": { "0": 25650.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c08f7d89-a982-4b80-bfe9-40ccb9e6ee6c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.542 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ac6020cc-3e03-45c6-8cc7-0c3cab0a9c62", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b7e8ddcf-8bb6-4df1-9302-37573c1cac22", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "06fb8bad-0653-4cd7-bfb0-8fcd3ac50371", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "94a9b997-b0ca-4055-b05f-4be3148d3ce7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a4ed88a7-6d48-4f78-aada-01bb6ec88769", "MeterName": "Compute Hours", "MeterRates": { "0": 0.817 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5039bfe7-5674-466e-bb68-fe08933c62d2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "23fbf784-511f-4590-a64c-80a2a673e4a9", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "23584662-b932-47bf-b35d-9bafd4a32cbb", "MeterName": "Compute Hours", "MeterRates": { "0": 4.5012 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "33fdfc79-05fc-4154-89e0-c3072a57f6bf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "daee1d0b-ddb4-48ea-a32f-9342d391d07d", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 511.182 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "53b75ff4-0860-4072-946f-7e9583dca53e", "MeterName": "Premium P2 (Hours)", "MeterRates": { "0": 1.332 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8d2a775a-6ddf-4580-8624-454d3f0202af", "MeterName": "Compute Hours", "MeterRates": { "0": 0.349 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "71bc9bd2-f3ea-4000-a2ff-376882679d7f", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "13fe87e4-d8cc-4784-9d9e-e8118c4226a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.111 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "448910ee-8225-4229-9a8a-05dde0a6fca0", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0604 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "23d122e2-0644-48f8-a70e-f71b7b98edd0", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "41ec770f-e876-49a0-93c3-36e40a3dd5ee", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7da0841b-f922-47df-acaa-679e3a39e76c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.655 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cbcd1e79-2692-4583-846c-cdcaa6aa6434", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.37 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0f3b5c30-6a4b-4191-b458-d190d469e300", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "905ceb23-e257-4874-892d-ec1c838b700e", "MeterName": "Standard CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.17 }, "MeterRegion": "Zone 5", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9ccd463-483e-4015-83a1-e1d8c95ffb49", "MeterName": "Compute Hours", "MeterRates": { "0": 1.056 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "949ec34e-ecc2-4beb-b5a7-389f8bac1676", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.64 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "84e893c3-2017-4670-8318-6306c51a80b5", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1771 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "180c25fa-cb5b-457f-b36e-39c836d34041", "MeterName": "Compute Hours", "MeterRates": { "0": 1.045 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "545d87c2-378e-4e0d-9d41-ea1658989e8c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "01941ad2-4d1e-4220-b442-6e505439d6e6", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.605 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "106c81fb-cdb8-47b6-a86f-a0aacb54a4a5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.62 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6ae0a9ee-4296-4dad-accd-0d1ec728e647", "MeterName": "Compute Hours", "MeterRates": { "0": 0.885 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0eba5887-4f6c-4cb8-a8e1-49414b39bf10", "MeterName": "Compute Hours", "MeterRates": { "0": 9.348 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8a8a2353-a930-4fe3-908d-281460de46c7", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 12.39 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a2ee536f-15fb-44e0-b715-d10daa6ddd1c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.054 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f1e53737-9692-4964-a7a4-a6e26e54b799", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6e01d62a-da88-40f5-ade0-23ef4499943a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.043 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1f08ea90-9f5c-41bc-802f-c29345e0117e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "df0df156-acdc-47e3-8d79-929d220af5d6", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 406.4592 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d02d2dc6-1570-419a-afa6-5e612aa482b3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.157 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fb272fe6-d4bb-480a-9a88-ee04982015ad", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.017 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "df5c25c6-f90a-4552-bd77-0c75efd2b33e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "03d0ab9f-b3d2-42ca-bb70-26deadd2abef", "MeterName": "Standard S1 (Units)", "MeterRates": { "0": 5.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Speller APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "66e8e541-b48d-4c60-b99a-8df6249bb82c", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.11 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "fdff7af4-ec1b-4a52-b993-8753bfe93fbf", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7b758715-7f61-48d9-9fe0-1e31c9246dd6", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "33c6746a-bb9f-4e4e-8bc2-5d9f3a56c2e5", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0955908f-5ef7-4834-81c6-7469200c5bf3", "MeterName": "Compute Hours", "MeterRates": { "0": 2.833 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "678c97d2-8190-4709-9e1d-bd86c09609c7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.188 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5c571185-1fdd-42b3-8822-de52ae6dfc06", "MeterName": "Compute Hours", "MeterRates": { "0": 0.237 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f2a80d60-1f36-48ec-8273-9c157db056a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.701 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3b1fdb9-141f-4931-87d6-1554b679f744", "MeterName": "Compute Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "44dceff8-e4f8-479d-8856-e11f9ec935f5", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8b8e7b7d-a97f-4c8d-9b6e-4116d26ff8be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.144 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1663075d-941d-40c3-a4e8-fcc5c598d76a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "b5a7ec03-749d-4a89-9828-b3bba5952106", "MeterName": "S4 (Daily Units)", "MeterRates": { "0": 1451.612903 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c03e3bb9-5ac8-4dbe-bcd4-83f3872e1d89", "MeterName": "Compute Hours", "MeterRates": { "0": 1.112 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "38b060a8-faeb-421b-a0a8-4d36bd92c247", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "becb4c57-49ea-4296-8ac8-06ff09b74d68", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "706c1963-8782-41da-8812-d78c161f5691", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.0064 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9b9cf84c-d8d4-4762-9282-8215c6883c1c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "62915977-0761-4d93-8499-039b03fac17d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "f7a376ca-7efe-4275-b51a-782e6513a78c", "MeterName": "Basic C2 (Hours)", "MeterRates": { "0": 0.113 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ea4cfeeb-bb25-4814-91cb-5861450b4aaf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e10b7f57-6739-474e-9638-c926a5feb482", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c44e509d-63cf-4ee5-8ba2-ad5a6bd6061d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (20 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b0b01749-c39b-4275-b283-6a92aabc3347", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5c7a80d0-80f2-45f7-9135-4b4ac42adf49", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0264 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "3b233522-9380-4c78-9c83-8235bb7cde91", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "770f4652-d1f5-4e4d-9ef1-1ec3e32e0764", "MeterName": "Compute Hours", "MeterRates": { "0": 1.464 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a10d3e6e-5b1b-4327-82ee-cb26e31baa46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise and WebLogic Server Enterprise (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "633164c3-12c3-45a0-9444-529b57290c2f", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d37cd98b-3c44-41a2-9d44-a67f6a39916d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "211e620c-ebcf-4db5-a7fd-996abebe9546", "MeterName": "Standard IO - Block Blob Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2493e198-3750-445c-8e83-d9de68e8029d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bb3e836e-34e2-443d-8b86-57da6711bf6a", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 33.0 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b7afc61e-dca5-4508-bf1c-06ddad90d4c5", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.216 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5cbd5848-f3d9-428c-bdab-7c5898f9747e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "90d0cd4c-9b2d-4a3c-9724-17a9c8abecc1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "29d6e070-8e5a-41e4-b28c-6f07a6517c29", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "53f2de3e-7e5f-4ebd-a3ee-f27e6840820b", "MeterName": "Premium Metered Data - 200 Mbps", "MeterRates": { "0": 295.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "19f8f99b-4b46-4ddd-9170-1799c7d98fc1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "14c79d86-8286-44db-be28-c9700663ae76", "MeterName": "Compute Hours", "MeterRates": { "0": 2.46 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0b7fac43-29b2-42d9-8f3f-7c2e90fe4cb1", "MeterName": "Compute Hours", "MeterRates": { "0": 2.285 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "022f5d24-dd0d-4c36-bcfe-a84b47b3c624", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3227f584-efdf-4a26-9986-11abb2a697ea", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7ffe03d1-f85e-4f30-9e70-31fa54867e9f", "MeterName": "Compute Hours", "MeterRates": { "0": 4.674 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1ff2fada-4377-4b90-9e82-e0965834ba86", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.3 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ede94c8d-9206-4723-b5f5-f009180e76b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Mobile Services", "MeterId": "6a279f31-1940-461c-aa66-3fdc5ff5a7ab", "MeterName": "Free Mobile Services Units", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7c4f3ede-7154-42d5-8c7e-dfd28438c5fd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9837aab8-8100-4899-8d06-a2b0351e7e09", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "d8f22317-5495-4365-898d-96ca9e69f54d", "MeterName": "Standard C6 (Hours)", "MeterRates": { "0": 2.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "32bf0f8b-bde6-4dae-9dbb-3c465021ddbd", "MeterName": "Compute Hours", "MeterRates": { "0": 2.7 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A9 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d52d1cd4-2e3b-4d1f-931a-268b78b3efe0", "MeterName": "Compute Hours", "MeterRates": { "0": 2.337 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "489f0880-9116-47eb-a277-92415b62c745", "MeterName": "1TB Commitment Tier", "MeterRates": { "0": 1.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57ad7cc0-c01c-41a2-bfe7-ea719d486504", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "75f1a53d-f12c-4736-9929-0085905ea0a7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f9c45122-2ec1-432c-92d3-32d7bb5de82a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.043 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c7cf66fb-bcc3-4ee2-b81b-160bcf6c6a14", "MeterName": "Production API Transactions (in 1000s)", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5900b0ef-6505-4fe8-95cb-d88b11faa212", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "615e360d-a02a-4fc2-af18-ee807025ed92", "MeterName": "Compute Hours", "MeterRates": { "0": 0.665 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82c30cad-c273-4a07-873a-1445748bc461", "MeterName": "Compute Hours", "MeterRates": { "0": 1.546 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9be55b2d-be4f-4b0c-aaa4-30643ba62343", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3dc20704-fab8-428f-98a4-2c4bb6277cdb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.154 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c65bba28-567f-4734-94bc-6dca4657dc6a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.193 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f31037d2-678a-4472-9f84-d084817f69f4", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0044 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "31169b2e-0754-4a9a-9c21-7eefa5d26587", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e87225c1-1a84-444b-a91e-6da20e0575e7", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.082 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-01-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3aab774e-ef99-4094-a954-29705e79ee3c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM Low Priority (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "783a4bf8-d1f8-4097-b593-5d69d8ad37e8", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.0963 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b8fb85a2-4961-4827-98b2-890c56be88d1", "MeterName": "Compute Hours", "MeterRates": { "0": 5.84 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a9af19a-1b5f-40e4-8a8c-068bbe89d2be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.313 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "306cb42f-e8d5-4411-8c31-426f93b957ce", "MeterName": "Free (Hours)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2f7a7471-72e9-4eca-81c9-5160b6656887", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0297 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "034905f6-497d-4848-9c6b-3ade284c8228", "MeterName": "Compute Hours", "MeterRates": { "0": 0.798 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "19c6c2cc-5c6d-437b-a30b-261ab98c3496", "MeterName": "Compute Hours", "MeterRates": { "0": 1.46 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5c1464be-1950-4c5e-af62-b8295618e9a3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.469 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "464963b4-1859-4392-a8f3-ce94308dc123", "MeterName": "Compute Hours", "MeterRates": { "0": 0.743 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "98f47183-0440-4ff2-8f36-0b938980ce5d", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.216 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cf76581f-7183-44e7-9a6b-7bc960c8db59", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "675fb310-859d-48e8-b55d-4eb0574603da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.029 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e47edceb-cd50-47c1-934a-e45eeed1154a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.125 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3afc164f-5d1d-48b8-9a14-ce809bb6273d", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 383.404 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "941aafd7-7c87-486a-98fd-d07a560912ab", "MeterName": "Basic Small Azure App Service Hours", "MeterRates": { "0": 0.075 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7b627a0c-1db2-495c-b673-94b0d4c5724b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.399 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f815204e-3dcf-4981-925f-5d4be32d937d", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e5549196-b976-4655-91d9-4877960536b4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f8dec6b-293f-44b6-ab6c-c6fad81904a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c4a9fffc-3a1b-46db-839b-d6827a1132fe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "45f7e6f2-9dac-4065-a6b7-808c8bdcdf4a", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "36328267-ede6-44b1-89ed-ff5b8b617e9f", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.153 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb72028d-4adc-46f5-97aa-0f9b69c7444d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "528724dd-b8b5-44a8-9afe-5bfd499817ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bc2a0d0b-7dc9-44fa-86b7-5d537278b58a", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.21 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "36621ddf-4735-4e55-8e5f-4aff4bc4c5da", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "68767751-9341-457d-bc07-5ea592845630", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "829db521-5386-4636-8c73-3a201f3d2caa", "MeterName": "Compute Hours", "MeterRates": { "0": 1.68 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ad68bd08-de63-4661-9bb3-e0a97659e0eb", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "cd62efa3-2376-475e-bd53-2b5a3b6a1f86", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.376 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "986ad515-d734-4f1a-8d26-609e702b21b3", "MeterName": "Standard C2 (Hours)", "MeterRates": { "0": 0.281 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "875ad816-ee36-4d5c-93f2-0fc491f77f65", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "22abbd77-2f3c-4f5a-ab10-6a6e10d5aa77", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0a1aabbe-5b75-4b5f-8e78-546f81ecbe02", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2a8f5aeb-d518-4417-a262-f168e3204a84", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 120.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd0806e8-f939-4d62-ba85-d96af76c70eb", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f6522325-5263-4a7f-a8c3-0c0d127da4dd", "MeterName": "DWU", "MeterRates": { "0": 2.0565 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ac2eff34-302a-446c-95b1-e10b5ea3eb16", "MeterName": "Compute Hours", "MeterRates": { "0": 0.22 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ba492db8-6622-4b63-bfeb-2538f3118115", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d125d1b4-389b-4787-af60-ce24321c994e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.912 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "877caf6c-9e1b-4e84-ba14-b379c7ababa3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.068 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4446d13c-a367-4d53-9297-b6000bb40d34", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "854ead60-2964-42d7-ba40-03248e21fcb8", "MeterName": "Standard IO - Page Blob Write Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0bbff7cd-6ca0-4961-aff5-53a7cb57841a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.097 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "e3c2436b-90a4-4c13-846e-031e650ca09a", "MeterName": "Standard S4 (Units)", "MeterRates": { "0": 2700.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Search APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6a756189-bcca-4675-b175-7a1e5ed1a951", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "1328d5dd-6f02-4c37-a972-dc4232340f53", "MeterName": "Standard C4 (Hours)", "MeterRates": { "0": 0.656 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9ad17ce8-836c-4c58-99d0-f0b599aea449", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.052 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "8b9422d3-7c2d-4a16-8732-91eb7d1abdd7", "MeterName": "Premium P3 (Hours)", "MeterRates": { "0": 2.219 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5a75190a-483c-4740-a439-8ed28839e11e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.663 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e326f0f7-e9c7-4ece-8fb1-c85cd05021eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "16c0c4dc-bc13-43b4-a965-686543a0bb06", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "565e447d-3702-4ffa-b080-77140138b8e4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "41e1b0d2-1634-4e90-a79f-7faef1774ee9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.073 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Batch", "MeterId": "0870cd14-62d2-4763-8c44-6667ee8b6251", "MeterName": "General Purpose Batch Instance Compute Hours", "MeterRates": { "0": 0.0075 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Batch", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "af1945e6-29e7-4ce3-98ca-199c00ae71b8", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.161 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c294fc29-5f06-4c9b-8d61-f81c6de58279", "MeterName": "Compute Hours", "MeterRates": { "0": 0.408 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "689c2a0f-63a3-49e8-b8d5-e7bfac1fc877", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b2745f89-eb16-4c4f-808e-6c9d273b76ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4b1c71bf-a2aa-4113-8eb7-bcf182f3eae3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b2bed43e-c448-4cd6-91fc-6b020db334f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.399 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "35247363-1056-467d-ab3f-be92ae05cdae", "MeterName": "Compute Hours", "MeterRates": { "0": 0.68 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1571549f-953a-4e7d-9ff1-ef5de63be9d3", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.017 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce89cb38-e808-4965-b0fd-44a4a0b40edb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.029 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bcada5c7-4787-4fc3-b5c7-66e5822749d0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4edd8991-1e58-4854-ae70-0825bd0eda49", "MeterName": "Compute Hours", "MeterRates": { "0": 0.353 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "63918874-b2ec-4926-8f8c-4c404d384703", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "16ba31dd-3374-41ee-97af-6b525090a41e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Security Center", "MeterId": "3fb05390-ab59-4f14-a55f-2408834816bf", "MeterName": "Free Nodes", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Nodes" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5de9a315-9f6d-4b43-8cbe-4f6c569ddacf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard and Weblogic Server Standard (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d4f77ad-9332-447f-a378-ba55830b0cb8", "MeterName": "Compute Hours", "MeterRates": { "0": 2.276 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "243756a4-8935-4ed5-b7e2-9d3e84fc5f5d", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c504a18a-223c-4b53-a7db-a1e6ed43a5ac", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard and Weblogic Server Standard (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "69f20fda-55c3-4dfd-8dc9-7a2491df14ec", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "aa057281-ad43-433b-ad5e-1c64f49f2305", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 15.6 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e9661e43-c9ad-424c-a71f-a67c5723d072", "MeterName": "Compute Hours", "MeterRates": { "0": 0.61 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "37efc94d-87bb-4441-a90c-018de5a4adce", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "19f49805-f47d-4591-bf60-5c36e7aa6fef", "MeterName": "Compute Hours", "MeterRates": { "0": 1.296 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9d9f8202-39ba-45ac-bd74-fd6f190e88c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.611 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1da67640-b1b5-4870-90f6-2edc97713d61", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "6e31686e-caea-4b84-8f76-c121282ee710", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.708 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "691b7ea6-cb5d-4a1d-ac05-769d92c7b3ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.86 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "50a17455-380d-445e-b41e-483995164998", "MeterName": "10,000-AU-hours Commitment Tier", "MeterRates": { "0": 209.68 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2d5e0769-0c30-471d-a7fd-1031dd8beac5", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 12.375 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "67d6a019-8ef6-4aaf-95f6-bc722c3a264d", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.252 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "24c5cf90-d3e1-472e-a2f5-1d731a764d49", "MeterName": "Compute Hours", "MeterRates": { "0": 0.21 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "165847e6-ea7c-44d9-a5b5-49f0dd8517c0", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 374.99 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8e44e311-c7b1-41cd-a4be-33b6b267ceb3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "78e135cc-7730-4601-90e4-3b3a1d0cdb42", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.74 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a698923a-8fb0-4d81-b0d6-1a132960d773", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 80.54 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "308f1f90-6cda-4052-be7c-edf767865911", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 8.821 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cecffc94-889f-4475-b62f-9ec980c406f7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6904fce2-285e-4954-8304-267679241611", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2fe5009-4559-48d8-884a-0e1e6383d445", "MeterName": "Compute Hours", "MeterRates": { "0": 0.707 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3e9f7c8f-83a3-4d25-b76c-ce5e8050e2e6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.509 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "c9624bc0-64c0-4161-83da-d19aeb612193", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.288 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "OpenLogic (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f6030dbd-ecf8-4535-a6dd-bdcd32719b01", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b48f5fa0-bf89-484f-85d9-2f24af7f0a16", "MeterName": "Compute Hours", "MeterRates": { "0": 1.894 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ca5639dc-abfa-4d39-b44c-060115dad0dc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "39bb4c69-c2a8-401d-93a3-d84820c64d1b", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2c0f1caf-9489-42f4-b06b-589a573b99ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d8927b5-227d-4c9c-a866-79263328300c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.099 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "51cccd3e-d8da-4ce8-bc9d-79c8d5b74a26", "MeterName": "Compute Hours", "MeterRates": { "0": 1.22 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "69f4316b-dce1-4e6e-9fda-424f3fdb442e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "54929499-594e-464d-ae7a-620f1460c1bf", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5268c28f-bd7a-4c14-95c3-23508e887e08", "MeterName": "Compute Hours", "MeterRates": { "0": 0.42 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b571e7bd-d995-4c11-a953-b7bc14a00838", "MeterName": "Compute Hours", "MeterRates": { "0": 2.928 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1015c7e1-903e-49e0-84e8-fdac8d661272", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "52cda397-f889-4dad-a069-0d8be331a3ba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "45e4c563-10e3-43b4-a904-4c4f6334bc14", "MeterName": "MSFT Peering Metered Data 200 Mbps", "MeterRates": { "0": 145.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8e889735-ed7b-4237-83f9-af2fdfec4207", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b9de203c-1a3c-4221-ac18-81a0406dd5b6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.442 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a92705f3-7503-4019-b01c-7faf74660231", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 34.32 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7e8fffd5-6f1e-470f-bcf2-67f4e9782a20", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e2281ce8-9d24-4c66-bbc5-23691e23739e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7527f53d-bb6b-4f9a-81f1-04f4859b93e7", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "78ce6262-3e65-4a91-a221-69ce6f81258e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.133 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "de368bc8-e087-4656-b5e1-080d8e209efb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f42006e0-2f30-455a-961e-b675370c8be4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "10a91d0b-4e71-447e-9426-9de0791dc36c", "MeterName": "Compute Hours", "MeterRates": { "0": 3.271 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f8579873-2b77-4558-bd16-fff6e17df977", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 135.61 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7e266189-fb95-4615-af5b-126a00e78714", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Standard (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ef1ca3ad-d5b5-4953-a1f1-fa94a0d150f9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4cfddfa1-0272-45f1-a206-85eefd9e2524", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.034 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-03-12T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e22e4189-b955-473e-809b-466b82aa2296", "MeterName": "Compute Hours", "MeterRates": { "0": 1.28 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f3aa3d64-d8e2-47ae-a6de-e527ac26d856", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "33b7e428-9425-4c48-904c-893c3c53d7f4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5a559e39-54f3-4d68-bb80-376cc16e8153", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d283d23b-5487-4376-8ff0-fa1c11e8d81b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.912 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "54e35db8-e5c4-479e-98e4-78733b5156cb", "MeterName": "Compute Hours", "MeterRates": { "0": 1.81 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "8d6ce3f1-3782-4ba4-b128-4b10654b345d", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "af8fb567-03c7-40c2-a169-d59256341eff", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.026 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "edc0c2dd-4576-4278-8782-a4babcbeab89", "MeterName": "Compute Hours", "MeterRates": { "0": 0.937 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b4eea7a7-fb21-4ebf-bec2-a294a98bbf5a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.087 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3f826cbc-f4c8-4cf6-9094-6c00964552c5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.749 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "981a12bc-2bbd-421d-bfe0-23661de69956", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "de1f6405-aa90-4728-bce3-86db59c25e69", "MeterName": "Compute Hours", "MeterRates": { "0": 0.875 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "21aee331-33c9-4b08-ae23-1f1dc2512296", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.163 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "02cdef9d-9289-40b3-aca8-15c7ffa905d4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.61 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4f48803a-f781-4d04-b644-a272ff8d68de", "MeterName": "Compute Hours", "MeterRates": { "0": 0.196 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a04a48b2-1abc-455f-afa1-aa337b1f215a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c929623c-629e-46e0-94fe-94852b021477", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2212a17c-20de-4e7a-8544-a91e80961231", "MeterName": "Compute Hours", "MeterRates": { "0": 0.056 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "46bdf0f3-5a8d-47c5-89c0-45defaa6248c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.474 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b5655643-0b84-4f0f-a813-0873d9a889e6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Xbox LIVE Game Services", "MeterId": "875c1038-f568-446c-8e44-a7a60dc4deb3", "MeterName": "Data Transfer Out (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "872e99f3-75c3-464f-b307-7a0f2e163758", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7773e37e-6883-47ab-acf3-33cfad7cb56b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.226 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "86b5b0b4-3c19-4720-82e9-874f8c58b48e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ca4422fb-2d41-4004-81ce-6ecc99f75a18", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b8e5192e-e4a3-4933-913d-ba45913af932", "MeterName": "Premium P13 Secondary Active Geo Database Days", "MeterRates": { "0": 335.48 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "5c33b840-166c-4ef2-a2d9-49fa9f9d456f", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A10 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Automation and Control", "MeterId": "6d63a798-4f02-45b7-9a47-6b4c2ff43585", "MeterName": "Paid Nodes (Node)", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "OMS Automation and Control", "MeterTags": [], "Unit": "1 Node" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 5.0, "MeterCategory": "Service Bus", "MeterId": "0d6714cd-bc0a-4511-9f39-37c5e91004bf", "MeterName": "Data Transfer", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Hybrid Connections", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc9f027c-f62d-4dd1-8241-068bd095dadb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "51261d37-962a-4519-98da-5d83f5e7ef34", "MeterName": "Premium Unlimited Data - 10 Gbps", "MeterRates": { "0": 85000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d0b97e12-383c-42a5-8250-8ba7b82815c3", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "f180ce13-b916-435a-b4c9-eb4388c43326", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e42c7901-ffbc-4c71-b5aa-e1244f6c12ec", "MeterName": "Compute Hours", "MeterRates": { "0": 1.097 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "49cc01ae-30f5-4ae1-8744-8bf8a854826d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.038 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4ebbc07c-5da8-401e-b8e1-6e26480ff76e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.138 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "09592c73-5c6f-44cd-b9be-c51f0e0271ac", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "02adc04a-ffe6-47be-96da-a572cbaa7eed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2a689b43-a7b6-4a65-8656-8e3c6c4420a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "37c72241-b376-41b8-9272-a4247e09e9c6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5bfa21e1-78d2-4965-b290-f76c652b0709", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "238b96fb-076b-4706-a7d1-d4d95928fb06", "MeterName": "Compute Hours", "MeterRates": { "0": 0.145 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9f1d9ff8-fff6-428d-9762-22d61aaa4bce", "MeterName": "Standard IO - Page Blob Write Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "df71375a-2306-4c01-9469-2a15a2c69619", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2e60d458-756e-41a6-8747-8b3f7eff2c62", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "134ac923-dbb1-47dd-9609-7c2a72013248", "MeterName": "S3 (Units)", "MeterRates": { "0": 8000.0 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3184ad7a-bed8-4f16-8a69-3a7d27bddbe2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.748 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "61ed2dd3-1337-44d5-a6bc-4d28fda02374", "MeterName": "Compute Hours", "MeterRates": { "0": 0.073 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "593d1a2a-2304-495d-b16a-d9e3ed0d01ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3e4d46c5-a424-408f-a0f0-179d99f47ab6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle WebLogic Server Enterprise (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cac16264-cc98-4298-ad94-1627a4d4e937", "MeterName": "Compute Hours", "MeterRates": { "0": 0.169 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7295c70f-0ce0-4b8e-8c2c-3a459bcd6078", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fb10b00e-2d64-465c-a6c1-91bad8ba7a45", "MeterName": "Compute Hours", "MeterRates": { "0": 0.639 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6a99015c-d33f-4f46-ae59-2e4d14091aa8", "MeterName": "Standard IO - File Protocol Operation Units (in 10,000s)", "MeterRates": { "0": 0.0015 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "adae4dad-1bcb-4bab-b3c5-902835c189ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.106 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b35b5025-28c3-483b-b2e4-66c604cf65b9", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "affdd639-678e-40b8-8b49-496596db82d9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5b78f2d3-3c78-4333-b6a8-7e2233433a0b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d129fa86-7cb2-403b-97e5-33cd4756ddd2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.42 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "89d865e9-61c5-4106-8b61-5043a370fe7f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc038b0d-fe0c-4f37-830e-124f7dd098c9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b9d5bd75-bbbb-44a8-bb5f-27253a42c04b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.242 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A10 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3292ab2d-0267-4e48-8941-6b8a8ba70fb6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.65 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1433d549-c4c3-4870-80f7-be531cca57a9", "MeterName": "Overage Unit Hours", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dcea4d56-21fa-4d36-841c-ce3ad281986d", "MeterName": "Compute Hours", "MeterRates": { "0": 11.1 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7b98b4fb-c447-40ec-bf3f-bf2413724dd1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "870bcbb1-48c9-49ec-9afb-5bc7ebc8cbcb", "MeterName": "Compute Hours", "MeterRates": { "0": 2.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (24 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2b6e2b70-6282-4faa-8e96-8318e157c7e7", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.0088 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "548022e1-db63-4868-a666-a201e0101e52", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 50000.0, "MeterCategory": "Identity", "MeterId": "9bc249d6-7af9-4237-bd4d-251c324f9e51", "MeterName": "Basic Authentications", "MeterRates": { "0": 0.0028 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Active Directory B2C", "MeterTags": [], "Unit": "Authentications" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e2650bb4-bcfb-4a70-a956-d8e060e3810f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "694c093f-6d19-478e-bbf8-f216b85cff32", "MeterName": "Compute Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "21d8965b-6c10-4f7b-b091-87509f1ab7ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e880f6b6-82de-479c-a51a-29fbe9b1b906", "MeterName": "Compute Hours", "MeterRates": { "0": 0.808 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "740bac0f-0db5-4b89-b8af-270bacc2c8da", "MeterName": "Inter VNET Data Transfer Out (GB)", "MeterRates": { "0": 0.035 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5aa1a995-b25f-43f7-8b28-3d6fc75676b3", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3b70e521-317b-47a1-a42e-86f9561773d1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ef5d838f-bed0-4e72-8fb2-ec32d6a715f1", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "831d2949-4078-4ea9-addc-713e2b19229e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.246 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2672a5f1-fcc3-4449-9d56-5ec7453312bb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.488 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0f27f4a9-457b-4c6b-acf7-6df344baa25f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.133 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ee78da9c-8d8f-4cba-a0ab-c80c01112439", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.201 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c90b8f68-2874-44d0-b237-bae9dc89c4a6", "MeterName": "Standard Managed Disk/S4 (Units)", "MeterRates": { "0": 0.845 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0d41ec57-1343-4db7-a767-8fbf10732e0d", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 282.263 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d16382c4-5224-4902-ba23-285406f4f86a", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "da36fb87-578c-4452-b575-af4aa66cca50", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6ad6e8e9-d9e1-4a76-b6b1-de3f67f4055d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.126 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "52805b9b-5d2d-46e3-a8f9-36ca8191d4bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "577590c2-9ff2-4226-95e1-3cfbe3bb876c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.705 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c1c33d95-5343-4aa1-bddb-cda66850d07a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.112 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "80d2459f-0e26-46c7-9d9a-28f65543951a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.752 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03da3a30-7d9b-4a97-a2cd-bdd130811d16", "MeterName": "Compute Hours", "MeterRates": { "0": 0.547 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a8e5826f-0b33-4241-8ceb-6e94e10994bf", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a95d15d5-c22c-4aa4-b576-db9219511f55", "MeterName": "Compute Hours", "MeterRates": { "0": 1.926 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1b8ca1b2-f159-484a-af5a-a2c40b7f8e87", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.0645 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "09b8662f-bc53-480a-827f-2ae6a9f637a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.593 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "048b1881-e3ab-4325-9e2b-b754401c2636", "MeterName": "Compute Hours", "MeterRates": { "0": 2.933 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1dd33da8-e927-4f68-bdaf-3aac8c2be2af", "MeterName": "Compute Hours", "MeterRates": { "0": 0.246 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0316ed20-88c9-4ca5-8168-4f4050f00995", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e9335837-382b-41ef-8f40-e5453c6923e9", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 135.6 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "736d4e73-38cd-44dc-8208-d7de20671a12", "MeterName": "Compute Hours", "MeterRates": { "0": 6.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (16 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6460fee7-8d53-4faa-89fb-4b3838edf3c3", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.082 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f95ee4fd-f655-42b1-9e24-a465a67fd1c8", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "64c30011-6bf8-4e07-9baa-17b63bb28eeb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.444 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "10b97fb2-5db4-4ad2-a4e0-69b858d6b52d", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b03000d4-bc4c-41e8-ba67-76ddf8628e53", "MeterName": "Compute Hours", "MeterRates": { "0": 1.25 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "G1 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f8119c58-2895-438a-96fd-cdbea940d4d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9a54f10d-e244-4dfd-b582-41d3f400eb31", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "eccaf38d-9f1c-43b7-97b6-2d91b2ea70e2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "27a1a289-da6a-42b5-88e1-814b002f8f19", "MeterName": "Compute Hours", "MeterRates": { "0": 9.99 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "23590be0-0f19-48f8-93f7-7090bd160f50", "MeterName": "Compute Hours", "MeterRates": { "0": 0.794 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3e41f77f-2d9e-4c49-bede-43c0fec13dba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.749 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6153d9f9-4fdc-4234-8add-459c8b05ba84", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "72ce177b-8b79-4bc6-82a4-c914e7de18ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.65 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "48284f63-9f0a-4eb5-aeb1-7e4c3594e366", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "23a287ff-d9c2-47b9-bbe9-16919a975c19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7e419ac4-8d7b-468a-9f14-4da5289d7770", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "be4ec9be-31bb-4de4-acc0-599e89eef9b9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "64a56cb6-0da6-48e0-849e-934c45fdde83", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "913f67d4-3439-4de9-8016-bcb4ecf399b7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.692 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a3993af2-fbc8-4106-a255-8e61cf37c106", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5f0c87bb-98c1-4660-983f-7fa94f81a20a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.563 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cdb7f481-a416-412c-870c-eec3869f60c4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.133 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "295de551-a288-4246-accf-713c452b97cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.104 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9be411a9-d884-4ee7-92b5-2e6a177b47c7", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e872122a-c8e4-40c9-bb60-1a862ada23a8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.114 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1f31ccc7-9360-47ec-983b-f4c7e8787aaf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e5b4772e-90c2-44e5-b2cc-85e4cf890f75", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "39f6bb2f-c05d-486d-85c2-7235c902aa68", "MeterName": "Compute Hours", "MeterRates": { "0": 0.394 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7d7bff9c-fee9-47e6-82e4-544eaf328034", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 50.94 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e9af043a-39d8-4d66-8d04-f4071430fd7d", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bd868b15-d9b5-454e-9d4c-63ec3e409f1a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ed336fb3-a538-43c0-bb46-cefa2ad53b8e", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.032 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "906f5413-d2cd-4035-b54d-6f2622d5a0be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "97ecb465-b05a-49b3-8c72-b0455788b7ca", "MeterName": "Compute Hours", "MeterRates": { "0": 9.658 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bb5b2483-4a4c-46df-a145-b1a4b13fb74c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A10 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f03ee233-e99b-4f12-be9a-b35636be9b41", "MeterName": "Compute Hours", "MeterRates": { "0": 0.592 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5698535c-5b69-4896-ba4c-32eb98733f7f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "bb1e4357-53f2-4a98-9f16-38b08759c3a6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.822 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3da3a020-24fd-409a-a2c9-1a87bedfc2d7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9c0616f2-f092-420c-acbe-75b6bc890c44", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "002c6284-d241-46ab-8f7e-b4c4a1b91622", "MeterName": "Compute Hours", "MeterRates": { "0": 1.134 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4abb5b37-7a0a-43cc-98e1-85440f44beb9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0d505678-5a12-46fb-88cd-d37f76c6b63a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.186 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "143ad8b8-6d8b-433d-9cf2-7dc7b5c90c71", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fb4fd05e-9a05-4288-ba9e-23b4438548de", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A10 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0c09b186-a40f-4f4e-846a-da0b8b1b3802", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 567.7408 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4ef05524-d3be-4819-b1c0-14b58cc74760", "MeterName": "Compute Hours", "MeterRates": { "0": 0.625 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "18340836-d5ad-46ff-8474-024af00cfecd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.983 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "96788af6-5916-4792-9a5d-9186ec2556bf", "MeterName": "AES Keys (in 100s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "100 Keys" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "846a8779-1ec8-48bb-acaa-d75d065d985a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8846dcaf-15c3-45cb-ad42-77542ca68b50", "MeterName": "Compute Hours", "MeterRates": { "0": 0.973 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8663c2cb-f022-4a88-8c54-559ecbbfc6e9", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 75.0 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3e470f60-a266-40e2-b9ec-26df83a15b28", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a5ae723f-71ad-4eed-a5b7-935361657e9d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6fab8858-5671-40ce-ab97-260c6ad9b994", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a5cf8844-b8f9-489a-b6df-983a4bab1086", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "21d907f2-ec6c-453a-a323-fae5c59fa48b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.759 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5f20fd9a-0f9c-45ad-b70d-9b768ad6134d", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.832 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "085f851d-315a-484b-b960-00a177f25c8e", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "a297e6d5-2ab7-4ed6-ae88-401af0d46918", "MeterName": "Widevine Licenses (in 100s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "100 Licenses" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9965db18-3744-430d-817d-28b9ff3f7b47", "MeterName": "Compute Hours", "MeterRates": { "0": 0.975 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "94580fa9-720a-4c3b-8c86-8a3cd4ad4719", "MeterName": "Compute Hours", "MeterRates": { "0": 0.311 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "538045a5-7281-477c-b20d-112f92954a07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "014a710e-54b6-44a9-b0b7-184f825e3544", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c5d14af5-ec9d-466c-b6a6-0e0a33ececf7", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.033 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "84e34020-353a-4723-85bb-8b2404107eef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.337 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4cb019c8-a86f-4212-8c16-a034faeb2934", "MeterName": "Compute Hours", "MeterRates": { "0": 0.255 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1e773d6e-1761-469b-a600-259c32d0f51d", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.0792 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fa2317a8-0dcf-483a-867c-85deea7032a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.672 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9b075707-7e5a-4450-b506-30e0af826555", "MeterName": "Compute Hours", "MeterRates": { "0": 1.144 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "dff42d4a-951b-411e-8e53-a84cf76709f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.781 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "524af1ac-c01d-483f-aa42-01263bdd19ef", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6f659498-ae97-46d8-b7c9-cc09a65747ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.483 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "dc1a0775-d032-4115-bfb2-289fd833949c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.175 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "50861a83-2ad2-4e0d-9871-41d712cebb37", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "174204f5-c929-422a-a36f-e82a07399940", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "05d8cdf9-3a31-49a1-aa63-fe4d01c686dd", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.061 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "63058f66-9e9d-4c24-9d4f-3fb6078c734b", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b222e90d-2ab5-49a8-a74e-5d505474dc8e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.77 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "383eaccc-acd9-49c5-b78d-47aa1ddfe114", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.41 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a25b9738-c7eb-4208-a8d9-91753f40bcdf", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8ddc1c2b-9d6b-4dba-b486-ddb2939b9887", "MeterName": "Compute Hours", "MeterRates": { "0": 1.121 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "21552936-235a-4ad8-979b-69f6412e2843", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fdbd06df-4e9f-4ddd-8611-46d12e773525", "MeterName": "Compute Hours", "MeterRates": { "0": 1.112 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60eacc21-c03e-4501-bc2a-bcdf228f60b1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.42 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "efdb48e1-6e65-4d8a-ba65-f7b6a04d05ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.128 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2027a817-1028-4985-b30e-1f3a04930416", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.14 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d01174fe-3968-46a4-b62a-572550530e33", "MeterName": "DWU", "MeterRates": { "0": 1.6633 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7672c3e1-4e2a-415a-a316-44697ba494af", "MeterName": "Compute Hours", "MeterRates": { "0": 0.259 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "adc4e0b6-6550-4fc7-a589-6515af9c59a4", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 211.7 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2ecc7597-9a40-4311-a91e-1930499aa6c6", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0548 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c222aaad-992b-41a6-bb37-237606580565", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "40aeba39-7196-4aab-aaa2-343f077fdb56", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "08e97539-3734-498f-8e1f-e6c00ad4f227", "MeterName": "Compute Hours", "MeterRates": { "0": 4.674 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1596304b-01c1-48d5-866d-b1e67d5244c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d18954a2-31b7-4582-ba7b-fd469a9e9817", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 16.52 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a1bfe8eb-1e3e-48d1-bc14-5ecdf0c54d86", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "358f3f9b-bb36-471e-987f-27147df67fc1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0fb708ff-6638-4d65-a800-9f26a96e3752", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0832 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b1f3c5d7-5a7e-4494-ba42-99956c93a282", "MeterName": "Compute Hours", "MeterRates": { "0": 0.376 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c897153d-45d0-41f7-956b-e16d8a04ab57", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "33427e34-0748-4bde-9328-23bf3338af87", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.228 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "14e91b79-e419-4a30-9eed-daedf7b5b35c", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 496.7732 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e019d2d7-395f-489f-944d-75297c8eaf22", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "97fa1a94-4e78-4580-9e27-f9878c4b7c83", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "3c5657c6-28c7-49f0-9456-9a165161954d", "MeterName": "Operations (in 1,000,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Messaging", "MeterTags": [], "Unit": "1,000,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "198586a6-04e3-4da8-ac62-f9b84fa99939", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "83d33c69-c5d3-4f47-97e1-d8ce13a17c07", "MeterName": "Compute Hours", "MeterRates": { "0": 2.138 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "61bf355f-0d08-480b-afcf-2d6e81777e15", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "91d88291-dc9a-46a3-80fd-2bec367aaaeb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "121219c8-4963-475a-b861-2cfe6667b9c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.306 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "117e8907-889c-4ccd-b1f8-b708a3070b39", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.063 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "88deeec2-3f99-482b-b75c-6b6b445ed886", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.114 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "2a402785-cf3c-4911-aba4-1e280a892d96", "MeterName": "Metered Data - 2 Gbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b92dc7a2-b467-4b5c-b880-6776416d7a4b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.258 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b72c99cc-65a6-4e96-9ade-88af0d90fec9", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 516.128 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d8a60e9-c822-4356-bc42-018d1dc6c893", "MeterName": "Compute Hours", "MeterRates": { "0": 3.73 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV12 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "66f5ed1b-089b-446f-ac52-2c165223b0e3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.6 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d495dd96-e6f1-4c88-948b-75ed69280435", "MeterName": "Compute Hours", "MeterRates": { "0": 1.013 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f7499985-5b63-483a-87c1-e9659afc1727", "MeterName": "Compute Hours", "MeterRates": { "0": 0.384 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2d4e4a27-738b-4f18-a7e3-cff7f4320aa1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "308cc02a-5f6f-46cf-837e-a91c35cac45e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.853 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "642ae1de-9bbb-4519-800f-5c59776d7c88", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c5a6ddb8-eb3f-4e42-883e-d2f48880ca14", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b167c343-39bf-43ec-90a6-e4e1b294c173", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.0177 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0cec7211-b92c-4bb6-9006-970f578871fe", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.084 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a8083fe0-a4b7-472f-a622-1b6abb1d7dd5", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0b8d746a-034b-42bc-affa-4cc1cf11bed1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "15e65e45-c594-44d2-8e6b-daceac905e80", "MeterName": "Compute Hours", "MeterRates": { "0": 0.405 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c7d94231-9fb9-4958-9ec1-b37b2849cd62", "MeterName": "Compute Hours", "MeterRates": { "0": 0.698 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e9573bfe-82a6-4e23-b5f9-f1f8d7c715cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.103 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1cc42fd4-699b-4ae6-841f-c7d3501465cd", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.74 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3e510eca-ac9b-4d5c-a470-e6ac215a4252", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bcd933e5-a830-4eb2-8b16-17f996003680", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "acca85ae-a728-4db8-bdf5-713548957bf2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.262 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2dc65bfe-ea3a-4783-b51a-a6503c7a9559", "MeterName": "Compute Hours", "MeterRates": { "0": 2.673 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2be0c8a0-cecb-4601-bf05-5bad3b63d132", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.2 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "15b7ec1e-eae4-414c-bf11-a9f1dc094fd0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.886 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c2d0eb2a-4dce-4a55-abc5-1222c87f8e35", "MeterName": "Compute Hours", "MeterRates": { "0": 0.106 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "d23b222d-e065-4aa9-8d5e-8c3990b4b0f7", "MeterName": "Standard C0 (Hours)", "MeterRates": { "0": 0.055 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "4e8eeba2-1991-4d33-b101-b5cb1a18673e", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e41c0dc6-9337-49a0-88a8-68df68c0b6b5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "01caecf8-c1e4-4885-8c13-3292721482fe", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.0915 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a07aea46-15ab-4d22-86b4-0f4e31417117", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 56.25 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1dd5c10b-82db-4ea7-9000-3385738203dd", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2696 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-05-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6fe6a770-9d2b-45ba-b76d-1b18c4b6eebf", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e2760555-159e-4844-8e0b-2a8128a0b612", "MeterName": "Compute Hours", "MeterRates": { "0": 2.496 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "434308ca-da80-4c33-be2f-df5973a85f91", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "84a3863f-955f-410f-8f0a-eee53a49143b", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.5033 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ea4a8814-d834-4c27-8962-e515d6a14bfd", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c3f95eed-a26b-4411-86a7-48e3c1b9133c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0734f87d-a262-4386-b4b0-e3bf1e5637ed", "MeterName": "Premium Metered Data - 100 Mbps", "MeterRates": { "0": 275.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fc0cbc14-ecd8-4f56-9483-5c15eeb54599", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72d57d4e-5857-4844-9ecd-b55f0cbceb3e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.242 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8d15c793-e4d4-4d94-a3e5-a51356c8cdb5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.226 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5706c62a-a842-422c-ae83-ade4cb723f3c", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 7.9839 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "be6da937-39de-4de2-a735-d6b63d5d64b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ff39f4c3-d935-460c-a1a4-a4937d202bb3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.645 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "7e32ad83-9839-46c5-9d90-19399bbab832", "MeterName": "Premium Unlimited Data - 1 Gbps", "MeterRates": { "0": 6450.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "65bd8e92-a37b-4f4b-8541-a2d8d60d3463", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "96c7a88b-71a2-4617-9824-9344fc9864d3", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.129 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1630dbad-d46a-448f-93e4-99e6c011b603", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 36.29 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a902daa7-3449-49d0-8299-1f28c6476ea6", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "c0f5cb45-6fb1-41c9-8545-72ad400d9da4", "MeterName": "Free App Service", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Apps" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d100befb-3816-47b2-9685-748deaa8cf9b", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "168dc3e1-2c1a-40c6-85b7-a0473ad5801a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a4daffb4-96f4-4fc5-b1e6-fd3a2cf3595e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (12 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5221381a-b229-41f9-98c0-11021a3227b0", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.544 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4e24103-a699-428a-9292-e0ec5e5954a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.043 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ffda6d02-d461-4844-85a8-c621f7cdeed2", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.375 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "41149d9f-a473-4349-94f5-3af6b2aba106", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.034 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c69eb35-4958-4c6b-b4cc-00e32199ac13", "MeterName": "Compute Hours", "MeterRates": { "0": 1.5 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b2482850-4201-4948-a0b6-c60a0cb5ea6b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.182 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "555f9d0b-d8ee-495a-8095-d849adfb9185", "MeterName": "Compute Hours", "MeterRates": { "0": 2.236 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "239dcfa7-e1e8-4ee4-bbd7-d91febf6fb9e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "9e48e5f3-a682-40fc-8d8b-dea08257d3df", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "a281365b-db97-4025-aa0f-380b14d98384", "MeterName": "Standard Medium Azure App Service Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1a5fcde5-b828-423d-b1f1-1ce5f358d119", "MeterName": "Compute Hours", "MeterRates": { "0": 0.648 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5b056dd5-4e11-4b04-8f7c-c8f0534823bc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "be54b003-d5e2-42ed-b929-df343b52a725", "MeterName": "Compute Hours", "MeterRates": { "0": 1.835 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a4744286-09f0-412f-8f7a-003cd4ed1d65", "MeterName": "Compute Hours", "MeterRates": { "0": 0.376 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "96257250-5558-41bc-8eba-66a40939d305", "MeterName": "Compute Hours", "MeterRates": { "0": 0.77 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3e44fa2a-dd0e-4e61-86a3-ba9a36e19b46", "MeterName": "MSFT Peering Metered Data 500 Mbps", "MeterRates": { "0": 290.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "28c5033d-2d97-4349-8d32-c24d40c764c2", "MeterName": "100-AU-hours Commitment Tier", "MeterRates": { "0": 3.23 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f761c02f-1767-4b3c-b1d2-accf33c0c332", "MeterName": "Compute Hours", "MeterRates": { "0": 5.36 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c12cb4fa-c6cf-4972-98c0-eb65115d669d", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c90d9636-9fe2-415a-abe1-4456bbbc84fb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7733ea4d-4f23-4211-87b2-54eccc99bb78", "MeterName": "Compute Hours", "MeterRates": { "0": 0.308 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "05c21a8b-3f84-4579-b799-f9fc9d23d6d8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.242 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "be895fd9-7157-4093-b027-14505c1d23ae", "MeterName": "Standard C5 (Hours)", "MeterRates": { "0": 1.313 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ea929c1a-ac3a-428a-be0a-b1eb8bef107d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.063 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2d7c9447-657f-4d93-8c0e-216b04860f70", "MeterName": "Compute Hours", "MeterRates": { "0": 3.218 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "134280bc-d982-423a-9061-bc3c289c5d6d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.459 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "34b1ff9d-ff18-4e62-af3f-9c63b26a4978", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.18 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "b4984cd1-6af5-414d-825e-73950591bf9e", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.972 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A11 OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "077a07bb-20f8-4bc6-b596-ab7211a1e247", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "15e0681c-188b-4c94-af53-1edfd1eae0e1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0984b7ed-975f-4dd1-8ba1-db05b74796d1", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "159d10d0-844e-470c-906d-3b4a394f1049", "MeterName": "Compute Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9743abf5-55ee-432f-8799-60d975d11121", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9c85e76a-3fd7-41b2-af8e-7b1586822481", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2b5301db-cace-4548-89e2-321c35a3f796", "MeterName": "Compute Hours", "MeterRates": { "0": 0.229 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f0076a96-54c4-4254-9a42-a56fa2c086f5", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 22.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "af3fdf26-861d-46c2-aab5-c9c5c05dc4de", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8f80e861-a0df-4ab9-8218-876cedc26e48", "MeterName": "Compute Hours", "MeterRates": { "0": 0.11 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d2bf5530-dfa6-4ea1-bfd7-0c889b9ba21d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8d5c083a-5e43-44e2-80a8-6856e81ff10e", "MeterName": "Standard Managed Disk/S6 (Units)", "MeterRates": { "0": 1.654 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7fee4018-c73d-4765-9c46-98b2b9b57b16", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "69dc9346-92fd-4e55-9a0b-a1139cc02b36", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e5d42d36-8381-46bf-8889-e98c2d385ceb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "9fded82f-7574-47b6-bd46-36f4e55056f8", "MeterName": "Metered Data - 2 Gbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7bb740ef-1460-4ff7-b26e-57e98218dbe9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1ad63626-a5cb-4a61-8bb6-d80c6876a9fa", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 79.872 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b13e0e9-cb9a-4e48-8974-afc03809b962", "MeterName": "Compute Hours", "MeterRates": { "0": 0.47 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e937e543-36e1-4de5-ab64-b13d76e327a2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "741080b5-e0d6-4058-b620-1f103917aa97", "MeterName": "Premium P2 (Hours)", "MeterRates": { "0": 1.443 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "61dca758-9105-47c8-8050-bc2ea5c3fcfd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "569cb4a6-dde3-404a-9804-4f2db0e14efb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.367 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ae64446c-5ad8-45da-9a2e-703b0e9abc79", "MeterName": "Standard IO - Block Blob Read Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "06f0e2d5-bf8c-42a1-986b-4d189002b46f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.983 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "768ff130-a8a1-49c1-9506-fe3fe5b29051", "MeterName": "Compute Hours", "MeterRates": { "0": 1.133 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3389f896-417e-4b75-888f-c5717b16b243", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "78d803eb-52b2-49d2-8534-c83303d4c453", "MeterName": "Compute Hours", "MeterRates": { "0": 2.44 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2796765e-d53f-48b6-8063-6f24447691a4", "MeterName": "Compute Hours", "MeterRates": { "0": 3.411 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "574e8c3f-fa18-48b8-86fd-50a9fcdf4b7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.054 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9aade493-c427-498b-80f5-0724884166d5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.033 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "95cd9c70-2d61-44f3-8009-b8b103fd6ee0", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.4015 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c2a5715f-92e4-497b-82be-b0d33637120c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c9a3f676-a75f-4a65-8012-e18768039266", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d9ea495b-75bb-4b2a-9b75-c7072dffb6ad", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "583846fb-f6ea-4ed0-9601-48dd7bdce01f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.472 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "47c22427-4176-4a1f-834e-1e062eade4f7", "MeterName": "Compute Hours", "MeterRates": { "0": 2.124 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "27e1d670-07ab-4014-991a-3bb50adb6d16", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ca2f5a23-f9d4-4a12-999a-0dd86fad57e3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.274 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f5f7cd8f-cfc5-40ee-9970-a9515f652425", "MeterName": "Compute Hours", "MeterRates": { "0": 2.814 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "323823a5-e988-4bc7-bc02-825f6233e436", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a738f35b-9373-4cee-91bb-3764a8201379", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "59cf60a0-cb53-48da-b6f7-d3cb4ed87779", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7dafb37e-6cf2-4481-8eb9-468e9e1840aa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "734ac188-22a2-4c03-a35f-2ebc69b61280", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.039 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "de2d6833-d369-49f6-a263-2adcbe2549ef", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c06c1695-162f-4b0e-a950-b56b7a1ff6f9", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.138 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "43ce52fb-323c-443c-bda1-ca24113c3b87", "MeterName": "Compute Hours", "MeterRates": { "0": 0.68 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0e7f9c94-e2de-437a-a374-3ad985215387", "MeterName": "Data Transfer Out - Unlimited Data (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2e89da8d-729f-41ff-b28d-abe561d747aa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A10 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "11a97f50-b7c6-4c2e-a617-853d0b594647", "MeterName": "Compute Hours", "MeterRates": { "0": 9.658 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5cf34f06-1790-410d-a40d-1586dca9f1e1", "MeterName": "100TB Commitment Tier", "MeterRates": { "0": 93.55 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8be390a3-b121-4937-bc0c-67776102ae5d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a266977-c0fd-4f65-b138-2375d3231248", "MeterName": "Compute Hours", "MeterRates": { "0": 0.316 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a0e7e224-c315-436c-a320-b862cf9641fa", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0b128542-39e8-4f73-ac2a-6c1d6e69625f", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.0805 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d89ce0e0-2209-4c6f-a952-0f3015606cec", "MeterName": "500TB Commitment Tier", "MeterRates": { "0": 429.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7b64c567-6767-41cc-b347-fb9f85343ee2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7aa45772-2ce3-4dd7-8f2f-55cde9ac8480", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8fa458b8-de14-45a5-bc69-e556412015ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.696 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "767660fa-525b-436f-a375-6da3e26f09b2", "MeterName": "Standard IO - File Delete Operation Units (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "459cc554-f5f1-4d51-b810-f506bcd35748", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "f0692ab1-0969-4614-90af-14c91e4d9705", "MeterName": "Basic C6 (Hours)", "MeterRates": { "0": 1.05 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "639b92f4-c4ea-4035-8e67-ecf6870e978d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.496 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9473e672-e6f2-4497-b457-93896fd1102e", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "b20c6a61-1eac-4ff5-a34f-50ba04d641a1", "MeterName": "Standard S2 (Units)", "MeterRates": { "0": 30.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Search APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6df0c453-cd7d-409a-92d1-6545c6718a34", "MeterName": "Compute Hours", "MeterRates": { "0": 2.933 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A9 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fcb7241e-f62f-4386-9a24-08ac0023fc26", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "49d4804e-2cc3-47c9-bf9e-4094875708b5", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.82 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e30c1c9a-5d8e-4990-a8f4-83643df9244f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.99 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24r VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6ebf8342-920e-45aa-9565-ba15ffd14593", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bcdeb9dc-975a-4cba-9921-f542c87d76c7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.178 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e3c4a934-9ce7-40a6-9a6b-4e1e8ca6bd98", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3eb5171c-9adb-4ae3-9ef8-b52c410afff3", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0455 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7befd184-6789-4a2b-aa79-644ba65c3a19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.079 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "eb0aaca4-70df-40c0-a1d6-ceddd8acb215", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 33.9 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4bc56657-fc3b-4194-bb8e-d23e26b81d7d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4848a06a-fff1-4e43-b803-e19e16af6698", "MeterName": "Compute Hours", "MeterRates": { "0": 0.435 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f6e37af5-c02f-4db4-a45c-937a00a576dd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5e94f338-64d3-499c-b11a-9e184f6cb2e3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.77 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a1a0f3fb-b281-41a4-b3f9-d559aab9ab8b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.224 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "cda4ba2e-083c-4239-a302-d1833f4cfe74", "MeterName": "Compute Hours", "MeterRates": { "0": 0.781 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "6ab280cf-e313-4402-8d8f-7e44dd948df3", "MeterName": "Standard C0 (Hours)", "MeterRates": { "0": 0.069 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d5030a85-27ae-4c5b-afef-10cbcacb15ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.404 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2478ad4d-37cf-400e-a3d2-857871312862", "MeterName": "Compute Hours", "MeterRates": { "0": 1.013 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4d224456-c469-4d5b-991f-7c000eec1de6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.297 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a0a14f71-37e9-44ac-b019-035b23d75a3a", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0326 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9faf8788-bc62-4afd-93b6-5fafcfb29cf2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.666 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6cb34eff-ee22-491d-9c0c-d7b2aebad064", "MeterName": "Compute Hours", "MeterRates": { "0": 2.16 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d11f3e4e-1850-4e1a-8376-a924bf3b4763", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.012 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "bc27b1c2-ca9f-410c-9748-f43796a61654", "MeterName": "Standard S2 (Units)", "MeterRates": { "0": 30.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Autosuggest APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b3a9225-8c08-4454-975d-d8a5abba5a8d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.681 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "567e0eb9-6c26-42d2-8537-9f75c6a42ec4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "82b96a53-df81-46cd-be8d-df9969e89cbe", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.0963 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "291e48a8-43c0-433e-8902-ab7e947b7e21", "MeterName": "Compute Hours", "MeterRates": { "0": 1.018 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "bf7a4cff-05c6-4964-bedd-0775e18cc28d", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0862 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a901e8f6-0e44-485e-9f81-b915e9504ff5", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 18.15 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "80e9cb6c-2b69-4b8a-a336-6fa1a5d4403b", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d35bf6c7-d3f3-4c24-a141-6e8fde18c639", "MeterName": "Compute Hours", "MeterRates": { "0": 0.301 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "28b5d272-b66e-4727-8f75-7f43f3e01c01", "MeterName": "Compute Hours", "MeterRates": { "0": 0.47 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "20c9f072-995c-46fe-97c5-35c7b20edbf2", "MeterName": "Compute Hours", "MeterRates": { "0": 3.54 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f559ee16-4644-473c-9979-e8c6a79c9277", "MeterName": "Compute Hours", "MeterRates": { "0": 1.466 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fe975e77-c265-423c-b9d9-8f8799f6a3d7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.288 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c2a96e47-52de-4166-b1ff-dca540c6b3b0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.498 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ff8c29bd-5dc2-4bed-be62-48a3587fece4", "MeterName": "Compute Hours", "MeterRates": { "0": 5.0784 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e847e487-74c1-48c7-a0e1-05bc7243ccd0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.88 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "30c12030-ba2a-466b-9630-cee4dd32413e", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 250.0 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0d9ace5a-ca46-4ea2-8c16-404ab1764e8a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c59d8a28-a6f6-4bc1-97b2-76de32ef8943", "MeterName": "Premium Metered Data - 200 Mbps", "MeterRates": { "0": 445.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2c514e07-f3ba-4dec-aa9b-209aa4230e74", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "77860eb6-e2bc-4d06-8efe-491d840adaf5", "MeterName": "Compute Hours", "MeterRates": { "0": 3.518 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "157da470-2c7c-42fb-8b1e-f52f45f35525", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3450de1f-262a-4b42-9ca5-18ca802648e3", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0375 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03e7dc8f-2673-4ada-8880-fe1c67b22437", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d607a843-f530-41a1-83f7-98735f27f4e0", "MeterName": "Compute Hours", "MeterRates": { "0": 2.735 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c3e1bf4c-ac07-4d63-a599-dfaf0637fa18", "MeterName": "Compute Hours", "MeterRates": { "0": 1.466 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "02302486-8064-4349-ad71-481cec3225fe", "MeterName": "Compute Hours", "MeterRates": { "0": 3.218 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "39b9be75-1947-4e14-b6dc-1bd865c05be6", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0375 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cbb21f5a-b453-4101-b240-21772070da0b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.133 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0187b977-d63a-402b-8b11-106c54af6aff", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0055 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "238b0711-0f76-445d-ab54-885555bbc34e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.081 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "286bf7e1-9b61-4739-9f6b-4583e64da0e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "618c2709-f53d-45fe-9bb3-3cacb9306593", "MeterName": "Compute Hours", "MeterRates": { "0": 0.904 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5f0ea997-e73a-4111-805e-199ded74020c", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 17.739 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f58e3424-4376-4cad-b653-38438f873b21", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d40f83f4-edac-4f27-bdee-163dd3c522fc", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.038 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c91b8d40-52be-4cce-a47c-045a2d1aaf22", "MeterName": "Compute Hours", "MeterRates": { "0": 0.308 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "3000577a-6739-4aba-93f3-773e6cedd7ab", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "1819735c-d31b-4a60-890e-e91a3ea516ef", "MeterName": "Premium Streaming Units", "MeterRates": { "0": 139.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "51d156bc-f191-4fcf-8baa-af606a472ad8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "079e188f-4fce-4be6-bd40-7d3ac989ce96", "MeterName": "Compute Hours", "MeterRates": { "0": 2.5392 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bdb75818-345e-4312-a841-ec111bf62c5a", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "957eaa9b-7c60-46a2-b833-00c9c5413c21", "MeterName": "Compute Hours", "MeterRates": { "0": 0.046 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3b9240b0-4e45-4aec-a7d2-b87dfda3d0b0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cb901e02-76a8-4476-86a4-12d7c183a79b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d0092912-446e-4335-ac3b-d215e072d5ad", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8eb2ec78-415b-4822-9d46-e99e6797e346", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.1077 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d27637cf-8638-40eb-befb-2a9c487c2090", "MeterName": "Compute Hours", "MeterRates": { "0": 1.094 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dee2f91a-233f-4509-8275-d7b7ff834fd7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.632 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5aba95bf-b053-4a9f-b019-c3c599a13819", "MeterName": "Compute Hours", "MeterRates": { "0": 1.1256 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "33dcf51a-a44e-468e-a4f5-24041b8875d5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.101 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "fde476f7-0102-4372-b7cf-38d1ebaba1a1", "MeterName": "Premium P4 (Hours)", "MeterRates": { "0": 5.772 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d7db5d72-8dc9-487b-a663-f846969bd55c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4c89295c-9f5d-45eb-96db-f6d799a9c1a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.869 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b56570c8-874c-4b26-b0b3-f07e013dd2d7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "925a20b0-36af-480d-b740-418c9d987742", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "42e2a22f-fabf-41ea-a21e-e86bb3ff5799", "MeterName": "Standard IO - Disk Read Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "466c389c-75d5-4c25-8351-78992ce2dff7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8981294b-c2fa-4f36-85f7-7ade62e90136", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4c15da54-19c6-40e1-b910-70f35f8aaf84", "MeterName": "Compute Hours", "MeterRates": { "0": 5.368 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "04b7b9ed-df96-4e2f-a6fa-dbcbeffaf616", "MeterName": "Compute Hours", "MeterRates": { "0": 1.168 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0dfadad2-6e4f-4078-85e1-90c230d4d482", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 21.68 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cef36e28-977b-481a-9b8a-41b6a4c4d52b", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c5ea8e2f-e913-41c9-a57c-11bb1359c0dd", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 60.83 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "96021e96-fece-4efa-b97c-10c33ac77534", "MeterName": "Basic Elastic Database Existence", "MeterRates": { "0": 0.02 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "059357b5-2f0f-437f-997f-9054f44520fa", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b32411be-dd01-4dd9-b174-2b25eff202f1", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 11.7613 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "42059891-1d2a-4425-9293-f503f48e13df", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Batch", "MeterId": "cc838a29-3cd0-480c-a0e6-416434fa3136", "MeterName": "Compute Intensive Batch Instance Compute Hours", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Batch", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8125b3ec-157f-4cfa-96a2-0f7a8fb05e38", "MeterName": "Compute Hours", "MeterRates": { "0": 1.95 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A9 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0b5ac6f-733f-45e2-9c69-da7fbbc97d47", "MeterName": "Compute Hours", "MeterRates": { "0": 0.069 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a645c7c4-78b4-4c15-9a57-051d672e25d4", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ba2e6c04-d521-4fb5-929b-5eaf7bd62db7", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "11aaad05-cf0e-4d33-ad13-ce376bd4c1f5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b1c0f383-eba7-4a5a-beff-a7337bd2dc31", "MeterName": "Compute Hours", "MeterRates": { "0": 0.886 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2f352354-1b50-4758-85b0-357bfec2762d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.89 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eef460a9-fb57-4544-9d64-2589f6278953", "MeterName": "Compute Hours", "MeterRates": { "0": 0.274 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "438279c7-b2d7-4aa0-b9d3-8372e8408e17", "MeterName": "S4 Overage (1 Million Characters)", "MeterRates": { "0": 4.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "1M Characters" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e380ec57-7763-4e0b-a8a6-18ec5ebbfe50", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f9a25a17-711e-4adf-98a7-4f2b4851e69b", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c69aed70-4d1e-4d58-8594-e275b2f7ea19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.054 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7fdeb1d1-db22-4df8-95de-9a1072882f79", "MeterName": "Compute Hours", "MeterRates": { "0": 0.396 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6ef074d8-e588-4978-bea3-6900887a152c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.792 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d02ca60b-c5ee-4bb2-af44-8d0ed8ff8b61", "MeterName": "Compute Hours", "MeterRates": { "0": 0.101 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5a69132e-5627-42e7-b733-03e0cd8a9052", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "31d26cf4-bd62-4eb1-9ab0-0c09b613ab43", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Standard (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1e2ef9a9-b011-49de-9097-e20558abd997", "MeterName": "DWU", "MeterRates": { "0": 1.6633 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "309fa474-1d68-4040-8576-fa886a0d0764", "MeterName": "Compute Hours", "MeterRates": { "0": 0.484 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "61226b2c-f21b-4a8a-b39d-5f619442169e", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0576 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eee0c5a6-370d-4b65-b095-f916c24fe093", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "e62cad52-77ae-4ad2-983f-f376a3a55cc3", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.212 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5867cf7e-d31a-4d38-9369-1b88c65942fa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.376 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8c26e7de-f781-42ba-8fc9-3a249b99da5b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "c9c24ccb-1b28-4923-8616-77ffaabd5c45", "MeterName": "Basic C0 (Hours)", "MeterRates": { "0": 0.028 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "3dbdef33-aca9-4dfc-95ab-93a4c5cadf2a", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.375 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5641ebf4-f440-4029-a7f6-d48e92b556b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "696220f2-91da-4ca5-920b-151e51a6d103", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2bb397de-da27-438d-8e11-d57a5d871f00", "MeterName": "Compute Hours", "MeterRates": { "0": 0.383 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "eb263b79-5d77-4a6b-85fd-0c458b3bf8c1", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "6876ecb6-f509-472c-83d5-2f1d7971d338", "MeterName": "Basic C6 (Hours)", "MeterRates": { "0": 0.84 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a206857d-3d4a-4d41-bb8d-9167c60573e1", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.1516 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6bafdc11-b964-4895-9d4e-a0e548db1b2b", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 4.8387 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb89a866-4e0b-472f-91bf-66511c6f79e7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.497 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b86a761-5284-439a-aa3f-247643a45ed0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "415d5d90-3599-4c7d-977a-7c60f23cde4c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.768 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "967ac796-7cba-4429-8cfe-7f2739d4929b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.743 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "898849c4-1365-4efb-aa8e-bf0205ce4d94", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 16.5 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "30e21f89-7f2a-4359-bef9-4eed5134c498", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.053 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "05145407-d741-4e4c-aa74-141a3610e059", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.3796 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "603fae4d-a396-4918-a735-ccf9e0f554ad", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.662 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0d1f3a43-810a-4ce4-a15c-59cc4e49389d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.373 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "95e9dcdd-4a5a-46b8-ac41-593121295732", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2edb893c-d301-4315-be8f-a4220d63a551", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 509.2629 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f05afa1b-7685-4e1d-bc06-06ee03689b57", "MeterName": "Compute Hours", "MeterRates": { "0": 10.536 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "df42b215-29f6-4882-995b-3a975ff893b9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.348 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f19f43f3-3e39-45b8-b3ae-1c907389224c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0056d2a6-4f43-4e2f-9cd0-0bf3cd49e45d", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c85e939b-7fd0-401b-8aab-47224fd725e3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ef41e258-9080-4d81-9f5f-493b6a8849cc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.336 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f8bef3d3-dad8-4a4f-866a-e8d47ada2509", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f6d8cdbe-efbb-42f0-bac0-91e5435137b9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1478c14c-1568-4a67-8a1e-3ae50f4284c1", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0548 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bbdf37a0-775d-4b88-915e-957767b07342", "MeterName": "Compute Hours", "MeterRates": { "0": 0.37 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b416267e-7623-4b26-a283-21f98bbc67a6", "MeterName": "Premium Unlimited Data - 2 Gbps", "MeterRates": { "0": 19650.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4bd52b17-d56b-43ad-82ea-37171a8505b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.583 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "eabee600-a8c0-4631-b410-d7bff4022008", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "3fdffac6-75e4-4828-b454-1447bcb4324b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.171 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1f4a272b-d9ac-400b-9b2c-767376072eb2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.742 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3aadb034-eb61-4a64-bd4f-ec2f8586825a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.219 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f4144fa0-cdfa-4119-896d-84c48808d419", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.153 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "11401df8-e39e-47f9-bfe8-6d0ae757a180", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 225.81 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "5a362b42-a880-43e8-82e6-3c8a67964fd4", "MeterName": "Unlimited Data - 100 Mbps", "MeterRates": { "0": 1300.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "115f6238-828d-48ce-97ae-c4312fae9c66", "MeterName": "Compute Hours", "MeterRates": { "0": 1.37 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV6 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 50000.0, "MeterCategory": "Identity", "MeterId": "fca3d249-4c6f-4a3b-b8ba-ee93943fe3e4", "MeterName": "Basic Users", "MeterRates": { "0": 0.0011 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Active Directory B2C", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0dc2fd3e-fe0b-4172-8c53-297851a3d2d1", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2d4b5ae6-b580-4c6b-9d08-30289d910b24", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "f94c4ebe-069a-4c53-8fc1-76365caaa9b0", "MeterName": "Premium P1 (Hours)", "MeterRates": { "0": 0.694 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d2eaa8a2-4653-452a-b783-3e7e49065efc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "74aa12f8-d483-4452-8a45-ce0681c608ba", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "8028c95b-adcc-43b7-8d4e-be65ef8ddce0", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.88 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "57c0000e-9352-4bcb-8b3b-b2852dec9415", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 33.9 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "59d6b669-a27f-43b8-b1d4-beb384a9103a", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XL SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d6338131-4b38-496d-b847-1e6bcba1c4af", "MeterName": "Compute Hours", "MeterRates": { "0": 0.111 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "deafcd05-71a2-4a0b-82de-a06b60b4083d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.874 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ec4b0893-9afd-43f7-af7e-609027099243", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9d3208da-7aec-477f-bad6-48b9dde57abe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cdfab75e-a15e-4326-a99a-527bccef8f80", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 548.856 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9e29f04a-55d1-46d3-bc71-3c73016961e5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.166 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "96019ff4-d889-4443-b8c8-2edf0d3fd81d", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.144 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c79010e0-54fd-43b9-9265-67f6a8f5293f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "608d3507-d03f-4235-a89e-260deb2f306b", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.2038 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "fb9c6230-31a4-47db-9755-81b1f088f6e2", "MeterName": "Standard C2 (Hours)", "MeterRates": { "0": 0.281 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a1ae9dde-e6bc-4a25-ac86-ea560eabb420", "MeterName": "Compute Hours", "MeterRates": { "0": 2.252 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "007b274b-ac6f-4c94-96ba-87a7452c2460", "MeterName": "Compute Hours", "MeterRates": { "0": 0.238 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "RemoteApp", "MeterId": "84add202-6535-4afe-a62e-ce30f181b6cd", "MeterName": "Standard Overage Session Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Named User", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "70ced248-63cc-48c4-be4b-c82f5ec572e6", "MeterName": "MSFT Peering Unlimited Data 50 Mbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6bd4c67e-ec09-4766-918d-49bdfd273204", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 150.0 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5a5965bc-25bb-4614-a6c8-dd7b0acbe068", "MeterName": "Compute Hours", "MeterRates": { "0": 1.343 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc64386b-b3a0-4d49-9ffa-0f79229b1766", "MeterName": "Compute Hours", "MeterRates": { "0": 0.524 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e99c025f-0eba-4886-80dc-0397ea0ad0f5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.11 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c47a9952-8952-4c87-af10-15a3d28353fa", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cf7ea5d5-a508-4364-870f-30d10b6f7337", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7b362907-1d27-4f3c-985a-99d2562fcedb", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0264 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "7f854932-e265-46af-b2fc-0936ecce0708", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "M SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "039fef54-22b4-49c2-9da9-53c87cf170ff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.794 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Notification Hubs", "MeterId": "5d75ae84-1488-4711-80a1-831f1e8bf851", "MeterName": "Base Unit", "MeterRates": { "0": 200.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Notification Hubs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8912906e-abec-4934-943a-2ab3042056a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.042 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2242dced-d6c2-48be-a940-d8096871d831", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d1be127-45e8-4698-8211-ac7de4ee9911", "MeterName": "Compute Hours", "MeterRates": { "0": 6.38 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV24 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7c7c0034-2a00-4164-9454-546b2b20b026", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3013a362-af6c-4849-ac70-eb605823602b", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "28713411-97ea-4a36-8fb3-82ff0d600fec", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard and Weblogic Server Standard (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5299df59-f8c8-48d6-bc8f-7a6d38e6fcf7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.231 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "4d6396e8-f52e-4505-986f-dde9e1bbb62a", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.488 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a22c3519-1734-4cb7-8e8c-60684ae5a1bc", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 66.43 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ca052728-507e-43c4-a9db-9fa115ac4a5e", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.5807 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f6eeff7c-d9e2-478e-b25d-670e485511cd", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "fa7ee529-9c03-4b0a-9007-f7671e15bbd3", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c48226bb-dbdd-4571-86b3-7819155301ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-03-12T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "799827a0-dc0e-40b8-bb4e-ec6628d71371", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b386db9f-770f-4ebd-a18e-de244427af94", "MeterName": "Compute Hours", "MeterRates": { "0": 0.62 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "88082622-24c3-4ef4-9111-09703b472ce4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.288 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f671d38e-9134-4482-8e7d-c9c242289d23", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d5c6e865-3c64-4b54-87f7-68847ef91631", "MeterName": "Compute Hours", "MeterRates": { "0": 2.954 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "53ef88d2-4e29-4b8a-a574-16288e717fe3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (up to 4c)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "60e48883-adbd-4f15-90af-7cf28225eee7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.691 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "e33e8741-d234-45cd-ae9e-c978e7d1d2dc", "MeterName": "Standard S3 (Units)", "MeterRates": { "0": 300.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Search APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7795898b-6d7a-40fe-a12c-2d950d773e5a", "MeterName": "Storage Transactions (in 10,000s)", "MeterRates": { "0": 0.00045 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Transactions" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2b1cc296-982e-4eba-bebe-c78b1f3732af", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b92f820-d605-472f-a905-6cd970202ba5", "MeterName": "Compute Hours", "MeterRates": { "0": 3.19 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV12 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "2e7e68c6-6ee8-4c78-bb27-551240cf729b", "MeterName": "Premium P4 (Hours)", "MeterRates": { "0": 4.44 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "34211276-e358-48a9-9107-563aad651600", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3226 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96a51c45-febf-467a-a35a-d9dff3bfe97f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "80bd213a-6a95-46df-b323-c9700c92dea2", "MeterName": "Compute Hours", "MeterRates": { "0": 8.78 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9fa6d7bd-40a7-4178-b323-a3f509b28f2f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.594 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "196cf194-679a-4c18-9aab-16daec24426c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e596f669-89c2-4b64-8d55-ff43f91ec709", "MeterName": "Compute Hours", "MeterRates": { "0": 0.275 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "14624711-b4f4-492a-8fe3-3bd06089194e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "ecff4b9d-5d93-456c-a0d0-16439bf99e65", "MeterName": "Standard (in 1,000s)", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Face API", "MeterTags": [], "Unit": "1K Transactions" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "706de8fe-67fa-42d3-90fd-7d01f4f2e735", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d6a5e999-fa77-4dd9-ac49-8589fa05c400", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 68.64 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "11214343-48e4-4b8a-8fb7-f2ed23716f2e", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "06895379-8977-403d-bcb8-8a012515bd30", "MeterName": "High Frequency On Premises Activity", "MeterRates": { "0": 2.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Factory", "MeterTags": [], "Unit": "Activities" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6c87c094-296e-4056-854a-6f1e5556ca91", "MeterName": "Compute Hours", "MeterRates": { "0": 0.528 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0c4f782e-7513-4b1f-af28-63db5fe816c7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.275 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b1f35ec2-0308-4b4f-9f19-96545df76cf7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "48c5e1c5-2278-40ec-858f-d94c3d01f2af", "MeterName": "Premium Metered Data - 500 Mbps", "MeterRates": { "0": 690.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b13ef59b-e50e-473d-a970-d78dee33cdea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.585 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0c622ef2-cd52-4909-b2b2-3f6e8f940cc2", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "782591e9-abf5-4c5b-b764-aaf746e71e85", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "185be269-2b9b-432f-8cc0-5ec4d6c5e6df", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c7b6df52-90ca-4b07-aede-b27954b2ca06", "MeterName": "Compute Hours", "MeterRates": { "0": 2.8 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "1b0fd2b5-5164-44c7-942d-02aac243b8c7", "MeterName": "HSM-key", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Key Vault", "MeterTags": [], "Unit": "Key Use" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d3e157bd-dc46-44eb-9eed-8c257601e800", "MeterName": "Compute Hours", "MeterRates": { "0": 0.467 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f370c0a2-57ce-45bf-a0f5-aab6c0a005bc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.394 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "901477a2-298a-4850-bca2-56909368deca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "526017ae-c2fa-45d5-b516-a641e34ae829", "MeterName": "Compute Hours", "MeterRates": { "0": 0.354 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "dff6ed03-1385-4a67-a854-d40aecaf7957", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.09 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d8bff32-972c-4feb-ba56-a1c9bfb9091e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4ce3cc34-ecc3-4f21-b01f-67ac0564811d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4e1afbb0-df00-41e0-b6e0-4cb1836d1625", "MeterName": "Compute Hours", "MeterRates": { "0": 1.81 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "SQL Gen 4 Compute (24 cores)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f3e51a26-ab89-422b-96ec-be8b158bd93b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard and Weblogic Server Standard (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "174deba4-f676-4e38-8d31-c35b68683b7b", "MeterName": "Premium P13 Secondary Geo Database Days", "MeterRates": { "0": 290.33 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d54686f0-77ff-43f3-9e7c-2099030d32a7", "MeterName": "DNS Queries (1M)", "MeterRates": { "0": 0.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "DNS", "MeterTags": [], "Unit": "1M Queries" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bf1e2e3c-eadc-4f19-9a96-8a4de7a14345", "MeterName": "Compute Hours", "MeterRates": { "0": 1.714 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2508709b-ceef-4a6a-9284-d6fe6bbf48a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.218 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4b68ed41-45bd-4a1c-adca-924de4c9ca72", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f5f3fdcc-9d65-4817-a35c-f201589a530c", "MeterName": "Metered Data - 500 Mbps", "MeterRates": { "0": 290.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cd4dde62-93d3-4c88-a041-7b392216c326", "MeterName": "Compute Hours", "MeterRates": { "0": 0.308 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "357c606e-1868-4f8c-9ebb-42c164290fa8", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.022 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2819fade-548b-48e4-b59e-7b00a4c7a4b9", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.275 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "35cf86f6-7923-4cb6-9867-4fe57ff87ed3", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.972 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A9 OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b443379-3edd-4b29-b0be-5dbd554c498a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "35623590-cb70-4f76-937c-040aec39ba55", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f59b982c-6454-4e53-ba74-5f10786b67a8", "MeterName": "Premium Unlimited Data - 200 Mbps", "MeterRates": { "0": 3520.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4a777324-6223-422b-b1c6-3b1cc102389e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.102 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "35e37c6f-fb7d-43ce-a97d-01f8c25f575e", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.416 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3deba93c-29c1-43c3-a775-ed343fe0375b", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ccdc31bd-f411-4c90-9293-8bbdfc6e3111", "MeterName": "Compute Hours", "MeterRates": { "0": 0.528 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a6b4f30c-ffc9-4758-9206-fa7ac2c6af14", "MeterName": "Compute Hours", "MeterRates": { "0": 1.879 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "095a0e8e-090f-43c4-b319-b207603db22c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.879 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "33501d1d-cc39-4216-96df-f5e8794d0e72", "MeterName": "Compute Hours", "MeterRates": { "0": 3.538 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e2b960d6-e14e-4f00-9e69-6a253015cc5d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "83271eb6-c541-4bc4-b61b-9f08e8142e21", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 645.16 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb11dc7f-2f3f-4624-87a7-a776c9101e5f", "MeterName": "Compute Hours", "MeterRates": { "0": 9.384 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "28867e2f-f6e7-4de5-8fe4-b65cf76cfcc0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2c061509-27e5-43d7-bf06-43fedc7bddd3", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.015 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "77d66fde-7530-445f-9416-76a368acf22e", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.64 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "39f422dc-abf6-41cc-aafa-03276cde242a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ec641281-7efc-48f2-8d1f-88ae77dc3f7e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.954 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "69c838a1-25aa-4ea4-94ce-851459ce64a1", "MeterName": "Video Motion Detection APIs (Minutes)", "MeterRates": { "0": 0.025 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "03d8b4ca-d966-401c-8f3a-99e58e02f652", "MeterName": "Compute Hours", "MeterRates": { "0": 0.625 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03479309-ca46-458a-b040-d7124c20c927", "MeterName": "Compute Hours", "MeterRates": { "0": 2.804 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a3dd3839-f638-493d-a529-e1e1427a5b78", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.07 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "33e0e9a4-f3c7-4085-9c61-116c18aeea46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f4e889a2-6224-46c8-ac42-40a209df8c12", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2200287e-a71d-487c-b3bd-75362ff9784a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.137 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ff697d73-39e0-43e0-bf67-79648ce16355", "MeterName": "Compute Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "787db389-df81-4d1d-ae40-6ce34bdfb9b1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.045 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5b843ebc-c10e-4177-b57f-9dcacd1f768b", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.08 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "231ab41a-e3c8-4f7c-9eb7-eb52200bb47a", "MeterName": "Compute Hours", "MeterRates": { "0": 4.532 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8fc2ae27-7eea-43ff-95d7-497e08a4c219", "MeterName": "Compute Hours", "MeterRates": { "0": 2.243 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A9 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd9d3bf9-714d-4b09-8980-68dcfef157ff", "MeterName": "Compute Hours", "MeterRates": { "0": 2.102 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a2b5bb2d-f4c6-4e96-8e61-bfdcae9166c0", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 132.0 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "445730ae-7795-4a85-b2e5-b6e3f6f90ff6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.483 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ac2b8d90-044d-4ae9-adaa-127945a3614e", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.732 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "207635cc-9a76-46e4-92b5-a3bb0b565892", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9f8ad506-5f00-4fff-b699-46e14cf30fa9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.081 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ffad071b-76f1-46a5-9eb7-f99462fd2c06", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "72d4a40c-5355-484c-b1bc-6f746466bfdf", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e3a600a6-5a85-4679-9721-1c0d192ed142", "MeterName": "Standard IO - Table Delete Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d480fb06-a438-464b-a88e-6148bf7926e0", "MeterName": "MSFT Peering Unlimited Data 100 Mbps", "MeterRates": { "0": 1230.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "658d854c-925a-4347-aeef-c3a5c4f55842", "MeterName": "Compute Hours", "MeterRates": { "0": 1.872 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2c7f8a5d-fb5b-4673-b20a-ad0197a6e445", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 567.7408 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8f084fd5-4df9-42a2-ad81-e9602a919489", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 61.44 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "14235ff7-5ce7-4aef-bb2a-a6d47ce48655", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.008 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ae6a7452-2e45-4343-8fbb-b8cb674dcabb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.472 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "522db746-72f3-4f9b-8442-013b5dce385a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.533 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7c536b60-a3b5-4f77-ae3c-4912e3e174e4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c2df1505-864f-4eaf-9a07-76254ba6cacb", "MeterName": "Compute Hours", "MeterRates": { "0": 2.833 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6316109e-0e71-422e-a8f7-b744a37d1960", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.0322 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "6446d2f5-66c8-4491-8ec4-595435d86c4d", "MeterName": "Data Transfer Out - Metered Data (GB)", "MeterRates": { "0": 0.05 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ec09df9b-7108-4ec1-b041-834c6a16375a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "0a0fe57d-728a-46c8-b1a7-6e188ae50992", "MeterName": "Standard S1 (Units)", "MeterRates": { "0": 3.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Autosuggest APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8da6b1a9-767c-482b-aa42-56d16040659d", "MeterName": "Compute Hours", "MeterRates": { "0": 5.46 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV24 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4910515d-fa3a-4e5c-baae-42b64d429f1c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.65 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c353e88-5c44-41ff-a545-8673e70b2240", "MeterName": "Compute Hours", "MeterRates": { "0": 4.051 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3f623114-640e-4f6a-b325-347b7ed51841", "MeterName": "Compute Hours", "MeterRates": { "0": 2.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "041c9b25-6556-42c1-8efc-bc3750c55ddd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.447 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f2a46495-36d9-4dcc-98ab-52155e374fc1", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 66.0 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ac680768-a3ec-49f6-9f04-35245ed69dd0", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "514d2095-d1d3-4c1d-a136-c38886a08ae5", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.161 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f52b5e4e-2c1b-4394-b256-355adb5ac70c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d1e046dd-bca5-4325-aba8-3d9eabeb0566", "MeterName": "Compute Hours", "MeterRates": { "0": 0.798 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3180a65-53ef-4162-a9cb-187cba43f633", "MeterName": "Compute Hours", "MeterRates": { "0": 1.396 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7dc6af9f-7a28-4bf6-a3ef-91d3473d19a6", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "101b5675-98bb-47c4-888b-beebd7dbc3bc", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.125 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b1251d25-5792-433b-af2f-cd7bdf7c70da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7b396c4d-5016-45dd-87f5-a49291de9775", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7061d805-de24-4d8e-883d-2cd6136fcb1d", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.129 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "a2fa0e1f-a4ab-4db2-9945-67d07df22591", "MeterName": "S1 (Units)", "MeterRates": { "0": 100.0 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8347857f-83b1-42b0-9e28-190e839bf069", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cd7b6e87-0802-44cc-a83d-50abf17b92a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.758 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ebc3ef62-78fc-4eea-a9b4-17b7ad783b79", "MeterName": "Compute Hours", "MeterRates": { "0": 0.459 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2d0e4d6-cc5f-44cd-bce0-2198d7b00225", "MeterName": "Compute Hours", "MeterRates": { "0": 0.15 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6ab58869-fe7d-472d-bd57-1b1f812b4e1b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.366 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5e2c99fe-dff1-468e-a5f9-3a2f6fec0dd9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8f5f73d5-08fc-419e-9e6d-40d64ff9fec8", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1006f953-47df-4c92-9f09-6ec3834d4e0c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c1cfd724-39d0-4030-ad64-30fb29b08221", "MeterName": "Standard Managed Disk/S20 (Units)", "MeterRates": { "0": 11.968 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4f2b36c6-e6d8-479a-9789-546adeb43c43", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2005544f-659d-49c9-9094-8e0aea1be3a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e8f03dca-a621-4c3a-bfde-0acc3ed8b072", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 25.74 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8fe45687-5272-4a3e-8d4a-acc1141c5464", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "601a1a89-81d2-4277-8e41-4256c85fa3ef", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9244109-c69a-4d18-a808-f666fc7b4be4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.46025 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "e36c98f8-8de4-4323-a576-7a41898e87b3", "MeterName": "Standard C3 (Hours)", "MeterRates": { "0": 0.45 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1ed339be-dbf6-40b1-a9e3-344a893c8ab2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.595 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a97262bb-334c-47dd-9074-7c1012519d00", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.4176 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ce0bcc66-446b-47f3-b0ac-094c3738dc21", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8ae60c37-2b1a-4798-9c19-dd0f4ec6b878", "MeterName": "Compute Hours", "MeterRates": { "0": 1.368 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "1b174502-a775-4055-b885-49631396b81a", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9f770265-4d53-4a51-973d-ead318642ff6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.875 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd18f5bc-0409-4e7b-bcd8-f613082ceceb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.043 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "d0a685ee-f093-4c5c-ba76-3ec342a75de7", "MeterName": "Ingress Events (in 1,000,000s)", "MeterRates": { "0": 0.028 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Event Hubs", "MeterTags": [], "Unit": "1,000,000s" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e266a9b3-59a2-4e98-8a00-d55fadf5a5c7", "MeterName": "Premium Elastic Database Existence", "MeterRates": { "0": 0.4612 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0bb1b5d9-f07b-42b2-83c0-302125cffa43", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "94ae4f63-5c28-4119-b2af-6474c2079336", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "20ae4ba2-14cb-4f1f-8b25-1d730ecace14", "MeterName": "Compute Hours", "MeterRates": { "0": 0.149 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "91913e43-6e39-4924-9d87-eaf75fbbc858", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0445 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3ebe2f42-28b7-40a0-9f93-99295632b80f", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.114 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c7929966-0a48-4f73-a86b-30f4e39d1995", "MeterName": "Data at Rest (GB)", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "abf75093-8aad-4b0e-a6b4-b560fe04f43e", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.1674 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "6474ab1c-32da-451b-af09-347c43b5b3a9", "MeterName": "Bing Speech Short Form API (1,000s)", "MeterRates": { "0": 4.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "73fa7e44-d523-42fa-9755-21f13bb17862", "MeterName": "Premium Unlimited Data - 500 Mbps", "MeterRates": { "0": 6000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7ba85e3b-1ad1-4d97-9379-23d23bb79d23", "MeterName": "Compute Hours", "MeterRates": { "0": 0.348 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a287a48c-8d94-49e5-a745-b46c130521b5", "MeterName": "Storage Transactions (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fc4e32da-ee4d-4c08-9123-58b49f16bf07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.193 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c759cc13-babe-401d-a6c6-470abaf16baa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.225 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8c0088a5-c620-426d-9f62-90835ccfdc52", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1819 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fe776f52-193e-488e-a411-c68ca5982410", "MeterName": "Compute Hours", "MeterRates": { "0": 2.131 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "fed263f7-bf07-4463-9976-58b1657efa02", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.424 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "369f2370-629f-4221-b776-bf7ca03e492a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0f240f9b-0271-4777-8153-57ea7fe23389", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f45b4061-88cd-49c9-a214-c144d30ccfe3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.2196 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03ac6ab9-fdc9-4bae-9c19-70013c387633", "MeterName": "Compute Hours", "MeterRates": { "0": 0.202 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f3f2fa69-a413-45a0-9d2e-fce71ebfd053", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0475 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e819a254-9fe9-451d-b2df-a1c878828652", "MeterName": "Compute Hours", "MeterRates": { "0": 2.686 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "600d1d78-c335-40ed-8888-ff6c5c91c850", "MeterName": "Compute Hours", "MeterRates": { "0": 4.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (8 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b4e18f39-951a-464c-9203-81ea93b6694f", "MeterName": "Compute Hours", "MeterRates": { "0": 11.88 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "G5 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d200b0b7-dee1-4c70-bc27-0be36a1b5a6a", "MeterName": "Premium Metered Data - 500 Mbps", "MeterRates": { "0": 1090.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "506baf95-496d-4ea7-a5c0-454b25f8a1d9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b6561f0f-da1c-4ffa-bef4-fa6a25586363", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 4.8387 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d8771d5f-8360-4935-8687-9dd153ef427e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.274 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9646327a-a170-4388-ae5f-b4d00add700f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5b58638e-0b79-4774-bddf-d8debdcc44f1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.324 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "30a5e31d-277d-4e45-9917-4236d0e54a18", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "10a04b1f-1cf2-45ce-a1da-9cd91abfccfc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4390078b-dd67-4707-87e9-e6d5e38a6d0c", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f0ccfec9-02f5-48ff-8ee6-a3177984dc34", "MeterName": "Compute Hours", "MeterRates": { "0": 12.731 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6700be67-405d-4d60-a823-943f85b5e6af", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "49dd9dcd-b341-4710-b8b3-d14ff83e651f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fa014ea4-28f2-49aa-8ed7-957df89d42da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.356 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Automation and Control", "MeterId": "3845957f-7838-429c-b826-c091edb6fe16", "MeterName": "Overage per Node (Minute)", "MeterRates": { "0": 0.002 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "OMS Automation and Control", "MeterTags": [], "Unit": "1 Minute" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "5ca0eab8-4072-4404-8c8d-666d96674095", "MeterName": "MSFT Peering Unlimited Data 10 Gbps", "MeterRates": { "0": 82000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b7a09aba-ed46-4739-ac54-4d99aa211195", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "771dd126-34e4-4dc0-8c91-8faa34e34e52", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "74361c94-a459-4564-b3d2-dd8dfd79e704", "MeterName": "Metered Data - 1 Gbps", "MeterRates": { "0": 436.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "78c9ed18-2cc5-45bc-a403-59aef71fe88b", "MeterName": "Compute Hours", "MeterRates": { "0": 4.034 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dd7fabe6-1049-40e1-aeee-f81e3651fe7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8efcaf75-6476-4413-be34-f75c42fd0926", "MeterName": "Compute Hours", "MeterRates": { "0": 0.67 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ca04735b-6054-42e7-9080-f3a27f368f4f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.405 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9a1a397d-b91e-4446-83ac-922c8c5ca8b5", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.161 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "29d77a31-e360-483b-a3b3-3b4f3f05bc38", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 11.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "18868a19-db6a-411e-9810-d337d44c66bd", "MeterName": "Compute Hours", "MeterRates": { "0": 1.872 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "981a258b-c47a-49e4-8e7f-a3d92afb5c22", "MeterName": "Compute Hours", "MeterRates": { "0": 0.046 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8d29f707-7e0d-4e09-b376-9535fed9863f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.68 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "721ab441-088d-4bbe-bc58-da66fc6d8b31", "MeterName": "Unlimited Data - 500 Mbps", "MeterRates": { "0": 5200.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4a5a4b83-6216-47c5-b3db-fe430fa6e2c3", "MeterName": "Standard S1 API Plan (Units)", "MeterRates": { "0": 3.23 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8bb48c82-7b3e-448d-b506-9db7c1278102", "MeterName": "Compute Hours", "MeterRates": { "0": 0.67 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ebd37945-6bf1-43ab-a925-2f67235e51ba", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 163.548 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d3824379-dc7e-472b-9e67-3f4a7eadc05b", "MeterName": "Standard IO - Page Blob Read Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "8dca9a1d-0589-496d-85b4-f93c5e22fb33", "MeterName": "Premium Apps", "MeterRates": { "0": 99.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "Apps" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5983e870-e59d-443a-829d-13530a2ee1c2", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 60.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "819d3dde-ccbe-45f7-9bc3-66cd68af3d10", "MeterName": "Compute Hours", "MeterRates": { "0": 0.759 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b6bc798b-dadd-42a6-9848-ac13e9c71309", "MeterName": "Compute Hours", "MeterRates": { "0": 0.786 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2c2efcf3-50fb-43a0-b253-75f3bdd09afe", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.11 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7a249e2b-a31d-4c54-b0fa-6f7f45927fef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services Low Priority", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4ac600d0-3006-40c7-bef8-5881c6d7ca50", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "71677ff1-e604-470f-95cc-16a626aed59b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.996 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "12f2dcbb-b14a-4c0d-90a5-5221356b06e5", "MeterName": "Standard Managed Disk/S6 (Units)", "MeterRates": { "0": 1.654 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4b8b8092-a2d7-4785-9b9f-76104f4c7269", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4223937e-516f-4ff1-9dfc-0e2ff39ec8aa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5e7a80e5-0273-44b8-a179-e4f62ea6ec9f", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "eb6bdde2-506c-4b1c-b5f4-259403ff0dd2", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.1188 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4142ced1-3ecf-4e76-bac7-c4875eb10e99", "MeterName": "Compute Hours", "MeterRates": { "0": 0.77 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "23c8e98f-5028-4330-9cfc-777e2a207f83", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.94 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "21510b9c-69a8-4a84-902e-8d6b735c5ff4", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.41 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c08e14e-5687-4be8-8f6b-99f1f9160acc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.446 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7aed6dca-0b30-4409-8f3a-b68eff473afb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "be88bcf3-1a6d-40a9-b006-ac29857c9377", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d7d527f5-3312-4052-be4f-fbbdde8ab1bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.096 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (12 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fbb6c1d5-3488-47d4-aca7-3d986eca81c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8b37732d-dd06-4cd5-b09d-cb829fecb879", "MeterName": "Compute Hours", "MeterRates": { "0": 0.296 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7e9ec9bd-045f-4540-b918-bd5f848fa88f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "285f29f0-cc2d-4ad7-8585-8f27bf6c874f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.858 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a7eb5d95-d003-4e4e-bcc5-381781b050d0", "MeterName": "DWU", "MeterRates": { "0": 1.6936 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a5e92164-161d-4352-a7fb-9b5782e58a48", "MeterName": "Compute Hours", "MeterRates": { "0": 0.262 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9bd33e8f-aa87-42c6-aba6-fd3ccf1fdf06", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1d9f1d7d-54d8-46e7-9e90-cfe4806d819e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.45 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "bfeea04b-3747-4ab2-9ce8-beda9033e7ef", "MeterName": "Package Management Users", "MeterRates": { "0": 4.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Team Services", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "42a3e6c7-d50e-4cc5-8c15-82f59a84c009", "MeterName": "Basic Medium Azure App Service Hours", "MeterRates": { "0": 0.15 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "4d56f98b-dceb-4c50-a197-0a8e36614656", "MeterName": "Standard SSL Certificate - 2 Year", "MeterRates": { "0": 125.98 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Certificates" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cb6296b3-56f6-4af3-931d-5ed6eefec223", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0dd27cb3-dc33-4ca1-a601-482ff4917012", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 372.5876 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "09a0f91c-3ccb-4a6e-a7bc-61c0781eb6d2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.417 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5467c7cb-951a-4218-8bb1-f656115176cb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "c9a05f12-4910-4527-a9ec-1db4e4dba60e", "MeterName": "Core Features", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1 App" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d71f5e12-ff4e-40bf-90fa-5a23efc54784", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "72746220-2fb7-4100-a6f4-4cd31b54b93a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "7104ebd5-45c7-4f96-8847-332a9630a291", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b8cc594c-522d-4b13-bfe9-0bdade2e94d2", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.055 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6591d320-03de-4f7b-a954-5ae2a562bb61", "MeterName": "Compute Hours", "MeterRates": { "0": 1.932 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c10119f-55be-430b-b189-a37492b2b0fa", "MeterName": "Compute Hours", "MeterRates": { "0": 1.3275 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9b1933c2-76eb-4cd6-83eb-6b7ea4ff7aca", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 33.9 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9faaaee9-161a-404e-83af-5ff317d66375", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0c11d1cd-655e-4369-b0fc-4cccf9a39816", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c5a93026-0905-44a9-8b52-06928b77cb3a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.924 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0db10bc-0d57-4ddd-8104-93ce2756c654", "MeterName": "Compute Hours", "MeterRates": { "0": 0.926 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0dfd69d2-e486-40b1-bdda-2ab5e6f043cf", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 49.82 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "af4ce32c-ec5c-497f-a92c-19e5ea580c21", "MeterName": "Compute Hours", "MeterRates": { "0": 2.486 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7f96c6fd-405c-4fd0-8773-1c1173bdcf5c", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 73.73 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f084eedf-a23f-46d2-bc24-b913ab919c95", "MeterName": "Compute Hours", "MeterRates": { "0": 0.316 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "c54ccb61-434e-4cef-b85e-6847a47a142d", "MeterName": "Basic C1 (Hours)", "MeterRates": { "0": 0.069 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "401cfa59-dac4-49f0-ad87-f75c5c7d07d9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a0005480-a936-4a70-80ec-d3e8f5b27519", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 428.56 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "47feaf27-c51d-4000-a98f-da029244d84f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.109 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4f8600c-19fe-406f-8d22-b55c43456835", "MeterName": "Compute Hours", "MeterRates": { "0": 2.342 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "5b14481a-dec5-4a46-9847-330d75701ee3", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d0b24cd4-63e1-4549-bb16-f6e7aea4b412", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.041 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2448dee3-09c1-4242-8a6f-14ce82cc2b49", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d333fd89-e3d0-45a0-871e-e4a4061ae0ee", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82faf9a1-6171-47c4-9919-f317717be4d8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4fe80b67-66f2-4fec-b281-22019bd6a8f2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A10 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "14963917-dee3-41a7-a37e-6ca27dad4cfe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "05ef7219-1ceb-451e-b1d8-27bf373addd6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.442 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cdb250c1-4706-49e0-93f4-941a627bde51", "MeterName": "Compute Hours", "MeterRates": { "0": 1.872 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e0e613e6-6659-4ddc-bc52-aba87401b461", "MeterName": "Compute Hours", "MeterRates": { "0": 0.111 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "29419ca9-a71a-464b-b80d-a35854227b40", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2c1805d-d937-46a2-aee6-66e441144021", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "15fb14e6-ece4-4981-a179-2bc796d0b65b", "MeterName": "Production API Compute Hours", "MeterRates": { "0": 2.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8dbc6497-3d3a-47d6-9de4-dd42072fad66", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8023b34d-cdae-4f78-a786-14aee78c327c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.097 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "42dbe3d7-0a86-4173-a4f9-185e7944ee29", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7397766a-fec3-4707-915d-d7ccd44ad8a0", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f5a999a1-da04-48d7-bd38-d8015cc81cb7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d0704cec-9302-4ffa-bdf5-2f296e19ef1f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "33dcb7a3-de1c-4add-8347-76064099f695", "MeterName": "Compute Hours", "MeterRates": { "0": 0.85 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "db78af8b-956b-4828-bf01-0489d6da903b", "MeterName": "MSFT Peering Unlimited Data 1 Gbps", "MeterRates": { "0": 8700.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "73ccc743-2385-4f35-a2ee-97b0f0f9864e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.5392 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57063526-33ad-47fb-b2bc-a0c0a07e2928", "MeterName": "Compute Hours", "MeterRates": { "0": 0.142 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9dbadd95-5f52-454f-9002-c666a8aff87d", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a8387712-c345-4137-9488-78ac0e0b9a8c", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0238 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "48888350-0dec-4aad-a3db-a5eb185275a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.294 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e9e6a774-4e00-4f33-91df-06eae1e584c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ad9fb5a9-673e-45d4-8b42-997c024bbdae", "MeterName": "Compute Hours", "MeterRates": { "0": 3.254 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "02124380-8638-4b50-a284-bc93cc236d93", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b065882b-982f-43ba-bba1-1308221cf860", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a808d9f0-4c85-45d1-a72d-dec03c281a34", "MeterName": "Compute Hours", "MeterRates": { "0": 0.056 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Integration", "MeterId": "0b98ee24-305e-40c9-853f-7e97e5ba7819", "MeterName": "Standard BizTalk Units", "MeterRates": { "0": 2.93 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Services", "MeterTags": [], "Unit": "Unit Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2b1dac7a-b200-424a-8ba6-698b4553dcdb", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.1771 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9e7a4990-9d41-420e-8d39-4400f813af9e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.374 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "40f2bbb5-1ca8-4ac5-afd6-b1e47f16314b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.246 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "058535f3-e927-4143-9b39-4e9ec2bcc825", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "00efea30-9dc7-476a-9597-ea7834555df3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.068 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4fc3d1e4-fd5e-43ac-b513-0be15f419422", "MeterName": "Compute Hours", "MeterRates": { "0": 0.549 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ba02ee99-0e56-4a65-a96d-9510cf31781b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e9617b6e-9905-40f9-bb14-f766f2626606", "MeterName": "Compute Hours", "MeterRates": { "0": 1.169 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "98903c93-47eb-4bb2-9784-cbb960ae94ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ea60328-178d-496f-aca0-70bcf192ea80", "MeterName": "Compute Hours", "MeterRates": { "0": 1.793 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d15cb650-ed16-4a9c-8dcc-08a9f8cf862b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4e7337c6-6316-4a5a-a2fe-3828e1e4ce6f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.481 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f61769f0-6f93-4181-b335-61fc6f70e891", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "18ada5c4-7206-43da-8066-7baf232d97c9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8cd2172b-a05b-451f-ac39-0b485ef652db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "87dcff9d-fd2a-467c-8f6a-5e7f452bbdca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "08823a7e-28ed-41f4-bccf-31db018890f2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.528 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5cd2167b-a6ad-4fda-9073-c70427a89a58", "MeterName": "Compute Hours", "MeterRates": { "0": 0.513 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b66176d3-cbc3-46ee-ab4d-068903b8d283", "MeterName": "Compute Hours", "MeterRates": { "0": 1.087 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a4bca5bd-4831-404f-992d-15196e612862", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "40dc23d9-437b-42fe-af9a-8ba9914cbac2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "37dff8e1-5245-43b4-a2d0-dfcc1145759d", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6dcc6da1-1a99-4279-b8c0-ac29adab9ae1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.39 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e8cd62d9-a575-48bf-a094-ca9ba9332648", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "e2f3c6d9-8189-492f-b4e9-570d1b6b2ef8", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.464 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9420a7cb-52b6-4450-8805-6e1775721111", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Analysis Services", "MeterId": "8e338e85-4baa-4d2b-b688-9b9ef57414d8", "MeterName": "Developer (Hours)", "MeterRates": { "0": 0.066 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Tabular", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c9711c6c-2fb5-4ff1-ad23-17e9beab62ba", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cde95cc6-ef30-4b41-96e0-90def531e381", "MeterName": "Compute Hours", "MeterRates": { "0": 2.68 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fd90cfda-a664-48f9-a4e8-1064566faea9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.598 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4d0f8458-89c7-4ac4-a7f7-14c39f4dda0d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0975 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9c7985a2-b936-41ce-84eb-3b156ecf0100", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "8b4daf38-f4d8-41a9-b500-270a563b1169", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "caa99e81-fbba-459b-a269-36d39b4a7472", "MeterName": "Messages (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "9ae0f39a-5453-4109-85b1-7a5d0e14c451", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d8d65195-870b-4a99-8798-e784d210e615", "MeterName": "Compute Hours", "MeterRates": { "0": 0.258 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "577e4b75-2b87-4de4-9e68-0075692545df", "MeterName": "Standard S1 (Units)", "MeterRates": { "0": 2.42 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "a435c5fc-1ab7-4be4-8cf4-223a670cae26", "MeterName": "Free (Units)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7eb49223-0e75-4ac0-9531-aff5d3e29c05", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c46a6b69-0318-4237-81ca-2f59d6cd40ce", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 112.5 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "767e96b8-656b-4d0a-b275-92ec00b9d08a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.24 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e5c6983e-1748-4a89-8f6d-8a28a3db7f64", "MeterName": "Compute Hours", "MeterRates": { "0": 0.884 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6413bc9f-b929-4d93-b0c6-f37fc0e7bad2", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cc6389e3-71bb-4c49-ba9a-ff54199ea600", "MeterName": "Compute Hours", "MeterRates": { "0": 12.315 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "G5 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5933e7cb-40ef-40d7-b835-924fb7b9f114", "MeterName": "Compute Hours", "MeterRates": { "0": 2.785 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "378ae26e-4328-424a-a19b-d7f9cf39610e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0ce1a04a-27bd-45f8-9def-affe0231b7ee", "MeterName": "Compute Hours", "MeterRates": { "0": 1.387 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "80ab921a-b92c-4d26-ac96-944bb3c932a3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.44 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b6acd199-645f-438b-88a3-490963d9379e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4d56d61f-ea3c-4f8e-a7cd-92e547efd4b0", "MeterName": "Compute Hours", "MeterRates": { "0": 1.749 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6bb99524-6633-4cf1-9a39-712256b833e8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5ac72f6d-067d-4910-bd39-2b5d8de39b6f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c90286c8-adf0-438e-a257-4468387df385", "MeterName": "Basic Gateway Hours", "MeterRates": { "0": 0.036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd7cbe16-51d8-4a11-81e6-aa2960683d33", "MeterName": "Compute Hours", "MeterRates": { "0": 2.475 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV24 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9230da20-e882-439d-bd40-14f5f65d97f1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8af30efd-d700-4bda-aa15-605683060c83", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "876d852a-fc2e-45f5-8c18-31a2158b6555", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d9c3a20e-e4af-4989-ba38-38e5f263d673", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.037 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "739bd0c7-f91d-4770-89d3-2d32ecc27573", "MeterName": "Compute Hours", "MeterRates": { "0": 2.267 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "22e34bb4-7687-49ad-8a3f-a317de55ff19", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0655 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a8fcd27d-ff1b-44d2-a9d6-cf6773a60aee", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 548.856 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "83b369ee-aa29-4b3a-9421-b8e7ffa27fbe", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 18.75 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "74b37d80-0208-4505-b6de-01c0aa7e7ccb", "MeterName": "Compute Hours", "MeterRates": { "0": 10.1568 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "48f97703-133e-47e8-acd2-0e6fcbfc82bb", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 411.656 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fa9dc70f-f562-44af-b965-b4576aefed95", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b381d19-e434-4bd1-8ddb-6bd522f3d298", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ab5b4394-b77a-4139-9457-ce65a0032ac9", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0706 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d52bfc75-dbab-4e07-a660-eb1693aa8d11", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "aa57abaf-ec18-4387-9348-07b177eab8db", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "bd46a1a7-70fe-488c-bdab-8bc27b9a07bd", "MeterName": "Standard S3 (Units)", "MeterRates": { "0": 270.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Autosuggest APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b907ef15-160d-4e7b-886b-53fb9bce4378", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0df258fe-cce3-421a-9ff4-4e50143e7eb5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.435 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e8f8c147-48fb-470b-ba4f-42d2778901f9", "MeterName": "Premium Unlimited Data - 100 Mbps", "MeterRates": { "0": 1475.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "33287f2a-0956-486c-b582-7a52b7c958b1", "MeterName": "Compute Hours", "MeterRates": { "0": 12.6 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (24 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "254cf0a1-1016-4f1d-81a5-2ec1551c6138", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "17b1cd54-1d43-4eb0-9920-b52c92a72b1e", "MeterName": "S2 Overage (1 Million Characters)", "MeterRates": { "0": 8.22 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "1M Characters" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "007b1c5e-cffc-4d20-b973-bb500d3a48ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.224 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d3103db5-2146-405b-9e46-342ba37f3c30", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f3217962-eb27-4458-b0bf-4590d734e4bc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.808 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8c244100-15f8-44bf-a154-889edac41c7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2fd570c1-302d-4f6e-ba43-99bdb401a4ec", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "76b1d83a-bc99-47c5-8d61-220e46cbe29d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "f1b450b4-7ad0-4b8a-9a10-96395fe8b67d", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.366 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d3be2491-c484-4e6b-a945-5ab2a16c1ba3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cd5ce06c-9ea1-4057-9ead-ca3e1074ada3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8489f14d-a5fb-432c-813e-173e65af4534", "MeterName": "Compute Hours", "MeterRates": { "0": 1.22 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ed5ea410-f2d6-45fa-9fcc-5ff1621c874d", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0484 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "91499451-bdef-4245-a396-391186f0c32d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.292 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fee0384b-8a42-41f0-a57a-154df6aa58bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.356 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d97ccd1e-c3f8-410a-9eb0-477cfc09332b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1d1812b0-6fd1-4f65-92c8-ee34be0cfb2e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9438a523-ecc8-4d27-96e0-fb2fb560a3a0", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "499cc0c4-cd9e-4d5f-bece-04b5562b2453", "MeterName": "MSFT Peering Metered Data 2 Gbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1990d677-c7a6-4535-aaa4-ff285544e837", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.015 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "10e6da54-063a-43a5-90c8-f44e452eda5a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.56 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9f3f7e8c-f456-4832-b83b-d67d9f3f8bb2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4d87714d-b231-4f85-8d20-247325b0e8ea", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "09204cf8-756a-4a41-baee-44b97084a0fd", "MeterName": "Compute Hours", "MeterRates": { "0": 3.08 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4ef99f5c-eac5-4de2-8002-33b1bd67594d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.264 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cd6819db-f81f-4128-8fa1-83e77d4426bb", "MeterName": "Compute Hours", "MeterRates": { "0": 2.236 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1d67db70-49a7-43bc-9e9b-f0d220770167", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.01496 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f16c5954-aa3e-44b3-b21d-28bdde7780ff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.068 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "bb1f930d-9a60-4d43-8120-383fa2095a7f", "MeterName": "MSFT Peering Metered Data 50 Mbps", "MeterRates": { "0": 55.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5b84dfc9-3ec3-401b-bf7c-a28baf971309", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "171e55bc-69b4-4321-9bc4-badf6be18d12", "MeterName": "Compute Hours", "MeterRates": { "0": 0.441 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ab491206-a35e-4494-ba88-6eae8cab5fc4", "MeterName": "Compute Hours", "MeterRates": { "0": 3.254 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4c646104-bbff-4be4-80e9-eb3b46e66dc3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.457 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2bb72616-fe42-493b-acc8-a7e469c1d10b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.25 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6dae61c9-d6c7-4a79-b4d5-08dc2772365a", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9299c6aa-2ffd-4c43-8651-d8fdc7b605e5", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "54e8283a-8b9d-4811-89a7-d278869e234c", "MeterName": "Metered Data - 5 Gbps", "MeterRates": { "0": 2180.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Integration", "MeterId": "7f58d3b3-5084-4cc1-b67b-6811aa90e0fe", "MeterName": "Developer BizTalk Units", "MeterRates": { "0": 0.09 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Services", "MeterTags": [], "Unit": "Unit Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "37951661-14a9-4902-b792-fe93c06db5f5", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0bb04aa4-6d14-4a5a-98e6-1a08cd41e304", "MeterName": "Compute Hours", "MeterRates": { "0": 1.551 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4798806-f76e-4a79-bb4a-4106f95ac4a2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.084 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC6 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2c38f6f1-08ae-4f71-be2a-90c399f6678d", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.156 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d00976a4-627e-4d90-aac4-c3a48a545baa", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "91fa5b91-a5c5-4e72-af7c-461c8e0aaaf1", "MeterName": "Premium Elastic Database Existence", "MeterRates": { "0": 0.4435 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "4c821f32-3dfc-4d0d-8993-9d29213cfa0a", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1673181d-64fd-4161-8d99-32f0fd6216b8", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.163 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "196c25b8-32a8-4de5-934f-b9596864d163", "MeterName": "Compute Hours", "MeterRates": { "0": 1.853 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6c6af78e-38c8-4d77-a369-089ec8684db1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.588 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "32a71824-3409-4f98-a230-206a9e2c7276", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4742b266-e4d5-41f8-a0db-2729b86b6a7d", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 438.176 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "62c64b6c-4033-4e20-ab33-9e81271ac12a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "8f967c58-b144-4bd7-8882-8bf02767c839", "MeterName": "Zones", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "DNS", "MeterTags": [], "Unit": "DNS Zones" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99f7b160-15e4-42c3-ac14-f8fec9161286", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c6cfc1de-0f0e-4801-bccc-8b96d4985e0e", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 88.594 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "616c2a83-75fa-4dda-b521-f0d823db9171", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "01ea797c-dda2-42cb-85bd-8aca8726752a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "713a9945-7322-4c6f-aff4-5f40a494d046", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b0e46a05-2eb1-41a3-bffe-fd8c117373a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "39f5d203-ea5d-47aa-8d8d-f218979237b3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.752 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "9e34aff8-7cd8-4462-8672-8a8611458f3d", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6ecfdba6-a686-4325-9381-cbab8f45ddea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c2ecbbbe-3acf-47a6-947e-5993860a45cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.888 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ed8a651a-e0a3-4de6-a8ae-3b4ce8cb72cf", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "10f9c657-5ede-47f6-a8e5-337a4a7d7b1e", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9e436e9c-9852-470a-9baf-2d79d5f4fa65", "MeterName": "Compute Hours", "MeterRates": { "0": 2.484 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 100.0, "MeterCategory": "App Services", "MeterId": "e0d5dad9-c5ce-433d-bea3-2b4c699c3d5e", "MeterName": "Active Users", "MeterRates": { "0": 0.01 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Mobile Engagement", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7c3e70b9-0447-45b1-8814-f895758bb050", "MeterName": "Compute Hours", "MeterRates": { "0": 2.73 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV12 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b79ddebf-0377-428e-8ecf-830f49e963c6", "MeterName": "Compute Hours", "MeterRates": { "0": 12.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (32 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "92bd3fb5-8753-4b26-9df3-e3d4150c0d82", "MeterName": "Compute Hours", "MeterRates": { "0": 0.73 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d6a436c9-342b-4a01-80bb-28cff2f170ac", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "06cd85e2-e7d6-49a3-bc94-2c31c8f7d433", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2735169c-ee53-4857-b649-911871cf1a40", "MeterName": "Compute Hours", "MeterRates": { "0": 0.575 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "87503d88-4da3-474a-85e6-480d8bf131f6", "MeterName": "Compute Hours", "MeterRates": { "0": 4.57 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b5120ce1-6521-489c-8654-b3d86894b3e3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.111 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "812a4cb1-2073-4798-9b85-12403bf0e10a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.452 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cedd8f26-0ac5-4701-bf1c-c3db8ca4ae9d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.607 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e5960556-fee3-41d8-9329-ae68f9aee68e", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9058f27f-aaa8-4147-98e9-bf8910101455", "MeterName": "Compute Hours", "MeterRates": { "0": 1.33 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "172469b8-5df4-4d98-a122-d0b5b85db747", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e2e9a516-56f0-42b8-b5ae-46f3c8031a89", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "c6b26e5e-174d-43b9-a4f6-177495eaff75", "MeterName": "Premium CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.34 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c40beff6-983d-4dc7-9be6-16d19a9fad7a", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 112.5 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "200aa0bb-a796-4a56-8fc9-8923633e8ca3", "MeterName": "Compute Hours", "MeterRates": { "0": 5.28 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "747b7ae2-1334-4818-8b89-071fd47e2b95", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "L SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "dae16e20-14b4-4e7a-b92d-888fc0dbe3b3", "MeterName": "Wildcard SAN (Units)", "MeterRates": { "0": 1950.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "S2 HTTPS Certificates", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "761e0657-8fec-4840-a7be-b7099817f573", "MeterName": "Compute Hours", "MeterRates": { "0": 0.119 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5b69bef7-ee70-4b02-89b8-3b3dd5ddcc00", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "19713ebb-dcd4-49c0-aab7-f94d918abf42", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "690e36d5-35b1-4f48-8388-af55eee973b2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.327 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dd364a43-b62b-488e-b4cc-f32eb80ef3e9", "MeterName": "Basic Elastic Database Existence", "MeterRates": { "0": 0.0193 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "b716ab59-2f38-4f5e-89a6-e8803311a749", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.375 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a65b178-2133-400b-8e4c-7b8eeda86d81", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c68c2804-7ee9-41e9-a4c7-1082df6b4b7e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2375 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ddfbd821-4670-40b9-bee6-408fec422e7a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.443 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "40bdb3b2-5577-4448-8614-398b4b63b7ac", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A10 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "59f510fd-2158-4a48-aae5-c75b7527b6a8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.446 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "46b89bd8-182a-4418-8feb-8242b1c97461", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b73c4c98-f0b9-4671-972f-6973689cbd98", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d0b04ace-4151-4dc3-94fb-89346c04b8e2", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 18.75 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c028d478-c49d-4e5b-9c82-116d4b30fe9b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1894e023-9852-4e33-8d0b-8c8fa480c7d8", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e284fd51-37b0-47c8-9219-76edfac28734", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.07 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "70ccc326-3eb4-4111-bb1d-d035865bf993", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "36b77e87-4987-4d19-9c49-319e9d55c296", "MeterName": "Compute Hours", "MeterRates": { "0": 5.0784 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e7056c15-dc2d-4913-8b0e-06fd876a88ea", "MeterName": "Standard Managed Disk/S4 (Units)", "MeterRates": { "0": 0.845 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a27a89b0-76d1-4b4f-a39d-76f469f01b70", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 6.048 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9952ec9f-916b-46f6-816f-4a1fef973327", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 499.982 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "81cdc11f-5653-4c41-ba45-7fb2d7db5f01", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "31997d1b-4106-4d0f-961d-782c9667ba6a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.675 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "65bc97c8-cdaa-4c17-acff-7d80c9f6dfac", "MeterName": "Compute Hours", "MeterRates": { "0": 0.586 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1b0dc313-f85f-46e4-aef1-3ef953281047", "MeterName": "Compute Hours", "MeterRates": { "0": 5.978 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e13adbc5-3ece-44fb-b579-1aaf67171eae", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 148.68 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "25a8afab-267f-4272-8bf1-12be387604be", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0413 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "26af5afe-468e-4c09-b45f-cded010f0ef4", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.145 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c361d09e-c625-483b-88f5-79ae9026c68b", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.039 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "af5d6bd0-7880-47f7-b79d-0d4cacb3b9e7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.575 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ed642548-1aea-41af-8416-200d47c7d39e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (6 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "794dcb90-0793-43e6-9909-70d29974e56d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (6 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fe7a13af-d09a-4dc9-87f5-4360b9e3e84e", "MeterName": "DWU", "MeterRates": { "0": 1.3307 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1af1ffa0-3398-4d72-ad92-41de56d854cd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08184 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c7f09e46-ad79-4984-89f4-77ebebe828e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4392 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57d93ed9-2467-4203-8daf-8c80c4aa98c4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.932 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "50d55675-fcb8-4354-a4fe-eb8c97a5f8b1", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.288 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60a4601f-93c7-462d-88a6-f4affb5f3d79", "MeterName": "Compute Hours", "MeterRates": { "0": 0.075 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f0a26d6-1731-417c-929e-c39b74c07219", "MeterName": "Compute Hours", "MeterRates": { "0": 0.61875 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ede0a17e-2710-42e3-9dec-52b599246828", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard and Weblogic Server Standard (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72a281ba-5a01-41bb-9a4b-2660ce110dc2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.071 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a2614b07-eb8f-443c-8f4e-1b3be07eab51", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.06 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d45c2320-4bf0-4c06-92f7-86ff495bfe9c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2f98d9e0-efbf-4043-ab55-9d5c9fc8de76", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8af4705b-fbeb-4086-8a40-ce9288bb9a0e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.351 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "7f02c835-8cdd-42c3-b3d6-676aa3b99a8e", "MeterName": "Standard C6 (Hours)", "MeterRates": { "0": 2.625 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5ea68dc3-5789-4f1f-875b-44ed4198255b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.356 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7ed5641a-0077-4aef-8878-a8bae9ed6e2b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3c261d7d-f303-4cee-83ed-d8b7bd606b1d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.132 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "81e3c8e4-c529-4a9b-b060-dd4181dcb4ee", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.376 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7f18b739-dc2d-439c-9062-ae5a9ee42205", "MeterName": "Compute Hours", "MeterRates": { "0": 0.37 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d96f1e8f-b4cb-4a24-8ab7-b20f4327ac1b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (6 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "930caaca-5f12-4ecb-a82b-984fee8af988", "MeterName": "Compute Hours", "MeterRates": { "0": 0.242 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57929354-a1fa-4827-af2f-952156021612", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "47ce0488-328e-4f4c-b03d-422842d6e3a1", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "314ac17c-0b11-4513-8be2-363b9fe40e77", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 16.5 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "30cf8266-ff5a-4f43-aa52-fa4d080ee691", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.605 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8946416-b0e7-4a8f-b89c-66f49d7742d3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.536 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2437caf-0a07-40ad-ab87-f7282fedf031", "MeterName": "Compute Hours", "MeterRates": { "0": 0.313 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc03c0ba-c517-48b8-9253-2b7e7b6b7633", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "44b17efc-018c-4da5-8696-98922dd0ff76", "MeterName": "Compute Hours", "MeterRates": { "0": 1.793 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8609a286-12c1-47b1-a299-e30cd9ba01d1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "41b9853e-a81e-4a11-a548-77473a656a73", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.032 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c59f00bc-78a3-44d1-80de-38d289063522", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.2038 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "edc74778-714f-4c0a-bea8-c9298f96b447", "MeterName": "Premium Unlimited Data - 10 Gbps", "MeterRates": { "0": 54300.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1256f12f-8cb3-40a0-88be-fa1bf3be3fbb", "MeterName": "Compute Hours", "MeterRates": { "0": 1.551 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "cd87d046-4b62-4f01-b50c-0f350da7c574", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a132330d-b04f-41c7-8de3-4c17db14294a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.804 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c2a1fffe-383e-4f1e-b08d-48074117d1af", "MeterName": "Compute Hours", "MeterRates": { "0": 1.032 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "42a5d99e-5f77-4f56-98c2-08b2db5b7f95", "MeterName": "Unlimited Data - 100 Mbps", "MeterRates": { "0": 575.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cc84f2f5-c33f-41c9-ba16-a616f9f9cadd", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 72.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "358f1f1e-6d6c-4373-b8ed-908d5fdc8c68", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "f2dee52c-2ead-4685-b743-d2cac3073ded", "MeterName": "Standard Automation Unit", "MeterRates": { "0": 20.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Automation", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3ce92048-3f40-4096-8be1-f396e3dc23f7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.672 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2a93ebad-7aeb-4ae2-9ff5-99e5f10f70ed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.233 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e17e579f-adb6-4068-a2a2-6fcd9d6723ce", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.177 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "11a9e87f-258d-4092-8108-0bbc3af4b012", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ca1abbca-7110-4bd1-ae63-fcbe038fde4a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.119 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "60bd8863-c921-488a-bb52-24f9bccb436d", "MeterName": "Compute Hours", "MeterRates": { "0": 3.043 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d09e639b-288f-4571-abbc-e1f42f934138", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0264 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a97168b1-7066-4da9-a035-cd5b4fec4e68", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8c8504dc-d1e2-4586-bd49-306cc22246a7", "MeterName": "Compute Hours", "MeterRates": { "0": 3.19 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4cb1dfe9-fcce-4260-9586-f504be3cb1c5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0e3a3c0c-b919-46d0-af96-c53285007dd2", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 5.3226 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d35bf47c-2785-430f-906a-da02524ba0d1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.645 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "358db962-a2e1-4904-b09f-dc1b070b322d", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.16 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d10dad3-0383-433b-8fbd-2dbd510a3d7d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.093 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0c39ace3-f009-4f3e-b0ff-ed336bbe658b", "MeterName": "Basic Elastic Database Existence", "MeterRates": { "0": 0.0184 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d6f15c7c-326e-4fdd-99a2-b962ee65399a", "MeterName": "Compute Hours", "MeterRates": { "0": 3.065 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1be90034-f439-4135-b9b8-6329123ca867", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c2ca408c-9707-4b1e-ac8a-b2c4989ca405", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.1136 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "99354be6-a7d8-4647-a20a-d2f300a9a9fa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "264a4a65-0528-41ba-a814-eb8d94f6ed14", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.055 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5eb50509-d65c-4f73-90a3-c6ee7d170e51", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 6.048 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cfb41775-3fdf-4fd7-93ff-de384d1bf014", "MeterName": "Compute Hours", "MeterRates": { "0": 2.351 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c82d4ba0-9629-45ff-9f73-a9e64afef5f4", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 13.5 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ad8b9e62-5b73-4de3-84ca-081df0a58adf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.585 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "90abe154-a008-4926-8400-58ad762a5e1d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "863d4bfe-32b4-48be-818e-d04b3ea6ff3b", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 193.74 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4511d5dc-c429-4271-b631-f5c3a6fe92f1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.396 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "89b769d0-4522-4dbd-9395-c67e4dee596e", "MeterName": "Data Processed (GB)", "MeterRates": { "0": 0.001 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Stream Analytics", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "845635b1-577e-4fc4-87d9-55dbf4b284e7", "MeterName": "MSFT Peering Unlimited Data 500 Mbps", "MeterRates": { "0": 5200.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8737ce3e-df4e-402d-8328-03cf1d544ee5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.057 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "426bc81e-8a78-4bf3-a8a8-c862324e2fb7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.249 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e452c905-a88b-4b71-9711-4e13c3f38098", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b37c324b-e6d9-4854-ba4e-4038b2208aae", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ee872742-aec8-4cbe-b674-e4773401df36", "MeterName": "Compute Hours", "MeterRates": { "0": 0.278 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7befeed2-59c7-4292-a6dc-50e6fcddce5d", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.7685 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "3244138c-76e9-4c90-9aab-954fde2ba7e7", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "cbd5bdb0-9cd0-4a36-b39b-4620a16116f2", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.033 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5002af8a-185b-4711-b1fe-95dd014d70e1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.256 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (32 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 1000.0, "MeterCategory": "Service Bus", "MeterId": "85f84482-123e-44a9-a2d5-cb53f2abe0f8", "MeterName": "Connections", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Messaging", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9e250639-2880-47d3-be00-6e2e538c6361", "MeterName": "Compute Hours", "MeterRates": { "0": 0.9 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC6 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b27247ee-a18d-4dd2-8b76-2e41bd30403f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.47 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "892fa864-ffca-4ab8-b3c9-2bb97f3fcc53", "MeterName": "Compute Hours", "MeterRates": { "0": 0.223 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "431ad86c-330b-49e5-a867-4cb68ef7e1bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "fdad599c-0589-42c4-8f8b-011e214baffa", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4562b9fd-4e8d-4391-8956-4ee862303a92", "MeterName": "Compute Hours", "MeterRates": { "0": 0.127 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7f5d9ed6-3ee7-453c-85a7-8aa5212a949f", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.477 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "bbef7984-0aad-47fd-87ae-ca432abca906", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "80d5d1d6-2147-4649-ae35-3c1f21156168", "MeterName": "Compute Hours", "MeterRates": { "0": 1.553 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "9d5aa7b5-5fd6-4784-b0ed-578f4468ad34", "MeterName": "Basic C3 (Hours)", "MeterRates": { "0": 0.225 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "19a0de76-1995-4ea8-8cd1-7c8a6931e3c1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "429a3742-bf40-4a16-868a-4a476c43caf0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "238bc0f8-d9a0-4260-86d1-04deeef23538", "MeterName": "Listener Units", "MeterRates": { "0": 0.00672 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Hybrid Connections", "MeterTags": [], "Unit": "Hourly Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "19eabdcf-9aa8-4211-b1c0-053a4c448705", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c29bdbe6-a8d1-4001-8b41-7c93b98a011f", "MeterName": "Compute Hours", "MeterRates": { "0": 11.59 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7b8ac714-fe76-4b43-820c-7a95720d4deb", "MeterName": "Compute Hours", "MeterRates": { "0": 1.478 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dfa19b87-291a-4ded-9cd6-70e2ae924cde", "MeterName": "Compute Hours", "MeterRates": { "0": 1.61 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "06a1fe56-789f-4270-9889-355d487ef8cc", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "01fb268f-b2ac-4f77-be63-80ce85a109c0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.646 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0500c456-c308-414e-83ab-a2950e3e019e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Enterprise (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "8fbcd0b0-01a3-4601-87f0-7e653955a56f", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.504 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "55361ac4-efc7-45d1-902f-0a5fe0810483", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5c2b734d-9779-461f-8281-a6c89c7eadf0", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cd16b940-42b4-4c0c-a68a-1cee7d98c278", "MeterName": "Compute Hours", "MeterRates": { "0": 0.196 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f39242de-ab79-4dd9-98b0-9d5de6f0ea74", "MeterName": "Compute Hours", "MeterRates": { "0": 2.239 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "05c20f9f-5274-4468-9f77-055569de29e6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a835327f-c6fb-4d1a-a501-803dcb41e304", "MeterName": "Compute Hours", "MeterRates": { "0": 0.186 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Scheduler", "MeterId": "b6b48f3c-29e9-4ca3-94e6-2a34c9246dbc", "MeterName": "P10 Premium Scheduler Units", "MeterRates": { "0": 139.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1 Unit" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "68eafe48-33d4-45c0-9560-de4c644dd1a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.404 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bc07e09f-e3b5-45f5-8b8e-cd1ed044a8fb", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.009 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "52c400e7-7180-481b-8aa7-5c021661d031", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.42 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1e2cb6ad-9fb4-4387-bbf6-ca1d01bf471f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.284 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a9d77256-44b5-444a-a619-9b201d0fc250", "MeterName": "Compute Hours", "MeterRates": { "0": 1.4 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "11f46405-b184-4c05-a057-c9a9393b475e", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "9f511a75-8eac-415a-8f9c-f14a1e389534", "MeterName": "Premium Unlimited Data - 10 Gbps", "MeterRates": { "0": 85000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "39b82011-38f2-4cae-9c0d-91064387e8a9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A10 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "62d94a65-9300-48a6-8c15-0e70fc41eb44", "MeterName": "Throughput Units (Hours)", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Event Hubs", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c3507fa9-88fe-442a-a984-c3278345f51e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "bb26636e-2a51-4a05-bb07-fbabf122ad5a", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3886 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e829dd7e-41f0-46d4-bc84-1cc13791e254", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "28ffa039-bcad-4cbb-964e-fa8bd19aab5c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.678 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a0a1729d-abe9-4ab3-9934-fa48acebb542", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0425 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f262096a-bbd5-4a02-8c80-a802580a6955", "MeterName": "Compute Hours", "MeterRates": { "0": 0.248 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "79f04bb5-2872-4b4e-84c5-c6b6006b4503", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.12 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6cc3fdfd-45fb-430d-846d-f9ba872b2342", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0044 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f36a9a42-8b31-47ed-9359-2c59f30679e2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "36dd022a-c4b2-4f41-b568-4097435f21fb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a2e2d172-7807-4356-999b-3a68c77e336b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.872 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "26794da9-d7d7-4a2e-a445-920bb5fd274e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4f46e575-3dae-405c-9b96-473bb08f22a9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.288 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b24b3aa0-f4ff-4546-9bbd-562b193f9924", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.012 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82d05a20-6c8a-44bf-9f69-063eb6bc4708", "MeterName": "Compute Hours", "MeterRates": { "0": 1.062 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3ad586f4-1945-46f8-9a96-db723f5432a2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "42b49a56-132d-4182-8061-aec164a8a5a8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1d0eaa49-0140-4f00-8b6d-2aacfd087e78", "MeterName": "Compute Hours", "MeterRates": { "0": 0.256 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c1f13300-3206-4021-99b9-ccbe72f0aa1a", "MeterName": "Compute Hours", "MeterRates": { "0": 4.742 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e622c817-bae1-49eb-880f-63b0b362de8b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.68 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c1a39f2-b65a-4f4d-b3be-687d7492cb27", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "72f848e8-95a6-4852-8269-f631faa9e526", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.114 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b7012b7d-8eb6-44a4-aa78-0c62926fb867", "MeterName": "Compute Hours", "MeterRates": { "0": 0.297 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c1ca5d61-2679-4721-91b5-d5d46e3e879a", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 12.71 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "2b0abe88-ac18-40b3-9d4d-6c44fbd020e9", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.756 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0ad0f511-be51-4fcb-89cf-10708ad27346", "MeterName": "Compute Hours", "MeterRates": { "0": 0.193 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a62b8222-14da-4bc3-ac21-c1fe1f033c64", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7f3e1d2c-74d6-4f47-b1f5-f929290ece86", "MeterName": "Compute Hours", "MeterRates": { "0": 3.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (8 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb81f807-54b5-415c-b040-3b6fd796dd46", "MeterName": "Compute Hours", "MeterRates": { "0": 2.9205 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV24 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d04f9494-9489-4ccd-88e4-a58f94862ab2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.572 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "faa5e005-c170-489a-b16f-0ab1a26f7ee9", "MeterName": "Compute Hours", "MeterRates": { "0": 6.36 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV24 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e454e560-982c-45a9-973c-6c770b900b51", "MeterName": "Compute Hours", "MeterRates": { "0": 1.23 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Analysis Services", "MeterId": "13a77aea-c723-4d48-b479-56d36fa53e62", "MeterName": "Standard S4 (Hours)", "MeterRates": { "0": 4.055 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Tabular", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "de9a824e-53fe-4a07-b5a6-d8c4e4e7131b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.382 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "55b377e5-ccb8-45bb-b5ab-fbbb968ea549", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "234146dc-aa5d-4869-a6e9-8bba3469518a", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 255.6 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "030ca10f-6965-4498-9708-2bf551da5d0a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.672 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2003e5cd-be8f-4579-87f5-13c871736c73", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3b888881-ffcd-4e72-b297-d4908a9ab208", "MeterName": "Compute Hours", "MeterRates": { "0": 2.016 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "aa0cc21a-0c1f-4d46-a094-dbbc115583fc", "MeterName": "MSFT Peering Metered Data 100 Mbps", "MeterRates": { "0": 100.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4285e88e-f4b0-47ea-aac3-2c59a3dbff96", "MeterName": "Compute Hours", "MeterRates": { "0": 0.73 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "580ad661-e826-4429-9cc3-f71625c675c5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ecd2f1b6-d122-4ee5-8ae4-94241da0f433", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "546766c8-64f6-41ba-9131-5fac73e1339f", "MeterName": "DWU", "MeterRates": { "0": 1.2097 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b4b48b24-be05-4416-81d3-87de01a7c264", "MeterName": "Compute Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "88b82ac7-2d90-40ef-bcee-0ea460b2dd20", "MeterName": "Compute Hours", "MeterRates": { "0": 3.105 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99d5147d-a59a-4ae0-85fd-34cb380bb1e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.9 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "b6a278bc-4495-4a3d-b04e-c2fefdc81211", "MeterName": "Compute Hours", "MeterRates": { "0": 0.42 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "87d8c898-ebcf-4d50-b38d-b6f22a402168", "MeterName": "Compute Hours", "MeterRates": { "0": 0.315 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "274d03d5-3adb-417c-b3ce-926183c65736", "MeterName": "Compute Hours", "MeterRates": { "0": 4.532 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d767dfd0-59c2-4fd7-9cac-27c071c705aa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.732 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "16a2ce07-c52e-45ec-9e6e-4098373d79da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.376 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "34b50850-816f-4e69-95a8-b51f7323f162", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "26a235b5-5510-41e8-88be-40255a42fe2d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.349 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7c7d0d87-ac55-438a-b6f3-e966d249ef85", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c8c3c48-e326-483b-ad9d-77f111c281ba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.106 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e3538ce6-2940-4c6d-b344-3cab43f70c2a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ec4fd5c7-b1d2-4e32-a9eb-051225a5bca2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "4e177781-3d01-4e17-8cc9-5c45cdc8f286", "MeterName": "Standard S3 (Units)", "MeterRates": { "0": 40.33 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e30fa569-1169-4da8-976a-210293a26450", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "b1257e43-ccd7-4204-b012-27b569aec51b", "MeterName": "Content Moderator API (in 1000s)", "MeterRates": { "0": 0.8 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1K Transactions" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "484f644d-7ac8-42fd-a69b-73bf8fdf4707", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5331cf2d-64e2-4b55-9275-96d5f2219bee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6d5ccf45-e791-4988-83f5-13f1e72bdc6f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.346 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bdba065d-516d-41f0-a765-d5d1f58f94bf", "MeterName": "Compute Hours", "MeterRates": { "0": 2.962 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "55541c08-cd2b-4178-8542-cf4ffd395fd7", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "50869abf-e114-4b42-bbe3-65ee0ddbd03d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (6 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5e946cfc-acc9-4a96-895b-92386fa63c9c", "MeterName": "Standard IO - Queue Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "30338b16-1cc3-4500-9f22-142da3f4c4e8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.18 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "45082891-53c2-487a-989f-60cfca62080e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e6ee62e8-23fb-4f93-aa38-d77328ccc311", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0e600eec-b55f-4f9d-8c3a-1cc44ba59d5c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.139 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ca78bb15-7891-4974-83d9-52f48dfca598", "MeterName": "Wildcard SSL Certificate - 2 Year", "MeterRates": { "0": 539.98 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Certificates" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5e57c3f4-0d75-46c2-9447-0fe12c780959", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.26 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "afa891c0-2cf2-4c3d-b6ba-37b485ec529d", "MeterName": "Unlimited Data - 10 Gbps", "MeterRates": { "0": 82000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0f5b7a97-87a7-43e0-9085-6b6250f0243b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a0a0ccfb-be28-4c4c-b790-b1d2c0bf9efc", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 24.74 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7ca908b9-ecfc-410f-b8e5-f24421fa6dc6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9de7a7e9-d20b-4ba0-8dc0-53bbaddb39cb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.468 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "844aaf9e-c927-4a9f-8a43-0f13e0cc9c07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.184 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4d67ea2b-68a0-4ac5-9007-f4c0e6e8da74", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a9e19c9-d012-4ba6-bdeb-a34e02f79681", "MeterName": "Compute Hours", "MeterRates": { "0": 0.598 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "59aa598e-f397-4465-a4ed-203d3ef63a40", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 679.0171 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e4b5c66d-cbc1-4885-b05b-c14c3ffeef64", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "1ad2312d-b4a1-428e-972f-01d5b511c7f5", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "645b4218-8e32-48a9-9077-4041a2da7e19", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A8 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2d95e452-196f-4918-9d23-a2208e62dca9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.089 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f1cba056-ef57-4ce1-831b-b67168724adb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.11 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "48261267-71d7-4f04-ba3a-2836753ee159", "MeterName": "Premium Metered Data - 2 Gbps", "MeterRates": { "0": 3122.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2cf60c40-2347-4e28-8ac9-a8eba2c6c6f9", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 169.36 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "be63f96a-ef4b-42c1-9365-f9fa0e7431d0", "MeterName": "Standard IO - File List Operation Units (in 10,000s)", "MeterRates": { "0": 0.015 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8909ae3a-eccc-42a2-8979-aa43f8409053", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95c1ad0e-1b45-4425-86de-85df061728ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.42 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ef7de424-8c0a-43b9-9863-d82fe5e9443c", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.055 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "61ba1651-3fb8-4899-b7e6-858c5fd9c7df", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "35c93aa0-9c89-458b-8b7d-0ada03106576", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2712f78d-e46a-4917-b631-0b25463b7e69", "MeterName": "Basic Elastic Database Existence", "MeterRates": { "0": 0.02 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9854f879-aaf7-4ee5-bfb2-773778935894", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 54.69 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "53cf4291-a786-4eac-b1e0-30cb12af74db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.893 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "84a87019-a487-4fe4-acc5-980c744d4c44", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 10.6451 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9fc25025-8706-4aa1-8a43-ba50c742b240", "MeterName": "Compute Hours", "MeterRates": { "0": 1.025 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ff7b2f74-2259-49ab-84dc-f6b0b1882729", "MeterName": "Compute Hours", "MeterRates": { "0": 0.437 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "8d8533bf-5142-40f7-a670-cbb5abb21c12", "MeterName": "Premium P4 (Hours)", "MeterRates": { "0": 5.55 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "5d6f9d93-4839-483f-ab6e-89621ef315fd", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "f5b2bd35-220c-4dca-8541-d7e32e5b9de4", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "af7c3f78-e523-474c-917f-7d7100b09399", "MeterName": "Compute Hours", "MeterRates": { "0": 2.528 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0b98d3db-29ff-43fe-992c-c77e6b402900", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dfacce61-cae1-44de-9c39-1ada59995bda", "MeterName": "DWU", "MeterRates": { "0": 1.3912 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "06ece668-51e3-4103-9959-21e38c5ff40e", "MeterName": "Premium Unlimited Data - 50 Mbps", "MeterRates": { "0": 972.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8f551411-842b-4a4e-b184-21d11d6ccb53", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "722fc083-df70-41ab-99e4-c33d72a1eee4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "74c05f9e-ef82-46b4-82bd-022f1c6c4310", "MeterName": "Premium Unlimited Data - 1 Gbps", "MeterRates": { "0": 10150.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "434a43e4-0028-423e-877b-c6cd0d99b98e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "42d19c92-8376-4965-939e-1c147656adb2", "MeterName": "Premium Metered Data - 1 Gbps", "MeterRates": { "0": 1886.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "34a8c52d-943d-46c2-8168-4af851e02b87", "MeterName": "Compute Hours", "MeterRates": { "0": 3.505 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d4a51af5-1df1-4751-8177-2ab5801a92a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.701 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c70ef5d8-8452-4ce0-90db-c88dd28e4d83", "MeterName": "Compute Hours", "MeterRates": { "0": 2.156 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "36c961e5-3c53-4481-b339-a10c6fe0f491", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0043 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "42a99550-efdd-4a25-be57-4653acec19a9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.068 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8b44130d-9689-441a-88a9-0ee61aa53f33", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e058c6a6-1ec0-4f26-8eeb-0280e746374b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.304 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e2febc1d-cdda-483f-8349-519bf84457ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.264 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dbfc8837-f8dc-4008-ae39-13e81052cb67", "MeterName": "Compute Hours", "MeterRates": { "0": 0.375 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ca31f7d5-3c61-4c9b-beca-54b5bbb4eca4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.64 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e39c3838-26f3-48cc-943e-59847da39886", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.19 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9d12b1b2-80f8-488e-9a1c-18951a684bb0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d688b491-e031-4aa2-bb87-be3f346e2b8f", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0e03afd6-cb40-4a1b-9938-0bf4aaca3879", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "e6236d80-a06e-4aa1-a0af-f1d566b27093", "MeterName": "Standard API Management Units", "MeterRates": { "0": 699.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "API Management", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f42c8e3f-f071-417b-9ca1-b61e258dd898", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 49.82 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c3c75f61-3ad2-4c65-adfb-ea824f22ac2d", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "063f5816-fb30-49ac-b8f2-918422c5c9de", "MeterName": "MSFT Peering Metered Data 500 Mbps", "MeterRates": { "0": 290.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "98ec2a99-7b0f-46e4-9f53-f2b026367235", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9fcfb086-65c6-4393-9086-f788cd7c1f95", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "995600f2-fffe-475f-b81a-58b0204ac1ab", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6336 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4f372b18-055d-476f-bc60-a3122322a91f", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b7b55a7-769b-4926-8175-8d62227090a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "93a70ba2-693c-4b44-bbbf-fe6fc1d1dcea", "MeterName": "Compute Hours", "MeterRates": { "0": 2.363 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ebc7183b-3c67-4bb5-aab9-8e7c6f9c493e", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bb138fb6-f26d-484c-bc6d-3310f7eb29f8", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 496.7732 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "da3b2fcb-7438-4f14-ab45-e0d20a4eca50", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0887 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4e9ac498-5cae-47c4-a56e-81bf98dc47b9", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 144.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a411b52a-ff69-4fc6-a1af-10bd4d87c794", "MeterName": "Compute Hours", "MeterRates": { "0": 2.285 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "8555280b-a4b1-46fc-9678-b69953eb6b75", "MeterName": "S1 (1 Million Characters)", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "1M Characters" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "90616ca2-ad11-4399-ac22-538d2b55ff5e", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.0706 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "369314c0-2374-43a3-972b-c4ff2c225d90", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b215c4fe-e9db-438c-9f3c-8293ab7700a0", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.1533 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "524d6c11-79ad-4ace-ba3a-7c23a4823aaf", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 75.0 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9b21f9a8-2a79-4ff8-b86a-499b2e7a30e6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f1283491-f2b8-4b2c-a22b-27cdaf0d563d", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.08 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5229ef8a-9100-4374-b92b-9062612fb6d2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.396 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a251032a-48b2-400c-8ebd-3c53f513cd77", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 258.32 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b5f52b18-a942-407a-bc94-215fa27bfaeb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "85552f02-d42b-4eae-9078-a7c3df9b06bb", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d856e8e9-da35-4258-81f9-8833747ab079", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e5d88e13-47d7-4a38-85c7-6a6d24f6b525", "MeterName": "Compute Hours", "MeterRates": { "0": 0.378 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b7c8a680-223c-4672-a75d-b48e932305c7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "55fb12e5-df8c-4f46-92fc-a33632a9d273", "MeterName": "MSFT Peering Metered Data 200 Mbps", "MeterRates": { "0": 145.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd62571a-6493-4254-9876-fcd5f78de617", "MeterName": "Compute Hours", "MeterRates": { "0": 0.223 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1995377d-4b3a-4d40-bf55-cc6084aa291f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.343 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "42bb05e1-6f42-4de1-a6ba-7ffb976cb560", "MeterName": "Data Transfer In (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9fba7d18-ce24-4e1c-b0be-b9b1f84ee772", "MeterName": "Compute Hours", "MeterRates": { "0": 1.283 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a5ae1d7c-12ed-495a-82b5-5eef7d45c442", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "234e1e79-d850-472f-a433-75c88dd208ae", "MeterName": "Compute Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "806f0a00-7fbb-4f67-a61c-26adc81327a5", "MeterName": "Studio Experiment Compute Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4dd36e14-61a8-4f6b-8c9f-98933e487d7a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "73dd3c48-d078-4725-9621-1f517fce8601", "MeterName": "Compute Hours", "MeterRates": { "0": 2.168 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC12 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "845cd1d2-a94a-4064-949e-ba9d18fd6227", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c41ce691-40c6-4d0c-afc9-bc1debfc2590", "MeterName": "Compute Hours", "MeterRates": { "0": 0.802 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "678d0e8a-df5c-481c-b180-aaa17471b1e4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ed15abb6-887b-478d-930d-08a4ea2bb796", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "eceaeb07-3247-4e79-8999-7b2d83b4ca02", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.034 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dadee234-c5ef-47e0-bdea-5c3ba14f0a49", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 124.8 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "12f463c6-c70c-4bdd-be76-c187f1f9ddc1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.488 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b268871d-3d5f-4763-a841-2c96e71ebcfc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.86 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "13692c86-fc9f-45c8-8156-cdec45e44e01", "MeterName": "Compute Hours", "MeterRates": { "0": 0.473 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e3e8ad1e-318a-4438-8a9d-2d7a03d09294", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 67.91 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8cd914f7-c15c-48c6-ae4b-32a244e4250a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.267 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c61d4186-f542-4ddc-af12-68e97afef4b1", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.0725 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "66b4c631-0299-49aa-a466-e6c5056ab88c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.229 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7182cc47-b654-42be-bb55-b882b04cf83c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fc203689-76e7-4fbe-86b9-968d73231c00", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "391dd9ba-465c-41e8-8ac0-5c0d5c05e67b", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.22 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ee476978-129a-4676-bdc7-28119eb6fcd6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.316 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "65397054-e00d-421d-a130-a616d314f981", "MeterName": "Compute Hours", "MeterRates": { "0": 0.904 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "0f824807-2376-435c-95c9-f992b67a07b0", "MeterName": "Operations (in 10,000s)", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Key Vault", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6cf8e60f-65ff-4b3b-b0cb-a97173dc969f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "488e50ea-7a2d-42db-990a-2df9463c5731", "MeterName": "Compute Hours", "MeterRates": { "0": 1.188 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "87b3ed97-63d0-4fda-8f6e-02dddfada17e", "MeterName": "Compute Hours", "MeterRates": { "0": 4.742 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5c40bc3c-dac7-48f7-a80f-dae6ab91cba9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.198 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "753539b0-595e-4c15-bf48-76726398e42b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.056 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "387d3aed-a393-4ea0-9f6e-5fa4f4ed0484", "MeterName": "Compute Hours", "MeterRates": { "0": 0.125 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "57bd5019-bcfb-4876-927b-f1e95248e08e", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Batch", "MeterId": "93fae6e3-3d5e-46c6-970d-0b51abe0ce04", "MeterName": "SSD Based Instance Compute Hours", "MeterRates": { "0": 0.0175 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Batch", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9c72c2b0-fcbf-48f5-b633-32676663a2dc", "MeterName": "Compute Hours", "MeterRates": { "0": 2.064 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c5f0cf71-ff36-4731-ba91-444ccf0590e8", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5a1638f0-dd4a-4aa2-9fb6-3592b781a8c8", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b40c3368-de55-4653-b7fd-5d3faca0b1df", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fc6283ae-2f1b-4ec4-9347-ed21c271f1dc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9995cfdb-2107-4bb8-8045-9bddd1773493", "MeterName": "Compute Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "759260fa-ca1e-42df-b715-c28ce325161d", "MeterName": "Compute Hours", "MeterRates": { "0": 3.5 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f7b6aea-8b66-498f-84f5-5426daf851c7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "d49c9908-5da0-4a31-baa3-9b7872fc3d09", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.366 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "26511691-774c-474a-bb32-7b7b6c87d5f4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.976 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "802c6139-c535-4751-aee6-87f01ab0ef63", "MeterName": "Compute Hours", "MeterRates": { "0": 0.786 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6fe7781e-b466-423a-98e8-e0e4eeb82443", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c2eeb134-301e-469f-b9dd-d52aef79f3bf", "MeterName": "Compute Hours", "MeterRates": { "0": 1.215 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ee5e203e-6b6a-4ba2-961a-683698d03a02", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f3a71ea-5bd1-4da8-aade-12a0f85146d8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd70200c-38d2-464d-9302-7e2d76d50665", "MeterName": "Compute Hours", "MeterRates": { "0": 2.156 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "47882bde-5989-4bd3-abba-1f58a9d4d756", "MeterName": "Compute Hours", "MeterRates": { "0": 6.16 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "345ad7b8-47cf-4fbc-9817-7863abd2af4c", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 90.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "85a742f5-4a8f-4a11-8d48-1c6559889d0c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.29 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "14453a9b-31de-47d1-bb87-45c907cd50a8", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "S SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "78593a17-7836-4f5e-b5fd-bbea0ba5cc7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "fb4b3d8f-c59c-42c7-84f7-94b6e39f2606", "MeterName": "Automation DSC - Free", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Automation", "MeterTags": [], "Unit": "VM" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9ee47aa8-3dd6-40a2-8c6c-24205a413c7f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.96 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (12 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d9b8457f-9fd0-431f-b4e6-beb0315888a1", "MeterName": "Premium Unlimited Data - 2 Gbps", "MeterRates": { "0": 12900.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "acd02e3d-72dd-40c7-9060-81c097e2af06", "MeterName": "Compute Hours", "MeterRates": { "0": 2.336 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "81081980-07ad-4f03-a8f6-351cabe34d39", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.263 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "49338a46-b1dd-414a-9eb3-a1092502853c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.205 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "911f7f64-6ce5-4154-886d-755fb62826c9", "MeterName": "Premium Elastic Database Existence", "MeterRates": { "0": 0.504 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "3663b628-2bfa-4c14-8892-4c115e61192f", "MeterName": "Speaker Verification APIs (in 1,000s)", "MeterRates": { "0": 5.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000 APIs" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "981293da-2827-4c3e-8b2d-d7718b6c7368", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "dfae0fde-5e29-4474-8d6f-0544d28a8677", "MeterName": "MSFT Peering Unlimited Data 2 Gbps", "MeterRates": { "0": 17400.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "671037e8-34d3-4057-a80f-3c6aad6f5903", "MeterName": "Compute Hours", "MeterRates": { "0": 0.504 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "36128a91-1e63-40bb-9674-6c61e999b0ad", "MeterName": "Compute Hours", "MeterRates": { "0": 1.596 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e1cbf0a5-d4f8-410b-90fb-981da262be39", "MeterName": "Compute Hours", "MeterRates": { "0": 6.08 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "59e9a26d-4876-4692-b3b5-a92a47df92be", "MeterName": "MSFT Peering Unlimited Data 10 Gbps", "MeterRates": { "0": 51300.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9290be13-07f8-4691-80ca-1c1bfbc8ffe0", "MeterName": "Compute Hours", "MeterRates": { "0": 4.311 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "243a7ede-007c-474d-ae93-3a629da977e0", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "000e0d7d-c353-4741-9ffc-e9fcdaebf8f7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.424 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "d75614e9-9c15-4553-ba4b-fc22b16ebcf9", "MeterName": "Standard Overage (in 100,000s)", "MeterRates": { "0": 30.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Autosuggest API", "MeterTags": [], "Unit": "100K Transactions" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d11920c-3c98-4b9a-90ba-95822d443400", "MeterName": "Compute Hours", "MeterRates": { "0": 0.084 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82974b02-9f02-48c8-81d8-7abed5e0366a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1e32f8fb-14ef-4e37-8127-e56c9b71ce75", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1db8b679-c9a0-474d-b102-fee48a5684f5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.833 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "499a38b7-b11a-4b32-9ecd-bdcbc1a0748f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7d6f0f15-3c5e-4d6f-8283-d98b3d9ed347", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6c76daf0-aeb1-4238-b8b4-18820c91eeef", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e09f47c9-bc89-4ad3-a7b5-294a647c889b", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "35ad9fdc-5b71-4dc6-a9b7-7aaec976adca", "MeterName": "Standard S3 Overage API Compute Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "30cec371-2b13-44fd-8eac-521676e0bab5", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.161 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c2d3b4e8-a992-4bdf-b8f6-f1abe98b7a9d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8ba99860-6393-4364-af24-81793bb614af", "MeterName": "Compute Hours", "MeterRates": { "0": 2.795 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7286acf5-4659-44cf-8117-81687e89d598", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0ff2ef7e-ac54-4c59-9b1e-48d77e578d06", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4435cfb2-f4da-4070-86b6-2da0e9b2069b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a19ceba5-a164-4881-abbe-d9482ac8ac01", "MeterName": "Compute Hours", "MeterRates": { "0": 0.102 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d2130d8-3ae1-4438-91c4-ee4f90b80c37", "MeterName": "Compute Hours", "MeterRates": { "0": 1.516 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5ce1c654-7050-4663-b629-bcd12eb12287", "MeterName": "Wildcard SSL Certificate - 1 Year", "MeterRates": { "0": 299.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Certificates" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5f08fa38-ace4-4e75-b13f-ff37a34e0541", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "adaa00f8-749f-4ec5-a9c0-36141e8cc010", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "21b60375-5db5-4536-9623-1e94dd8c82ba", "MeterName": "S3 Overage (1 Million Characters)", "MeterRates": { "0": 6.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "1M Characters" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c02d68cf-36b2-476b-8854-66fcf7c4a921", "MeterName": "DWU", "MeterRates": { "0": 1.8146 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7caf87c6-82d3-4862-9d94-a05a41bf180f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5907b69-eb24-4a45-babf-1e34b86ad723", "MeterName": "Compute Hours", "MeterRates": { "0": 16.8 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (32 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2388a15b-1c42-4e8d-8ae8-69868b94455e", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.163 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8c2fec08-2cf4-4c5e-ad66-28d2621141ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce4a0abf-9245-44e2-9cbf-137f04491938", "MeterName": "Compute Hours", "MeterRates": { "0": 0.154 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4c4b11f-ca34-4165-b75e-629b3572aadd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.128 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0b7bee3d-3ed5-43a0-9798-08f694bb8c84", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "776a858f-25d6-428d-808a-aa4f2a954dac", "MeterName": "Compute Hours", "MeterRates": { "0": 1.1 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "b2b7a89d-3208-4450-ab5e-a857ce780715", "MeterName": "Premium P2 (Hours)", "MeterRates": { "0": 1.388 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4f6ae82d-1e88-4cb4-b4e7-93dae4083f97", "MeterName": "Compute Hours", "MeterRates": { "0": 5.0784 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4a3343ce-a1ab-46da-befe-8cb8e64396c7", "MeterName": "Compute Hours", "MeterRates": { "0": 5.027 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fa70198c-dfa3-40c3-835b-e2677dce2d91", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.107 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b2cffe2c-fa49-41e5-bdf8-59f74b3cb770", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 16.52 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d9ee7acd-f50e-4620-a895-52f23002d789", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f0f393c7-b999-46bb-a6a9-fadc085f45ab", "MeterName": "Compute Hours", "MeterRates": { "0": 1.92 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (16 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "aeb193e4-4c43-4255-8f0c-c7d7ce898316", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ba50fd90-a437-4a4f-bcdf-70eaf6751eef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.408 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Integration", "MeterId": "7485e33f-6be5-4a5c-aacf-08c2aec688f8", "MeterName": "Basic BizTalk Units", "MeterRates": { "0": 0.48 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Services", "MeterTags": [], "Unit": "Unit Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1e555ae2-05fd-493f-90cb-a8aaf83eeb93", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2a00fd31-1c03-49e3-ad32-928479d7a925", "MeterName": "Compute Hours", "MeterRates": { "0": 9.65 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "1fc19824-44b4-4247-b0c5-0137f98bfe7a", "MeterName": "S1 (Hours)", "MeterRates": { "0": 12.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "43c47123-353a-4b1e-8f4b-a15be1cc7ba6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.043 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fbe13d3c-0ac7-4f07-8f22-c70c9b41a83b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.367 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a4ec27b4-c834-47d0-9195-35143f8bc182", "MeterName": "Compute Hours", "MeterRates": { "0": 0.143 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ecf34d9e-0d4c-4051-be2a-138d4d83fb67", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a0915495-9565-4569-9179-cf2703f5d160", "MeterName": "Compute Hours", "MeterRates": { "0": 0.88 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "01e8eaee-ba76-4b8e-928b-0ca5a0d4358c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "54a377aa-8820-4916-a5ac-3b160c73d249", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.1948 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d3b65a9-3e55-43f2-bb10-09144daf94a9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.53 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "924bee71-5eb8-424f-83ed-a58823c33908", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "M SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2bfb3801-1ec2-4f66-8a7b-be2f01ae3b7a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.092 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ff4f37d3-8a5c-49dd-9303-a9547f7d598f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb5b077e-cadc-4a88-afbb-86151fe028bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a57441cd-6513-4e57-9a6f-bcac09315f4e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.975 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "152d2bf5-73db-43a0-8674-af33507558ea", "MeterName": "Compute Hours", "MeterRates": { "0": 2.065 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5fa93943-9970-49c1-b2ac-d3f3fb8e7818", "MeterName": "Compute Hours", "MeterRates": { "0": 0.327 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "0ee6fc6b-9705-427a-ab32-17598ededbea", "MeterName": "Indexer Input Minutes", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60bf2422-274b-43c5-97af-ce6cae691bc3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.65 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "97b39017-2e66-4b67-9f7d-8ec4dbf375de", "MeterName": "Compute Hours", "MeterRates": { "0": 1.188 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c4126ec0-f26e-4222-9774-bd40d36d46bc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9660d899-da2d-46e2-89fd-9bc046630414", "MeterName": "Compute Hours", "MeterRates": { "0": 0.293 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "795bbf88-99c1-46e4-8db7-4b27ce527c9d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.21 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6fed54e7-d7cb-4163-8a72-f1e324377146", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "de41ce76-7859-4333-b291-bf2cc454b955", "MeterName": "Compute Hours", "MeterRates": { "0": 9.348 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "965eb40d-f596-4240-aba1-b7ba8cc7e558", "MeterName": "Compute Hours", "MeterRates": { "0": 0.061 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "9dadd0dd-20c6-4898-be95-19a4089b678a", "MeterName": "Premium Metered Data - 50 Mbps", "MeterRates": { "0": 155.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "a7d3bf42-bc5c-479b-be12-78a6de16f85a", "MeterName": "Premium P3 (Hours)", "MeterRates": { "0": 2.885 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "56f176bc-7bbb-41de-b043-148ba6fb07ad", "MeterName": "Compute Hours", "MeterRates": { "0": 4.84 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a7cabf63-e8ad-4b56-bb1c-f8b9abce4448", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "41f467b0-5780-4c34-89ef-cbc454778514", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f7e7a2fc-3980-4718-be11-66edcec3bffd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7f627a53-5868-48d7-b4e5-7140894deede", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "df20461d-8344-4524-935c-2ed1094d4fef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.378 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "74c92629-8d27-4701-a6fd-c9966147e4bf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5f0abf97-90bc-4614-b49e-5f3806729b9d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.504 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4e9518b1-3f80-4e8c-be0e-ff53c44a243b", "MeterName": "Azure Endpoints", "MeterRates": { "0": 0.36 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Traffic Manager", "MeterTags": [], "Unit": "Azure Endpoints" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9d45f844-b959-4370-a73d-8922f30c41be", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "052b396c-1cad-4cb7-a60d-e6fe13b0f312", "MeterName": "Compute Hours", "MeterRates": { "0": 1.924 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "08bdde57-7811-467c-b4f7-ccc2e367eee7", "MeterName": "S2 Media Reserved Units", "MeterRates": { "0": 139.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c13850a7-fad1-4ae3-8d3b-8d2a55899548", "MeterName": "Compute Hours", "MeterRates": { "0": 0.77 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "69736010-807b-43e6-b519-a413cb864ca6", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.876 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a91ea88-4a32-4a59-92fa-351908fd0268", "MeterName": "Compute Hours", "MeterRates": { "0": 0.226 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "69d491a1-faad-43a9-b3aa-e3d2885b6efd", "MeterName": "Compute Hours", "MeterRates": { "0": 1.018 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e28527aa-ff33-49fa-aa98-6b2c5046a9d9", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.226 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Logic Apps", "MeterId": "155afecf-5804-4ca4-ae3d-2cff595ab8d4", "MeterName": "Actions", "MeterRates": { "0": 0.0008 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Logic Apps Actions", "MeterTags": [], "Unit": "Actions" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c40bd04e-b8e5-4d4a-a523-daeae986ef68", "MeterName": "Compute Hours", "MeterRates": { "0": 5.28 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "369ad022-e4e5-4239-9021-e4acce780b86", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e25bb519-8586-4cc6-81f5-ba9256351ded", "MeterName": "Compute Hours", "MeterRates": { "0": 0.294 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c32a4d92-6167-40f5-bda2-7017383f43e9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.23 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "018981ea-a504-4144-9ef4-bb4283d081c5", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.0767 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e7b71d28-8da5-4c96-9e56-28a23af25618", "MeterName": "Compute Hours", "MeterRates": { "0": 0.292 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "35e2af9d-6f9a-4427-9813-33d617fb2858", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 36.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "02b92ee0-5564-43d0-b768-9d92ee0b211d", "MeterName": "Compute Hours", "MeterRates": { "0": 5.584 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8dbf7cd3-d2fe-4080-8ddc-8f0578e2355b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b6b0549a-b11b-456d-a870-264cf7eea1c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7c8450b5-5d9f-4f4c-a9eb-5faf8aa4bd85", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "33ccb5ca-8fa8-4278-8aa2-006dc33d4c4f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9ee077eb-c902-46ef-b7f9-2caeade852e0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Insight and Analytics", "MeterId": "6a11eb4c-01de-4438-88e0-e95b41869197", "MeterName": "Included per Node (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "OMS Insight and Security Data", "MeterTags": [], "Unit": "1 GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f8dd8c8f-4ac6-49f1-ba01-38376b8347ae", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "048c136a-6670-4285-87c0-3f1b33a6be13", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.165 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3220582c-b918-4276-89ca-7a8c2c43c3aa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.266 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a151b8e-94a0-4df4-9c1a-18c24eaf41cc", "MeterName": "Compute Hours", "MeterRates": { "0": 3.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (32 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9c6406a5-7e50-4b14-ba0f-be602156c53e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.916 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7d468e0f-a7f5-4eb8-8b55-7604c2eedd8b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "a36d229a-595c-44ad-a66c-1287be4bf433", "MeterName": "S2 (Units)", "MeterRates": { "0": 500.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "86883060-6341-42fb-a4e9-00ee722214ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.175 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "34afb9b7-0917-4acd-a105-2fe2c0cf951d", "MeterName": "Compute Hours", "MeterRates": { "0": 4.532 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ad4d0278-4c8f-4298-a99b-1952ec4440b9", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5536 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "27f013da-7932-46ea-bebc-a11854dfa6b9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.73 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "cc2a802e-6a8d-47d8-a6aa-cecef8c6b0ec", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8704ae8-1b74-413e-9981-85179098e61c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.327 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6fee079b-45cd-4bd7-810a-3903ea962ebf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "de0d1714-0abe-4e75-bfdf-161b0d17656f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services Low Priority", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "93754c8b-f7c3-4a68-b6dd-42d760c338d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.326 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "839e838f-8288-49b2-a11d-7a6f076371db", "MeterName": "Basic C3 (Hours)", "MeterRates": { "0": 0.18 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "432cdeee-4034-4ddf-9ba4-9250a19b0d5f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c983130f-7497-4000-b12d-a884296a76b6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4ad28e15-4add-4f85-8472-365c30a7cf40", "MeterName": "Premium Metered Data - 5 Gbps", "MeterRates": { "0": 5180.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "802a9d10-e933-4e23-8728-8f7e3f71630c", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9efc0c87-afb5-40a4-80c5-1c647948083e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.124 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "a96e18a1-a1de-4a72-a5be-b8ccfcc03b1b", "MeterName": "Bing Speech Text to Speech (1,000s)", "MeterRates": { "0": 4.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "26586f97-b6fd-4bb5-9d05-1e11493cf746", "MeterName": "Compute Hours", "MeterRates": { "0": 0.324 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "188d6aac-56a9-49ef-ad33-eb55a09f62c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.625 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4b14a253-cdca-47a2-be9e-d082116f5e2d", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 499.982 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fc7c7c1e-10b2-45e1-8aa8-a5734d5c88c4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.238 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "50938df9-5452-4888-b712-64df5f66b386", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2d9e7c8f-0c58-46da-bb47-55a28e7ce605", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ab5b133b-d9da-4c2d-be66-0c3d70a8e69c", "MeterName": "Free Search Hour", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "287a6e61-483a-41f0-81db-807561e8d11b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.396 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "453633de-18ab-4057-acfb-3779dd691d5c", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0f0c5e45-2657-4afb-b27c-4526c9890705", "MeterName": "Compute Hours", "MeterRates": { "0": 1.25 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9caecc04-e579-4fd2-ab2c-0fd624e3487d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.033 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9cdb0b20-13e0-483c-a343-effdd69c7fdb", "MeterName": "Compute Hours", "MeterRates": { "0": 1.306 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "448e43c9-416f-4b53-be61-258f8197e4f1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.918 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 5.0, "MeterCategory": "Networking", "MeterId": "c089a13a-9dd0-44b5-aa9e-44a77bbd6788", "MeterName": "Data Transfer Out (GB)", "MeterRates": { "0": 0.181 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fbbde0ca-b8dd-4d55-99ba-00b28f18e442", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-06-12T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "297d6b49-87be-4b70-97fe-0fc31ec85287", "MeterName": "Device Handling (per device)", "MeterRates": { "0": 80.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Import/Export", "MeterTags": [], "Unit": "Devices" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "67706dc5-2a9e-4626-82f5-817a54343cf0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "50b5bb3a-bb93-42d7-8496-551f8c410dad", "MeterName": "Compute Hours", "MeterRates": { "0": 2.333 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "51b394a1-a487-4d04-883b-a38c04b1d9eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.229 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fdb1c7d9-6d00-407e-91fd-05133995489d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.387 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "37b7e74f-0401-47c1-93c3-dc767cb7d88a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "9052c099-4bbf-4f2a-82bd-11528aa590aa", "MeterName": "Basic C2 (Hours)", "MeterRates": { "0": 0.113 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d1ab384d-6dfb-4928-b52c-f88711c513ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.22 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "19814557-03dc-4347-bcb0-30a80c380264", "MeterName": "Compute Hours", "MeterRates": { "0": 0.62 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "43044ba5-b76c-4245-a512-aa310edeab17", "MeterName": "Compute Hours", "MeterRates": { "0": 0.744 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "02f80beb-65da-4fde-8fbb-484f460aa817", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "eae9321f-81e2-49be-8506-24a8334f735b", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 0.9677 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c492e654-0316-49dc-acfc-e8e8b2627679", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0604 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f2c23bda-95ea-4d1b-a3d3-0848a73824f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.516 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0e8e172f-a937-4a03-a5cb-654cf32a4214", "MeterName": "Compute Hours", "MeterRates": { "0": 2.655 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "462fb824-3bc1-4a25-800a-bf35ed4a62ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.336 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "2aeb42d2-e5ac-460c-ba22-353e39e145e0", "MeterName": "Unlimited Data - 10 Gbps", "MeterRates": { "0": 82000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4195bfe4-7809-467a-ad60-06cbe32f4df2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Xbox LIVE Game Services", "MeterId": "73d283ca-dee8-4d5c-b158-97092e970514", "MeterName": "Session Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4b6019d7-c01a-4a2e-ae61-866b3cc4626f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.759 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "896f4f68-ec9d-4536-be0c-d9f11e9817e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.372 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "88f17724-e3bb-40da-a64a-0d434c262b5d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9336a078-360c-4369-9af8-64c54fde50d1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.073 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "753b814e-f51e-4a40-89b9-64326323bb22", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 16.95 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "818def1d-898e-488e-9271-800928934f34", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6a03b082-449f-45dc-bc35-831c79d63a48", "MeterName": "Compute Hours", "MeterRates": { "0": 1.044 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6072b4dc-4fc0-4049-9ba6-8b3071f08e7b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.933 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A9 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b5ccee19-ffe6-428e-8d30-90d06ed29b5c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.137 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dd6cbd58-9b16-40e3-98e2-fe593cbe9f65", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "963edd42-e771-439f-b55a-0fad4bd529f0", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d3084fe4-630d-43a2-94e8-56f0178628f9", "MeterName": "Standard IO - Block Blob Write Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1d16b784-10fd-4f5b-ab50-ad4208aa67b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ce7867f9-3fb8-45b4-8eb4-914c7962dad5", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 282.263 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "b4444c45-98d0-4a04-b816-b688a17b844f", "MeterName": "S2 Overage (Hours)", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fe20832a-252a-43af-9269-07e72982e6cc", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "27fda617-6c9c-46f6-aa20-04cb4c172e45", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "76d38362-04a4-48f9-8fde-4d02595d51d2", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.605 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1a4a664f-4878-4b7e-9722-2a3217a0af55", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a8fccba6-1070-483d-a82b-88bbabcb409f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c9a03571-1c92-4c4e-bcb2-05884a8b4682", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.1612 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6d149115-d739-4a2d-a346-9412d3c93d32", "MeterName": "Compute Hours", "MeterRates": { "0": 2.462 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "20ec0aa5-d438-44e5-9298-c5bb719f97bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d88c5275-5b4a-488f-bad6-feb13d9012cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.671 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1c2b2552-514d-4522-a273-abe2257600b3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.292 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7580bd03-fedb-4309-9427-32e6051cfa64", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.1841 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d6e10a1e-f202-4ae1-bf9c-55c02fc3994a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b0834e3c-5dc4-4ed8-9835-05696a895dce", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 150.0 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "02a82cf5-c939-4cb1-9c37-5f58e3d1306f", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7af4c14d-6288-43d8-bfc7-bfbbab841c06", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "88d46227-e484-469e-a06a-6a31a14dc022", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0975 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Scheduler", "MeterId": "2d7eeaf7-2c4b-4229-a6a1-b6de0153f5d3", "MeterName": "Standard Scheduler Units", "MeterRates": { "0": 13.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1 Unit" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "003afa77-88c3-4da1-9464-69f643721f8b", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4667920a-730c-4ba1-9c51-f378d3d01e8e", "MeterName": "Compute Hours", "MeterRates": { "0": 4.07 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5687907-6698-4a18-9bde-2439048b9d25", "MeterName": "Compute Hours", "MeterRates": { "0": 0.316 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3af92420-ca25-4fbf-80e8-81c78658f18d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.135 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dddd59fb-03b9-494d-868a-11c2a079a777", "MeterName": "Compute Hours", "MeterRates": { "0": 2.44 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "be55d4e5-a0df-464f-bf7d-fb25088f83ed", "MeterName": "S3 (Units)", "MeterRates": { "0": 8000.0 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ed4deaec-a388-45a0-9874-9a3a785115f4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e819fae8-4d0a-47f0-9ee6-3d1635f22ca6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.219 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "953e7a10-9a6d-496f-ae0f-c6033373ea29", "MeterName": "Compute Hours", "MeterRates": { "0": 0.106 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96642a69-8e14-42ac-a2d1-74643d08e05c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.162 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a58844d-1516-403e-894d-951c57ec8a57", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a88fea88-bd2c-435e-a518-567213e92a15", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.015 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "baa3b29d-c50b-410e-8ce1-7674202ec46f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "043f9146-0dfe-4bfd-8040-07c7bdef37ab", "MeterName": "Compute Hours", "MeterRates": { "0": 0.038 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "ffbfdc29-bba7-4d67-858a-8125be34e183", "MeterName": "S4 Overage (Hours)", "MeterRates": { "0": 3.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cd7b802a-4007-464e-aef9-c3689a3b62a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.631 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e68b650b-fc82-4294-be36-c37dbb05f706", "MeterName": "Compute Hours", "MeterRates": { "0": 1.396 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4cac486-eec8-46e0-9f17-a5d996a5c1c6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.995 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "433d1ed7-7014-400f-8165-c58c06a04adb", "MeterName": "Premium P13 Database Days", "MeterRates": { "0": 369.03 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "26374bd8-72b9-42d3-9df6-d1af0c282e16", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "94f054a9-fd89-44b1-aa6b-704f68debb89", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 50.94 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "918bbeef-3e9a-4e71-b262-d2c2dc4437dd", "MeterName": "MSFT Peering Metered Data 10 Gbps", "MeterRates": { "0": 5000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "aa8010ed-4a97-4811-bc68-8e8f702faa5f", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A10 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6faa9139-4844-46cc-b961-d7b9a7750182", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 18.16 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e3aa4ebf-c1ab-4dc4-a587-4ab49cb54e0e", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1df60a0b-f88f-417a-86f7-ccc2b9659e7a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.681 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b113152b-5b7b-46f9-a7aa-e04841c3b420", "MeterName": "Compute Hours", "MeterRates": { "0": 1.242 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A10 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4016f50b-3a8d-4c37-929e-70871df54d82", "MeterName": "Compute Hours", "MeterRates": { "0": 0.944 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d9ca461c-ff9f-4b76-b1a0-61030f3f830d", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8ed862bd-4de2-4759-82e3-413992166752", "MeterName": "Compute Hours", "MeterRates": { "0": 1.018 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0fb8dbaf-54ee-4dd3-815b-80d7a073c909", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8fb53c97-faa6-49f8-8081-2a440b1b621c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e6c2f613-5014-4f7e-808f-78643434dc63", "MeterName": "Basic Search Hour", "MeterRates": { "0": 0.133 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "2b44acb5-fe98-4276-acd7-f86587760133", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cbcb7604-78d6-41e0-bdfe-f6676bff8829", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "eeb8053c-41a8-45a7-9e45-356cd5b172a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.404 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1535aa76-5517-4687-8a32-61dcd5a82f53", "MeterName": "Compute Hours", "MeterRates": { "0": 0.261 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6bf604a5-353c-441b-bee2-334e85f55aaa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5f2591e0-5697-477b-afb5-8f7d28f4155a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5a28a0dc-06ef-48ac-97d1-5787cc12d68e", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.055 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d1ff5194-e3d1-4d04-83f4-1b1fc80487fb", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7f125834-30d2-4be1-99d2-f1ea3cd24a6f", "MeterName": "Compute Hours", "MeterRates": { "0": 9.0024 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6bbddf59-3fce-4600-90bd-d8f1e565ebe9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.106 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c799ccdd-765e-432b-a4e9-db2d6b422ad8", "MeterName": "Compute Hours", "MeterRates": { "0": 2.267 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fab8b169-dc06-4675-86ef-0aed348f154e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "1fc5550f-2090-48d4-a564-5623eb4874c9", "MeterName": "Metered Data - 50 Mbps", "MeterRates": { "0": 55.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "290567e7-f130-4113-925a-1665a8b87edd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.698 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "93688123-e719-4e37-a654-e9c709bbeb57", "MeterName": "Standard S3 API Plan (Units)", "MeterRates": { "0": 322.58 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ca71cb21-0ba8-45d1-b746-3b9763de6414", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Enterprise (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e328e392-c7b5-4fea-b8ed-0a3ed5be87a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.142 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "ffb4ec45-369e-4e1a-b48a-94d7c220f7ff", "MeterName": "Basic C5 (Hours)", "MeterRates": { "0": 0.525 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "40ec5381-a01d-4bc0-bfc1-257378fa8da9", "MeterName": "Compute Hours", "MeterRates": { "0": 2.065 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2d6f5341-c2ae-4d34-afca-94391ff66d8b", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.039 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "893c116c-f39b-4568-9c85-52cf02bff44b", "MeterName": "Compute Hours", "MeterRates": { "0": 3.18 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV12 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "daec6c53-0399-4985-a370-1f7f2c361492", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.033 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fe6db92c-824e-4334-a7d1-6b2adcbf7a65", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.0645 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "10077071-cceb-410e-88b0-8ba90d5bbcd6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.099 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "494931a8-9f6c-4ad3-80b3-b1686cf0e64e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.44 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03d1a259-9237-4c00-8de3-9e6c73f58f59", "MeterName": "Compute Hours", "MeterRates": { "0": 0.225 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6ac925ed-5127-47bf-853f-f1883069cc11", "MeterName": "Compute Hours", "MeterRates": { "0": 3.95 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "122f793e-02e7-442c-a2bf-247ef0ce1342", "MeterName": "Compute Hours", "MeterRates": { "0": 0.947 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c069fd89-c3ce-4caa-b018-0bc26dd0a6a9", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 20.61 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ea80992b-9870-487e-b9c8-0d0e33b6867e", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.153 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fbe6007e-9bf8-4d51-89f9-6c15354bc9a4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.308 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e21b5b90-24d8-4c45-aa19-6278838de1ca", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "a4784e8f-3e5c-431f-9818-c8017ec735bd", "MeterName": "Advanced Analytics", "MeterRates": { "0": 99.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1 App" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "132ade99-fcb8-48d8-a971-23e81cbfc90a", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3d656db2-de1e-43a3-a987-5d2cda5d63ff", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e6153c90-a3c6-494c-98c7-c564f4f75ba2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.21 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "4efdf688-bbb0-4891-a548-603f335543c8", "MeterName": "S2 (Daily Units)", "MeterRates": { "0": 66.290323 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5f045ba8-1314-4b6c-adcb-58e180c5a7b5", "MeterName": "Compute Hours", "MeterRates": { "0": 2.56 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "806ac19b-c75f-4815-8b67-e116472b85da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "8a968a09-9805-4e74-9bc6-ab617cf292b0", "MeterName": "Metered Data - 200 Mbps", "MeterRates": { "0": 145.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fae11530-0266-4c53-9300-f6dd65a2bd53", "MeterName": "Compute Hours", "MeterRates": { "0": 0.696 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "db412d6a-6c34-47e0-a657-c42c0fff28cf", "MeterName": "Standard S1 (Units)", "MeterRates": { "0": 4.84 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b9f11db4-043b-4510-b6ba-1d758497b271", "MeterName": "Compute Hours", "MeterRates": { "0": 0.563 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e52303cd-3fad-457e-b2e4-14220ed42218", "MeterName": "Compute Hours", "MeterRates": { "0": 1.54 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d01e0c9c-66fc-45a0-91e0-43598bd91f8f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.886 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ed53f3ea-0e3c-47b3-9b98-c77adcbe2f86", "MeterName": "Compute Hours", "MeterRates": { "0": 0.305 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fd157900-03ef-4680-89aa-a24e299bf982", "MeterName": "1PB Commitment Tier", "MeterRates": { "0": 838.71 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b8961563-0af6-4c1e-a84c-7383c51c3b2b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b39cc42b-6545-439e-b77b-7f557f974b36", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4035ac14-a53f-4539-bef4-7b0b4b7f553a", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.143 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "36427a6f-ece6-4146-8f68-816e6f755ae9", "MeterName": "Metered Data - 50 Mbps", "MeterRates": { "0": 55.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f999926a-6006-4930-9570-51baeda16d80", "MeterName": "Compute Hours", "MeterRates": { "0": 0.875 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8873f8cb-95a1-49c4-ab72-b4936448d9ee", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a723b12a-d3e1-4572-ba2f-a0bda169d2ee", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 203.23 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "619643d8-d44c-4176-8acb-01b705f9e870", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.5536 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95ae23db-8670-485c-8cf7-eb316214b491", "MeterName": "Compute Hours", "MeterRates": { "0": 0.61 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "af1215fe-210e-430c-93ca-cdbd568ff09b", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 144.0 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "edc2da3b-3251-4f39-a114-f9792c29f288", "MeterName": "Compute Hours", "MeterRates": { "0": 2.933 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A9 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d006360b-cc81-4726-99e7-dd205004b9e7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.066 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "24fa7ce6-c64b-42c8-a9e4-619bb4d0f277", "MeterName": "Compute Hours", "MeterRates": { "0": 0.297 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "adc752ab-1cd8-4e30-957b-fc7d0321fa03", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0e56214f-e5f8-4a8d-8a16-487376556597", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 24.75 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ff59d3f4-f926-4c4e-a7d4-354ee5d24972", "MeterName": "Compute Hours", "MeterRates": { "0": 0.043 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "37e24472-a65b-435b-91bd-7c9c02e9085d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.478 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ddbf6d8-cc61-40e4-b848-0bbdf3fbc76c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.464 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1bac8c6e-3f6d-4514-9d57-022478c5a5da", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0732 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "cf47dddf-23f0-4f64-9a9b-617e3a192bdd", "MeterName": "Academic Knowledge API (in 1,000s)", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000 APIs" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "e931f717-a078-48f6-b4c2-e88da25c4e44", "MeterName": "Premium Live Encoder Input Hours", "MeterRates": { "0": 34.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "15bdc4fa-9389-4249-9e72-2bdf6586b156", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a9d73689-c3d8-4b76-be02-a972287443e9", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 541.9344 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fe72f2b5-30f6-4fd5-966c-5cda70a7f8a4", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 132.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "2d8562b6-beb9-4185-af16-aea3c1b4d434", "MeterName": "S3 (Daily Units)", "MeterRates": { "0": 193.548387 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "039ecc8a-25ab-4aa7-b578-5c8fa4c015a5", "MeterName": "Compute Hours", "MeterRates": { "0": 3.538 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "07135832-4a64-40b6-a093-30af0d2b6f54", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e6784273-54d0-4261-8734-1ef0bed373eb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f5c756b2-15b2-46cd-97b9-df8953afedd1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.025 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ee33f71b-4168-40b9-abcd-5c8f24a3331c", "MeterName": "Compute Hours", "MeterRates": { "0": 5.0784 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2236370b-4365-4a26-88d3-6913c6540d86", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a6c4068a-cbc2-4ce6-b8c5-910b6b7352c5", "MeterName": "Compute Hours", "MeterRates": { "0": 2.999 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "81438903-630b-41a2-a5cf-7ac65b61bd37", "MeterName": "Compute Hours", "MeterRates": { "0": 1.481 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b106c5ca-d9c4-4bee-9f5d-0b83fd7dbdd7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.482 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "36085934-4216-4d15-a257-9670b5eb12dc", "MeterName": "Archive (Hours)", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Event Hubs", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d5b2043-d7dc-4112-9d7a-16441dab7905", "MeterName": "Compute Hours", "MeterRates": { "0": 1.776 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fc2f46b2-91c1-4983-831c-796e6d88b640", "MeterName": "Compute Hours", "MeterRates": { "0": 1.482 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a83bd049-0f0b-4164-a69a-f7ba8eb11f02", "MeterName": "Compute Hours", "MeterRates": { "0": 2.73 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b7bfe936-caad-4bb7-98c9-7b6a11379c00", "MeterName": "Compute Hours", "MeterRates": { "0": 0.356 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3d1e5eb8-8f78-428f-8c8f-f4bd4814c693", "MeterName": "Compute Hours", "MeterRates": { "0": 0.712 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6b25367f-5d8d-4f41-a995-481757aec6db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4031e931-56e8-440a-8c08-a45cef6d4314", "MeterName": "Compute Hours", "MeterRates": { "0": 0.244 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3c36498c-c413-47ec-bc0a-ea684f678873", "MeterName": "Compute Hours", "MeterRates": { "0": 0.232 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "aeac4340-ca22-4e2c-9dde-552bc0a0fb05", "MeterName": "Premium P3 (Hours)", "MeterRates": { "0": 2.663 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "335462ac-c880-4a7f-b6bb-94a968754d76", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f18caa33-54d7-4337-b909-1a0f268d9df6", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 14.063 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ab3787a5-e154-448a-9169-6176f807883b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.137 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "538201b5-1e82-43c3-9043-9a19f9ce16f0", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3456cf7c-a131-47e5-83b4-177c3ab49a4c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.16 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "91a8eceb-98e5-4683-acf1-8752b130ae20", "MeterName": "Compute Hours", "MeterRates": { "0": 0.349 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2686e417-3d61-4e02-b25a-8ecc224d7ef4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Standard (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6f57a920-4e4b-4422-a013-6ce0c20ebd13", "MeterName": "Compute Hours", "MeterRates": { "0": 2.576 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c9456f44-976f-4265-9c3f-1ab410e35f65", "MeterName": "Compute Hours", "MeterRates": { "0": 3.043 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7cdcb3ea-9229-497f-b84e-a6dd06e74d36", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "330a6e17-bfe2-4cfb-9049-78054e806f11", "MeterName": "Compute Hours", "MeterRates": { "0": 0.016 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4f2ae6d4-3dcf-4092-a333-fbf152ef2bf6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.153 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7d5266aa-8a8d-4ca0-a388-40e467b4803d", "MeterName": "Compute Hours", "MeterRates": { "0": 2.24 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "b55d6482-4726-4fab-b4a5-ed8f3b39b5f7", "MeterName": "Standard S1 Overage (in 1,000s)", "MeterRates": { "0": 0.75 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "43235116-3f85-49f7-a20c-63636a0631eb", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f91b13ab-62d7-408a-aeb3-b93d4374d6a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.291 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e14bcbe5-c79e-467d-b3ea-e12d5e4403ba", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.1007 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "27ea8cae-1ce1-4cd7-ac57-8b7c341e9243", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "62b3e65c-6247-4656-ac55-07145f13a42d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.744 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1800bd5a-4452-44be-a6a6-1aa30b4c9a21", "MeterName": "Compute Hours", "MeterRates": { "0": 4.9 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "904fd065-e9f4-4b4c-9faf-5c8bb7b90d4e", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cd14d934-d909-4610-b8bd-48e52d0bac1b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.62 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c906e161-98b8-41b1-81e2-b59e0b263740", "MeterName": "Standard S1 Overage API Transactions (in 1,000s)", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "26bf6711-daba-40e4-8ff2-f0417328866e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.177 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "39586e1c-2e57-4dc6-8fcd-b8591274a3fb", "MeterName": "Compute Hours", "MeterRates": { "0": 2.086 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "34eb4ae7-9997-40f5-9fac-2fa718879f5a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "adc54be1-0921-481b-90c3-2d7938e4c5ff", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.365 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1c648c7d-694b-490c-a9dc-ae978cf936fb", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0146deaf-f348-4c60-a0f9-6fbcc1843b75", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 255.6 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "802e2b7e-9334-4ce7-8077-cde958483715", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f03e0e4d-6077-40f7-b61e-bda0c51a1113", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f0003a8b-a639-4b28-89e9-025cdcd629c9", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "565086f2-5d3f-41ab-a1b5-07a713d56f69", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.126 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "318657e7-f19e-44b0-9ecc-f5b711f00b59", "MeterName": "Compute Hours", "MeterRates": { "0": 1.264 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4ecfe7d8-6622-45c2-9745-974c7c7dce2a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bcf83d75-144f-4295-9a50-64349060de00", "MeterName": "Compute Hours", "MeterRates": { "0": 2.343 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c00ee14-e9b8-45f8-973f-285ce53941c9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a479ac51-7504-492e-b703-378eda58cedf", "MeterName": "Compute Hours", "MeterRates": { "0": 1.752 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "84347b15-0694-4b7b-952b-865bb238b196", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 1.8824 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c3624ee-228f-4363-9a44-bdc7dbd875c6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "82a33bcc-18b6-40bf-b364-51ebea7c8dac", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "c7c86eef-7094-47d5-83e7-c3c9be5af0bf", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.656 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A10 OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5aaad335-46c8-4ebe-ac35-13100376378d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.098 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9908ed0a-dba7-407f-b611-fc390325d48a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ad6b5c49-6f02-4531-95a8-8cafe447d203", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8377fc32-8a1a-44af-942f-0a1af85dc4d0", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3e8b6de8-56b3-41d5-bbb9-724882f0710a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "3a9f22cb-107b-4d4b-878c-2f9125c7abc7", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 116.74 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Batch", "MeterId": "e8db11cc-89b9-4061-b94e-eb7c18707e52", "MeterName": "Memory Intensive Batch Instance Compute Hours", "MeterRates": { "0": 0.0175 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Batch", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "b3841bec-a610-4e54-b8af-6d54feafa6dc", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.928 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f786602e-05dc-4157-8b85-c4b587d0aaf7", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.09 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a7fa021d-1f90-4ffc-988b-0bdb8d46bf2e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.82 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "dc5d40f7-474d-482a-b47e-ebb934547535", "MeterName": "Standard Emotion APIs (in 1,000s)", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "64cabb4c-1cdc-45a7-b682-8c5e0febbb51", "MeterName": "Compute Hours", "MeterRates": { "0": 0.69 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "464b3492-72cc-4c70-8ac6-8d0319d39623", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "755e3dd7-1fa5-4923-8186-441b7f73a274", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e2f73349-0c42-46de-a33a-bb4547ac4f04", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.038 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "924b9bcb-9cb4-431c-ad2a-eefd5c74c894", "MeterName": "Compute Hours", "MeterRates": { "0": 0.349 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8e7ca98f-0214-4f5b-9b2e-10fe4596798e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "86fbf081-4a0f-4992-9336-6159391c28c0", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7419dc08-5eac-4502-b454-a1712417ddaa", "MeterName": "Compute Hours", "MeterRates": { "0": 2.659 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a6a95131-bdea-462c-aeb1-13772339f36b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96257598-6119-4dad-94d7-06f026fa9f1f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.268 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3d5409f-cb28-42a2-975d-a9e715e9d330", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ec04e0fa-6825-4077-8d2f-27aac12ea927", "MeterName": "Compute Hours", "MeterRates": { "0": 0.221 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5e87a460-80ae-4eb4-81f3-4344896797f3", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.94 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "45201f28-fbf8-4037-a51a-df777d40930d", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.125 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9e4e879d-c0f2-4623-8051-b0fb279b4425", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0264 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "066748db-57be-4f94-9a5b-f7b82a96c7ab", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5f6887c1-100f-48b5-93a2-c0b0498ed356", "MeterName": "Compute Hours", "MeterRates": { "0": 0.425 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Scheduler", "MeterId": "be2eb73c-cc40-4a0b-9511-af1c5a247fbc", "MeterName": "Free Scheduler Units", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1 Unit" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "1cd23e91-a422-4dc3-acbc-feafc509f19c", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7277b7c5-2c80-4ea8-bd6d-a2e0d11aedee", "MeterName": "Compute Hours", "MeterRates": { "0": 6.48 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dec0a68c-f66f-45d0-8361-e13c4492a4f2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "544d011e-8ed2-4e78-a99e-d87c0f5d5f19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "98683f53-70aa-4d9c-9715-70f6a5b6f85a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d8bc616-4348-4245-b74e-bea9125bc891", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9e3b7351-2718-4545-9d8c-43fa053cf98a", "MeterName": "Compute Hours", "MeterRates": { "0": 7.46 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV24 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3a520096-32a8-494a-b58b-885de9e5ad4c", "MeterName": "Standard S2 Search Hour", "MeterRates": { "0": 1.478 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "47eaf23f-7713-4b0c-9c1b-fe064ef77c9e", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.0 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ff669cec-98a6-403c-ab6a-8642e2b249e6", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 627.264 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Analysis Services", "MeterId": "9901af91-2b08-4f58-8aa1-d54ab42054fe", "MeterName": "Standard S2 (Hours)", "MeterRates": { "0": 2.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Tabular", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "382401f1-e439-48ac-842c-bb0933e2da38", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0536 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "27fa1d2f-b93e-4f2b-8dd9-9f257c1f51f4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "91905b98-178f-473d-b701-7ceba4c5017c", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 0.9677 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6f303b87-fccd-46c7-9789-ccf8fea267d9", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.06 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c7c276e-a394-49db-ab0b-69dc00eb9f38", "MeterName": "Compute Hours", "MeterRates": { "0": 0.248 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d618ab9b-6d75-454a-9bbd-3a3bc01c927a", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "76b67d78-4b91-41f2-93c8-fb3d9de7a704", "MeterName": "Compute Hours", "MeterRates": { "0": 0.953 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4072057f-b2b2-4c2e-ad12-716181e57e64", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5033 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "30106156-d005-4b27-abd3-1b9fbeb12c25", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9543b36a-cf96-4b48-b0b4-a7258977e706", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "51bdafdb-ac85-40c4-b783-032fbcea84f7", "MeterName": "Video Stabilization APIs (Minutes)", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c87db1ab-3fdb-4749-88e7-782b114db747", "MeterName": "Compute Hours", "MeterRates": { "0": 0.852 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "85285026-59c5-4029-9272-88d85040ce9d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.161 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "bd69546d-19b0-4776-865f-8753b800883b", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.07 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2dc242ef-0443-457f-8e45-2d535735f983", "MeterName": "Compute Hours", "MeterRates": { "0": 1.895 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "99fc0555-094e-4c25-bcdf-ca0199ab4290", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.0151 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fd2abd54-414d-406c-ac77-753eb420003f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.281 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8b8c895b-bca0-4f0e-9fbb-16c13512b8d0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4fd45738-9a0e-4a95-b4d1-b81809af9f1e", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.225 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4225a259-3557-464c-a76c-6f3e0672735a", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a73fdaba-6b94-4934-896b-b43759867987", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4ac7ee83-215b-4da8-a309-fa833827734b", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 33.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c27635f1-38af-4eb9-b440-faf198237f18", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1d4a40f5-9661-4c3c-bee5-2c48c9e8371c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.298 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "65d33994-62be-46ce-9e4d-c154f959cd8b", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8028f3e9-1946-4785-8c83-07cf4440d9de", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "10dac30e-20bc-484b-b94b-9853fde83b15", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "297878d1-5f55-4392-9755-b78ee5be1a33", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0862 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "585de8d6-61a9-4ef4-a528-35be2500a359", "MeterName": "Compute Hours", "MeterRates": { "0": 0.86 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6711cb05-7c2b-4f8c-885a-f45b35136e3a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a77d8574-a69f-4150-9b06-26f43fe075d9", "MeterName": "Compute Hours", "MeterRates": { "0": 5.856 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "517d05c5-989f-4b37-8462-e857145e7228", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (12 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ef6fe897-dbe0-40c2-bcc9-134c75b61fda", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f5eaac8f-b96b-4aa4-a9e9-76cf04fd9d82", "MeterName": "Data Transfer Out - Unlimited Data (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "df908fa2-21e0-4890-9ad9-2df392d45122", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 72.92 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8869dd8a-f05d-4a07-9bf4-b1ef9a9bffec", "MeterName": "Compute Hours", "MeterRates": { "0": 3.752 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "74821000-4eb0-4106-9992-5574ef750c15", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c35103ee-0f05-4b68-a236-280a4e4b56d5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "baf0f0b4-ce1f-4d7b-81e6-b131b708858d", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "44cbd36b-f261-4e8a-97a9-74b11cdd74c7", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9d22589-3e0c-433e-8561-6a07454e2d3f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "4bf8396c-beb3-4de0-9471-48ce8c906091", "MeterName": "S2 (Units)", "MeterRates": { "0": 800.0 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1269a8c6-499f-4b63-8709-19e70eb09643", "MeterName": "Compute Hours", "MeterRates": { "0": 0.069 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2265feee-a1a2-4aad-83aa-a4b35824f677", "MeterName": "Compute Hours", "MeterRates": { "0": 1.366 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4d97520d-90d9-48fa-93d7-ebf44b3c9924", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.022 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fd9c4dfb-c43b-402d-abc5-4545323415a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c61984c9-3733-4818-84a9-5dc881ef47c4", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0375 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "acc1a1cf-e786-4ee7-86c4-9f827cac71c0", "MeterName": "Compute Hours", "MeterRates": { "0": 1.478 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "25f947e3-026c-4416-84cb-e8c366e7da8e", "MeterName": "Standard Managed Disk/S30 (Units)", "MeterRates": { "0": 22.528 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "045aa6f5-e9f4-4ff7-b377-f9baa1d986ce", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fee1c571-5e0d-47ef-b031-3ba67f6a67c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Identity", "MeterId": "6d7548b2-bf39-40b7-8df8-d3354a17668e", "MeterName": "External Identity Authentications", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Multi-Factor Authentication", "MeterTags": [], "Unit": "Authentications" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6da415ef-d1b6-4b9c-b72c-457c4dcc3aa3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise and Weblogic Server Enterprise (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "56f07b6a-c7d9-490f-a196-a7ee08e28712", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "795420fb-100a-4a39-bff2-9f45d4aee1b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9ae12c16-c7d7-4cf2-8e61-af58ad102afd", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1c833e7a-2490-4f89-ba38-b98637e848fa", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f8eeb06d-e9b1-4792-9562-184213b97d03", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "64819db7-40ae-4288-8f30-25dcc45de6e9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6970b587-0491-46be-a15c-f7e7a4429ae6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.516 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "589566a1-649d-4e26-9272-fc16d61b3dc4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "517fe269-c5b1-4572-b89e-6b4053bbc61d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.481 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f8b8852d-f482-4563-80c2-fe347291644b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e549b039-3816-45ec-8be6-60ef2d2cc8a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3168 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb31bf05-ed22-46f8-a604-c963353264d0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.84 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c51e22e4-edad-45a1-8721-f7f3c2de512d", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 12.39 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8ff6cb38-2fd3-460e-b99b-76042d798a98", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d6cf437a-0992-436b-9147-4c57b7415b9c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.178 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "dde2e971-287a-4b1e-a0b5-b11297fab73d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.54 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "209f4cd2-ad49-467c-b1c0-68e0731ddc86", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "22122ec6-250a-44b9-a031-3058f2acc104", "MeterName": "Compute Hours", "MeterRates": { "0": 0.632 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c2854a76-748a-493d-8ca0-0e7640b17aa0", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "67bcb0f1-d856-4bf8-b6cf-ccc932f4a9a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.268 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e25f4479-3084-4e1c-b89c-2b0bae2b79e7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "13553d04-5057-4557-872b-cafaf85e256a", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.16 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "75a71915-a991-4eff-a4b7-72ec860e4e15", "MeterName": "Compute Hours", "MeterRates": { "0": 0.178 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7d86696e-c986-446b-8af6-be767c35775e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.264 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "459af3c2-cf85-468d-ae77-c096858dfef5", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.11 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "688cd530-3034-41b6-b429-02856500a9a8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.572 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dab7bc99-944d-408b-80f9-320c0e55f42d", "MeterName": "Compute Hours", "MeterRates": { "0": 3.059 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8765ef09-db5f-4a66-90ae-3ade3c8a2783", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "11b1515c-7490-49a8-b32f-aae0cfa9c021", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 108.9 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "61405941-cb44-4382-9949-9acf4779b186", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12f637bb-97b1-43b4-9c56-5370b344d768", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b64cacb6-afef-4e5b-88ff-58f63099bd05", "MeterName": "Compute Hours", "MeterRates": { "0": 1.22 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "66aacf77-57c2-4a1b-a3a4-064273d8aa58", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 22.67 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d57d08d3-32d1-4631-af7a-fff018f4d09b", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d15fac4d-36f6-4583-964a-e7ec20bd193c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.035 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1cf14d7c-7cb6-46db-ab44-793ca6506f7a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.765 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6efda682-f82b-4ef0-9324-a358f3b64f00", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "31a62457-ff05-4084-ad52-c47d8f51f154", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 61.44 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "78b73662-ca16-4736-a23d-d44704860efb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b9b795de-d63f-478d-a111-5bf05bdceb87", "MeterName": "Compute Hours", "MeterRates": { "0": 1.542 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "39c25c2e-dd6f-47a6-b39b-779c9a4257ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "9ca789a4-04dd-40c8-84d4-19cd7cb21078", "MeterName": "Premium CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.5 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "27e99b56-4e56-41f8-bd5c-3c07ab4393cf", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 37.5 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a5965539-c524-4112-b4c5-091680938b3d", "MeterName": "Standard IO - Disk Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "329bae5f-a339-487c-ac90-d1ef93c73731", "MeterName": "Compute Hours", "MeterRates": { "0": 0.852 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0168b9e9-d153-4754-81a4-3e03473c13e8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cd89bb1c-026c-4823-ab36-d40b27d87c7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.312 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ad2e895f-a4a6-4e7e-ac97-4d9b8edeb547", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "670a674b-152c-46cc-8f44-c682f3b660bf", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.088 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "78aab249-4dc3-476f-b673-27f177e8ff41", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0735aae7-8bd5-43ad-a131-7c3886591c2c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.187 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bea268fd-3894-418e-9a24-8800e3e869f5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.225 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "12e1237d-a0b1-4630-93d7-5090224dc30f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.296 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "24768197-32d7-41f3-9129-81ab6913bb54", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "20db517b-cf48-4111-b894-2a4e207fd27a", "MeterName": "Basic Redactor Minutes", "MeterRates": { "0": 0.045833 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "be138253-d904-4529-b83f-b0a6f1c906a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.467 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4c196433-36e6-4e28-a31d-e70b6a7c0d7f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.549 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a438d0ea-c92e-445e-bade-158f22680dd4", "MeterName": "Premium Unlimited Data - 5 Gbps", "MeterRates": { "0": 44000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2801bf73-919d-40a8-a9ac-a1abc9a945a2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.346 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "148c0a3c-40e8-431d-8870-ae0c0c2ac63d", "MeterName": "Compute Hours", "MeterRates": { "0": 10.536 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9ba37508-fbab-4f2a-86f5-4861f19db872", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c28ac367-7449-4cb9-9324-81b657bc5a6a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.345 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "78f10ecd-833b-49d9-a405-778c5fb85b5e", "MeterName": "Standard Managed Disk/Snapshots (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8e7ddd98-7ec3-402e-b996-af088997d72e", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.04 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5694395c-4eff-4325-87d8-19920377a16a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.115 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f3668cce-b518-451d-a402-aed7a6aeee45", "MeterName": "Compute Hours", "MeterRates": { "0": 0.672 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Recovery Services", "MeterId": "0b1fbb84-8967-4cb4-9288-c3cf8ca3090d", "MeterName": "Additional storage for VM replicated to Azure", "MeterRates": { "0": 0.28 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Site Recovery", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ceb6e85c-a477-4787-8942-24d1abd76ea3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.061 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a149966f-73b4-4e1d-b335-d2a572b1e6bd", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.4839 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "d898ec8a-0795-4066-9199-effdb181a288", "MeterName": "Premium CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.28 }, "MeterRegion": "Zone 4", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bed86b46-f90f-49ac-b60b-35413bed8cf1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7ef144e8-61b2-4575-bed9-aa1f153f9bdf", "MeterName": "Compute Hours", "MeterRates": { "0": 2.136 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "29187de1-b4a1-4503-a6f6-078271b3fc9d", "MeterName": "Included Quantity API Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "96de8d2f-46c1-4249-90a7-532f7824eb1d", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.504 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "7bcaed13-b9c9-408c-a66f-a357e3dba257", "MeterName": "External Endpoints", "MeterRates": { "0": 0.54 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Traffic Manager", "MeterTags": [], "Unit": "External Endpoints" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1b648a0b-3296-4e12-91f1-de12e972933d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb97da0c-a6b2-451b-a174-93b444fe8853", "MeterName": "Compute Hours", "MeterRates": { "0": 0.735 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4b6c5b2-dc9b-4a66-abfa-3f77887d27a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.119 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fda24285-b1d0-4f58-b957-e1685125aff7", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4c58289c-1fd1-4651-a34b-30e165c57df4", "MeterName": "Compute Hours", "MeterRates": { "0": 2.659 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "25f34193-df0c-4477-a736-6e9180355d9b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.933 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ad924267-2ddc-4836-9158-4e25bb38e5f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9e227951-45cd-43ee-a92f-cd7b59304f81", "MeterName": "Compute Hours", "MeterRates": { "0": 0.128 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9872ca9d-24b6-4cb7-a5fd-5c91ac7e7388", "MeterName": "Compute Hours", "MeterRates": { "0": 1.097 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d3102795-4058-4a12-97fe-76603e1c4290", "MeterName": "Compute Hours", "MeterRates": { "0": 2.16 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b209087-dd46-4379-bcee-b873fddc0e1b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.891 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e0a9ccb5-6e4c-484f-bb82-8ee5577726e6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.212 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fd6d7628-b2b6-4102-b5d5-a2fc9c6d0726", "MeterName": "Compute Hours", "MeterRates": { "0": 0.976 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "addc715e-5a96-4b81-9029-f7900979fd1a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "80fed039-68d7-4025-8c7e-7eaed3e0bad8", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A11 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "537706bf-b05f-4cff-bf15-35773c13e8d0", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 5.0322 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c1d03ac1-bd3f-4b1e-b17f-064a4f92914d", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 11.071 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cba56cbf-040b-4bf0-ae5c-729b318cab65", "MeterName": "Compute Hours", "MeterRates": { "0": 0.057 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f0fb10d7-942c-4e16-8955-8c9237c451e2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.209 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dfb0e6b9-e53d-4b2e-a5dd-f6b8f5f2066e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.058 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b47020d7-ff24-4cfd-8d80-df58bdd2ddda", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 282.263 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "744cc0f3-1253-4509-96c5-b70d9b674523", "MeterName": "Compute Hours", "MeterRates": { "0": 0.332 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "05d1841b-e0d4-47e7-a023-a77b8c5c2672", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "dd75c4ed-be82-4c52-9e65-f63f0b544941", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "S SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cc35bac9-b6be-4367-acf5-2ddfd2facecc", "MeterName": "Compute Hours", "MeterRates": { "0": 9.348 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f48659e-7381-4c95-8a57-4819881f54f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2d8bae6b-ad6b-4149-8fbb-f52a71a73502", "MeterName": "Compute Hours", "MeterRates": { "0": 0.131 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "546d77ff-f05c-4c0d-8eaf-46260027a4de", "MeterName": "Compute Hours", "MeterRates": { "0": 4.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (12 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "e63d425d-5148-4a02-abf0-f5d801ba2a89", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A11 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "099ec3ac-ce52-4964-a5dc-809c7c91f4f1", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "23c32d2b-b75e-46fd-b0ee-80bd8327d834", "MeterName": "Standard MS1 Database (Hours)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MySQL Database on Azure", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "af803a77-8a45-426a-909a-4169c4ba4bf0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.428 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0a0ea38e-b04c-4323-ab35-842deea3a45d", "MeterName": "Compute Hours", "MeterRates": { "0": 4.311 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "98c5eecd-32d3-4616-a3ea-b3642c00f607", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XS Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "bc10a8d7-d4d8-49be-a182-20f5a7a88814", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XL Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ca107cbb-49dd-4567-bf73-09ae02574474", "MeterName": "Compute Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "92eb9e1d-b0e1-4a31-ad2d-497c2580e902", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "735ba9e2-5328-46b5-95cc-5c40d1e1e473", "MeterName": "Compute Hours", "MeterRates": { "0": 0.249 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b8f8bc0f-e4dd-452b-b9e1-23eefc8895b7", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d3c01bc-8791-49c7-b986-10fc34514ade", "MeterName": "Compute Hours", "MeterRates": { "0": 0.996 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb800ecf-abcf-46d2-8fc8-4d8cea4abcf7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.556 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "85f538f3-5160-4e57-8a99-37c100d3a3b3", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ca29e46d-955a-40e8-80d5-287471165c96", "MeterName": "Compute Hours", "MeterRates": { "0": 1.197 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0f727a51-58cf-4a0b-b76b-0a2ee0403460", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1d2d3288-3b01-4d55-a642-73f07cd3f477", "MeterName": "Compute Hours", "MeterRates": { "0": 0.702 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fae2d2b2-b6ee-4aa5-b64e-2ee5b0a940e1", "MeterName": "Compute Hours", "MeterRates": { "0": 3.518 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "45763c9c-9eb2-40b1-bfde-0ba052f51a2b", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d9759a8-2e3a-4f77-99ae-e82ab6c0ca43", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "842f92f7-a46b-4522-ac62-8134271dc591", "MeterName": "Standard S1 Overage API Compute Hours", "MeterRates": { "0": 2.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a96d5442-6664-48d5-b61d-f819f9a887fa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise and Weblogic Server Enterprise (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8ed9141a-9814-4700-824f-352cd1952f61", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2bd4b50f-a11a-45a9-b28f-d2e7e248d7c9", "MeterName": "Compute Hours", "MeterRates": { "0": 2.337 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "55474677-9809-457f-b8f9-dd912b063772", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.033 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "23fe334d-c9c9-4bc1-abb5-e6d398787ad4", "MeterName": "MSFT Peering Metered Data 5 Gbps", "MeterRates": { "0": 2180.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ce1e156d-8253-42f4-bb9e-409708366fea", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 15.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "040bce04-82d6-4337-a7dd-50a8971c4e79", "MeterName": "Compute Hours", "MeterRates": { "0": 0.544 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b50bf2e2-ce4f-48d3-ba9a-27b433f90fa4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.389 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ad22fac8-9da5-4577-8683-56ae94d39e42", "MeterName": "Standard IO - Table Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f18ee3e1-a8a2-4b57-92e4-440257cb49e8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6a6a5344-8478-4803-b1c3-229d08c10383", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5855 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bcca2d1b-9cfe-434c-86b4-7b27d2b77810", "MeterName": "Compute Hours", "MeterRates": { "0": 2.156 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "eb573bb3-d2ef-4df9-91e4-8f25b2be1c45", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0408 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "12306611-b02a-4739-99ce-3d8bd3d8f713", "MeterName": "Compute Hours", "MeterRates": { "0": 0.393 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0fa7bd26-4603-4171-ae1b-889d7f532f65", "MeterName": "Compute Hours", "MeterRates": { "0": 3.105 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A9 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ae11fbae-49aa-4713-aec7-372109c9931f", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 33.0 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9fdb5b1-11f7-477e-a9d3-5ee50dd7ee62", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "01a1aa40-44c1-4a90-9419-d596d8fbbe06", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0403 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 10240.0, "MeterCategory": "Networking", "MeterId": "c31b2562-1c9f-4a13-9c0b-f00848068558", "MeterName": "Data Processed (GB)", "MeterRates": { "0": 0.007 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "c4d6fa88-0df9-4680-867a-b13c960a875f", "MeterName": "Load Testing VUser Minutes", "MeterRates": { "0": 0.0004 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Team Services", "MeterTags": [], "Unit": "Virtual User Minutes" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a749b90-5da3-4f41-94c3-9caa315e7eea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.297 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "9de7adab-6b51-4fed-82e5-dd8846025da9", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.016 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6e6509e1-6f27-4422-adc8-0cfee6f0f9e6", "MeterName": "Compute Hours", "MeterRates": { "0": 5.36 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2d2494e5-f100-45da-9bbc-a191723650c1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.704 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7bd38858-97bb-4e1b-903b-33d8d319a00b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4ac0b0bc-7537-40bf-8a97-33dbac709c59", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 10.9539 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "14c84391-c585-46ee-bc26-78920acb34fe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "1f222a62-fd30-4285-80f0-d5442be33081", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b4d8861-8cbc-40c8-88f9-e1b78509c3be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8adf9e3c-41d6-473c-ae9d-7b42c4eba895", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5b25df92-8bf0-497f-a4df-e279e6dadb01", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "52865987-78c6-46c1-ac7f-79203006467c", "MeterName": "Managed Capacity (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "StorSimple", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0d14ab9b-679c-4482-a935-4cbaebbd5af1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f5bcb3fd-89e0-46a1-9f1a-c1f417806237", "MeterName": "Compute Hours", "MeterRates": { "0": 0.131 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "35cee2d8-2542-4b63-898d-0a1a9ef3dbc8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95ea396b-5a94-4e31-bf52-d065c3ec8769", "MeterName": "Compute Hours", "MeterRates": { "0": 0.068 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f646fbfb-3a49-47c4-b3dd-f5a927fad89a", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3252c8bf-be2c-4c36-a1d8-791b3278999f", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 7.2581 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e5921380-3088-471a-ae87-a47cc97e98dc", "MeterName": "Standard S2 Overage API Compute Hours", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "556704ad-c004-4017-9e2c-d7f451ec0dee", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e7e4d225-c521-4771-ada0-94c787ace59f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4246e9f3-c6c9-4a52-bdc1-d83279f90315", "MeterName": "Compute Hours", "MeterRates": { "0": 0.684 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d7ef8df1-8f44-4b15-9d54-3cfe5119c153", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 584.208 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0242cdc7-456a-4024-a1d5-f00b54f37b76", "MeterName": "Standard S2 API Plan (Units)", "MeterRates": { "0": 32.26 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "035c0bf1-402e-424f-8850-7315ac39a3fe", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.0697 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "0204158c-944a-4a56-ade0-9cf6e06d7512", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "S OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "62315887-a65c-4cd5-89e7-b393e22487a4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bc2ced7c-f98e-46af-bc4b-18f081a9d829", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4d9dcbbe-af9e-4dc3-83f2-fb054e015c14", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f14382b0-1838-48e9-9314-c7b6eababc81", "MeterName": "Standard IO - Page Blob Delete Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0e3167d0-f738-4026-aafe-3897f5e18abc", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 187.5 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0cc0b81f-e04d-4bde-8a61-954ae4d6d471", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5b68d4d5-41cf-40a0-9edf-841283f73eea", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c6bd24de-da5e-4651-a7bd-5f76b9c04f82", "MeterName": "Compute Hours", "MeterRates": { "0": 0.746 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "37482b95-29e9-4d2b-b035-8e9178807c36", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "674d03d7-82b1-47d3-a4d7-f98cf35c3ef9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.65 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "992c13b9-9aa1-4675-8e60-9d3337392215", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.129 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a35e79b9-c4f9-4efb-ad2c-594221352dd8", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ff79cd83-8a39-47cb-b459-0977e3e89e77", "MeterName": "Compute Hours", "MeterRates": { "0": 1.853 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7e4c4c72-a61b-428e-9e3c-7a79d89dd9b1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e8f65007-bf26-47ab-9500-d611cde8e191", "MeterName": "Compute Hours", "MeterRates": { "0": 0.299 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "c82dbd27-c978-43a7-ad41-525a90d8962b", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A11 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7399da09-25ea-469f-886d-e592603daa18", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 66.56 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "74dddeed-eab9-41bb-b4e1-08695751c738", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "49369c7a-bf7b-4ad6-978b-952fc99b54a7", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9e374059-62d3-4e66-84bc-3b4046ab7476", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5b0c2c3-9ce3-48ab-a8c8-706e53790875", "MeterName": "Compute Hours", "MeterRates": { "0": 0.152 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "54d268c7-7734-4b69-bece-ebbf202cce90", "MeterName": "Compute Hours", "MeterRates": { "0": 0.625 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "12da282f-7e96-49e2-983a-9a65da2a4866", "MeterName": "Standard IO - Table Read Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "c212cac3-156f-4b68-81c0-ababa07ba911", "MeterName": "Basic C2 (Hours)", "MeterRates": { "0": 0.09 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "56a39682-a27c-4c5e-8e99-da2823a49e05", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.605 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3cd66222-4d2e-4d68-b6bf-5f80f58c4a85", "MeterName": "Compute Hours", "MeterRates": { "0": 0.827 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d2bc9901-976e-4fe1-acf2-68e3044cfe82", "MeterName": "Compute Hours", "MeterRates": { "0": 0.817 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "fabb6ca8-ac26-4948-b3dc-6d70873b53f2", "MeterName": "MSFT Peering Unlimited Data 200 Mbps", "MeterRates": { "0": 1150.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "27618e6e-6e8d-4e91-adea-d8aed1302c76", "MeterName": "MSFT Peering Unlimited Data 100 Mbps", "MeterRates": { "0": 575.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57398c05-f43e-4f1c-8f37-6a16c9a507c3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.045 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a9df2950-9bdb-46e9-a73c-b4f1e7307a8d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.236 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4a6ab383-ec62-47a1-bf83-249fe1d887ca", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ece72ad4-0639-4687-a28d-c6597cc14fb6", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.7685 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "9958dcdb-4161-4941-b46e-33aeb72ec9a3", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "adb55c65-7f0d-4ffe-9e0e-a37d5ce6fd60", "MeterName": "Compute Hours", "MeterRates": { "0": 3.96 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24r VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d204e666-c47f-419f-a6f3-9d23ae5c8cbc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ec1cd117-3f47-477f-8ee2-b94b803649ae", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "35d1d9ed-ef1a-4d42-8ce7-644981a88aef", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 511.182 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "28988efd-fc1e-4981-8bd8-c576981cf77d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "21fcab3e-6854-4e4c-b58a-9ca7ac974a2e", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 23.4 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4e67d1d2-4b88-4b52-8664-4c5757ed3283", "MeterName": "Compute Hours", "MeterRates": { "0": 0.491 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c5c59c07-827b-4bb9-9f01-6421d84752a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "7c8f5b20-386c-4078-85de-14d64b3e059d", "MeterName": "Standard C2 (Hours)", "MeterRates": { "0": 0.225 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e31a6c11-cd68-4639-8bb1-bc218a9537dc", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "032065d3-7112-4150-bd43-4ef521488557", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fbd8a891-35f2-428a-b57e-d0522586a044", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a292bb0d-72e7-4fe0-afa3-d83a5ed8b37e", "MeterName": "MSFT Peering Unlimited Data 1 Gbps", "MeterRates": { "0": 5700.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb7b86bd-7fbf-4e37-872b-dcf1728dfb63", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f6440c00-2acd-4b5e-857d-4753b5725b1c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.411 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8dd340a5-b9d8-4731-9c82-039f0d45bee4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.44 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (12 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fe82dacb-c546-4797-86e8-6fc3fb5f1f19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BYOS Red Hat Enterprise Linux (1 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "45c7c113-397d-44b3-9808-b0c7128753dd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8ce2780e-f219-4d9f-87aa-330a39b70b2f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.732 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f9bd2d0-496e-4fb2-a9ce-0ff10e190832", "MeterName": "Compute Hours", "MeterRates": { "0": 0.089 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "989ca342-61cf-4ed3-a3b1-7d50f490c46a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1c0cfb69-d818-42e1-8a2e-eae014e59158", "MeterName": "Compute Hours", "MeterRates": { "0": 5.84 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "7f59b5b2-1fff-4426-b43a-3ed8141548fb", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.375 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4c3bd520-1098-4e72-9a28-7e49df37d934", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5efb5036-06ff-4a8d-bd99-0f569fc5ba12", "MeterName": "Compute Hours", "MeterRates": { "0": 0.61 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "35c7a5fd-ae46-405c-ad6a-8081526d090d", "MeterName": "MSFT Peering Metered Data 2 Gbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7d497e63-48d8-4497-90ad-265412de9e25", "MeterName": "DWU", "MeterRates": { "0": 0.7 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8b044f0-b0ea-4844-a35f-1863850968aa", "MeterName": "Compute Hours", "MeterRates": { "0": 1.912 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "90598c0c-0402-4295-b5ef-2ffdbf5426a8", "MeterName": "Compute Hours", "MeterRates": { "0": 3.15 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (6 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "d18f523b-a7c8-45f9-82cf-4bfb4b8dbee6", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f51e1c6-077a-4a0a-b461-1ecb368670ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.491 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "07501d86-23ee-4838-9a35-09e078fb151e", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 36.3 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "18eaa967-b5a8-4fab-9753-dd9f6356a886", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ace6791a-8564-493d-b0c4-849a9e240610", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "12f2b340-1c2a-4790-a67e-b70f178e1d01", "MeterName": "Premium P4 (Hours)", "MeterRates": { "0": 5.328 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c26ff60-d1bb-4427-952f-cfd65ff75e4e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.486 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f944287f-b55b-4e88-8c17-a13a31521f35", "MeterName": "Standard MS4 Database (Hours)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MySQL Database on Azure", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5166f630-3883-470b-81ef-9d77b25b964f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Scheduler", "MeterId": "02e3908e-c446-48df-97c2-be94bab1951f", "MeterName": "P20 Premium Scheduler Units", "MeterRates": { "0": 1399.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1 Unit" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "558f3e41-b808-45e3-98a9-ab4206ddd016", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7cde3bdb-9afe-4b7a-b657-57f84f25662e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c81ea2bb-4ed7-4e86-b963-19bd7a2bfdee", "MeterName": "Compute Hours", "MeterRates": { "0": 5.856 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b73bd808-47ad-4b8d-aa8e-728c6667cbc3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.446 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-01-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "d3dc1d24-38a3-4932-865d-778f06b38eee", "MeterName": "Business XXL", "MeterRates": { "0": 500.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "HockeyApp", "MeterTags": [], "Unit": "Plans" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "85212205-1ce7-4249-ad85-6183348e3dbb", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3cc2f7d5-59cb-4879-9974-d403be1f9331", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b223fc4b-0e48-454b-b1d5-61441b3ca632", "MeterName": "Compute Hours", "MeterRates": { "0": 0.084 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9988e02f-5ef1-4fe1-b855-2835cd2bd1db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.516 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "664574fa-2c39-4caf-8b94-57bf5d0e1a62", "MeterName": "Compute Hours", "MeterRates": { "0": 1.169 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "375020be-5146-4cb5-907b-3b0aa1c4acd4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.681 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5f2f47e6-bcf4-462e-b22d-ea76ba528369", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "df180dc6-14c1-40af-b94d-ccaaf0afb6ce", "MeterName": "Compute Hours", "MeterRates": { "0": 0.021 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Integration", "MeterId": "558debd2-68bd-42c9-9303-2c7b2a281031", "MeterName": "Premium BizTalk Units", "MeterRates": { "0": 5.86 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Services", "MeterTags": [], "Unit": "Unit Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "47ae2469-9fd8-4f1e-9a05-5900b470d8b4", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "37a224be-47e1-42bd-b2aa-f08060e965ee", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "2885a6b2-5013-4fa9-8f3b-fc3ead8d136d", "MeterName": "S1 (Units)", "MeterRates": { "0": 50.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fccd24ea-f6e6-436c-ae40-853d0f38b9e7", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "1ef7d3bf-4224-456a-9b06-aec74f48cdbb", "MeterName": "S2 Overage", "MeterRates": { "0": 30.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Search APIs", "MeterTags": [], "Unit": "10K Transactions" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "415cf463-a8df-4065-a0b8-c0fe3719da50", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0375 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c3e83e79-5fd1-4902-8f09-319d7caf23dd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.383 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "4b32b9e3-09be-41bb-b643-897568d9c0b9", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99347b75-034c-442f-97c2-8e58559d0b17", "MeterName": "Compute Hours", "MeterRates": { "0": 0.536 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2bd52869-3e3f-409e-a092-dc4d0c854122", "MeterName": "Compute Hours", "MeterRates": { "0": 2.5392 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "66d3680e-f733-4710-997f-463a73a885b1", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f6ea544c-9ce1-4f5d-a1e6-929f9b175e59", "MeterName": "Compute Hours", "MeterRates": { "0": 0.208 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "212c584d-7738-44c4-9323-85720de0a8d1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.498 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0b18980d-6dcc-4f45-915d-7cb2b36737db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.704 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fb059566-63d3-406b-bfd7-a3a6cbbdb66d", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.153 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "d6bf4b6e-1c0b-43cd-8bb9-edd93991cefa", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A9 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "92b23694-ecdb-49ea-8f63-bea87dbba044", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a7dbe155-d28f-47f0-b926-1edb31c80147", "MeterName": "Compute Hours", "MeterRates": { "0": 0.82 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2d00018a-eac5-4532-979d-147f89762a67", "MeterName": "Compute Hours", "MeterRates": { "0": 1.283 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c15147af-e2cf-40c8-9e92-e9f6b33b4435", "MeterName": "Compute Hours", "MeterRates": { "0": 0.238 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f7f05aaf-c250-4fa1-b883-4682ddff86e4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cdd52a05-9159-4cb9-8440-dc58f8a5f9a2", "MeterName": "Compute Hours", "MeterRates": { "0": 2.236 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "344dd460-e2bc-4c41-9f27-5c4fbdb1022c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.259 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4068a61c-e6e4-449e-88c8-d715e95e2937", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "693094b6-03ee-42ee-89f9-964904e636dd", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.109 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4f99337e-7987-4814-92fe-77c6e0cda1ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.149 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a1945374-05df-45d3-8f69-1aaf85d30101", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ddd423d8-fdf4-4909-8bf5-798d02146c16", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc75d256-94d4-4706-9e0a-953412f2f40a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7e584588-160a-410e-a65a-ec3510ea935f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "32e2d715-b6dd-4ad3-9a3b-93085c8622e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "53bbfe19-c977-42c8-911a-d7817319ec44", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "36293e8f-ac3c-45cf-bd4e-dc2542bdba03", "MeterName": "Premium Data Analyzed (GB)", "MeterRates": { "0": 3.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Log Analytics", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "923e90a1-f27e-42b9-b572-0fd1fba05c00", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "43414975-13e4-47f6-9770-663d938c8236", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Standard (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "55d6913c-a5af-4e8c-8e9a-855c536f5166", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7d817d0a-603b-44a8-88c4-1ccdb91ab3ca", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 18.0 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d4b7f209-f44c-40ba-a7b2-fe6a99efdb1e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.144 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9f3b11dc-38e0-4449-9ef8-eb884224fa9f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.794 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "aace4d2f-175a-43e5-8e28-ce76139c6c76", "MeterName": "Messaging Unit", "MeterRates": { "0": 22.26 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Premium Messaging", "MeterTags": [], "Unit": "Messaging Unit" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1ad2a734-9682-4741-a93e-adbed7ea38ab", "MeterName": "Compute Hours", "MeterRates": { "0": 2.08 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "85867f1c-2678-4ded-8fce-cb1a7cc3401d", "MeterName": "Standard SSL Certificate - 3 Year", "MeterRates": { "0": 167.97 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Certificates" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6c6af233-53ed-4718-940a-3c1999d25490", "MeterName": "Compute Hours", "MeterRates": { "0": 0.713 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "59c75e42-762e-47e1-94a0-aa1d82d1f23d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.549 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e2909253-87cb-4fb6-8097-0f8a8c74821c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.64 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "511fb4b1-8a6a-4633-9889-076918f28004", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "4b471c53-cfaa-4c1d-8325-4ebabac62212", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2cacc6e9-9715-4542-a7f8-68f68bfb9d78", "MeterName": "Compute Hours", "MeterRates": { "0": 1.464 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "c0d5b2bf-4083-4fbe-8939-c7d0a35ce6c3", "MeterName": "S2 (Units)", "MeterRates": { "0": 800.0 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c27dd007-950b-436c-96b3-276ebff63c74", "MeterName": "Compute Hours", "MeterRates": { "0": 0.066 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "540ace59-9c1d-4418-8ee1-07d857d7b7fd", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c5248cf8-ecba-4807-9304-6a8f14b5805a", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "51c8e114-ad37-4046-8b1a-21d2e9cd679a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.885 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6452c91d-eae0-4262-8b8d-1822c144efe1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ff9d6adb-e1db-447b-ad38-63eb7cff2909", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.101 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "a697336a-8ef0-43f3-9e07-1f1e66cebd52", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0056 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3489054e-9396-4ea1-87e0-2f8eec691d48", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 258.32 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a21777e6-cedd-4086-9990-2718569c8c44", "MeterName": "Compute Hours", "MeterRates": { "0": 0.939 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6b5ae2c8-b3b1-43ab-a897-15750fd974a5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.202 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2416f530-b190-43d7-9fec-239e1a57ea66", "MeterName": "Compute Hours", "MeterRates": { "0": 1.396 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f5a1c44e-f6cb-4223-8954-db0650c7b1cc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5257180f-3f05-40eb-8364-aa21d997b2dc", "MeterName": "Basic Large Azure App Service Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6a1449af-6a8a-4fa4-a106-f74d5aae0edd", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.536 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "51e81064-e0fb-4db3-84e1-9fca0dbf9a94", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 10.9539 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1c9ee768-8e9b-434d-9de2-4a7b67c844d9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9e6a219e-f10b-4035-ba32-8856f48742a3", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.0064 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8520df01-1358-4b00-91ec-2b491d44bc5b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "42fb7fdb-e89f-49d4-854b-aad60b7e8c93", "MeterName": "Premium P2 (Hours)", "MeterRates": { "0": 1.11 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2b0c7480-6afb-4d8d-a112-7ee2f020680f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb6adb50-fe05-4897-88bc-0af2b2430b83", "MeterName": "Compute Hours", "MeterRates": { "0": 0.206 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7394f56f-e03c-44da-a29e-7958f8999d95", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "74a9795f-28bf-4bff-87ae-bb8bd87dc2fa", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2bcfd0e1-e812-48f8-908c-4e24c4fcd0ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.39 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "93a18a5f-d98a-41c9-aafa-1e1e6f58c7cf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.143 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "207dcebc-f6bd-48eb-9ec4-ec1efafe4e1f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.202 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "66a10a5e-b332-424f-8d85-b6f2aa8400f4", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0252 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "feaf29ce-96bd-4895-bc6a-7b368b6af1e3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1f0b8904-817c-48c6-9886-c9ce8bec6cf1", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "599d8114-9825-4572-a41e-6f6540eda937", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.11 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "662d05c5-854d-4b41-a124-8ff89cfe8ad8", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 75.0 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1b37f488-f844-4545-a9bf-e24c728f42da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.081 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "53d2c5b7-7766-4252-a72f-d5a5a92bf206", "MeterName": "Compute Hours", "MeterRates": { "0": 1.492 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "31fadbe3-05d8-4a3a-9881-9b2661e26500", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b1c3135c-e5b0-4d3c-b945-7fff5a62942c", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.011 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b6caee93-d882-4081-986a-7a9604eca996", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "67a2faac-4879-45e6-8cc7-20f181b1425e", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0528 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "799d23fa-6848-4c65-a3c4-064f1b897107", "MeterName": "Compute Hours", "MeterRates": { "0": 0.071 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "64a11e57-33f8-43a5-8057-bad197432639", "MeterName": "Compute Hours", "MeterRates": { "0": 0.644 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "633da1bc-9294-4330-be48-e1d9d135a7cb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.21 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6a476bc7-b392-4bf4-b1a8-591ae0acf335", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.11 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4faa1e00-12cb-43d9-bfe0-e84a2c5103b1", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ad92d711-0a96-408d-9ceb-d2c83f1f8531", "MeterName": "Compute Hours", "MeterRates": { "0": 0.836 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d1c9abda-ba4b-4dbd-a240-bee3a9c6ecbf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.066 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d0bfd1e0-05e8-4ef9-8648-9b91fd3a109f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.44 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "76bbfa2e-d64f-4479-bc5f-8ded27d193bc", "MeterName": "Compute Hours", "MeterRates": { "0": 3.227 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8a98f16f-fa8a-4670-9995-e535357a30e7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99e96e8b-46a6-4666-b4d2-c55778d92367", "MeterName": "Compute Hours", "MeterRates": { "0": 0.059 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4b836326-7e19-46e6-8bce-1b19bb6cd91e", "MeterName": "Unlimited Data - 1 Gbps", "MeterRates": { "0": 8700.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4912d84a-709c-46bf-948a-f2f1672e38dc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5a3e7c3d-bf8a-4b6e-842e-110b8524eb6c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.193 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0d56e2ba-6a08-4722-82a8-00b5c1445609", "MeterName": "Compute Hours", "MeterRates": { "0": 1.069 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f77e0007-79bb-4084-ad1d-e032332ca0de", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6e933ffa-3472-4ce6-ac6d-225932565273", "MeterName": "Compute Hours", "MeterRates": { "0": 1.771 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a021fa38-430e-4d72-8e85-c48c4e17871b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.89 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "35a6c73a-1f03-4c29-819d-9ebba158c4b2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.874 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "38d1f914-6fc4-4eeb-841f-9e293b66a8a2", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0b3bf1de-bace-4fa2-819c-36d0a68dc87c", "MeterName": "Premium Metered Data - 500 Mbps", "MeterRates": { "0": 1090.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "f6a8c17e-81aa-4749-a5be-d718b13b6116", "MeterName": "Premium CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.56 }, "MeterRegion": "Zone 4", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5dc1ff3b-83bc-4bba-ab2a-5cb3aadbc68d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d75fb159-1a02-44b5-bb5c-fc204f93e846", "MeterName": "Compute Hours", "MeterRates": { "0": 0.099 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d1548cd3-4157-4354-9b4b-1c3945ca600b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "850e32c0-2e70-477f-80c8-a687cf90cbed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "131624b8-267e-4598-a413-406dacac7f90", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "0a06f0bc-935b-48cc-b186-6c0fc958af57", "MeterName": "Standard Large App Service Hours", "MeterRates": { "0": 0.472 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d34378b9-7e62-4059-9455-cc7c3d893ad7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.516 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a6d448d1-9628-4cd4-8861-f83781b38e9e", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.144 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "08751b2a-9d63-44d6-9097-bbebbb220c3e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3d4a8a87-4a21-42aa-8acf-e49c56cef148", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ea6f7056-06b0-4fac-babb-bf63e9df78d3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.546 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2ca64efa-a6d8-482d-bd68-58809f238498", "MeterName": "Compute Hours", "MeterRates": { "0": 1.242 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "41f2c58c-cd3b-4ca8-bb2e-8df3ebef92c9", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0536 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4e84bc5b-2f95-4f8a-a104-0a8ab42d8690", "MeterName": "Compute Hours", "MeterRates": { "0": 1.486 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "adb811b9-536d-4d77-bbf7-08d52c5013e0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8944b556-1ecd-4af5-ba4e-21d6eef87a81", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 10.0645 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5de48299-d812-4dbd-b1e2-99714e5bf7ef", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "22c53c77-198b-4357-b1f8-59b9fb790b5a", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "86c35ec3-0a48-426a-9625-22d80e6ea55b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (64 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5bdd6b41-bcff-42c1-ac50-1589366d2657", "MeterName": "Compute Hours", "MeterRates": { "0": 0.417 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "7152c7d8-e834-41f9-a957-07d28a914039", "MeterName": "Web Language Model API (in 1,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "e5bfaf00-3fb5-4eba-9e82-d88c836f05eb", "MeterName": "Standard S5 (Units)", "MeterRates": { "0": 8100.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Search APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "59d1ce45-9e3e-44b2-85c5-4677230ecc88", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c0d070a1-109a-4680-882d-ffd690a650fa", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1771 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2012-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "46c02a5f-778a-4feb-85bf-de4148636090", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database Premium", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "191ad589-61e5-4594-9210-fa95d558d9fe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.068 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "99f4dbeb-2b87-4ed3-8d60-2e53cc8c42a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.405 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "75985cb6-97f7-419f-b9c0-b474c0ca917e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.498 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d2fdb608-8d44-41b5-a3a3-65ad2aefbfd7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4a02d15-0363-47aa-b0f9-eba6352e2b89", "MeterName": "Compute Hours", "MeterRates": { "0": 0.55 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9b64a312-f905-47dc-b2c7-df55b98d8787", "MeterName": "Compute Hours", "MeterRates": { "0": 0.992 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "07f2cec5-9b8a-4e61-908c-b595b9751668", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.4118 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d10f3a9d-6938-49ce-9131-f0045260163e", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9a17738c-a44d-4b21-9933-a0d9f641bd79", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 2.172 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c9aad52-7ba7-4091-97a2-9921beb53694", "MeterName": "Compute Hours", "MeterRates": { "0": 1.35 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "577ebb1e-e1c6-4574-94e5-fdf42c26cd95", "MeterName": "Compute Hours", "MeterRates": { "0": 1.24 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6b288fb0-8311-4dd2-9b80-049267aabc89", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "67cf08ec-f742-4d89-ba10-60ff525dd71f", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 2.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "57c3fc29-f201-4b57-81cc-1f1d7370ee54", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7fc61108-5209-4f54-a47d-c3b0420067c4", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "4eea7f36-94f2-4063-bde7-6bcf3597a368", "MeterName": "Storage Transactions (in 10,000s)", "MeterRates": { "0": 0.00045 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Transactions" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96b76006-b409-4d24-b20b-0e464b89bf23", "MeterName": "Compute Hours", "MeterRates": { "0": 0.044 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "acc6e3ce-2e13-4b31-8c10-6cbea9cdcea8", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.2188 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bc7b6c39-9972-42cd-97e2-f6dfdace5026", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0fa1f4d8-0759-4388-96f0-d81c8693482a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.038 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc6018da-b9d5-4e88-8394-5ab24c3ff8a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.183 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b07b3e32-66b0-4e76-a5d0-34a3c469bccd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.449 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2638e2d5-1b48-4d70-babb-b3532f83033b", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5323 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "187814b2-8d92-4177-ab9d-f750a58e1280", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9af05e34-bf29-4ff3-897a-400d5458fedd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.384 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "863ca6b1-00d3-44b4-87e9-5aad9fa0ece2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.996 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d6013ce8-da29-454d-a946-dbf30b75b81a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0ca2c2b3-effb-4204-8c9e-a79f62e47893", "MeterName": "Compute Hours", "MeterRates": { "0": 0.204 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ceac40b-a2e1-44e4-9263-336b54e5cca0", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "574b4779-7c85-4019-96b2-6df26fb7c95f", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "116ea09d-799d-4f5f-b6f2-fb657dadd785", "MeterName": "Premium Metered Data - 10 Gbps", "MeterRates": { "0": 8000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Xbox LIVE Game Services", "MeterId": "edab46fa-fe89-4a59-a10f-34d0f15c7d71", "MeterName": "Data Transfer Out (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2fee86b7-7c49-46ac-851f-95094c188ef6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c1bf2374-cc2e-4d2b-9e34-8182cfc6e908", "MeterName": "Compute Hours", "MeterRates": { "0": 1.459 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3407ac53-95e8-4162-9c94-f22d9d766202", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6342d833-86aa-4984-9659-dbb69e79e64d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8d85f56f-03bd-4f1f-b5cc-06c4db133f63", "MeterName": "Compute Hours", "MeterRates": { "0": 3.5 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "663397f3-4446-4ec4-a00c-ff7c8046d565", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "04f74f93-7f74-47e0-8309-37c7ec2f5cca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f3d2ca12-995e-4314-8054-1dd48319df09", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8b620e2d-6f16-4301-abfa-74ddefd908e9", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 121.653 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "03a406f1-fcdd-4662-932c-91652842e835", "MeterName": "Basic Elastic Database Existence", "MeterRates": { "0": 0.0177 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2384a7ee-120a-44f4-a6dd-497eab2195e4", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.032 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fc4bbee0-9ba0-433a-8731-66fdab16a591", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.091 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0c50be21-2aa3-455b-92ee-a50aaeecbd7f", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0beefb4a-8f54-4f9a-acfa-3707b3e7aa13", "MeterName": "Compute Hours", "MeterRates": { "0": 0.582 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6769d71b-8499-4168-bfcf-c84219e6654d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.466 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "3f5a1f85-0a6f-40f3-b81f-8f440c1300d8", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "65d3e0d5-c88d-462f-a3e2-f954e6c60361", "MeterName": "Compute Hours", "MeterRates": { "0": 0.98 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f4bb3c38-588a-4856-88d1-d6880ba5e256", "MeterName": "Compute Hours", "MeterRates": { "0": 3.54 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "4e62a388-c558-44dd-be07-b7dce949efcd", "MeterName": "Enterprise (Annual)", "MeterRates": { "0": 2999.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Annual subscriptions" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "95eca2c1-9519-4c55-baa1-9a0e0b201e25", "MeterName": "Basic Automation Minutes", "MeterRates": { "0": 0.002 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Automation", "MeterTags": [], "Unit": "Minutes" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "29b0f50f-478b-4b18-a0a3-0f2b2bc52231", "MeterName": "Compute Hours", "MeterRates": { "0": 0.099 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "da55f3c8-c8dc-4f65-8f99-9d6f201b1ea7", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "76e51cba-3292-4d9d-a556-b268d61b0f0c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.435 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6a58cfd3-f46a-4634-9202-b0d962003a79", "MeterName": "Compute Hours", "MeterRates": { "0": 1.4 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c761fd09-4df5-4e41-ad54-ca093f8840a2", "MeterName": "Premium P13 Secondary Geo Database Days", "MeterRates": { "0": 266.13 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "dbedc6e2-5aca-41e0-8481-7203e4d7718c", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c80a3636-2edb-4248-bcb1-04ef818a75ac", "MeterName": "Standard IO - Disk Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7793f433-c5bc-4f3f-b240-c10ffe8cc53b", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.803 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5b50a2ef-bad3-4614-b502-17465754854a", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.07 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e11d4e94-59a2-4542-a5d8-a485288cc1e7", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "17a7522f-1e03-4a46-8400-53066aad0cfc", "MeterName": "Compute Hours", "MeterRates": { "0": 4.051 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0a255378-40f2-4fb4-a88f-bf739c4878ed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.662 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f89726f3-c447-4fe8-9614-0ea94259c815", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.067 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b0673c88-aa75-44d9-9823-00bdc14523de", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7a97e8d2-1eea-4313-b762-8fde2944667b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.452 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c4ff08f-7a50-4872-b64b-28817a7e99e2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.047 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "83901175-ffc6-4efa-8e32-4fe3278d38d0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "49a64606-30d8-4387-9d7e-759248ad7b23", "MeterName": "Compute Hours", "MeterRates": { "0": 0.633 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7dd4443a-eee7-47a3-8f7e-40dd40e95b26", "MeterName": "Compute Hours", "MeterRates": { "0": 1.833 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "46859d3d-1681-4417-a55d-ad6bedf5745a", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5468 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5e415bc9-7936-445b-9215-306205de24d3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2a4a93e1-73e7-4f6e-b8e6-40b8b00d0074", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "76f9882b-7d4a-4356-804f-99a392b50bed", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 93.6 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "18ec36e4-d126-40b6-b06a-53e8bf18309d", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 584.208 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "27722013-7a53-4a35-8272-9ae43b946965", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 211.7 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2197fb0e-f9a0-4d1c-99ab-f158e6228e91", "MeterName": "Compute Hours", "MeterRates": { "0": 0.736 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce200878-26dd-4083-8a39-8166f81997ac", "MeterName": "Compute Hours", "MeterRates": { "0": 2.016 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4d58644f-2a15-4ba7-9df2-c2dc92e7576a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.166 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "79f8bb51-1197-4222-adc5-65ad5d4e2516", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "22b47bde-0361-4f0d-b7b5-9a093cf67c98", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e0dc5a61-7529-4641-93e9-3253f83d1944", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.3744 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ab4cd6f2-99fc-4f56-b3c8-3e01aecf3f38", "MeterName": "Compute Hours", "MeterRates": { "0": 1.907 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1a5eabae-3ecb-4762-a84f-937fc6cef037", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "702e9999-b340-44aa-b466-ada5552b8f85", "MeterName": "Compute Hours", "MeterRates": { "0": 2.576 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c9157d13-bf43-41ad-b270-f5d6dbf336ea", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.1993 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "efbf19a3-cd04-4d22-870d-d6838497d618", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 255.6 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6c29d974-16dd-462e-b117-393749e90f1d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.081 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a504eaab-0932-41b8-9297-53613397aa8f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard and Weblogic Server Standard (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "817e52af-0065-43a3-b2eb-2ab33482bbf3", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a19cefd2-e440-4983-b03a-f861f4312f60", "MeterName": "Compute Hours", "MeterRates": { "0": 0.166 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "3ec1aea7-28a6-4c59-b645-446836260939", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e46739a2-f90d-4c77-8120-b76d7a839949", "MeterName": "Compute Hours", "MeterRates": { "0": 0.101 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ba66f4c5-bf33-4548-adac-d32652c8ae23", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d9e2713a-d51f-450a-a38c-4ec5f41cf630", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "47ff3834-1ed6-4610-b089-9a33be58fe3a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.853 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "72f659e7-5880-47ce-981d-ddc828ce89e6", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d3515188-f20d-4dd6-9ef0-61c0f0b792bc", "MeterName": "Compute Hours", "MeterRates": { "0": 4.5012 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d817c09e-b8b9-4d2c-8de0-5c34d5148bf3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.098 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ae141c30-f6a6-41ff-997d-48c1521a9224", "MeterName": "Compute Hours", "MeterRates": { "0": 1.551 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "87ff49bc-9c61-4494-8127-12ab834236b6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A10 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8fde27a4-f37c-4af2-ab00-f53eac8f1925", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6bf0fbd7-9dd3-4cfd-97e7-e9a6403df152", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 5.5354 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "848e5302-c41a-4431-8b57-1ebd3603c7d8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "70653a90-aede-4e59-a122-265a80801f27", "MeterName": "Compute Hours", "MeterRates": { "0": 9.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Enterprise (24 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "df8ad0fb-dcb6-4749-a52c-3aeaf69435ac", "MeterName": "Compute Hours", "MeterRates": { "0": 0.336 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "93f05093-c98c-49f0-832c-9ac7020050f9", "MeterName": "MSFT Peering Unlimited Data 500 Mbps", "MeterRates": { "0": 2750.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9670348a-c726-4402-b54b-f931ffb56b1e", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d2aa85ad-233d-4e55-a30f-36cb6a2e0166", "MeterName": "Compute Hours", "MeterRates": { "0": 2.659 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "626d5968-01bb-46f1-8f26-97aa6fd64c23", "MeterName": "Compute Hours", "MeterRates": { "0": 0.376 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "10155e99-5e40-4dc4-84bf-d5ab7c7cf012", "MeterName": "Compute Hours", "MeterRates": { "0": 0.093 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2012-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "47146c02-c177-4c1b-afd5-06780c8472e6", "MeterName": "Database Hours", "MeterRates": { "0": 0.625 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database Premium", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3efe89dc-d410-4dac-8b3c-1429a46b6888", "MeterName": "Compute Hours", "MeterRates": { "0": 0.085 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fff068af-d2b2-4ffc-895e-d2be686d9b39", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0425 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "12fcc5d0-2596-4266-8ff9-25f547ad1385", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bbf64453-c36c-4156-adc9-1cc53c9139f0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "481d417e-9f85-4b8d-8210-2bd93983f04e", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d1e2abca-d7b7-43f6-92b7-41cf38a2d7ab", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "68b92e75-54c9-4b37-a0c7-35b38f639c97", "MeterName": "Compute Hours", "MeterRates": { "0": 2.484 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "0831c2bb-a6cc-4625-af33-f1ace5842337", "MeterName": "Basic C4 (Hours)", "MeterRates": { "0": 0.21 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0fb551ea-6cde-4c19-ae7e-7f851b142062", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-01-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0a0504db-881c-4e74-a111-0ae9b1036025", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services Low Priority", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "69c70c12-70bc-4a98-8268-7443a8ceec15", "MeterName": "Standard DocumentDB Days", "MeterRates": { "0": 0.73 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7da9ad8e-f3e8-4d91-87b8-9746e0dd7a50", "MeterName": "Compute Hours", "MeterRates": { "0": 1.771 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "40551b4c-e8be-48ed-b70b-f8d25c7de724", "MeterName": "Standard IO - Block Blob Read Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2626cdeb-73d2-4fbd-ae22-5e0c6066c41b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.758 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a6995e08-df5a-4617-b712-9ff0767a706b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.294 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "3b81b7ee-cf08-4625-9ba5-d3aa0b424d6c", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 3.0 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e6e1d991-8e82-4f8e-85d6-7ba85b67fcd9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.25 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "13c3eaaa-d5bc-4ff1-8df4-3c5347fc3fb5", "MeterName": "Compute Hours", "MeterRates": { "0": 2.617 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "a11726b3-27b7-4012-9630-b8434d9ca8f8", "MeterName": "Wildcard SSL Certificate - 3 Year", "MeterRates": { "0": 809.97 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Certificates" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f03a2649-c2b8-49c9-a63a-02b31884dfc5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.491 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d2651b1e-e0a7-460e-ac74-0147971ba7b0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "88dfea34-b63f-460b-82cc-22750f689c86", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0ff80052-eeaf-49d1-aa95-f2f6b0eb8ce2", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.011 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "81d1cc1a-fb59-4b84-b6b2-1ec654985a8e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.87 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "bad80588-600e-4e40-9dc1-af46266235e7", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 3.024 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2423b132-5a85-4143-a023-3841f808ba15", "MeterName": "Compute Hours", "MeterRates": { "0": 0.325 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3fb6903d-106b-487e-8bc3-46efe8e541ce", "MeterName": "Compute Hours", "MeterRates": { "0": 0.224 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aff46940-a2c6-46c0-9dd8-2a18816c8415", "MeterName": "Compute Hours", "MeterRates": { "0": 0.531 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b1d08d37-71a0-4c19-9072-d07296a8e767", "MeterName": "Compute Hours", "MeterRates": { "0": 1.952 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1febd7b1-0981-4f31-970c-114eee7f8fd4", "MeterName": "Premium Elastic Database Existence", "MeterRates": { "0": 0.4193 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "7b399fdb-dcd7-49b6-a02a-d42354934a4c", "MeterName": "Premium P2 (Hours)", "MeterRates": { "0": 1.443 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0edeac0b-bd6c-47fb-9325-45e4f7adee3a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.035 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d29e058-214a-4ec5-a52a-df7d76ce1683", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5df0b68a-14df-4e53-b4d7-80a5d839a07e", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 120.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "96d7e0e7-ec9c-444e-a09f-11120a7ae253", "MeterName": "Compute Hours", "MeterRates": { "0": 0.256 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e70070ba-91e3-48b8-a2c6-6060704cb7a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.68 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7836a3b9-6e89-4630-8370-ec9f5427d9fc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "90a20b8b-de68-4f1e-9f08-1bc70aa170e1", "MeterName": "Compute Hours", "MeterRates": { "0": 3.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9769b669-1e76-45f8-99fa-a779c5598226", "MeterName": "Compute Hours", "MeterRates": { "0": 1.92 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (24 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a017bece-ced2-4a16-9939-993d40b086fd", "MeterName": "Compute Hours", "MeterRates": { "0": 2.486 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b1d1445b-213f-499a-bb19-070a2d50248a", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.055 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d19f36ed-e606-4cf0-b5de-d38e484a348e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.651 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ba5ea988-bc12-4945-a8ab-1d20074f9a98", "MeterName": "Basic Medium App Service Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a3834edc-199f-447b-bc92-1d73c1d13e64", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0d8672e9-c981-4980-a8b2-92a91fd0d983", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a8e1572a-f70b-4651-ba7f-10b5883a1a7e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.267 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "779c78a3-ce9d-475a-9830-1e7f1759cf16", "MeterName": "Compute Hours", "MeterRates": { "0": 0.786 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d3b2ba19-019b-4d6c-a451-c790c4d361cd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "290d414c-c892-4e22-bd94-fdba8a30798a", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0df63342-0a5d-4d17-a618-141acf35b84b", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3bdf5d3e-fe86-4d3b-ad42-86309b3063ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.584 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ed004e7f-32cf-476d-96e7-2666d175acfa", "MeterName": "Compute Hours", "MeterRates": { "0": 2.346 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2eaa171a-68e4-489d-a914-54489cb2ab9f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "703cabb2-a30d-44e2-be47-cc8fd1ec25fc", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.015 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d661e656-93ca-48c3-87ac-5c57d5a336d9", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "812dd3b7-5bb0-4f0c-9761-cfb449185e77", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.354 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "63c7062e-7bdd-4cc4-bd18-dad930113649", "MeterName": "Compute Hours", "MeterRates": { "0": 0.87 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aaca138e-b0b4-4210-995c-0403935f30f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A10 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 12.5, "MeterCategory": "Service Bus", "MeterId": "2a9992f8-e914-490b-a7a6-6d21ba55acda", "MeterName": "Operations (in 1,000,000s)", "MeterRates": { "0": 0.8 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard Messaging", "MeterTags": [], "Unit": "1,000,000s" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a2e54082-24f3-4aca-abea-c055d5e781bc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.81 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c3a1efb2-3186-4d07-89ed-fe27eb037e12", "MeterName": "Compute Hours", "MeterRates": { "0": 0.099 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2d19b1c3-fbdd-4afe-b626-5ecd85572af2", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0264 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9d5a76cd-a00f-4049-9ee5-e5b259dd6039", "MeterName": "Compute Hours", "MeterRates": { "0": 1.168 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "56432ae2-acd2-4a72-bee4-87c0190fa02d", "MeterName": "Premium Unlimited Data - 200 Mbps", "MeterRates": { "0": 2600.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "11361e68-c109-4d89-b206-090b98a9bdad", "MeterName": "Compute Hours", "MeterRates": { "0": 2.753 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ff6337ba-f0af-43b1-971f-5a100bed5a99", "MeterName": "Compute Hours", "MeterRates": { "0": 0.408 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cb276b0a-ea08-4a83-b6d5-45d89f048dc5", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 274.43 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "94f06d38-6599-4642-a40e-092f05bdc423", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "de8fff51-3f4b-416b-9833-58f93db65d14", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e95f0563-89c1-4fc1-a047-9f9fe4d317ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "15289f97-4295-4187-8880-7824fff7bb29", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e314e832-45b6-48b7-9e81-f3c9cc00abeb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "84af43ae-2cff-46f6-96e1-f03d27dfeb55", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.026 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c880c666-747a-49bd-9ae9-80058a40cbd3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.178 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 5.0, "MeterCategory": "Recovery Services", "MeterId": "fbadd0ef-6666-4d56-a827-fe1bd8769d15", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Backup", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c118d699-ac19-4fbf-a15b-058be21e29a3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.242 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "64a0ff57-b773-4f5d-b372-3f55b368bbad", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 99.0 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "36d6dff9-7b8b-41ec-970f-ddedac86d1a6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ba302f7a-078b-4141-a636-a76315ba44ce", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.075 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ee91827c-0eeb-45bc-bfef-bdabaf8b21dd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.794 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9af5b606-965b-4c39-915a-a7e81ab1a9c3", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c9dee6c3-b377-4125-ab03-34187dca32c0", "MeterName": "Job Units", "MeterRates": { "0": 0.025 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "5b2d57c7-c637-4224-9e46-59c821440dea", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c2c93259-bcaf-42cf-b11e-15b37ca598f0", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0e7b0b55-5f1d-4617-a87d-7956d51eef49", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c9fe92a8-fbbb-4ab2-bbc8-6e2ab7638470", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cc18e51b-0840-4519-820c-f12e41ed62fc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.29 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0787e845-dc3e-40c2-a093-868205c57706", "MeterName": "Compute Hours", "MeterRates": { "0": 0.234 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8dde8b2e-acd0-4835-8804-539beace387d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "acc82e43-c1c8-4fe8-84c4-bc2f6335353c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d56287c9-d109-45a7-b3e6-eb93f1e0a70f", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.904 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "85fb2294-8995-4b39-a0f1-e453f5df4ebb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Security Center", "MeterId": "15e6182d-2afe-4c9e-8c23-4062bd80b3d4", "MeterName": "Standard Trial Nodes", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Nodes" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "baba89e7-bf49-4814-8e99-0873b7a6e592", "MeterName": "Compute Hours", "MeterRates": { "0": 0.411 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fb847935-9c23-47dc-a7ed-f0f8de600307", "MeterName": "Compute Hours", "MeterRates": { "0": 0.524 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "29d80157-6618-412b-8b53-41a09b811adc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.704 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "739d4f95-af86-4065-bcad-454a12e030f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.386 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "516d1f4c-5f09-43c2-af5d-3325d984de55", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8d487cfe-50fa-4a5a-8f6b-b5033de5e3e6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.584 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "41e0b729-b549-4a82-b6b9-a40024c571ce", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.125 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a78db867-be55-4621-8a40-a7d452605ea1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0171 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "51607b3c-9707-43e1-a608-27f5d42f0696", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 124.8 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a50a04b5-2c4a-44ba-bc55-ec0025fb661b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d963fcb5-ca86-46dd-ac1a-95a52ab154b6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.513 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "72f3794f-05db-4ff8-a92d-20d7c4f8d09c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "65f64746-ab4b-4236-b2b5-1ff0b0ed82da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b4175747-cca9-49df-9c4b-4f74be74d376", "MeterName": "Compute Hours", "MeterRates": { "0": 0.477 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ec512cda-5778-4fb9-b9f8-cac82ff35b17", "MeterName": "Compute DSU (Hours)", "MeterRates": { "0": 2.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Stretch Database", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fafdf2d7-f2ff-45aa-ad19-e576978c9174", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 31.2 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "84bffee5-ab4e-457e-ae0a-0747f53e04fc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.238 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3e96e963-2fc1-4163-ae72-d742707c54db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d3881530-461d-4736-b8ca-a02a9d94adc0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2a3fdbe6-adaf-4590-b938-8b96b6a60893", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.8351 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a7e87e9a-a6a9-4495-9dc3-261774b93704", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "94b67630-61f2-465b-a0bd-c2fb8bdd1136", "MeterName": "Compute Hours", "MeterRates": { "0": 0.322 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "a84e42c4-d199-4cce-b2e8-9fefe6fa2ee2", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.0138 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f3485115-5e7f-4add-94ff-ec5bb77b8bf0", "MeterName": "Compute Hours", "MeterRates": { "0": 2.035 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3d03000b-d983-437c-8be2-18708795d648", "MeterName": "Compute Hours", "MeterRates": { "0": 0.034 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "bf20e6b9-2040-493c-aaf3-a61ceb7de3b9", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.055 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d67bddb-b6df-43f4-ada6-24222268beed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.392 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d5fd3c5c-e51b-41be-b8ab-34399ed389c3", "MeterName": "Premium Unlimited Data - 500 Mbps", "MeterRates": { "0": 6000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9dd9d29c-710f-43d5-ad66-6eafe95ed48a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.835 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7f863132-b367-4b10-91b4-e87401aad714", "MeterName": "Users (in 100s)", "MeterRates": { "0": 50.0 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "Azure Data Catalog", "MeterTags": [], "Unit": "100 Users" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "748d0c9d-f81d-44ac-9c18-1bcd1cc20a68", "MeterName": "Unlimited Data - 10 Gbps", "MeterRates": { "0": 51300.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6bf946f8-fbbd-4d45-88b8-3184a7dad257", "MeterName": "Compute Hours", "MeterRates": { "0": 0.986 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "938fc20c-a31d-4594-a651-03c4d1a68f90", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.0963 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cca0599b-a1f0-4731-8e1c-73867b093ff8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.148 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "5833c72e-4737-416d-816f-7ed7b2e892ac", "MeterName": "Premium P2 (Hours)", "MeterRates": { "0": 1.332 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d3945604-5bb6-4d9c-8266-8233648d9d5b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.225 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5e2c8dd2-7899-4cb4-a9e3-0f08c3f90022", "MeterName": "Premium Storage - Page Blob/P4 (Units)", "MeterRates": { "0": 5.2801 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9ec1557d-a16b-4acc-aaa2-926a22541a53", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0d825caf-c52e-4778-9703-c05a14ebe506", "MeterName": "Compute Hours", "MeterRates": { "0": 3.059 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "56c39162-0826-4651-9f21-b5e62119c5a6", "MeterName": "Compute Hours", "MeterRates": { "0": 3.5 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d1ee12bf-83ce-4be7-b0d6-3ec88afd784c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "97257700-ef12-4785-9a97-306393acac14", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ec9c3c03-f0c9-4bbd-95af-1c141ba033e4", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 338.716 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2e3c2132-1398-43d2-ad45-1d77f6574933", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d22785e-55f5-406a-b053-39346d79eee3", "MeterName": "Compute Hours", "MeterRates": { "0": 3.04 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f387ec7-12a0-46a1-a94a-4d5d2878177c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3724ca9f-7356-4114-96db-dd63fa2ded59", "MeterName": "MSFT Peering Metered Data 5 Gbps", "MeterRates": { "0": 2180.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "57adc0dd-e490-4db5-a420-a586dd1d5f62", "MeterName": "Compute Hours", "MeterRates": { "0": 0.848 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "326f855c-2e02-46c0-a34f-2051cef5dd61", "MeterName": "Compute Hours", "MeterRates": { "0": 0.992 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "39cbf8ac-08cb-4b39-9cfe-50ed2374c8d9", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "102173ef-b7bd-4729-a3f3-8231b84688b5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.069 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4da9deaa-6718-460c-a61a-278433741340", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 18.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "26d8935d-84e1-4207-a0e5-cb2728227840", "MeterName": "Compute Hours", "MeterRates": { "0": 0.5 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b4a5be5e-7d2d-416b-bb54-8355ac8fd46d", "MeterName": "Premium Unlimited Data - 100 Mbps", "MeterRates": { "0": 1405.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ea89d54-25fa-409e-9b68-ccd73dc45ac2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.88 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "70dcc916-5f58-47ab-8fc5-c72a31ab144d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "ff92c14c-af83-412e-9144-a2542dfe0b4f", "MeterName": "Certificate Renewal Request", "MeterRates": { "0": 3.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Key Vault", "MeterTags": [], "Unit": "1 Unit" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "623ece87-17fd-488b-a642-b70be13c26ba", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.11 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "72e7622d-8c26-4c80-8000-f31cb6b125c5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "177ee643-5434-4c04-ae11-9e01672ed87e", "MeterName": "Throughput Units (Hours)", "MeterRates": { "0": 0.015 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Event Hubs", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "03629172-8caf-40cf-847b-93b12f93b5f7", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "60b3ae9d-e77a-46b2-9cdf-92fa87407969", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "L SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aaa7d6b9-acc0-49f6-bb2e-d41b45980650", "MeterName": "Compute Hours", "MeterRates": { "0": 0.128 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "68628f65-110b-40ed-9ded-1c724de31696", "MeterName": "Compute Hours", "MeterRates": { "0": 0.71 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1c995ee7-e5a5-4cea-bc7b-473d436a6f7b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dfddbb55-b36b-42ce-902a-5622584e548c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9ac8c8b4-69c5-4103-9f43-5c86ef1986b8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.464 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b925488d-a109-4294-9d73-6f359f61ba5b", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 1.81 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "149e175b-7ec7-4c7d-8ddd-68f0240e1884", "MeterName": "Compute Hours", "MeterRates": { "0": 1.706 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a1d12714-8dce-4a5a-b3f5-4c62036d2b74", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 33.0 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1faac307-99a5-4baf-9af2-b073292ac89f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.632 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fbfb1ce7-4723-4e98-9d6f-68400d9d5611", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "82146033-26e1-4269-a393-7d1fb1e3dfb6", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A10 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0f8dbe2a-21a3-42fa-8ae5-fb51ba7f4a6c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "9ed09a51-dc57-40e3-8951-d63327295380", "MeterName": "MSFT Peering Metered Data 500 Mbps", "MeterRates": { "0": 290.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ba244a7-727d-4287-85a4-d38b704c8114", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f7c90308-4da6-4bd6-84da-0228b485bfe2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.89 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A10 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4dc09ffb-fa71-4223-98f7-03b2461d569e", "MeterName": "Compute Hours", "MeterRates": { "0": 1.125 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 5.0, "MeterCategory": "Networking", "MeterId": "fe167397-a38d-43c3-9bb3-8e2907e56a41", "MeterName": "Data Transfer Out (GB)", "MeterRates": { "0": 0.138 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "634389ad-e60d-4d4d-a9ca-38cd74f69f26", "MeterName": "Compute Hours", "MeterRates": { "0": 1.0 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "631dcf36-ec32-4309-9b2b-8874c991dd94", "MeterName": "Compute Hours", "MeterRates": { "0": 0.297 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6196d4b3-8056-4d9c-bf78-3793461a8fbb", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0047 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9d9b2196-19eb-4d4c-a260-9fb424c026a8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.122 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "180c1a0a-b0a5-4de3-a032-f92925a4bf90", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SLES (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "4fc327d2-f962-4beb-9f21-ab3234509a54", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.011 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "243ff232-d876-4ab5-b953-ba59f171ccc8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.163 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d83b9e75-6108-44c6-a7aa-1536af74a720", "MeterName": "Compute Hours", "MeterRates": { "0": 0.891 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c8ed793e-8dd7-4c18-9d4b-d1398dbec48a", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 2.956 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "11278850-f161-4a6e-86ef-d650a29fb62f", "MeterName": "Standard IO - Page Blob Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "10192ffe-382f-4695-bbd5-fa4024be43e4", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 62.4 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6fe73cf3-5ef3-435a-b3be-82e7d9983499", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4bdbdfd4-7163-4e7f-be56-d0a3cbe4eb96", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 645.16 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "764121ff-8cb2-4278-8a57-1d6ed8ac3e23", "MeterName": "Compute Hours", "MeterRates": { "0": 0.198 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2a3f83a3-5505-4647-876c-ccce4628ed7c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "bfda4742-c304-46d5-a6e1-248cc10767bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.768 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b2cc5210-7ffa-41f0-9525-bdd47947ece2", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "04988c17-fbbf-4aec-afd0-29b020e7cea4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.386 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ec877d02-e97e-41ca-ac02-56d733eac098", "MeterName": "Compute Hours", "MeterRates": { "0": 9.65 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b24017a6-c177-4280-8306-0d4e320b8a78", "MeterName": "Compute Hours", "MeterRates": { "0": 2.276 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "32b320b0-eb93-4487-a81e-2f885bc2391a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.615 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "78304818-717c-476f-8e29-bcc6b9a43273", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.06 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "37bb729e-2ae2-4195-b13a-275a5131b197", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise and Weblogic Server Enterprise (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e560f389-ee78-4704-b336-39a19f46c2a2", "MeterName": "Premium Unlimited Data - 1 Gbps", "MeterRates": { "0": 10150.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1f68c2e0-76e5-4d27-a12e-99a5be9a9aaa", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b963aed7-0fbe-46f2-9e6c-24bd975b6bc0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "392dcf2a-b424-4ccb-a0a6-5da6843e4152", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "66fe442d-3ec3-4bf3-89d5-943124d4aeb3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "382d35d5-27f9-41f4-83dd-c8057387f31f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4b3dee13-e854-400e-bf8b-d85215487c41", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.5323 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b26e25f3-b970-4e68-aa8e-cca97a646005", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.087 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cf53500c-dc47-4772-a8f4-faf69566f6f3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.32 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4549f2e0-b433-4f94-b73a-3cfa77d950a0", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fe7f12a1-1945-4132-b339-b8c03336753a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.202 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "07273c13-0b43-4aff-8f6d-9c35b5ab84c7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d1e40041-22fd-4815-86e2-f067dace7a59", "MeterName": "Standard IO - Page Blob Read Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f4b954d8-bbd7-4f99-ad62-f14f106bae4b", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "db34174d-62aa-456a-b7c3-d3872aaa389c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "54c6bbf3-322b-406d-8411-101bc4b9443a", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 0.9677 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0073dcb5-c9d8-416c-aea6-919a52badac4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e84b8971-c5cf-4da9-be6b-ad923445afb5", "MeterName": "Core Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "HDInsight R-Server Surcharge", "MeterTags": [], "Unit": "Core Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "10e5ee74-8fd6-4972-909f-65a83f92f0ce", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c1fa2cdf-a2fb-4801-9224-67840621eeeb", "MeterName": "HP1 Gateway Hours", "MeterRates": { "0": 0.49 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9445fceb-3ac5-4ab8-9fb4-4dca5f2f058c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.816 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ba3ef55d-e757-440e-b83f-7a8493c13ee7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.798 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "80a8965b-d659-4c4c-9514-a5963386e26b", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.106 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "943e338a-003d-408e-838a-1998caf3f163", "MeterName": "Premium Unlimited Data - 5 Gbps", "MeterRates": { "0": 28650.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0aa4df8e-0496-497a-b1b1-6bf1c17324a4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.292 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0ba80ebc-df6b-485b-9c12-131969e84524", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3456 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "333f45c9-207a-471c-ba6f-4200ae8214a9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "54ef6a12-60c1-4248-878f-1d3d9da46833", "MeterName": "Compute Hours", "MeterRates": { "0": 0.041 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ebf7cc26-6b9a-41d3-8768-d890fe566e00", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 16.94 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7587fb8a-4434-4700-aaea-f51b24991de7", "MeterName": "Premium P2 Secondary Active Geo Database Days", "MeterRates": { "0": 33.0 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "48dc3acf-ab2d-4360-8405-1717c6916108", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9611d0a7-e5d6-49d7-8800-77472ef4a492", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 4.536 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a18b058f-def2-4920-a23f-d39488e402fe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "dc9208fc-ebf9-4845-a862-172cca61c010", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XS Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "3e3585a6-bb6d-401f-b9bf-973ca29607ac", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d4758477-e269-4d29-9098-9b121ea6bb3e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.192 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "166119a4-ca96-47b4-add8-3fe0963b8518", "MeterName": "Compute Hours", "MeterRates": { "0": 0.142 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Insight and Analytics", "MeterId": "a4e29a95-5b4c-408b-80e3-113f9410566e", "MeterName": "Paid Nodes (Node)", "MeterRates": { "0": 15.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "OMS Insight and Analytics", "MeterTags": [], "Unit": "1 Node" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ab3049b4-0a43-46e3-9b2c-a37ac14785d8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.559 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0b9bcd8-8dcf-47e7-8f49-78e1a4052efa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "08b5a298-725e-4857-8693-db6e76bcfef5", "MeterName": "Compute Hours", "MeterRates": { "0": 10.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Enterprise (20 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f303a21a-05f1-4563-b2ad-7523eebc4058", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.42 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cf79d57f-a665-44a7-a759-00e2938a1e7a", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 7.5484 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "28722468-eae4-4c36-9459-5453244362c1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.665 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aa23554d-5637-40df-99ba-6199badd1ff7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.486 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8b6d2696-456c-41e1-a09e-73efeb109a63", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7b3fd390-3a9d-419e-b19d-a75199b7c9d7", "MeterName": "Compute Hours", "MeterRates": { "0": 3.255 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "G3 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5e02b0bc-21e5-410c-ac8f-e7c37e12e98d", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.22 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9b25ee17-78ef-44dc-9d0e-43ee6f3ca17c", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "13274838-f91b-449d-9d55-6a9a6b5b92ad", "MeterName": "Metered Data - 5 Gbps", "MeterRates": { "0": 2180.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "6b03850c-ae44-4ad4-b942-1cc856f278a7", "MeterName": "Basic Large Azure App Service Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "42923449-6550-4ebb-b79c-98785cf55b0a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e400bd85-62c1-4008-8447-7d217dbf31a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.313 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "757d2cbf-578c-4560-8d2b-5ddb262e179f", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 250.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "d388d280-f5f3-4af6-b945-b84b2c8eee53", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8ab419c9-b30c-4dff-8f6b-a28e18dbd14e", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1674 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "5c2aad26-7d6a-4422-b399-c56d8530c923", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8788528e-5f5d-44c0-9838-a912dd3cfa64", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "1fb98075-ab1b-4aaf-a70f-030c435f2cef", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f8cc8e26-97d3-468e-a156-ee9f80e395c0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8de34d2b-d93c-4a10-9c21-5e9308001143", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1891cbcb-3061-46c5-b831-7dfc0b5ae5b4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.996 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1e15b985-52dc-4c4f-b2b3-49a1f850adf5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3f353f1e-e470-4a17-8cb5-63c336fafa46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.281 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e7c714d8-1575-4442-b476-5a3bfb7a95a2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.258 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9387a505-a130-4481-a688-7323ac34cf28", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f96bf734-0afa-4777-b64c-a8bdf33524d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "03146d09-fc2a-43b7-8488-c8bc60967619", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3a6a3048-9ac0-4069-9ff9-f1c2056c8194", "MeterName": "Compute Hours", "MeterRates": { "0": 2.2512 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c850c89-8632-4c4d-a81a-306185a1f54f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f3e734c0-bd1a-46cc-bcb2-8b25fb6464ed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a9d1a21f-b52e-42c8-8e07-082d2931fbaf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.062 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "219c2d13-b9e3-4f5f-b042-0c0cf8fbee4b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.44 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f941300d-785f-42a3-9ab6-b33da842ad53", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "015c573c-865b-45e2-96b1-05ecfee8946b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.191 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f0ff652b-892b-458f-b945-c252377a33d0", "MeterName": "Compute Hours", "MeterRates": { "0": 4.742 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b3a9cd8b-f48b-4c83-83c7-85c830abd94a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "RemoteApp", "MeterId": "14db424e-e05d-48a5-a2aa-2e39230c6fd4", "MeterName": "Standard Users", "MeterRates": { "0": 15.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Named User", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e1422cce-8e82-44f7-8a10-78a04d55f158", "MeterName": "Compute Hours", "MeterRates": { "0": 1.74 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dc766448-422a-43cf-9fd6-00e5e9007159", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0581 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "015d491e-bfb1-481d-8fc4-bfaf9ce737f1", "MeterName": "Unlimited Data - 50 Mbps", "MeterRates": { "0": 610.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a3ce4838-6f58-435e-bb04-8f9bf8e79d03", "MeterName": "Compute Hours", "MeterRates": { "0": 6.425 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "G4 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c5647410-2402-4109-b178-7d0f56207b71", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "20f1b323-0950-4527-b4f3-d77e2b7aca16", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A8 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "56ac24bc-5a56-4331-84b5-2297354ca41c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.264 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0bd3e772-c3ce-4d0b-a6db-210190c18a4f", "MeterName": "Metered Data - 10 Gbps", "MeterRates": { "0": 5000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a79da633-6978-4e1b-9f32-c99581129746", "MeterName": "Compute Hours", "MeterRates": { "0": 0.55 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "db394620-d69c-4ba6-b402-88108a27a4ae", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "2c1f4f60-f147-4b64-942c-dab273f98e80", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A10 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ef7c4307-326e-4905-af37-6e694c1574b3", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5da710e0-516b-4a5d-9be1-1c56c7897c78", "MeterName": "Compute Hours", "MeterRates": { "0": 1.52 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "abc3680a-1dfa-4397-83d7-6120fa044a62", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "09b83c38-1b21-4a90-bf0c-141ea61ad31e", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "30cd0f6d-9e46-47ee-a67e-84fa3e6db9cd", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "966ffa85-0757-44eb-b198-04281e317525", "MeterName": "Compute Hours", "MeterRates": { "0": 0.183 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3073fb71-c919-4f50-ba21-43df907d0606", "MeterName": "Compute Hours", "MeterRates": { "0": 2.673 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0883795a-0ef6-40a1-bbe6-a201246ee4e5", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1841 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "15e3cdab-e44d-4758-8429-95d06d2dd108", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f8e0cd6f-76e3-4364-80d7-1723b4b090b7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "45c9240e-43e1-4abb-8b6c-f37296c36687", "MeterName": "Compute Hours", "MeterRates": { "0": 0.107 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "8303edd8-7a66-4bc6-aef2-89f46925316c", "MeterName": "Standard IO - Disk Write Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "9d796645-ffe8-4778-b384-cbd5ebd48222", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.1252 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "a05f8b31-228c-4826-862c-6cdb578784a3", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "362e5fdf-eb3c-46b7-89c7-32bbf3828f60", "MeterName": "Compute Hours", "MeterRates": { "0": 0.408 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "b7aeadbf-3cd2-4dfc-ac6d-afc44a8524a7", "MeterName": "Standard S2 (Units)", "MeterRates": { "0": 50.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Speller APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Insight and Analytics", "MeterId": "df358314-e5e3-4230-9258-86b5850ef495", "MeterName": "Overage per Node (GB)", "MeterRates": { "0": 2.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "OMS Insight and Security Data", "MeterTags": [], "Unit": "1 GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f74a555b-a7fd-43f8-bfd9-e9b03106a5a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.068 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "20c9c6ca-43e5-4487-b43c-9e06b302461b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.187 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3671905c-0d8a-43fe-934e-5111bb3f2354", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b741411f-b23b-49ee-aac6-5ada452af6cc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a3cbc206-a0a6-4d02-94b3-5b41cd9ab200", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.1771 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "75e74d58-f259-4821-85e6-d5861f663a10", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 163.548 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0377be69-4b0d-40a5-b3b7-4a67f0ef62e4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.233 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "84969491-ca1a-4413-82c6-8b35ee5852b6", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.4839 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "50088234-abcb-41a1-aa2c-9ec7a49d7adc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.897 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c2c57b4b-3b6d-4219-b3d9-6ac445d2eae0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.69 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e9230107-4ab6-4141-b4ff-0dc8eed70178", "MeterName": "MSFT Peering Metered Data 2 Gbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1a14ea5b-c4ea-4de2-a663-74e55e3f7818", "MeterName": "Compute Hours", "MeterRates": { "0": 1.56 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "db86ac86-db22-48a4-8385-cad776727575", "MeterName": "Compute Hours", "MeterRates": { "0": 0.081 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7af2bc0b-9b64-41e9-92c9-a6f7f921873c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.75 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "G2 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "25cd7f37-50c4-4c7a-8db7-f5ddcadfe240", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "251dff4d-3a98-4147-a6e4-503c4164b8d2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.404 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "04f46858-e485-41a4-84a8-dbcb4f80f8c6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5521fd84-3230-47f3-8247-4e7b8ea00faf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a39864f6-3e0d-4637-86bb-1e53251ecef9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "391d4fb3-98bd-45c1-a81e-13d17fb0587a", "MeterName": "Data Transfer Out - Metered Data (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "de59f888-758c-4bf2-9e5f-d8c254a7d16a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.7 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "9c651cab-7d79-44ca-a7ed-2774beaa555a", "MeterName": "Free", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ec40c4c2-c5db-4c7c-991f-41d31d8f2bf9", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b3da8307-0d4c-4935-9b3a-1cb48d9fc43a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.059 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "13268250-7429-4443-9e83-cb802bf8e136", "MeterName": "Compute Hours", "MeterRates": { "0": 1.043 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0aae2541-5b38-4b15-9334-f9cbd11f0912", "MeterName": "Premium Storage - Page Blob/P6 (Units)", "MeterRates": { "0": 10.2081 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f104144a-498f-49e4-a431-06fbbc2019f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "698457d6-f367-4cb7-8d67-0529485048a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "722926b4-ea0c-40d3-837b-12d8a2d49930", "MeterName": "Compute Hours", "MeterRates": { "0": 0.58 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "85a9c337-9ef1-4885-b343-947e942ca0fc", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ae184e1f-aa21-4387-a46f-3d1cce8dad57", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "471e3bd7-d8e0-452c-821f-107ad7c13bbb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c8a25804-f50c-4cac-908e-d6783eac4617", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "d4b029f8-2352-4670-ac8e-ec078103a244", "MeterName": "Standard S3 (Units)", "MeterRates": { "0": 450.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Speller APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6b23937f-c9b5-409e-9324-7b4b6aeafba9", "MeterName": "Compute Hours", "MeterRates": { "0": 1.771 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "82d4564e-133d-4699-b0b9-81f82a8f27ec", "MeterName": "Language Understanding APIs (in 1,000s)", "MeterRates": { "0": 0.75 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5f9d4381-d6b7-47cd-be01-309ba68275c4", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "fb2898b2-6ce6-46e3-9ede-4e82ba465fb8", "MeterName": "Free", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Recommendations", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "681813ea-a3a4-44fa-82a4-902588427fd8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9cf4c8c6-a1d8-42cc-956c-86cd71eca089", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "991b1e89-77fd-48a4-a6d6-b8484b9f5a6b", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "420fa5a1-99a9-4d8d-87db-2d6663f96343", "MeterName": "Compute Hours", "MeterRates": { "0": 1.343 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c6067198-1a09-4382-8607-a750ad29560f", "MeterName": "DWU", "MeterRates": { "0": 1.8146 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "562d12a5-08f8-4199-adbd-39ee82375333", "MeterName": "Compute Hours", "MeterRates": { "0": 0.047 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1e5de507-c021-4bec-abd2-ac68060929c6", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 132.0 }, "MeterRegion": "AU East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fd0c4484-f366-48f3-8ae0-7b338b1cc278", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.11 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ef8d62df-264f-48d8-aad5-8640497152b6", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d888363b-b962-4d9a-a948-32b849f316b6", "MeterName": "Premium Metered Data - 2 Gbps", "MeterRates": { "0": 3122.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "afe173cb-c4ea-46bd-81c5-d856d11993ae", "MeterName": "Compute Hours", "MeterRates": { "0": 1.306 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8e5e00c9-82cb-4e20-b7f7-fbebb4b6dfbb", "MeterName": "Compute Hours", "MeterRates": { "0": 1.342 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c3a82c70-2ad9-4901-9492-d82ec03cf21d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.551 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "da9743df-c38c-448b-928a-0596503926c5", "MeterName": "MSFT Peering Metered Data 100 Mbps", "MeterRates": { "0": 110.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "357eb6d1-d528-44fb-bcc2-ec2281db1db9", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.04 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0e02ab98-dbe9-45f6-987f-b8283aafaa30", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9a8df657-2b2b-4326-b9e0-00af990b0141", "MeterName": "Compute Hours", "MeterRates": { "0": 2.708 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "b00ea85f-530d-40c9-8ce5-847dabe777a4", "MeterName": "Premium P2 (Hours)", "MeterRates": { "0": 1.388 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "8ff01f8c-c2ce-4c2a-bf43-201a13d22945", "MeterName": "Compute Hours", "MeterRates": { "0": 0.34 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3e7fc27f-95cc-452f-a3f7-4d182019eefd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b1e41f68-4bfb-4a85-8e55-bb509aa07791", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f9cd05ec-dccb-4c1f-b8bc-65d1e71ac77c", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "74a43f0f-34d7-4341-9a38-4b814feac136", "MeterName": "Compute Hours", "MeterRates": { "0": 0.047 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9377beba-f5b6-4baa-a085-0297220dec00", "MeterName": "Compute Hours", "MeterRates": { "0": 1.692 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "32b21f42-4d6f-4e88-acb0-1657cabc51c3", "MeterName": "Spell Check APIs (in 1,000s)", "MeterRates": { "0": 0.8 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "b4d1c760-640f-45ca-8815-5201f6e1a70d", "MeterName": "Shared App Service Hours", "MeterRates": { "0": 0.0136 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f8e62c07-a49b-4789-ba6f-84fdd5904491", "MeterName": "Compute Hours", "MeterRates": { "0": 0.206 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "20994b3b-bc8f-4dd9-a30c-bec3b71516fe", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a4726471-1b49-42f6-aa13-c69fe7e605ea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "40db34c2-6817-457a-b33b-3fb2b5a2d4bc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.367 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb2ceb60-7694-47ca-8297-ddfbf9f98e05", "MeterName": "Compute Hours", "MeterRates": { "0": 1.117 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "481eb91e-ddea-421a-81f5-ad3d99798232", "MeterName": "Compute Hours", "MeterRates": { "0": 0.242 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2bbe2140-2764-45af-ba6a-7c34824b6182", "MeterName": "Compute Hours", "MeterRates": { "0": 0.971 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "77c7367d-d710-45f3-a4a2-729fcd66e3be", "MeterName": "Compute Hours", "MeterRates": { "0": 10.1568 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a71fb7b5-ef9d-41a6-9032-d1d7e95bbc40", "MeterName": "Standard S4 Database Days", "MeterRates": { "0": 11.6129 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "533dc2ae-140e-42df-8d8c-785057716db2", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.125 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "629194b4-db61-4a55-ad90-c65894f69715", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0ca65088-b8e3-43e2-b89c-344c2e9d4c0a", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "863a361a-ae37-4cc7-a111-fc3ac23c9ccc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "fbd377b9-eb02-4b4e-9da4-302fac870ebd", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.031 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "68637dc8-25d6-4a9f-ad61-0e6233b9ad24", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.0588 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6f6f549d-5a0a-45d2-b122-530967cfa73c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "438ea1b4-f661-4132-b857-90f10d9ab8b4", "MeterName": "Compute Hours", "MeterRates": { "0": 2.684 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "019046e3-1be3-4b63-b8da-ca3987127c38", "MeterName": "Compute Hours", "MeterRates": { "0": 0.917 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c9c6cf62-8b9e-4c77-b31c-1cf9236609c5", "MeterName": "Compute Hours", "MeterRates": { "0": 3.5 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "94f38974-9279-49f2-992a-f05176ffc1c8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.058 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "a68b7c67-c7da-4f84-9a5d-52568d253684", "MeterName": "Standard Computer Vision API (1000s)", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "1K Transactions" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce32fcc5-66f2-483f-8b9c-816395f63ba1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.802 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4d590ea2-c98b-4f55-8282-76333a5303d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.495 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8878d5d2-6b98-435c-b91b-7e079c649123", "MeterName": "Compute Hours", "MeterRates": { "0": 1.542 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "30ab1dae-8172-4b24-aa5b-3666d3f0fde1", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.095 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "db38ea22-8395-4dbd-96af-4ea6d0330128", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f21bc78c-3ad6-4cce-a34c-1845a8e7d9a5", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 84.2 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a329232f-c89b-433f-abba-2fc810762aaf", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 2.688 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "03bd7742-b66a-47ce-bde4-2b0c37334ca4", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 470.464 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c0fa7610-3405-42da-93df-c34c8e350be8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f45bb57d-d696-4148-9727-02bdf14ee397", "MeterName": "Compute Hours", "MeterRates": { "0": 1.025 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5fdad69-c9d0-49f0-8db8-b51f68595b24", "MeterName": "Compute Hours", "MeterRates": { "0": 0.056 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "71164b2b-6eb4-4ce9-af84-9f5b9067f66c", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 5.8806 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "89832013-beee-46c8-bec0-0ade009afd4d", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 13.61 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2a31de90-0d6c-4ee1-bdaf-65398e98bf1c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6d3cfada-a09a-482c-a927-5f2b21edd2f3", "MeterName": "Transactions (in 1,000,000s)", "MeterRates": { "0": 0.07 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "1,000,000s" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9d5e072d-3a9c-4e42-a38f-2ab1091636db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.926 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "93dbc90a-fa3d-4128-8950-0b28437be121", "MeterName": "Compute Hours", "MeterRates": { "0": 0.191 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "08caf470-a419-4e61-a379-48d684559bf3", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.44 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e0ec387b-5c15-420f-ab57-5556ecc8a319", "MeterName": "Compute Hours", "MeterRates": { "0": 0.016 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "05e50686-36c1-41ea-8537-75d4da79067c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.861 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c93b3016-1dfe-4347-a67c-1bc6a1ffcd36", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 0.9677 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e496f65a-d0a4-4ff9-b5ae-e89170d61a01", "MeterName": "Premium Unlimited Data - 50 Mbps", "MeterRates": { "0": 375.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1b841068-c475-4486-bb3e-c0151722d6aa", "MeterName": "Standard SSL Certificate - 1 Year", "MeterRates": { "0": 69.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Certificates" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "12263426-0c92-4d0d-8368-69cbc669c7e4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.398 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "951b2a0e-1a0b-488c-b20a-b4254edba928", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "1444f89b-6017-465b-a5a9-4e54b4155a00", "MeterName": "IO Unit Hours", "MeterRates": { "0": 0.0075 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "627355f7-5c0b-40d0-8620-fc4e81f9f64b", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 8.3032 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "58424b4e-d306-49d3-9938-607e93d001cb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.584 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e91454fa-ef4b-4360-9382-7b8f96001f30", "MeterName": "Compute Hours", "MeterRates": { "0": 0.744 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d4240cf8-c48e-401a-be29-65e4f195fdd9", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 176.13 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f6aafe92-51ae-4e3b-af93-7aa0eeca7e1a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.178 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "963c3ab9-5ff4-4e09-937d-b5b1e06df793", "MeterName": "Compute Hours", "MeterRates": { "0": 0.52 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82e580a0-f4ea-46b9-bffa-afba2681923a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.954 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "36216e45-b7d8-42f2-9a52-241e8eb1129d", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 24.74 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "515c0fd0-e2e9-4865-acbc-e13bac953ef2", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 27.0 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b6f6c71e-4321-47ff-bcf2-dda2a8dc2654", "MeterName": "Metered Data - 500 Mbps", "MeterRates": { "0": 290.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9e670c6c-5846-4b24-837a-59cc363ba607", "MeterName": "Compute Hours", "MeterRates": { "0": 0.592 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5d41af6c-f137-4f8e-9a2d-d1d715aff55e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c4e200af-c022-48cd-8164-3e9b7693565b", "MeterName": "Compute Hours", "MeterRates": { "0": 7.82 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "54da788c-4da6-413c-9ed6-c6e472a8610b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.96 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (8 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ab1147b-1075-4566-8f01-6f7001bddc7d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.371 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f531c06a-c2aa-4d9a-87e4-b0ee5219128c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6c906e01-c692-4cd5-9bf3-bd2fab31b3ab", "MeterName": "Compute Hours", "MeterRates": { "0": 3.075 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5ff4bee9-762a-4613-a25c-bc45685e1701", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6decd9c0-f04d-47ab-bdf5-57ea8e352d62", "MeterName": "Premium P2 Secondary Geo Database Days", "MeterRates": { "0": 27.23 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "72fb063c-631e-4256-8543-7fa0bde227d9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "23b7514c-47a4-4271-abca-2fd9e4fd9405", "MeterName": "Premium P1 (Hours)", "MeterRates": { "0": 0.694 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8e2b9efd-6226-4b17-9325-97788b5fa0bb", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.0671 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4478cc63-ca72-4ff7-907d-6a2b47962e75", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "d4af2942-f317-4584-8b2b-b2717f8f6579", "MeterName": "Premium P3 (Hours)", "MeterRates": { "0": 2.663 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c6936549-1eeb-4b49-ace5-d00f3b517135", "MeterName": "Premium P11 Database Days", "MeterRates": { "0": 270.97 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a88483d9-22a1-4957-ba20-45286b69ef2b", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.456 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "6eace005-7b3c-4846-aeef-84f21b5ca32e", "MeterName": "Metered Data - 200 Mbps", "MeterRates": { "0": 145.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6e9d5775-c707-403e-9027-1ddd34eeaeb6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "6b5329c6-86e7-45cd-b49f-c34239697bb8", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ba1d4e6-64f5-44b8-bc83-98adfb729524", "MeterName": "Compute Hours", "MeterRates": { "0": 0.773 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "89c1b157-7ea3-475d-867f-f04e498a5620", "MeterName": "Metered Data - 1 Gbps", "MeterRates": { "0": 436.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7056fbc8-1b29-4036-bf00-17a2c7d20e57", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10K Operations" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "28a25776-3295-4ede-a0a0-c60026589b46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8f89de2d-5e65-4560-8d94-208ad84b4881", "MeterName": "Compute Hours", "MeterRates": { "0": 2.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (20 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60ef9d65-2ae9-4e25-b08a-5eaa7fd924d5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "55040bb3-35ab-4f8d-b85c-85fe84e5001c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.258 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "f93e0c84-948e-4eb7-8b2f-54593ab43964", "MeterName": "Standard Medium App Service Hours", "MeterRates": { "0": 0.244 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a501ea5a-1873-439e-8a37-82e5429ee4e0", "MeterName": "Standard S3 Secondary Active Geo Database Days", "MeterRates": { "0": 5.8064 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0518417e-e62c-4d34-9634-9ac7c0580f4b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e4ae82a2-f743-48a2-8315-adcdbb18eee6", "MeterName": "Compute Hours", "MeterRates": { "0": 2.64 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "dd4f6bb8-03ff-4c57-95e7-e4859c888c80", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 3.024 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "fc72e5cd-54e0-44c7-bf6e-85d6cf55bc50", "MeterName": "MSFT Peering Metered Data 5 Gbps", "MeterRates": { "0": 2180.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "edd11046-ec5b-456a-81c3-7bfc6d9b5f4f", "MeterName": "Premium Elastic Database Existence", "MeterRates": { "0": 0.4838 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "fe214bd3-e0b5-498f-85e0-f2f75b096fc0", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.031 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6df2fe2e-469d-4fb5-b925-fd0284993999", "MeterName": "Compute Hours", "MeterRates": { "0": 0.437 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "dbb918c6-1fa9-4f27-a5ef-8f65c59ca333", "MeterName": "Relay Hours (in 100s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "100s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a634fbaf-539e-41e8-b961-4286a20d0aea", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c09fcd6-88ce-4ccf-8297-36b5ba060854", "MeterName": "Compute Hours", "MeterRates": { "0": 0.81 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "87266122-5059-4244-bc57-f1a17d25227f", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "11dc0654-64fc-462b-ac12-54a2b6d2cd71", "MeterName": "DWU", "MeterRates": { "0": 1.8146 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "81e9a0ba-2f06-4933-97aa-d8700c70d98f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.69 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "G2 SQL Server DW VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60183ce5-4327-47ae-ae0f-3590c2920039", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "016284cd-2b47-4ba4-9f41-2b3b26ee7d6e", "MeterName": "DWU", "MeterRates": { "0": 1.2097 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fc4409fd-52ed-4ada-93b9-bf1bc3db67f0", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "19a35a32-daa5-4f03-8feb-0151ed734a17", "MeterName": "DWU", "MeterRates": { "0": 1.8146 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 400000.0, "MeterCategory": "Functions", "MeterId": "2a384075-01d7-4f66-a84a-0eed3ca58876", "MeterName": "Compute Duration (in GB Seconds)", "MeterRates": { "0": 8e-06 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB Seconds" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "734b802a-0a4e-490c-98dd-a4ca285d835b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.8 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (8 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8d2a1442-ebeb-42b2-b250-db4ef542a0fa", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 18.75 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "cc7c7a41-fea2-42c6-83e9-3870205634f6", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.034 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1086cc44-ab49-4943-8525-b7a3c6392925", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bccfc944-5fe0-4427-ae26-ab8c2de410f8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.073 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8376d911-1e62-4896-a324-5290c8ce2f7c", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.034 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8405dbf3-ffda-4d3c-85e8-716ec6bd2fbf", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.015 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "57fdf439-b2b0-4eaa-9f8a-31a70ccdbf3f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "372ad328-1f3d-4f6e-a4c8-bb068ce7b900", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.0092 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fc074bcd-c679-4ae5-a7fd-2668ba169509", "MeterName": "Compute Hours", "MeterRates": { "0": 0.605 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d72ca4ba-8925-4d30-bbd9-ebbe0c917841", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.201 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "9cb0bde8-bc0d-468c-8423-a25fe06779d3", "MeterName": "Standard IO - Table Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "98d93f1c-7f95-4620-a44d-5e851006452f", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 145.19 }, "MeterRegion": "BR South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1b426790-a4fd-462c-af92-8796ca8c419f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.228 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "56ae806b-665c-41c4-9773-f82d2b2c98ce", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "61f622cb-f30e-4ca0-aeff-41462944e704", "MeterName": "Compute Hours", "MeterRates": { "0": 0.743 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0d824549-9a8d-4204-a69f-833b9c587181", "MeterName": "Compute Hours", "MeterRates": { "0": 5.368 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "caa454d7-e42f-47c4-9e28-773bf7b739fb", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "291b2cbc-6c34-4e2b-a4e4-1ff8c106f672", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "23581df3-94d7-4621-8507-b1c7cb4b6d27", "MeterName": "Standard S3 Database Days", "MeterRates": { "0": 6.048 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "fed0286c-5505-4f37-b1ef-89edf04239ee", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.4839 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d223dd64-e471-418a-beca-eb63185da795", "MeterName": "Compute Hours", "MeterRates": { "0": 2.44 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f6d44310-cb84-4578-bef0-642ee0c75016", "MeterName": "Compute Hours", "MeterRates": { "0": 0.115 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e44fde77-75b3-40d4-9dd0-f14220b963ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a4bfab03-a19d-4f19-b067-cb7411384d8c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0a4628b2-cf77-4f0a-b29e-9cfae4f71f6f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.306 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "55169dff-26e2-48e5-a57c-85104d82ca58", "MeterName": "Compute Hours", "MeterRates": { "0": 0.123 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3ae5288a-02b1-4d17-a73f-de110df5992b", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 17.16 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "312ec9d2-3c50-4a0e-818d-9f5eafb1c7cb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.451 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "681920dd-a782-4ad1-9d44-1e37533d4081", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "456a33ee-39d0-4bea-adbc-707440398e67", "MeterName": "Standard IO - Disk Write Operation Units - Free (in 10,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c08405d3-05f7-456d-a92f-19e23cc8ef95", "MeterName": "Compute Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "31717765-af35-4dd3-8cb5-42071cc1ba8e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c98cd699-0e17-4174-989f-eccc7333ab77", "MeterName": "Compute Hours", "MeterRates": { "0": 1.59 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV6 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f03d38d8-8041-4410-828f-5d85b5a5ad36", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "26b919e5-59f1-4c90-937f-5d329fdeec84", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0732 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4a6a2258-2b7c-421f-a87a-1c9da19eac5d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.268 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2f86264f-ed38-41fe-be0e-bc42f8e5bd41", "MeterName": "Compute Hours", "MeterRates": { "0": 5.36 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "dec787a1-5d84-4432-b9db-e08a6657e9e8", "MeterName": "Compute Hours", "MeterRates": { "0": 5.027 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16mr Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ed45ae8d-a734-4d21-bc88-e5b54f9e903e", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.004 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce3b9051-6362-4593-baca-0f5baef50983", "MeterName": "Compute Hours", "MeterRates": { "0": 0.699 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b2d3ed0d-64b0-4a41-8c5a-cb49dfbb84f9", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 30.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e258c52c-75c7-464c-8674-66340a29d297", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b25416bb-76e8-43cd-9579-f29f09887ce2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.392 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bdd780ef-52c8-42ce-9995-05637b030062", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 67.91 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "003c2bb8-70a7-4e81-9ade-2fb8b5ba0487", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4d0833ba-44fb-4b4e-823d-403828abc33b", "MeterName": "Premium P6 Secondary Geo Database Days", "MeterRates": { "0": 101.71 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "dcdfe574-d2d2-4b8b-8546-284f90c6cc3d", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0784 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "0ed56b26-586c-4679-ae45-119ff855fa0f", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e389df43-a2d4-421f-8791-7e59c5419a57", "MeterName": "Compute Hours", "MeterRates": { "0": 9.064 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8e8799f4-c494-4141-9308-e8f012a7b2c4", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 17.92 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "96c50999-57d3-47e2-b28b-63d758f84d22", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "4b2389e1-6ff5-4b14-a810-d29d722c0719", "MeterName": "Standard Video Face Detection APIs (Minutes)", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Content Minutes" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "39df9b84-10b8-47da-b32a-0095e17b224e", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 387.104 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6fdb58f8-2bdf-4468-b72f-771be1862539", "MeterName": "Compute Hours", "MeterRates": { "0": 0.467 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "69472fd2-67c1-471f-9324-6f4961cd392e", "MeterName": "Compute Hours", "MeterRates": { "0": 4.57 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "93a5b34a-1146-40eb-b4cf-c9132d7fc31b", "MeterName": "Standard S2 Overage (in 1,000s)", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4018a121-f1c4-4405-aa40-a59df52080ab", "MeterName": "Compute Hours", "MeterRates": { "0": 6.48 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "fbd4e133-ec4f-478f-bf52-f04c6e0d7195", "MeterName": "Basic C1 (Hours)", "MeterRates": { "0": 0.069 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6308d3fc-bf11-433e-804a-76494245714a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.054 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "47cd02af-fcf7-4007-a773-fef174ceee77", "MeterName": "Compute Hours", "MeterRates": { "0": 0.743 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd274564-0f9e-49a7-964b-31dca4919115", "MeterName": "Compute Hours", "MeterRates": { "0": 0.524 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "81f02e66-386e-4877-bd67-40b66aa53580", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.025 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "eb07634d-10a5-4f2c-8e88-46303321465a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.933 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4dca4ee9-9223-4a93-aa7a-b8d63c4cce91", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e5908969-8f7f-489d-8e1c-44dabfdd0d7c", "MeterName": "Unlimited Data - 2 Gbps", "MeterRates": { "0": 17400.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "1e25650b-c0ce-4143-ab65-bba733dce381", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.126 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ae37db55-3cd6-419e-b490-225015348ef3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c1c58d57-f4eb-46aa-832d-e24c0d712d0d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "abf7d235-6045-4f02-802a-acbad7418578", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a564b5f6-3d29-48fc-a13d-da081e506714", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "20b839f3-ccb3-40e2-8e31-4264a4068560", "MeterName": "Compute Hours", "MeterRates": { "0": 0.549 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "31cecc81-9662-4beb-a81e-2b72a712d1c8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.226 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f45dc700-e58d-4b6f-aa2f-35f77d9180d3", "MeterName": "Compute Hours", "MeterRates": { "0": 2.415 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A9 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "78de3d06-0948-4d71-8a80-447b010e4dd8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "1ff8223e-a66e-4d66-9a57-f6c5b84c8828", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8dda06af-95ac-4ecf-a7ce-d9ffe046a518", "MeterName": "Compute Hours", "MeterRates": { "0": 2.928 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8adbecba-6230-4c52-b6cd-b843211af131", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 16.94 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f5552671-e2c3-468f-8801-d7f1d2041aed", "MeterName": "Compute Hours", "MeterRates": { "0": 0.47 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "add38ca4-3402-4f5f-af24-fb2ef31fe6fc", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.913 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0dbf9156-f6ad-4935-97bb-f9ea9b52d171", "MeterName": "Compute Hours", "MeterRates": { "0": 0.393 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c60db0cb-11f8-432b-b410-3902cc8d8536", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b4412aec-427e-43d1-a7e4-a3b42a688750", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "572eeca7-16b5-4b8e-89b9-7b012ca0beeb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "aaa1f4d6-28c0-43f1-a499-3dd4e4c3eb46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "0c873ca2-4113-4997-8cf6-ad5df5775599", "MeterName": "Basic Search Hour", "MeterRates": { "0": 0.101 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3bec1178-9944-4e69-a543-72ebb78f38c3", "MeterName": "Unlimited Data - 50 Mbps", "MeterRates": { "0": 300.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "064d1cc9-01af-46ff-a382-6ff1520b78a2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.064 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7211f3f7-931d-489a-bfa7-a8cdf8954f3a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.17 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "1703498d-2b7b-48bf-84e6-d47462f5c21b", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f62fafc1-3b22-4d08-9765-15bd45bab87d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1dd468b5-cac3-4d96-9b28-701adf1853dc", "MeterName": "Compute Hours", "MeterRates": { "0": 3.84 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (32 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ace30b39-5349-4478-a583-24001b1d38ea", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e0ab81ca-9767-4c18-a338-2f982b1637cd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.675 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9bb81ad6-5ef5-4ad6-a9cd-1dada0d53702", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "bfd75a78-3acb-422b-a4c6-17a0503aee14", "MeterName": "Standard S1 (Units)", "MeterRates": { "0": 3.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Bing Search APIs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3678953a-ef42-4b8f-8687-8de1c4225c0b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.197 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "14efde27-264a-44d2-a15c-8bd2cdb73481", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1771 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b3922ce6-b68c-4956-a29e-4f1b2209db09", "MeterName": "Compute Hours", "MeterRates": { "0": 1.402 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A10 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4ca5e77d-c176-4a37-b3a4-6f4046518c7b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.7 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f00ea971-6ace-4974-b79d-fe1bb7bf2314", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.168 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f90f81d2-238a-49d0-9f1b-9df13a859843", "MeterName": "Standard IO - File Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.015 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0cccb09d-c7fd-4614-9f96-d4544f58ba42", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 66.56 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ae2f461-4d59-4639-bec3-e464cbe59e7e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "39b0ec90-10a0-4fe1-a52b-d9d04dd9d38c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.768 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "66f96a20-4f85-41fb-9c70-74ece7663b39", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "49523413-e2be-4a74-9d79-6b28fe89d5da", "MeterName": "Compute Hours", "MeterRates": { "0": 2.854 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "6fea3a48-e38e-4857-bf37-40d4b70621f5", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "e3bf3e5b-d9bc-4148-b735-51ae4375c06c", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A9 Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d5137365-8535-434f-83a2-4af109e91e60", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd9b61fc-5d11-434b-a9fa-e245b2351d33", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "89f20818-e778-4bab-ba31-b7e3e7f196fa", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.0645 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "580821c7-79b7-48d0-b44f-3f5398418af2", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.025 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "145e6045-1c39-4a55-bc44-325b20bf8e65", "MeterName": "Compute Hours", "MeterRates": { "0": 0.966 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d8eabad1-acdd-4b64-b593-8ffc9751017a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.21 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ba5d362f-a5f4-44bd-8842-7467c263ba1b", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 248.39 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b492a3c1-fa75-4eba-a34d-a9f4c9e7b1ba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.744 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "160ec60c-d0f9-4baa-a663-b70ab6b832fd", "MeterName": "Compute Hours", "MeterRates": { "0": 8.69 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2cc7d467-9f2f-4654-a9b2-29d3aeb64e2b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "494e1103-2c70-46a9-906c-080715e95299", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f8e353d0-10ff-4b12-9df4-fa53d7c7ca69", "MeterName": "Compute Hours", "MeterRates": { "0": 0.902 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "1ae54f83-7a36-4104-8c29-f4054900a96e", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5bbb9ba2-e2fc-43e5-aa23-d225cddb338d", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b2048190-2afb-43a5-b5f4-af7a885396c1", "MeterName": "Standard IO - File Write Operation Units (in 10,000s)", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8335ab4d-e225-4509-9990-ee6bfd893e63", "MeterName": "Compute Hours", "MeterRates": { "0": 0.741 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f556bec2-a286-4171-bbf5-4fddaaafef99", "MeterName": "Premium Metered Data - 5 Gbps", "MeterRates": { "0": 5180.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "21676e32-89e7-44e5-a4ce-43eb4caea6b8", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.016 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "4ba8a96a-24b1-431b-b16f-374f983c08ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.684 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dbafbdfb-9e61-4cdc-afa7-90fc6e296ecd", "MeterName": "Compute Hours", "MeterRates": { "0": 1.187 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "d4f972f8-636c-4fa4-96dd-67d78ec1ff18", "MeterName": "Premium P13 Secondary Geo Database Days", "MeterRates": { "0": 276.78 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6eaf9150-cee9-4835-9c85-b1f9094ee397", "MeterName": "Compute Hours", "MeterRates": { "0": 1.486 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "2cf4341c-5363-4026-8ed4-d1ddaa0a8276", "MeterName": "Standard IO - Hot Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.0044 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd6ed7ae-3dd7-4e12-b9c3-10507b8d7e91", "MeterName": "Compute Hours", "MeterRates": { "0": 0.15576 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "eb990e94-da32-4e43-8907-37e8108279b5", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a44644a2-a649-4bbe-b6b8-fd7cfb7eacf9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0f521674-5ebd-4679-bd97-8bc2ac4a9040", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c2827b48-09b6-4490-a2c3-190a3197e453", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3579e013-6f8f-447e-bd2f-4b4cecef5917", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-23T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Notification Hubs", "MeterId": "f6bdc96f-65a3-41c7-913b-34b518bff0ff", "MeterName": "Base Unit", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Notification Hubs", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1852ff0f-fd73-4683-8a94-a205d1f64e97", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "87f6d477-c1b0-4dc5-abcf-d03b4b33ab88", "MeterName": "Compute Hours", "MeterRates": { "0": 1.17 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "aed66f98-ea48-44e9-a316-47c404301c86", "MeterName": "Premium P13 Secondary Active Geo Database Days", "MeterRates": { "0": 387.1 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8254ec81-3aee-4198-86b1-0637419eef4c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d8f0abe0-ebe9-4181-9239-6b6f9d516e8d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.128 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Web (16 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "627916dd-3eb1-4b1d-bd1c-9f19593f6d25", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0288 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "e9437e62-afa8-4a78-9025-c886c04a8d1e", "MeterName": "Standard Large Azure App Service Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3139e6c8-7ccc-429d-8968-9ccd8b796835", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 65.898 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cb94a3cc-bc75-4343-b102-4a871ae5ff3d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "beac8d1d-9571-4d9a-8414-4ed63ca2ec01", "MeterName": "Compute Hours", "MeterRates": { "0": 1.032 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ceba7f47-6ed6-4942-9909-7e2ddcaee83c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0c259952-f0d7-4c48-892b-5fd329583456", "MeterName": "Compute Hours", "MeterRates": { "0": 0.54 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "78a15035-8e38-47a4-bf17-bed40e6235b2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.648 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eb591a1e-3aa2-45c5-85bd-491965382973", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0cbe80c3-663b-466e-a93d-e448cf81abc2", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.099 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-03-12T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "53cc0061-0fe2-4249-bf62-e1008c811f5c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "06e16816-5010-4281-b15f-6e921c98de6e", "MeterName": "Premium Metered Data - 10 Gbps", "MeterRates": { "0": 8000.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3372c087-75e2-443b-b4eb-e4e9d449a533", "MeterName": "Unlimited Data - 5 Gbps", "MeterRates": { "0": 41000.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "23c4fe6a-7072-4454-b253-f37197ce79de", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ea950d97-8415-4b9b-80d0-536e51ba41f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.059 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "203385a9-b52b-4a98-b8c3-2cb90652fb64", "MeterName": "MSFT Peering Metered Data 1 Gbps", "MeterRates": { "0": 436.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "075e92be-f685-4d8d-8ee3-e75b11c42e3c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.632 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e86ccf31-0baf-4233-9418-a1e9ebf78945", "MeterName": "Compute Hours", "MeterRates": { "0": 2.684 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d28bad6f-033b-429c-81cc-a6d9324a70eb", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "462c0174-6967-4e09-a765-24fa53e0c582", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 3.9919 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "235b1e01-d3b9-42b9-948c-cbf8bfbada6e", "MeterName": "High Frequency Cloud Activity", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Factory", "MeterTags": [], "Unit": "Activities" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dac67eef-852f-45b8-9fcf-adc4a6a51ef5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.827 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7ded2c93-5742-4baf-8390-7649f77f57b4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Enterprise (8 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "324e7e3f-2a83-4580-a1a7-3fcbf0219efc", "MeterName": "Basic C0 (Hours)", "MeterRates": { "0": 0.028 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "76744481-9534-4c91-82ae-d3847ea29982", "MeterName": "Compute Hours", "MeterRates": { "0": 2.346 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d2814d47-36d4-4e71-b2be-9140c3d09f28", "MeterName": "Compute Hours", "MeterRates": { "0": 0.311 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9a721778-24e6-40c4-a4e5-02014fd8f6ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.077 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8aaffdfe-1709-420e-b847-017242cf7a5d", "MeterName": "Standard S2 Database Days", "MeterRates": { "0": 2.5168 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "833595f5-a519-4b33-af7d-f4fda9495198", "MeterName": "Compute Hours", "MeterRates": { "0": 2.735 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3f69ee96-a423-4e7b-b370-ce4bf98ce1db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.327 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1f6bef0f-ed22-4d62-8999-73dd61e5756a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.581 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "7aae1507-5b61-4125-ac2a-66ea118b150e", "MeterName": "Standard Managed Disk/S10 (Units)", "MeterRates": { "0": 3.238 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "57b0ca21-389e-40ea-84c3-79a2724e8308", "MeterName": "Basic Elastic Database Existence", "MeterRates": { "0": 0.0081 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "375abf1e-e407-46e0-a3de-35a9180d6289", "MeterName": "Compute Hours", "MeterRates": { "0": 3.065 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "108a63a0-143f-4aea-b1a0-6a931d5d8bb9", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9db3576d-f80a-41fa-93c4-f16e87e13e47", "MeterName": "Compute Hours", "MeterRates": { "0": 4.9 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "58addb81-4c03-4db1-adbd-bbde0b43fdce", "MeterName": "Premium Metered Data - 100 Mbps", "MeterRates": { "0": 200.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5f98a9df-ebf6-4b36-9a63-e806780afc6c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.776 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "83d9848f-562f-4941-b79e-93228e36bb44", "MeterName": "Compute Hours", "MeterRates": { "0": 8.78 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "617091c0-d92a-4d18-89dc-ec0ed8d93342", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "5d7995b3-7053-4c16-9a87-fe7537ecde07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.148 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1ebe219d-f620-47a3-8086-fb605dbb5cc3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.058 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d92a5514-2bf7-4bb1-8a72-0ac7b7f2023d", "MeterName": "Premium Unlimited Data - 5 Gbps", "MeterRates": { "0": 44000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "79a801ca-db77-4e40-8236-7cbe8dac8051", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.5323 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "178593fe-7927-40e3-9096-38baeb7d33b4", "MeterName": "Premium P13 Database Days", "MeterRates": { "0": 387.1 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d23a5753-ff85-4ddf-af28-8cc5cf2d3882", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.05 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "238957b1-62b7-40fa-8f95-b3b36c4d031c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.959 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "84c69252-6c42-400f-8bc1-56df43201707", "MeterName": "Compute Hours", "MeterRates": { "0": 0.07 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "32dbc775-b0e1-4c2b-bb3e-3a930b5dcc3e", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.033 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "414e7527-91f1-4e86-8353-5b1b41bb6f25", "MeterName": "Compute Hours", "MeterRates": { "0": 0.466 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5431c933-cb1e-400d-ab8d-ef18b5297dc4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.34 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "G2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7218abc7-60c9-4020-bd35-2cb44f4a42c6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Insight and Analytics", "MeterId": "8c945adb-3f9a-40d1-a661-efc36fa4a3e0", "MeterName": "Log Analytics Data (GB)", "MeterRates": { "0": 2.3 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Log Analytics", "MeterTags": [], "Unit": "1 GB" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95b16456-5dab-46c9-9afa-943acb9bfaf8", "MeterName": "Compute Hours", "MeterRates": { "0": 5.6 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d4181f74-4046-401b-9168-e3211167445b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4825cff2-a186-4a49-9f55-8cfed4c02778", "MeterName": "Compute Hours", "MeterRates": { "0": 0.112 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5bac21dd-31ea-4af4-9f9b-9c53472db61f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (6 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "709fb951-cbf8-425e-9baa-cf504880d6b5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.154 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "bf9ab6b6-ba11-44de-825f-754c800c077d", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd98b0e6-e7bd-46c2-af5b-ad1baef749a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "06cdadf9-e6f8-4bf9-b00c-4ba96b291263", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 17.92 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c65c1816-ed83-42f1-a07e-e37e667a1c01", "MeterName": "Compute Hours", "MeterRates": { "0": 0.474 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "abf68ce2-a95e-449b-9f4e-c5e9096b7a4f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.276 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c18d79b3-f3c9-480b-9f4c-7ed410ea3313", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.027 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fac079bd-39e8-40d8-a9df-06d2b1cb4dd4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "39df68e7-3504-41e8-aaff-046e3250556a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a51ac8a1-8bfe-4979-9488-658ede49f108", "MeterName": "Compute Hours", "MeterRates": { "0": 0.074 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "91967101-dd9d-4c5f-aece-b32e77a15544", "MeterName": "Compute Hours", "MeterRates": { "0": 0.504 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "aa165f78-f022-454f-abe5-8c8086f36d9a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.769 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ba7a1dfb-f2de-4363-a6b5-75b4f8f6b8ab", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 541.9344 }, "MeterRegion": "CA Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d8387905-8ec6-4da4-b23a-3d9d77807088", "MeterName": "Compute Hours", "MeterRates": { "0": 1.663 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a07423fc-6af2-4af9-87e9-b1260b2a5abb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "5a52f29c-0b10-47c6-9eb6-7f668ab6635c", "MeterName": "Premium Encoder (Output GB)", "MeterRates": { "0": 3.99 }, "MeterRegion": "", "MeterStatus": "Deprecated", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e56de096-6d48-48c1-becc-5b43cd9f1a14", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.05 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "95861166-e640-457a-a6e9-bfeacdd0ca2c", "MeterName": "Unlimited Data - 2 Gbps", "MeterRates": { "0": 11400.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "5a209209-b372-4dab-9d56-0c2fefae16c1", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.096 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "10056506-dc72-4b6e-96c7-c39b0d908b9e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "6213bf32-4e36-4c00-8240-747bdac2db55", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.272 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "87f3affb-3314-46a5-a56a-569355dcefaf", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 451.612 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "444db22b-1d6e-4116-b199-a8d137e84ef8", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.1252 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f6bbf355-3406-40dc-8983-3fa94a466c0a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.624 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "835b1880-0c95-4d4a-a849-0f951ed6cc2d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.188 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "7a42eff4-681c-49b6-829d-4f6d38b25086", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f59263c9-84d8-4704-b376-266b60887823", "MeterName": "Compute Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8adec5fc-02a0-46ac-9ac1-b15d358fceb2", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0838 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3ab7e5ec-71c8-4505-aa09-000a5645dab2", "MeterName": "Premium P15 Secondary Geo Database Days", "MeterRates": { "0": 428.56 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd877939-4a15-4f1a-a69f-0fb33417c47a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.143 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c9209a46-64d0-4d1b-a01e-229c0fe3e7b7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.401 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F8 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 1.0, "MeterCategory": "Power BI", "MeterId": "924c0a27-3db9-4413-8d1d-40d94c7987eb", "MeterName": "Sessions (in 100s)", "MeterRates": { "0": 5.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Embedded", "MeterTags": [], "Unit": "100 Sessions" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "186a16bf-2c6e-42ce-bed8-059db2f57486", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "161a0e9a-c2e1-4162-9077-6416d02844a2", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.0756 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Medium)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f7ac1c02-9ca7-4e5f-a2c4-edc3435734d4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Enterprise (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "22d85d60-c41c-4542-bedf-1a3bac96937b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.18 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "470d9aa5-21f8-4dff-a880-d6d72b3f59c7", "MeterName": "Data Transfer Out - Unlimited Data (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1ccfedef-65f7-46d6-89cc-3658db2d14ac", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "09edff4b-66d0-49c4-ad6e-9c5765103f67", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.074 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f5c28252-7d44-446e-adfe-e097fb87f340", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 571.408 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6f8ee651-a6ab-48e1-b292-77aefb27f645", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.2825 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "aa0a44ba-fdec-4c16-9b16-44a99b5b473c", "MeterName": "Compute Hours", "MeterRates": { "0": 2.462 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b43ff1c3-31f9-4b19-8f3b-5557ffb8f157", "MeterName": "Standard IO - Block Blob (GB)", "MeterRates": { "0": 0.033 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Zone Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c97e16c4-2789-4afb-9371-f109dc4e2217", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "43ebcd16-a388-4d6d-84b1-ef953baa7f61", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ace09fbe-4629-4da8-8723-a06b4bb5115a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "74b451a1-6b3e-4e0a-9f8a-d5ee7fcd9fa3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e7d4f4ca-0abf-4f2f-9c32-0d608668db67", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e6584a84-4190-47aa-ab57-f44fcfda5f8e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8ae013c5-03d7-48bf-b190-0227b00a6b93", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8297cba8-cbd1-49e5-8404-8a85013c008e", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "64443c94-8202-4c8f-bdb3-9d00e7148dc6", "MeterName": "DWU", "MeterRates": { "0": 1.4516 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a02d767d-d301-4890-944c-2d1201fed9db", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "469a7d8f-36f1-4a99-a884-6eb97643be2c", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "7d00b59f-3460-40ff-a89c-324c644f77a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.102 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dfabe369-3ccd-47d0-a26c-afc744bdc10c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.211 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e96a821c-4cb1-4254-a2ab-a0c579d51f83", "MeterName": "Compute Hours", "MeterRates": { "0": 0.433 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5e81d0b1-4c37-44c7-addb-59bc8aba8035", "MeterName": "Compute Hours", "MeterRates": { "0": 0.11 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dc0f7040-7861-4e1b-b9f4-07bbf009c117", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.42 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6a7bf979-bbdb-4336-97b4-01d50f48ad16", "MeterName": "Compute Hours", "MeterRates": { "0": 0.292 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b8ed6239-58d6-449b-b1da-34d0b4eff476", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0413 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "32d2a614-7fe4-4517-9054-747974227b48", "MeterName": "Unlimited Data - 200 Mbps", "MeterRates": { "0": 3220.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c89d2470-38e5-4f78-9531-d505c2e178fd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.322 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5ba9e46a-2456-44bd-9eed-decfa41819c7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.296 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4831a7b4-bdd4-48a2-8e95-18d053971ede", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (4 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "02cb2c4e-8548-42a2-b044-540da3343557", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2e29319e-ffa1-434e-b6ff-77a30d0e6683", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "814a4328-d48f-4a94-a3ef-cf9fb9955dd1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.516 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ea8e044b-900e-4137-b26f-7e41eecef1b6", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Identity", "MeterId": "7ccceb80-e77e-4b06-9bed-c1f80eb8ff02", "MeterName": "Authentications (in 10s)", "MeterRates": { "0": 1.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Multi-Factor Authentication", "MeterTags": [], "Unit": "Authentications (10s)" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9a4aa17c-cdea-4948-bc62-4a22d1299b25", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 499.982 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9ff9206a-5a63-4c25-886a-f4fd19c89fa7", "MeterName": "Compute Hours", "MeterRates": { "0": 3.54 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16r Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "016c50fc-0267-4002-8e23-31776e77b3e7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.769 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9e4032dc-9f37-4f9a-882b-4c004b1c896a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.769 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "45cd4bfc-20a2-48c3-9f03-2816edb5c5ad", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3456 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c9840930-3d15-4b1f-b1f4-5cb5e0b8980d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.256 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "eaf96dc7-97d7-43d4-b69c-be223f9cea0f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.496 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "884a7710-279d-4ad3-82ef-4d2e592e0e89", "MeterName": "Compute Hours", "MeterRates": { "0": 0.76 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e320974d-3fb9-41f2-80d6-e8bd289b37a0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8440c7c9-5522-4f6f-8c8d-42cb8ecf523a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.23 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e4879456-0fe3-401a-8ffe-1317dbee9287", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.039 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "31997b13-d049-43f5-8bf7-cee61fbb6d54", "MeterName": "Premium Metered Data - 2 Gbps", "MeterRates": { "0": 2372.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "dc0bb519-a6d0-46ca-9e19-9e034b445eed", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 122.88 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "00c7e75c-8710-4941-a917-449cfabd79ea", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "04363242-b094-4c7c-ad25-c0c451ab2d1d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.222 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7b5efd2a-b249-4a6a-a522-bab7ccdfb74f", "MeterName": "Premium P1 Secondary Active Geo Database Days", "MeterRates": { "0": 15.6 }, "MeterRegion": "IN South", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c90f4d88-01c1-48e9-ba9d-cb9c6ccaedd3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.073 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "f2b896ed-0fb5-48a5-a687-70c2f63e137b", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.108 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "92808e25-462d-44ae-af54-1a5b7f7c9a9e", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb4d7e6b-4bec-45b4-8c6e-03fb74c646ef", "MeterName": "Compute Hours", "MeterRates": { "0": 1.8 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC12 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8c7ff689-1ce2-49f9-be24-abf82b79a736", "MeterName": "Compute Hours", "MeterRates": { "0": 0.021 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "8e224de0-27c5-41e5-b890-565a7e2a6a82", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "acf26b15-ee92-440d-9973-9a72d77641aa", "MeterName": "Free Data per App", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1 GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "00e47962-832f-4e9b-94dc-ab7e637ea92d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.291 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "168736ab-5930-4325-95d5-35bcd09457fc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "719fc63b-9049-45b7-89f3-746513707f5b", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 66.56 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "951e0599-a983-448d-8f72-cb366fa7596a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.024 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8f412096-89b2-4a4d-80b1-72da6f557a67", "MeterName": "Compute Hours", "MeterRates": { "0": 0.452 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6d2a2461-578d-450e-8d5f-0a03220e74f2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "098eaacf-acd2-46ac-8b17-d8b66371b710", "MeterName": "S1 DocumentDB Hours", "MeterRates": { "0": 0.0354 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2f36fff-5302-426f-a51f-8a82acd1eac7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.62 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "26000933-55ee-46b1-829a-126876898eff", "MeterName": "Compute Hours", "MeterRates": { "0": 0.137 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "df14d9be-1b23-4e6d-bf70-4a4f0071025d", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 135.61 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "5c2baada-d524-4027-94cb-43c225469a15", "MeterName": "Premium API Management", "MeterRates": { "0": 2849.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "API Management", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "801366bf-804b-4b1f-9078-517f203e4aa3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.418 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c4db260-4bc7-4388-a42f-b0c709255ae8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.64 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "14acfcc6-9368-402d-9fb4-dbced00798ab", "MeterName": "Standard CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a6dcb69a-9f5e-4c8a-9e39-0adc138b1278", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.7592 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5aae31e6-f8f6-4d66-8a2e-2adcd540699b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.433 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a0244804-7057-43fb-9741-c2c6bda7b1c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.063 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "bf20ce29-80d6-4b39-8966-187bd0519f21", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bc15d35e-40c3-4f79-82fb-278d0bee5faf", "MeterName": "Compute Hours", "MeterRates": { "0": 0.411 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "96b59323-b38e-453c-bbc6-01cbffe2fe3f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.593 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "65d4ded2-41ae-43a8-bb68-3c200e1ba864", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.008 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "abbd81a0-cc95-476d-9b16-b5aab77e39fc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "25e78bdc-41af-43e0-ac56-aeba945f6ba7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.368 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8521220d-807f-4f58-9b1e-bf6ae83ca011", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 191.7 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "98e31dfb-389f-4e25-8b50-f38e29e84274", "MeterName": "Standard C3 (Hours)", "MeterRates": { "0": 0.563 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "beffb77f-1238-4149-a78a-bfc782c0b68f", "MeterName": "Premium Metered Data - 1 Gbps", "MeterRates": { "0": 1186.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "505db374-df8a-44df-9d8c-13c14b61dee1", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.1 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b7f80c20-f4a5-476c-8237-f3baaa671255", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7cb727f1-3834-45d4-92f5-d49e62641089", "MeterName": "Premium Elastic DTU Pack", "MeterRates": { "0": 0.198 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7614df31-630d-466a-b2cd-b73fc23931e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.384 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4c2d1c48-6c1c-4f37-ac7e-b38e86008036", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 679.0171 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "300132ca-146c-48d0-8216-c86998f60db6", "MeterName": "Compute Hours", "MeterRates": { "0": 7.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (20 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "e11331a8-fd32-4e71-b60e-4de2a818c67a", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XL SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "792894ed-5b32-452e-ac70-0463d027d90b", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Canonical (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e3a07909-e1a1-4e0f-af7a-cea8a49f50e1", "MeterName": "Standard IO - Table (GB)", "MeterRates": { "0": 0.077 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "86279f50-4cda-418e-8dc2-bc1770d59915", "MeterName": "Compute Hours", "MeterRates": { "0": 0.183 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8bb670ad-5d59-4723-99d9-1e040a6c5b13", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 3.025 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a8082c50-37ee-4195-b614-d4d408b615d0", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 2.42 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "App Services", "MeterId": "da02f8be-997c-44a8-bb21-deb811177a5a", "MeterName": "Automation DSC", "MeterRates": { "0": 6.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Automation", "MeterTags": [], "Unit": "VM" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "3900f89a-8667-4a76-8984-504d4bf0ddf9", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 74.34 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c68cda95-e1f3-4e54-a85c-32ed5b900edd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.185 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "15b2ed74-d530-4521-a813-a32d069e4bf3", "MeterName": "FairPlay Licenses (in 100s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "100 Licenses" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a5d9f3be-c88f-4393-8302-de6af76dad80", "MeterName": "Compute Hours", "MeterRates": { "0": 12.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (32 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b553abf1-9582-4795-a786-feeabed98f46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.132 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-03-12T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c92a7ec3-d054-4c9d-98c1-ef708e97a201", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Java Development Environment (2 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "77d94e56-0590-47e7-953b-17feb313be82", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8c78a0f1-97b3-4df7-b87b-783874d4848c", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.017 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ec2457ae-8775-48bf-8bdc-f1c94e96eb56", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "d1f893a4-6aa7-431b-984a-04414c453819", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3315f5d6-a492-4f66-baf4-c81a47ec3fd1", "MeterName": "MSFT Peering Metered Data 1 Gbps", "MeterRates": { "0": 436.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "97e03f3c-0892-4ea2-87c6-f60c06d4710c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.139 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b56a540f-d226-408a-ac76-6e6ec85bdb96", "MeterName": "Compute Hours", "MeterRates": { "0": 2.496 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7b5c8556-24e2-42bc-8f46-da45ac53aee4", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8547d777-4230-4ef7-ac27-0b2e63f33587", "MeterName": "Compute Hours", "MeterRates": { "0": 1.04 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4a68c477-2ad5-4b7e-bb39-61886883f101", "MeterName": "MSFT Peering Metered Data 50 Mbps", "MeterRates": { "0": 55.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "404de555-ea2a-4a14-8a76-8955438216e1", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.03 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8c934b0a-290f-4e40-ba60-eb56f767f5c3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.464 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ba181a95-5112-433c-ae9e-551146b5f1f6", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3942 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "5f688460-13f4-43e4-93b8-0086c0d28efc", "MeterName": "Professional (Annual)", "MeterRates": { "0": 539.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Annual subscriptions" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "806ec6e9-9c5e-438b-8802-2ea4daa35f12", "MeterName": "Compute Hours", "MeterRates": { "0": 0.229 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "67ea9764-1433-4e4f-a761-2d74741369da", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise and Weblogic Server Enterprise (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "41bb4a09-0f02-4dac-ab73-e2c8f31963d5", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0208 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a2d3232c-e4d6-4535-bcaf-350491f11884", "MeterName": "Compute Hours", "MeterRates": { "0": 1.25 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "636a5df9-bdfe-4fef-a29f-88566b6ce93c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.932 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c7d16067-dc2b-4a82-b970-1cf55190b54a", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.0963 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a65783ec-b3c0-4235-b5ff-d5d4a13b92a8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "042c2ad3-a656-46e3-a339-0e228b6c201b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.2 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "17c078d9-61d2-4984-9ff2-c147df5826ac", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "05790f64-156c-44b8-87b9-9ada20c86640", "MeterName": "Compute Hours", "MeterRates": { "0": 0.275 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d6dcc45d-cefa-4bcb-8c8b-1f47b4bb8f58", "MeterName": "Compute Hours", "MeterRates": { "0": 0.129 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "24b4ac5e-65f8-4136-b48d-15dbf86cb054", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 12.87 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "d4816704-ab6b-49be-8958-62d3581ac1bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.274 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "152ccd59-845b-44d7-9a05-5b0af2d501a6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.124 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "c2b9b3e7-a1a2-4b8b-8f38-81a50ce18821", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.011 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "af32d3ed-94a1-40ee-a20d-975356b21d28", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 150.0 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "3c95dd0f-555c-4caa-9d03-958a6778df30", "MeterName": "Ingress Events (in 1,000,000s)", "MeterRates": { "0": 0.028 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Event Hubs", "MeterTags": [], "Unit": "1,000,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3c159e90-2794-479f-a63b-8794328a4986", "MeterName": "Compute Hours", "MeterRates": { "0": 0.372 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c2036e92-a7fc-4315-9043-8269373b3345", "MeterName": "Compute Hours", "MeterRates": { "0": 2.43 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "695f605c-f3d7-43aa-a0eb-15c8290cd704", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8a7d7499-7ec3-46dc-8697-355ac2fc14bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.036 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "52670bdc-1da8-43ad-bc26-d1b2e064ef3f", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 21.504 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "bb1dde0a-4473-4457-9ddb-d55d4aca3b93", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "b33b1ec8-9cf7-4d2f-8f25-7b2581ad0b0c", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.1045 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7ee5cf19-c864-4038-b4ad-bcfc8e63c508", "MeterName": "Standard S3 Secondary Database Days", "MeterRates": { "0": 3.629 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "4e435593-08e3-4159-9c2f-374618fd11f0", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "b4a70377-5177-4367-ade0-7f47af3e7c52", "MeterName": "MSFT Peering Metered Data 1 Gbps", "MeterRates": { "0": 436.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8f4a412e-3b8e-4e4c-85c2-46a96d851ada", "MeterName": "Basic Secondary Active Geo Database Days", "MeterRates": { "0": 0.1771 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "251ae557-c741-45e1-a91d-10d98f925083", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "092a9b85-fd4f-4925-b241-72745aae80f2", "MeterName": "S2 (Daily Units)", "MeterRates": { "0": 32.258065 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Speech Translation API", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "43d8ab6b-6aed-4019-b83d-fe4d0c449ce2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0171 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ad6ad1c-3c84-4e00-afe4-9818c2a08ed3", "MeterName": "Compute Hours", "MeterRates": { "0": 1.124 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1e585364-9fa3-4720-b24e-e681845bfd63", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "87296176-55e9-40de-91e8-816669a46f3b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5f75c8da-e2ff-4e2e-a939-f372463b6b4b", "MeterName": "Storage (GB)", "MeterRates": { "0": 0.25 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b77aa88d-50a4-4936-9277-babc8774dda7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.463 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "296a5c51-33ca-49af-8ca3-de6661d09771", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "4cfe3a23-13ea-4218-8e17-7bff8fce1b88", "MeterName": "Compute Hours", "MeterRates": { "0": 0.195 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "585e9440-27b2-4fc7-a22d-fe53e028affa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.199 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "de5d84ea-63ee-430c-a456-ad68029b89bd", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "244c1fb7-cbe9-49d9-8c4b-3c1fe31ec2a9", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "108c3046-32fe-472f-9a7b-ccf35874892c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.076 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "15cd325a-c594-438e-8e0b-9598de1ad57a", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.3584 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d7488c0c-1f72-4887-9adf-e11419b28bc2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.333 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2d340261-41db-4be1-9426-dc9784f29e48", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0900568c-28c5-4cda-a43e-88671e36fa39", "MeterName": "Compute Hours", "MeterRates": { "0": 0.226 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d18c8c36-0471-44d2-bc16-c3ea3ccedc60", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a20f0805-7d55-4674-899f-10907b9bbe7c", "MeterName": "Surcharge", "MeterRates": { "0": 0.02 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Premium", "MeterTags": [], "Unit": "Core Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "caeb31bc-8c7f-4ccb-b62b-b99b93d62b1b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.732 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c3867359-7044-4ef7-9049-01ef23565e7b", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.024 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a0d60409-83d6-4026-9122-a1b103311ccc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.467 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "955c7d3a-efd8-49f7-a4bd-e71cde2aa138", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "c240c688-f075-4691-99f2-7cdaef88e4b1", "MeterName": "Test Manager Users", "MeterRates": { "0": 52.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Team Services", "MeterTags": [], "Unit": "Users" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c6a07dcf-f269-456c-85da-ef574ffab7e2", "MeterName": "Premium P4 Secondary Geo Database Days", "MeterRates": { "0": 56.25 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ab30cde-f481-4976-b511-6fcd3b477bae", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "470cc61d-890b-4b11-8b18-123f1ad37f91", "MeterName": "Standard Small App Service Hours", "MeterRates": { "0": 0.11 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "3a8f4481-d93e-4064-80d2-d128bd9ea742", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "c8e955ae-f19b-47a9-bc1c-846382d6daa0", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "753763fd-7c2e-4c10-8ea2-10be34d4e36d", "MeterName": "Premium P2 Database Days", "MeterRates": { "0": 37.5 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "404b8578-546e-49bf-bcf4-a47b5097bc67", "MeterName": "Compute Hours", "MeterRates": { "0": 1.018 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ab99bd15-c0d1-43c1-8e09-9e83f9fa5b5f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.2512 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "01a2828d-f337-4387-bdb8-217fc47877c6", "MeterName": "Compute Hours", "MeterRates": { "0": 3.227 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e63bcbe4-2a9b-41cf-922c-3b5444bd0eca", "MeterName": "Compute Hours", "MeterRates": { "0": 1.87 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_NV6 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c7bc816c-6c79-4cf2-b6cf-b36c5dfaf5b2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.58 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "605bbfc8-6a48-401d-a5ca-f53ce90069f3", "MeterName": "Premium Storage - Page Blob/P20 (Units)", "MeterRates": { "0": 73.22 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6417d428-fe3b-4270-951d-5a67e6411a8f", "MeterName": "Standard IO - Page Blob List Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e51f6a34-91af-479e-ad0e-4ebac30031a1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.204 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "12f548fc-5b9a-4664-a9ea-4d3a9b68d7fd", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1cc5131c-4d1f-4e2c-8ea1-65b640416829", "MeterName": "Compute Hours", "MeterRates": { "0": 1.405 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "219ecd20-6cc1-478d-81ba-a1a967d6a0db", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.094 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6bb41d64-700b-4094-b299-07fbd021ea5a", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.444 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "e9faa2d8-24d4-417a-a20a-e80106325bbd", "MeterName": "Data Transfer In - from China (GB)", "MeterRates": { "0": 0.09 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8e700f3a-08bf-4e24-89e2-e6faaf4f2379", "MeterName": "Premium P15 Database Days", "MeterRates": { "0": 619.3536 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "094f91f9-f1f8-4050-9c10-f621e50f1005", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2938dd7b-29d6-4a9e-97f8-4eb2c74f72ec", "MeterName": "Compute Hours", "MeterRates": { "0": 0.352 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "948d4975-d782-4e2f-8f72-ccc8efce10ab", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "c6f239e3-3e2a-4ede-8112-1ee2a0dd140b", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 61.44 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e90a84ba-b3b3-436e-af1b-24824261c7f9", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 187.5 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-01-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "59e53aad-6b76-49ca-b647-9a44c39cad90", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services Low Priority", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "767a249c-98a9-458e-9567-367120c60a08", "MeterName": "Compute Hours", "MeterRates": { "0": 0.456 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ea47b72c-a90e-453f-9de8-8fd121cdbd0b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.296 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fb2f07e7-20be-43de-a5d7-73aef550c22e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.232 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "283f166f-fa2b-4466-aaca-e77b730e70c5", "MeterName": "Premium P1 (Hours)", "MeterRates": { "0": 0.555 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "622ce29b-9869-4726-a45e-772e6ae9a219", "MeterName": "Standard S1 Search Hour", "MeterRates": { "0": 0.403 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "0c4d13cb-7134-4be8-a6fa-a52fdcb87e4c", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b08cec03-dbfd-4cef-b793-1d02dbb4b4ca", "MeterName": "Compute Hours", "MeterRates": { "0": 0.21 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "50cd4076-72de-4f42-a240-63d75f45df02", "MeterName": "Compute Hours", "MeterRates": { "0": 1.301 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8m VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bca046ea-ac28-4a17-bdbf-59acc88a6089", "MeterName": "Compute Hours", "MeterRates": { "0": 0.983 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0ce0553-b825-4810-9b3c-f062301d523a", "MeterName": "Compute Hours", "MeterRates": { "0": 4.532 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f7160398-9710-4663-bed9-238d3534711b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.389 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3ee653f7-3319-4d9d-898c-dfe48f5092f5", "MeterName": "Compute Hours", "MeterRates": { "0": 0.291 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b29222d7-79f4-4662-9270-b59f7a48ee59", "MeterName": "Compute Hours", "MeterRates": { "0": 0.36 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "03bf9426-2cb0-40d2-8c27-38e3bff2f1ba", "MeterName": "MSFT Peering Unlimited Data 200 Mbps", "MeterRates": { "0": 3220.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ba94eb13-49d7-42db-aa50-c1c45a7adb1e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.119 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e890fc6f-c1c6-4365-8031-d57b7d034e9f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.158 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d5bace6f-c712-4b30-b473-28eb8ad129e0", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "52ed4b36-b910-4ce7-be41-e08b60cf2c31", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A6 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3f6360a7-756c-4a5e-b464-069a28d53d36", "MeterName": "Compute Hours", "MeterRates": { "0": 2.246 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f7a83bd0-b47c-4e8d-ac62-da11325848a3", "MeterName": "Standard IO - Table/ Queue (GB)", "MeterRates": { "0": 0.1252 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e8bbd55c-3700-4d4d-9940-1a785f5b3a2c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "82b34d1e-456f-4483-9015-bf96bb282749", "MeterName": "Compute Hours", "MeterRates": { "0": 0.399 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "539935b7-c891-4c8c-af68-eeb71de37de9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.9 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "1ee4c93c-c068-4d6b-b4cc-5145ef2f26b5", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A11 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c31ba90d-da1e-4665-85a1-f80f1810dc05", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d9089bd-c8ea-4b98-b246-8d016fd2c20b", "MeterName": "Compute Hours", "MeterRates": { "0": 3.227 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ec122893-1646-4e2b-b9f8-3bad09490d1b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3f3da0fa-5694-462a-b013-ef7b59556fb7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.305 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0b789296-ba17-451f-9dd0-5cb514b096b0", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.712 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "fd05ccc8-ea8c-4985-8a31-5fd897475bdc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.385 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D2 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "20f70c29-cf95-4a6c-884f-83475ea9e28e", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 8.0355 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "19853b60-be75-4aa3-b462-98188219952e", "MeterName": "Compute Hours", "MeterRates": { "0": 4.07 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a9e85b51-6dcd-4b1e-9079-7394410fa021", "MeterName": "Premium P18 Database Days", "MeterRates": { "0": 511.182 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cfac34fb-c029-4c92-815e-a4a3c963af6b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.161 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e214be74-25c4-4fa3-8366-f710a94c063d", "MeterName": "Compute Hours", "MeterRates": { "0": 1.219 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4c14fdf2-2e55-45c0-95e4-16eca3f49046", "MeterName": "Compute Hours", "MeterRates": { "0": 0.585 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "98d75907-4688-464d-9ef2-ae7692872151", "MeterName": "Overage Data at Rest (GB)", "MeterRates": { "0": 0.039 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Store", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "68c797b7-f215-4c3b-ae9c-aaa1b94f6457", "MeterName": "Compute Hours", "MeterRates": { "0": 0.66 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a8ba8fe4-285d-494d-90d8-5339b112ea40", "MeterName": "Compute Hours", "MeterRates": { "0": 2.24 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "562a0a36-b282-4c60-b636-c137ff56e83f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ffcf5d7a-99c4-4030-8699-c9423edcbb20", "MeterName": "Compute Hours", "MeterRates": { "0": 0.136 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b25e6dd4-75d3-480e-960e-649e0f7b945c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "d0cb76ad-7474-4083-ba41-fe75266d9341", "MeterName": "Basic VM Support Hours", "MeterRates": { "0": 0.03 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "XS SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b8b11c98-f0ee-460b-9626-3bdd0cd62fa5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.08 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "d1c3128a-d1e4-423e-a917-394b7294f435", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1a2c181b-8445-49c9-8b8d-1a9ceb7bdf99", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Enterprise (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "00f88d73-6fbd-4955-9c6d-57ce7ec6ea10", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.016 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a9a2a4b0-4a1f-46dd-b2e6-b2bed0c2cad0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.38 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "95c1589b-4a62-4fff-aeb0-bb17d0098c9e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.458 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f5af6951-80ba-4e4a-8c51-7b6c6ecffb59", "MeterName": "Compute Hours", "MeterRates": { "0": 2.202 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b5f4a5af-9641-4fb0-a4cc-77d032abbc20", "MeterName": "Compute Hours", "MeterRates": { "0": 2.44 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4de4ab44-1e88-480c-b560-f091f5e54f5a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.518 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "153f1e57-2a58-4e97-94e9-1beea575e196", "MeterName": "Data Processed (GB)", "MeterRates": { "0": 0.008 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5370392a-4fef-4d26-85c1-cb2cd5a1f541", "MeterName": "Compute Hours", "MeterRates": { "0": 1.546 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "dd183633-4455-44e5-9258-bad3854c17b9", "MeterName": "Premium P4 Database Days", "MeterRates": { "0": 67.91 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "bed0aa77-9920-4a56-ac95-a0912a338e91", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.438 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "be1ac0e7-2e70-45d6-90f4-4684c68927a3", "MeterName": "Unlimited Data - 500 Mbps", "MeterRates": { "0": 5200.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "05212985-faad-4b6c-8ddb-c08cc8e37f79", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 19.71 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "952aabf4-6502-43d9-936c-19f6b5b692a6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b1d7eff6-5b66-4b3d-98e4-6a7911725399", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "44acc2ec-252b-48ea-a086-e14ed78c5e27", "MeterName": "Compute Hours", "MeterRates": { "0": 0.027 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "45e7b24d-c367-454c-b136-b2ae4e665ecf", "MeterName": "Premium Storage - Page Blob/P4 (Units)", "MeterRates": { "0": 5.7601 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f0949791-7f08-46d9-ac54-92d5099d994c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.198 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "28c11fc3-0e9d-4cbf-81d7-48ae8cea70f6", "MeterName": "Premium Storage - Snapshots (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "aa753d9e-909a-452c-813f-477a16754810", "MeterName": "Compute Hours", "MeterRates": { "0": 0.088 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b9e91eae-a5be-4bbf-8cf2-0fe526737bae", "MeterName": "Standard S4 Secondary Database Days", "MeterRates": { "0": 8.7097 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cf287676-717e-4e97-9606-300d57d0614e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.24 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f6a8b881-4c7e-4ca0-ae42-f0e9f35a43eb", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 17.92 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ae037cc8-2326-4d3e-bee7-b674651d84f5", "MeterName": "Compute Hours", "MeterRates": { "0": 4.311 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H16m Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a642c6cd-544d-4aaa-807b-397b43720f03", "MeterName": "Compute Hours", "MeterRates": { "0": 0.134 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a8999dbf-0a4f-4336-82db-72f644502475", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b1b93a0c-a928-4d20-a54c-e220b271b09f", "MeterName": "Basic Elastic DTU Pack", "MeterRates": { "0": 0.061 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b5c35d52-c111-44c7-b47f-b86944270eb2", "MeterName": "Compute Hours", "MeterRates": { "0": 1.197 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "893280e7-0a64-4535-922b-82b0a0da5ea0", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a7d1f653-4382-406e-a99b-cfa924d17f8a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0623400b-f198-453e-b090-f09555b18e6a", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "193a0217-0a7e-4e03-b141-3f28419da168", "MeterName": "Compute Hours", "MeterRates": { "0": 4.1 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A11 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "124b916f-7a0b-49fe-a83e-ad00333847df", "MeterName": "Compute Hours", "MeterRates": { "0": 0.081 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6a168742-d7bc-4315-8d68-3eafc1ee0150", "MeterName": "Standard Elastic Database Existence", "MeterRates": { "0": 0.0455 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd92c0ee-4577-4a49-bc32-88d1a919e07c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.35 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A8 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "7784341b-7b0a-46c9-99cd-44e397ff75ca", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4a29ad11-b248-47f3-b4cc-745dea04598b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.054 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ebff4fe1-5153-47ea-97c0-ed330493fd4a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.16 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "f0e0687a-1ea3-44e7-abb9-80498915b66f", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A5 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cb761e8e-ac81-4efe-86ee-f7a21fc57256", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2f29032f-38e6-4b02-b11f-af4d02e5d2da", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5323 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "dc264c7d-52b6-43c1-8edd-7e1ce6da677c", "MeterName": "Free (1 Million Characters)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Translation API", "MeterTags": [], "Unit": "1M Characters" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a63ab405-5854-426e-ae2f-35d495646af1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.336 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b16005af-86c3-4d5a-aeb4-5dab885b3b32", "MeterName": "Compute Hours", "MeterRates": { "0": 4.88 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-10T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "557495ef-6150-4699-91f4-cf0e62cf16dd", "MeterName": "Custom Domain Resale (Domains)", "MeterRates": { "0": 11.99 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Annual Domains" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f525f30c-c344-42f3-8aa1-f971b93338b0", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "450e3d99-4ba5-40d6-99f3-b3f779e61de2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.521 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d4d9e93c-83f0-4380-ad49-303469bef64a", "MeterName": "Compute Hours", "MeterRates": { "0": 2.346 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "8795ab57-9cf7-482f-ab5e-f549536af7cd", "MeterName": "Standard MS2 Database (Hours)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MySQL Database on Azure", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "94db869d-b0ed-486a-8995-ddff0eba7412", "MeterName": "IP SSL", "MeterRates": { "0": 39.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Sites" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3f0f3397-5a9e-4590-8bb4-c4469f634e10", "MeterName": "Compute Hours", "MeterRates": { "0": 0.671 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f9762b14-5e33-4846-8282-7e04a2a65723", "MeterName": "Compute Hours", "MeterRates": { "0": 0.286 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "bc234a3d-532e-4117-b6f6-a16dc199cfd6", "MeterName": "Ultra-Performance Gateway Hours", "MeterRates": { "0": 1.87 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4948d0ec-8435-4f5d-9dca-f253e03d1676", "MeterName": "Compute Hours", "MeterRates": { "0": 0.616 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "3f2a709d-5add-4461-9daf-ce44586676f1", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 137.28 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e81fb376-3130-4866-a237-6bcd68e905d9", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "a99d0577-66c4-4bc7-8858-737da568e1fa", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "7b1c4383-af05-4b36-9eeb-a507ab6c91ba", "MeterName": "S1 (Units)", "MeterRates": { "0": 80.0 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "714be93d-955c-4ca5-947b-285ccc69040e", "MeterName": "Standard IO - Page Blob/Disk (GB)", "MeterRates": { "0": 0.05 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bcf0cd59-1293-4451-af4d-2988e253ce89", "MeterName": "Compute Hours", "MeterRates": { "0": 0.588 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d30fdaf3-0eef-4bd3-b557-8781746e22d6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.568 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fabeaa41-a09a-4fe8-abfc-39e66dd66dee", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0832 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ce622662-60c4-4a4a-9723-9af0921c5ecd", "MeterName": "S3 DocumentDB Hours", "MeterRates": { "0": 0.147 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5d8cd12c-3288-44a3-b6a9-75bd52b919aa", "MeterName": "Premium P1 Secondary Geo Database Days", "MeterRates": { "0": 14.063 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7a6c4c40-b914-4d0b-8594-a022308181f7", "MeterName": "Premium P11 Secondary Active Geo Database Days", "MeterRates": { "0": 255.6 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "46f7694b-0985-4757-8af0-a65f3b425e34", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 21.68 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d07849bc-0cd7-4caa-b2f1-39ee0ecb6765", "MeterName": "Compute Hours", "MeterRates": { "0": 0.096 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c48425d9-b8d3-433c-9830-e9cb9d220162", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "aa773dd2-51ff-41b0-a06e-7f49a68c8699", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 67.91 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b755407a-f95a-4cba-9f38-15ebee34f3d8", "MeterName": "Compute Hours", "MeterRates": { "0": 1.501 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "77abbc7b-ab09-463d-b97a-fa10bdbe4f80", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.12 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "ed8b40eb-7183-429a-a52e-bf960dbbd929", "MeterName": "Premium Extra Large App Service Hours", "MeterRates": { "0": 3.0 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b8933f5e-59c6-434d-a2bf-c391b914ea10", "MeterName": "Compute Hours", "MeterRates": { "0": 1.219 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "25e4b7d6-0d1c-4855-bdb2-250d26c5c0fb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.348 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8b3ed95b-c4cc-492b-8f8f-cbfa8946c0f3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5a14a7c1-b19c-40bc-be85-710204d067d9", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8a073f8d-bc48-49ea-8bc1-7fc5af07483b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.411 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9f3b839f-4463-4749-a7dd-4ebf8d378142", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.4 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "75d01b20-ab5e-4cba-9df7-88a0ffc00b9d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.672 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "ff4b3c7a-60b4-4701-a7a9-53afabd9b397", "MeterName": "MSFT Peering Metered Data 10 Gbps", "MeterRates": { "0": 4350.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "90eb72e9-4c2f-4012-82c7-aa4f68a0c9d7", "MeterName": "Premium CDN Data Transfer - S2 (GB)", "MeterRates": { "0": 1.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c0798977-f486-4a4a-aea7-06c9c6155506", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.82 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2c106181-356f-418b-ab7a-856d5cfbb320", "MeterName": "Compute Hours", "MeterRates": { "0": 0.29 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b44a2ed-1103-41f3-90fe-8aaf147c3e41", "MeterName": "Compute Hours", "MeterRates": { "0": 0.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SQL Server Standard (up to 4 cores)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "38df4981-0ab9-4ba0-87ab-f2012e35851a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "aff3dd6b-bc53-4573-b814-c7de690b2b59", "MeterName": "Compute Hours", "MeterRates": { "0": 0.31 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2bbbb0c7-0281-416b-84d7-03ea1155a1d1", "MeterName": "Compute Hours", "MeterRates": { "0": 2.318 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ba620efe-2691-47eb-8056-42524499fb84", "MeterName": "Compute Hours", "MeterRates": { "0": 6.82 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "c7107dc5-43b9-4d42-9ba8-161345a976a3", "MeterName": "Basic C0 (Hours)", "MeterRates": { "0": 0.022 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "59a69bac-2338-4521-8b15-1708093b7615", "MeterName": "Compute Hours", "MeterRates": { "0": 3.075 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "0e59ad56-03e5-4c3d-90d4-6670874d7e29", "MeterName": "Compute Hours", "MeterRates": { "0": 0.029 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "77a1a55d-2e77-418d-a313-ac8ba17a59bc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.09 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3fc6cc9f-c924-40d1-a0a7-3fb0c96c8762", "MeterName": "Compute Hours", "MeterRates": { "0": 0.29 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "3f86ed36-f23c-41fd-8197-949bb4db4524", "MeterName": "Compute Hours", "MeterRates": { "0": 0.45 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e67fe802-d939-4c01-8d67-310db9115456", "MeterName": "Compute Hours", "MeterRates": { "0": 0.167 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "d3aa0e4b-fa3c-45dd-9c37-e8cfcd740cc7", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5565996f-6719-4a62-b2eb-f6c3b28d388e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.623 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "c2e58b2e-18a6-47ca-bb17-c64326404300", "MeterName": "Metered Data - 2 Gbps", "MeterRates": { "0": 872.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "608d24cf-8db8-4aa8-bb93-c0a281555c9f", "MeterName": "Premium Metered Data - 10 Gbps", "MeterRates": { "0": 8000.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f734df52-f7fd-47cf-a279-9b718d15c0b9", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "91d1ae38-82b5-4d2c-a109-66d2818b3e66", "MeterName": "Standard Managed Disk/S30 (Units)", "MeterRates": { "0": 22.528 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "b7ecc630-9105-4be3-b944-1ba2b0107d63", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.04 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "L Canonical", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "6232586a-5a0e-4162-9776-010ed4bb000d", "MeterName": "Standard S2 Secondary Active Geo Database Days", "MeterRates": { "0": 3.025 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "ad62198b-dcff-4cf5-8804-9d70d34191b2", "MeterName": "Standard VM Support Hours", "MeterRates": { "0": 0.108 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "M OpenLogic", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "d38af928-fdf2-47aa-bfc6-f2df5278207b", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.084 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "b699d0d7-798e-48e1-96aa-6c85d1fde13d", "MeterName": "Basic Large App Service Hours", "MeterRates": { "0": 0.354 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e7cc5499-e93e-4f4f-b311-7ff2de78858b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ab49d92d-3edd-4f98-a67a-f9d6c59b0288", "MeterName": "Compute Hours", "MeterRates": { "0": 2.363 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Service Bus", "MeterId": "04ab1ff5-7967-4d6f-b29e-3ffcab9e05b3", "MeterName": "Capacity Unit", "MeterRates": { "0": 733.129 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Event Hubs", "MeterTags": [], "Unit": "Daily Units" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e66dbe6c-85cf-40a1-9351-063c5bf6a7be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.567 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2f9a6072-fc32-4e75-8909-ac91a16febe8", "MeterName": "Compute Hours", "MeterRates": { "0": 0.133 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "37c8dbd7-412b-4892-a31a-915b96a66885", "MeterName": "Standard C1 (Hours)", "MeterRates": { "0": 0.138 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "21d14890-136e-4ae0-b402-ee7818908a79", "MeterName": "Standard S0 Secondary Database Days", "MeterRates": { "0": 0.456 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "bb20dfda-6d18-4bb1-b7fc-86a05d9cfb8d", "MeterName": "Standard IO - Table Write Batch Operation Units (in 10,000s)", "MeterRates": { "0": 0.00036 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "96105def-6396-4a25-8696-732db318c750", "MeterName": "Standard S1 Secondary Database Days", "MeterRates": { "0": 0.8 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3dc510c6-0868-4fbc-98cb-2cd8db95060b", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.15 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f62b84ae-fc24-4482-9f70-9a88211dd5db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.044 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "28685d12-2ba2-4c00-9cad-ce08f1c0068f", "MeterName": "Compute Hours", "MeterRates": { "0": 1.12 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "CDN", "MeterId": "6b88ada0-cbc0-4874-be0e-23004f8b4de7", "MeterName": "Standard CDN Data Transfer - S1 (GB)", "MeterRates": { "0": 0.14 }, "MeterRegion": "Zone 4", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "690adf25-1673-40d7-8117-07391d8b1b20", "MeterName": "Compute Hours", "MeterRates": { "0": 0.21 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f52acb67-19ab-4162-82c7-4022917c33e7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.22 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1848dff2-1a52-4723-b4c3-484f668e44cc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.425 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6cbf6bf0-2443-4a9f-9ed1-d63bef845d28", "MeterName": "Compute Hours", "MeterRates": { "0": 0.161 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "97059b34-33a0-45f2-977a-2c78608ba3a2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "6cb4da42-7563-489e-ab51-a65858347a61", "MeterName": "50,000-AU-hours Commitment Tier", "MeterRates": { "0": 935.49 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "c5228804-1de6-4bd4-a61c-501d9003acc8", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SLES (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "993126ae-d47b-465c-8ca1-f68b2a0d2046", "MeterName": "Unlimited Data - 5 Gbps", "MeterRates": { "0": 25650.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "16f78242-0606-433e-b7aa-ad08bf1f9eea", "MeterName": "Compute Hours", "MeterRates": { "0": 5.584 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A9 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "7a3b7628-9449-49fb-8c64-30a875e81254", "MeterName": "100,000-AU-hours Commitment Tier", "MeterRates": { "0": 1677.42 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "be244c54-8aae-4fd4-a5d1-0dbda93f2772", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "2150bedf-fb47-4146-aafa-57c042744431", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.21 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3d22ec82-227e-4c62-b083-ec96b68e1de6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.175 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "a3c8dc9a-5dde-49e3-bff4-5444dd197cfc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.059 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ebfc2fe4-eab3-4685-898b-122fc86ccf18", "MeterName": "Compute Hours", "MeterRates": { "0": 1.33 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "07107e05-2dbf-44d9-aedd-d7310bce1317", "MeterName": "Compute Hours", "MeterRates": { "0": 1.44 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "A7 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "86ad736d-989d-48a4-a498-4a87626b275a", "MeterName": "Premium P13 Secondary Geo Database Days", "MeterRates": { "0": 251.62 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ce906012-c444-445a-ba6f-5af4e8267a3b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.111 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a7000de2-db97-40cb-bccd-a63c76600dc1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.269 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "eee1feb4-3655-405f-9354-356c41a627cc", "MeterName": "500,000-AU-hours Commitment Tier", "MeterRates": { "0": 7548.39 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "96558206-8bf3-43fb-9474-6d0ce733482a", "MeterName": "Premium P4 Secondary Active Geo Database Days", "MeterRates": { "0": 66.43 }, "MeterRegion": "AU Southeast", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "97239e8b-d288-46a5-901c-3bb4556f3b2f", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 137.28 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "df9dd79b-1729-42aa-aef8-6d9f26ce5d9f", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "73b28345-781a-46a0-86cd-822df3ad6190", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4e7f9a04-6566-4216-bd0c-b35ebf0dbcee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.234 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e7f01606-3c2b-4fc0-ad9b-5228a914e289", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.088 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1bf9b643-a2f4-4a03-a0e5-2086fecfa5ca", "MeterName": "Compute Hours", "MeterRates": { "0": 1.944 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2ff87c86-3c0d-42e3-9b52-c89b23f98c99", "MeterName": "Compute Hours", "MeterRates": { "0": 1.853 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "22d87c50-5bb3-4502-a8ce-9c30daf45f7d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.459 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4a828d79-23d5-4143-9681-5ade8aa7e21a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.78 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A10 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "98fc2852-0ad8-4a09-9799-865c144578db", "MeterName": "Compute Hours", "MeterRates": { "0": 0.155 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D1 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "9af22389-7a72-4c7f-8295-ed0c1a370ca9", "MeterName": "Standard C0 (Hours)", "MeterRates": { "0": 0.069 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "ff472be8-4a43-436e-9a80-f8c4af8700ef", "MeterName": "Compute Hours", "MeterRates": { "0": 1.594 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "6c248e49-2c88-40a4-80ab-d469e72b1a46", "MeterName": "Premium Storage - Page Blob/P10 (Units)", "MeterRates": { "0": 17.92 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b65a815f-330a-42a9-aca9-71def78a0435", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "8a781e83-61af-4fa4-90ad-3a3067553ba7", "MeterName": "MSFT Peering Unlimited Data 2 Gbps", "MeterRates": { "0": 11400.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "b4c4f6e0-5321-4feb-8c65-b054ec023c06", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1819 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "15381d5f-c3ad-43c9-824b-9463db008a67", "MeterName": "Compute Hours", "MeterRates": { "0": 1.187 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c5eb81dd-b9a3-48be-953f-627577b6a033", "MeterName": "Compute Hours", "MeterRates": { "0": 1.306 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "34013683-6f3f-4b90-b235-aa579b1f2881", "MeterName": "Standard IO - Cool Block Blob Data Retrieval (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "88aab413-fad2-42d6-b205-c881ef9c43c1", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.0576 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3aa4f34c-6290-4ccd-bbe2-4f6b0a5c9783", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e84a9ce7-0696-45e7-a826-080aefb8e985", "MeterName": "Compute Hours", "MeterRates": { "0": 2.081 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "0e640d75-28b9-4d06-bb9a-ec794eb17842", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.0416 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "59bc01e3-9d3e-4b9f-baef-35e696aad6c4", "MeterName": "VNET Peering Regional Ingress (GB)", "MeterRates": { "0": 0.01 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fc7c9c41-3aa9-48fe-96a4-86457c7c9cfc", "MeterName": "Compute Hours", "MeterRates": { "0": 1.288 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b305836a-0df4-46b3-839f-423292ca40e6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.025 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F16 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "452de456-2197-463a-b434-8d8b3cf77670", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.11 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "d65dfe7e-956d-4b2b-ac8b-da546738da01", "MeterName": "Premium Metered Data - 100 Mbps", "MeterRates": { "0": 275.0 }, "MeterRegion": "Zone 2", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "f02890c5-0a60-4cf3-b1d5-b6b5f2a96a99", "MeterName": "Compute Hours", "MeterRates": { "0": 0.17 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A2 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f246df93-e03d-4e52-ae97-a43e8f3d542c", "MeterName": "Standard Gateway Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Virtual Network", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "f7870069-8483-47ba-8fc6-050af76c8a85", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.061 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1bd1dec6-11ca-4e45-9160-d30d4f028011", "MeterName": "Compute Hours", "MeterRates": { "0": 0.671 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_G1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Recovery Services", "MeterId": "6551548b-7e61-4f51-896e-eb907d256b95", "MeterName": "Protected Instances", "MeterRates": { "0": 10.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Backup", "MeterTags": [], "Unit": "Instances" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "bb17ae0d-e26f-4bdc-875a-9cb6406a3ea7", "MeterName": "Standard Apps", "MeterRates": { "0": 24.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "Apps" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "3674cb21-5cac-4e21-8a6f-dc17181a0cf8", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8f433e69-804c-4037-a1e6-462c319d0147", "MeterName": "Compute Hours", "MeterRates": { "0": 2.639 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "49fb871c-2c87-46a7-9127-f375831917b4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.918 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ab365613-251f-4202-8c09-8a8ffa26323e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.616 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "078d8ace-8c31-40aa-acf1-136e1bf3030d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Standard (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e084c594-0403-4a6c-bc3c-48322c4acac2", "MeterName": "Basic Database Days", "MeterRates": { "0": 0.1932 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8ba53379-2d64-4ef7-9a39-48a71212d293", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "1e75383d-869e-41ed-9e27-a869ee3970c4", "MeterName": "Premium Unlimited Data - 2 Gbps", "MeterRates": { "0": 19650.0 }, "MeterRegion": "Zone 3", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "47305f4d-28a4-47a9-b6d0-4d07c9b5ba90", "MeterName": "Standard S3 Search Hour", "MeterRates": { "0": 3.552 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Search", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "31409cfe-275a-4e00-8a23-ecdcba10c268", "MeterName": "Compute Hours", "MeterRates": { "0": 1.946 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L8 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e2cedf98-2946-464b-af11-c8e9b4cce4f6", "MeterName": "Standard IO - Cool Block Blob (GB)", "MeterRates": { "0": 0.04 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3f4dbc45-47d0-428d-9a9a-468ce55a0d07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2eeb1af9-0c41-4fcb-81cb-d7130675cc6a", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 135.17 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "0245ef75-e0d0-4bdd-91d7-8d3dc3ba5dba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "303743b6-4cd0-44df-8ec2-a93c8f14943b", "MeterName": "Included Quantity API Transactions (in 1,000s)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Machine Learning", "MeterTags": [], "Unit": "1,000s" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "34b6728d-e233-4b0f-add4-e69d7f7f4005", "MeterName": "Compute Hours", "MeterRates": { "0": 1.043 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b5382a12-9c04-4756-9cc0-ab78acd76f2b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.156 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7c7d6a94-b6b6-4e36-adb3-1f673c7e7129", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 584.208 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "ccd398f9-39d1-4b36-bfa2-fcb90bd859d6", "MeterName": "Premium P18 Secondary Active Geo Database Days", "MeterRates": { "0": 511.182 }, "MeterRegion": "JA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "456820b1-42df-4c28-9fb9-b60f4eb234e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.256 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "57250bbd-6640-449a-82bf-4f990f98e6be", "MeterName": "Compute Hours", "MeterRates": { "0": 0.7 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "40f52f75-97ad-44f9-a842-239a2baf096b", "MeterName": "Standard S0 Database Days", "MeterRates": { "0": 0.5323 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "684b3148-ec75-4010-90b6-8af7ebf2a1ee", "MeterName": "Compute Hours", "MeterRates": { "0": 0.452 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8d998c26-3749-4d5c-bc7e-cbd9e15b91d7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.616 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "12ce51cb-c2ed-43e1-8ce0-9a9cd5fdeda3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60e04289-f16f-468f-82f8-fc5b03661f69", "MeterName": "Compute Hours", "MeterRates": { "0": 0.282 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "2b916213-fe52-45bb-aab5-b31027fe35ad", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 122.88 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b22e5c15-4330-4a92-805a-b9dde5e60930", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "904e7109-d9b8-4021-9827-0529957d57a7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.781 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A6 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d0b7af45-3d37-4c6d-8978-2a4f42f3fb5e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.39 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "99f0c54e-8bf7-40d5-9c2e-7ec5300c4fd8", "MeterName": "Premium Metered Data - 50 Mbps", "MeterRates": { "0": 130.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7415685f-1f86-495b-b67e-72339d4d7878", "MeterName": "Compute Hours", "MeterRates": { "0": 0.488 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "a17966d7-bd06-489a-b50f-ee6aec448502", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 132.0 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1d4ad16e-cfcd-4d5a-a170-507649bf6254", "MeterName": "Compute Hours", "MeterRates": { "0": 2.7 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "A9 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a1640807-64aa-4156-9f65-60ce1debb10a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.39 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "05fe7510-61d7-44fe-a925-adb8c8615688", "MeterName": "Compute Hours", "MeterRates": { "0": 0.939 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c3cba63e-4c34-4fed-9a89-34333b5c6800", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.0096 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "096748f0-e075-4be4-a5d8-1190e67fdd29", "MeterName": "Compute Hours", "MeterRates": { "0": 0.552 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d6d25058-9815-4214-af04-68ff97b0c9fa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.22 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "905b9188-6417-4097-81f9-a4381dd1550b", "MeterName": "Compute Hours", "MeterRates": { "0": 2.92 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_G3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "4965021d-2599-4bd4-84d5-6cf2996826bd", "MeterName": "Standard S1 Secondary Active Geo Database Days", "MeterRates": { "0": 1.107 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cda73cca-973a-4b06-8b47-8aaf63759965", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.0091 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "8742cbe9-6b7e-42fc-b35d-b8b4ee447de1", "MeterName": "Compute Hours", "MeterRates": { "0": 3.6 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_NC24 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f3801402-49c4-4fda-97fa-b85eb7d8d4b6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.05 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "da6c4d55-5c6a-4fd2-960c-d604769542b7", "MeterName": "Compute Hours", "MeterRates": { "0": 1.61 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_H8 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "32407022-8eb1-44f9-8a92-4b934ada0764", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2696 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ebc92ae4-5845-45c3-a08c-ef0aeb80067c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "f67c233d-9c4c-4bf9-948c-d116bb5eed1e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9ae3d375-b492-4ce9-b67f-1985b8f09a68", "MeterName": "Compute Hours", "MeterRates": { "0": 0.581 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "1c0f0b94-5be9-486b-98fa-d942bc9ecdad", "MeterName": "Compute Hours", "MeterRates": { "0": 0.443 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e6921fa7-82ca-4cee-a3c8-5f21627e9879", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "e20f4ed0-67d3-431d-a4c8-6e0d878a81a1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.533 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "b9fd285b-fa40-4954-ab77-56b6a1c4eeea", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.0025 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "8b3daac0-33bd-4989-98bf-dfb96839840b", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.512 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "63172e00-4760-4ba9-babf-2c3618368139", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e80b9379-508f-4856-851a-45851532059a", "MeterName": "Standard IO - Cool Block Blob Data Write (GB)", "MeterRates": { "0": 0.005 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d80d13ad-7410-4d23-b0e7-2dd24c589ace", "MeterName": "Compute Hours", "MeterRates": { "0": 1.366 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fba86e55-b774-478a-aca9-f156cf2f3e71", "MeterName": "Compute Hours", "MeterRates": { "0": 0.357 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a68f49a8-9e88-48cd-ab70-a50b2a3e3c9c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "499bf0ad-ec99-49d4-8214-553645f4f28d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.345 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2152edcd-a901-4759-ad65-8728589937c4", "MeterName": "Compute Hours", "MeterRates": { "0": 0.275 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "945fa653-08e4-48e4-bfc5-872424ea629c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.3 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "bc4fc736-2274-4796-979b-8e63807425c2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.56 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "ef010b9a-4b5e-42af-bd11-1b7960dfbc29", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7ad5d268-d6b1-4dec-ab20-79eada91d6f9", "MeterName": "Basic Elastic Database Existence", "MeterRates": { "0": 0.0167 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "e8299206-0fbe-477a-b3e5-a88bce95d152", "MeterName": "Compute Hours", "MeterRates": { "0": 2.276 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2dfc7a6-d31d-43c3-9dc4-27365cde7b0e", "MeterName": "Compute Hours", "MeterRates": { "0": 8.14 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f1aa70d9-1880-43d3-8eef-a66921c5a0ec", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "db5cd96a-4852-4e0b-94e5-5c915d9c1879", "MeterName": "Compute Hours", "MeterRates": { "0": 1.173 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A10 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ec91e985-a405-45ec-9032-bb4429484b8c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.133 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f32a896b-2d51-45c7-b75c-b8558e39be32", "MeterName": "Compute Hours", "MeterRates": { "0": 2.617 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "585a4f17-51ed-4304-8a1e-ac7355815cd8", "MeterName": "Premium P15 Secondary Active Geo Database Days", "MeterRates": { "0": 590.4457 }, "MeterRegion": "IN Central", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f2ef9574-2073-43e9-9264-840ec46532a2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.457 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "61ffdc30-4ff5-4bc5-941d-c09b5048ae48", "MeterName": "Compute Hours", "MeterRates": { "0": 0.159 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "03e1ae28-ea98-4c53-aa7e-0f47c6e2e7be", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.0092 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "16336d11-4cef-4d26-a3f5-43b7ffa896d8", "MeterName": "Metered Data - 50 Mbps", "MeterRates": { "0": 55.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "Connections" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "e2613a8a-62a3-4bb2-9558-c51db8294b0f", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "98638d0f-6448-4aff-9228-118a0f6c1fa3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.665 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "5a5be520-1a9f-4f13-8e0d-bc4aad63d41f", "MeterName": "Users", "MeterRates": { "0": 1.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Azure Data Catalog", "MeterTags": [], "Unit": "1 User" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3f69a91d-5169-4657-9a63-60ae3269ac46", "MeterName": "Compute Hours", "MeterRates": { "0": 0.099 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2cc19612-cf8a-4c19-90f7-390512f2b378", "MeterName": "Compute Hours", "MeterRates": { "0": 1.188 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0e77ab82-88a5-4351-a87a-c196e46fb84b", "MeterName": "Compute Hours", "MeterRates": { "0": 1.41 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A7 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "6773b871-0d96-4d04-9932-073d74096a14", "MeterName": "Compute Hours", "MeterRates": { "0": 0.298 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "0ef7d1ea-e461-4881-9b57-c6e29384d711", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dd1b1b44-7155-468f-8677-31bc1f39b1f9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.146 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 5.0, "MeterCategory": "Business Analytics", "MeterId": "2acc87fb-e9e1-42a6-a8ec-4d92598b7367", "MeterName": "Low Frequency On Premises Activity", "MeterRates": { "0": 1.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Factory", "MeterTags": [], "Unit": "Activities" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4082fa20-19d0-4388-b91e-a8150bc6ad4d", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-08-02T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cache", "MeterId": "5fb13099-4de0-419d-9fb8-4aef0cf575b1", "MeterName": "Standard C5 (Hours)", "MeterRates": { "0": 1.313 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "Azure Redis Cache", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5cc745aa-756c-4d5f-a45c-d80ae3d24bdd", "MeterName": "Compute Hours", "MeterRates": { "0": 8.78 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_G5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "067023b9-5c2b-428e-a4f7-f13e655f5e10", "MeterName": "Data Transfer In (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "Zone 1", "MeterStatus": "Active", "MeterSubCategory": "ExpressRoute", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7f283d9e-e6e0-439a-aa11-7629ca78cae4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.995 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6bba4748-99f7-46d9-9b18-a41275c0d97c", "MeterName": "Compute Hours", "MeterRates": { "0": 3.891 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_L16 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c323c94a-ccd3-4dc5-82a7-c1e18dd1913a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.322 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "65dda5ab-c6a3-4e8d-8dad-1bdd67947927", "MeterName": "Standard IO - Cool Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Visual Studio", "MeterId": "378eb4e8-8d82-46ee-aacb-460e00002b4f", "MeterName": "Standard Overage Data Points (1M)", "MeterRates": { "0": 1.75 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Application Insights", "MeterTags": [], "Unit": "1M Data Points" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Identity", "MeterId": "5ebd8165-26c0-4d5e-8444-155121adc72b", "MeterName": "S1 Domain Services (Hours)", "MeterRates": { "0": 0.15 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Active Directory Domain Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ef52f6ad-a301-4dba-a43e-48e8e45f176a", "MeterName": "Compute Hours", "MeterRates": { "0": 1.2696 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM (Windows)", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "60596994-ce9c-470c-a8ee-853b694a3037", "MeterName": "Compute Hours", "MeterRates": { "0": 1.222 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c0536b57-709b-4f22-9250-6b7e57523e19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.078 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "204dae38-a8b9-4c6a-91ba-9d4d4472295d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.02 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "A0 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2415f8f4-90a8-409f-bdcf-23c0a2969717", "MeterName": "Compute Hours", "MeterRates": { "0": 0.449 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A4 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "57e6ef6c-9915-4a73-ba80-b19491aed497", "MeterName": "Standard S0 Secondary Active Geo Database Days", "MeterRates": { "0": 0.4839 }, "MeterRegion": "JA West", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cc48b523-5c6d-4ed9-a56b-21b1c9209e4b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.584 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "8cda1ae6-8888-4024-b1f4-bcdb0af88739", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.144 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "5500ea5d-925f-4aca-a6f5-6055ef5ef662", "MeterName": "Premium Large App Service Hours", "MeterRates": { "0": 1.512 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 40960.0, "MeterCategory": "Networking", "MeterId": "acac7492-1c40-4088-bf01-40d582b85b63", "MeterName": "Data Processed (GB)", "MeterRates": { "0": 0.0035 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Large)", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a7ecea5a-5bff-4861-9c2b-8f6f6888c6e0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.27 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "ca2d160f-694a-4ff4-bb15-bffaad99af9e", "MeterName": "Geo-Replicated Data Transfer (GB)", "MeterRates": { "0": 0.02 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4186f61c-b5c0-4c1b-9820-56250933b9f0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.255 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2m_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "38e85549-aba3-494a-9829-9b5309a2ab16", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "35664b4e-f7a5-457b-b60e-eff0015f2cdb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A0 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "a4b3fde1-3fa6-476d-ac12-36af7cf416d2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.622 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d6885952-e050-4907-b240-8b1b3dd2a52c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "4140440b-610d-4d33-9530-9462155b920f", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.028 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fb38caa1-2aa6-4a4c-8c0d-b04ff1bb0669", "MeterName": "Compute Hours", "MeterRates": { "0": 0.323 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "7adc6db5-d01d-4400-b10b-156a95de4738", "MeterName": "Compute Hours", "MeterRates": { "0": 1.794 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "A11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9f0edb03-a2ad-4d5a-a211-d2fccb638ded", "MeterName": "Compute Hours", "MeterRates": { "0": 1.34 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_G2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "76480596-7ad0-4efc-afac-f95e1bbc0e30", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Database Enterprise and Weblogic Server Enterprise (16 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "085dc9ee-005d-4075-ac11-822ccde9e8f6", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.48 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "SLES (24 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "eb71a1ca-a317-41bf-b8c8-15b9fad365ad", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.75 }, "MeterRegion": "UK West", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b974c36-56fa-41ab-b3ed-b8ca3d3ea33a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.133 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "160cd7d1-5e79-48f6-938a-8daca7717323", "MeterName": "Compute Hours", "MeterRates": { "0": 0.536 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "22a3461c-d980-48ba-ad80-9e16761ec7a5", "MeterName": "Compute Hours", "MeterRates": { "0": 1.995 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "f7caafcd-8df6-46d1-98c7-77d962316fe7", "MeterName": "Data transfer - Geo-Replication (GB)", "MeterRates": { "0": 0.0 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "4eb56078-50d1-4fa2-9867-c4b7c6173d20", "MeterName": "Compute Hours", "MeterRates": { "0": 1.1256 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_L4 VM", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "75eb68fb-f31d-440b-b1b7-72beee9f709c", "MeterName": "Premium P6 Secondary Active Geo Database Days", "MeterRates": { "0": 132.0 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "560c52dc-c267-4416-a290-a89289d58490", "MeterName": "Premium P13 Secondary Active Geo Database Days", "MeterRates": { "0": 354.84 }, "MeterRegion": "CA East", "MeterStatus": "Deprecated", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fc680266-4c2a-49b7-bfe4-901e496bf68a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.12 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8858a39b-007c-4ef7-aff1-53a36ba6dca2", "MeterName": "Compute Hours", "MeterRates": { "0": 0.41 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "7a3b96e3-1c68-4506-86d8-224b89b3347f", "MeterName": "Premium Medium App Service Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "c3f976e0-7f7d-4ecd-b858-96c16c0169fa", "MeterName": "Compute Hours", "MeterRates": { "0": 0.23 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "bd1097ad-f37c-43a9-9774-a61c1d4d8711", "MeterName": "Compute Hours", "MeterRates": { "0": 0.746 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D3 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fb8386fc-29c3-4203-973b-8a7bd78b0a05", "MeterName": "Standard IO - Files (GB)", "MeterRates": { "0": 0.11 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2c6d0271-97a7-4945-8847-0aab5f73ab3e", "MeterName": "Compute Hours", "MeterRates": { "0": 3.075 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D15_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-02-11T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "48994c38-10f8-4861-90e2-743bf7121c37", "MeterName": "Compute Hours", "MeterRates": { "0": 0.018 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c8556bb9-c013-498b-95f0-5740bef731ba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.08 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "336457ad-03aa-4405-9a96-f1dde25e5cfb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.355 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "16e8b048-23d3-48c3-bd9d-4953466cd84d", "MeterName": "Standard IO - Hot Block Blob (GB)", "MeterRates": { "0": 0.048 }, "MeterRegion": "US West Central", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "efae3eca-ee16-4095-800d-e712456bc886", "MeterName": "Compute Hours", "MeterRates": { "0": 0.702 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "62e5583c-5b2c-4032-8ff1-0b31c8d53023", "MeterName": "Compute Hours", "MeterRates": { "0": 0.456 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "D11 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "29085ce9-61ec-4e9e-a13d-10bba4ae03d7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.14 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "9e4ccbd2-f157-4a20-8ba6-be70e33eb488", "MeterName": "Standard S2 Secondary Database Days", "MeterRates": { "0": 1.991 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "f63c87f9-6ff4-4aee-bbfd-39b337729cdc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.137 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_F2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5ccba2b7-0734-4693-8cd1-2bcc8ae1110c", "MeterName": "Standard S1 Database Days", "MeterRates": { "0": 1.21 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d09f877e-03b4-48b2-b11a-782b965cff19", "MeterName": "Compute Hours", "MeterRates": { "0": 0.13 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Red Hat Enterprise Linux (20 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0688e907-64a4-45c5-9c42-4a3224219a03", "MeterName": "Compute Hours", "MeterRates": { "0": 2.708 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "741a12b4-7c9e-4362-9a7c-f826f7427054", "MeterName": "Compute Hours", "MeterRates": { "0": 0.441 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A4m_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "248ab64b-28be-401b-b4bb-ae02cda1c810", "MeterName": "Basic Small App Service Hours", "MeterRates": { "0": 0.0885 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bd3cb0fa-3e81-4e5d-a517-a7f0c67de5d7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.72 }, "MeterRegion": "AP East", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Linux Support", "MeterId": "bb21066f-fe46-46d3-8006-b326b1663e52", "MeterName": "Premium VM Support Hours", "MeterRates": { "0": 0.32 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "A9 SLES", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2015-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Networking", "MeterId": "56501055-e134-4cf2-baa5-19f3703d0b2a", "MeterName": "Application Gateway Hours", "MeterRates": { "0": 0.027 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "Basic Application Gateway (Small)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bbee8f6b-f17d-405b-8269-d7214d3acb21", "MeterName": "Compute Hours", "MeterRates": { "0": 0.575 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "8eac41f4-00e2-4bf6-b605-5adfe00dc28a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.575 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ddfd2072-6a5a-41bf-bdc6-f2be3ab6a283", "MeterName": "Compute Hours", "MeterRates": { "0": 0.433 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Identity", "MeterId": "d148a09e-07a5-4e98-89b3-a10fe304be30", "MeterName": "S2 Domain Services (Hours)", "MeterRates": { "0": 0.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Active Directory Domain Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "7a1f4266-4be6-4b5d-bc69-dac76f15fa55", "MeterName": "Premium P11 Secondary Geo Database Days", "MeterRates": { "0": 186.3 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "74c51fe2-14af-471c-9589-10074198ae4c", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "6446f0b9-46ca-445b-8ee6-a1f925bccb5e", "MeterName": "Standard IO - Cool Block Blob Read Operations (in 10,000s)", "MeterRates": { "0": 0.01 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1edf624d-028f-4945-a3ea-244e65afd0b7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.19 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "9f491c66-b113-4aa3-8847-a02daae3f6f4", "MeterName": "Compute Hours", "MeterRates": { "0": 2.659 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D14 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "c0394e55-83aa-4bc6-9bb8-0df26714d2e9", "MeterName": "Compute Hours", "MeterRates": { "0": 0.113 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A1 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-06-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure IoT Hub", "MeterId": "b42f9a44-d1d2-4792-bc98-fdaa614bdeac", "MeterName": "S3 (Units)", "MeterRates": { "0": 5000.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "aa269bda-859a-470f-ab46-3554f72a6287", "MeterName": "Compute Hours", "MeterRates": { "0": 1.478 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "D13 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "028f1bb2-4b88-4a92-937b-0721ccbab1a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.33 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6d2100f0-e28a-4f20-a5a5-ebb7b8521477", "MeterName": "Compute Hours", "MeterRates": { "0": 0.374 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A5 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "cef301fd-47c0-4d4e-b6cf-3eecf67ed8bb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.21 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D11 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "e80bd6e2-731d-4e39-92cf-06482af38e4a", "MeterName": "S2 DocumentDB Hours", "MeterRates": { "0": 0.067 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "2e988a1e-9fbf-4406-be8a-4029925adcb0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.095 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "58d279ea-4aa3-49d8-b458-a4e2a8ad466c", "MeterName": "Compute Hours", "MeterRates": { "0": 0.221 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Media", "MeterId": "b0d6a4e5-da22-44a4-94bd-3648fb427e13", "MeterName": "PlayReady Licenses (in 100s)", "MeterRates": { "0": 0.2 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Media Services", "MeterTags": [], "Unit": "100 Licenses" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "fb32496d-55e3-439c-bb9b-6ad853342d54", "MeterName": "Compute Hours", "MeterRates": { "0": 0.299 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "d4c29129-7523-447e-be06-ae1a1835bbd4", "MeterName": "Compute Hours", "MeterRates": { "0": 1.68 }, "MeterRegion": "AP Southeast", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "36b36c0f-f834-413e-a801-3a724659b49f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.101 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "A1 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cognitive Services", "MeterId": "8d892860-f58e-4ee4-b54e-902928c9da5c", "MeterName": "Standard S3 Overage (in 1,000s)", "MeterRates": { "0": 0.5 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Text Analytics", "MeterTags": [], "Unit": "1,000 Transactions" }, { "EffectiveDate": "2016-03-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "be5fd77f-e2dc-424f-bb67-0b5363a1f8b3", "MeterName": "Compute Hours", "MeterRates": { "0": 2.08 }, "MeterRegion": "US West 2", "MeterStatus": "Active", "MeterSubCategory": "Standard_D5_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "3cb550c8-1f2b-4912-b765-544c2754a90a", "MeterName": "Compute Hours", "MeterRates": { "0": 0.065 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "5bef5b01-8fc6-444e-ad53-fc6f04eadc6b", "MeterName": "100 Request Units (Hours)", "MeterRates": { "0": 0.008 }, "MeterRegion": "EU North", "MeterStatus": "Active", "MeterSubCategory": "DocumentDB", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "cfc04eb4-da44-457c-89e9-6547186c2408", "MeterName": "DWU", "MeterRates": { "0": 1.6936 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-30T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bb4decef-9eba-40b8-90ea-ee6de30a7b6b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Oracle Weblogic Server Standard (32 core)", "MeterTags": [ "Third Party" ], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "ad1bd262-83bc-41aa-a7c9-8a5fbe3b626a", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.119 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "2a9b748d-198a-4bce-8802-0888060ec9f1", "MeterName": "Compute Hours", "MeterRates": { "0": 1.54 }, "MeterRegion": "AU Southeast", "MeterStatus": "Active", "MeterSubCategory": "D4 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e19f265b-d4ee-4a59-826d-99a5a0d6e72c", "MeterName": "Compute Hours", "MeterRates": { "0": 1.164 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "A7 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f3f8d7ca-ff5e-4291-b96e-31824105973a", "MeterName": "Premium P1 Database Days", "MeterRates": { "0": 16.5 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "cc6f7131-74ac-4feb-ac28-f514b32abd40", "MeterName": "Compute Hours", "MeterRates": { "0": 0.398 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "153c9c37-2689-4299-be94-56a542698dc9", "MeterName": "Compute Hours", "MeterRates": { "0": 10.1568 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_L32 Cloud Services", "MeterTags": [], "Unit": "1 Hour" }, { "EffectiveDate": "2015-01-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "980b4362-5f37-4932-a3e3-a3ff8ee308f1", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "BASIC.A3 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "dc2f8c69-3f2c-4001-8ce4-e6534bab9085", "MeterName": "Compute Hours", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Standard_D13_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "bdce8a99-d717-43f0-b77e-8e70da8abb8f", "MeterName": "Compute Hours", "MeterRates": { "0": 2.4 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "BizTalk Server Standard (20 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2014-04-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c7c7fad9-875d-472e-afe6-90a776e93273", "MeterName": "Premium P6 Database Days", "MeterRates": { "0": 135.6 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "395e9151-35ad-4920-9b7e-d23b1fb29ddb", "MeterName": "1,000-AU-hours Commitment Tier", "MeterRates": { "0": 25.81 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Lake Analytics", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1ee544b4-d008-4f33-992f-4158003126c0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.176 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "2b9e6ef0-6519-4fe6-9ec1-5fddc4e038a3", "MeterName": "Compute Hours", "MeterRates": { "0": 0.35 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A5 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "fcdb50f8-69e6-4461-9ca6-bd7cfc7bb919", "MeterName": "Premium Storage - Page Blob/P30 (Units)", "MeterRates": { "0": 147.456 }, "MeterRegion": "CA Central", "MeterStatus": "Active", "MeterSubCategory": "Locally Redundant", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Management", "MeterId": "830aab6c-b809-4ce2-8556-2adc72b0ddd5", "MeterName": "Standard IO - Hot Block Blob Write Operations (in 10,000s)", "MeterRates": { "0": 0.1 }, "MeterRegion": "US East 2", "MeterStatus": "Active", "MeterSubCategory": "Geo Redundant", "MeterTags": [], "Unit": "10,000s" }, { "EffectiveDate": "2013-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "e65abadc-5a30-4aba-b014-f1ee54bf4bf6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.06 }, "MeterRegion": "US East", "MeterStatus": "Active", "MeterSubCategory": "A1 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "03e1858a-3870-4604-b596-5b9770c3688e", "MeterName": "Compute Hours", "MeterRates": { "0": 0.443 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A5 HDInsight", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "62c66f65-0bc1-4e66-b98f-b2df055a45d1", "MeterName": "Compute Hours", "MeterRates": { "0": 2.447 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D14_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "9c5e4df1-6e31-448c-8470-08f7cdd08d4f", "MeterName": "Compute Hours", "MeterRates": { "0": 0.459 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_F4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-22T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "a896844e-46ea-4f97-a782-34db7f307e18", "MeterName": "Compute Hours", "MeterRates": { "0": 3.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MSFT R Server for Linux (8 core)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "1fd67ea9-ba92-4f3c-a3eb-2b7a0d151c07", "MeterName": "Compute Hours", "MeterRates": { "0": 0.022 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A0 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "f7654217-eaf6-4563-800a-ba3c03be1f94", "MeterName": "Standard Elastic DTU Pack", "MeterRates": { "0": 0.0798 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2014-05-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "5f5ce76f-fced-40b5-9f30-b9a8acdd99e0", "MeterName": "Compute Hours", "MeterRates": { "0": 0.562 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "A6 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "b5c4a1dc-aa2d-47b9-bde4-a0552a9303b7", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "0222c4ce-52e6-486e-a370-9b615a0e4361", "MeterName": "Compute Hours", "MeterRates": { "0": 0.822 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "D12 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "774a37b6-5e00-455c-b4bc-fe4d738bfeba", "MeterName": "Compute Hours", "MeterRates": { "0": 0.6 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_A8_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-08-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "b4a51469-59bc-4c18-8257-b19b842e4150", "MeterName": "Compute Hours", "MeterRates": { "0": 0.379 }, "MeterRegion": "IN South", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "074c3623-419a-48c0-9453-7430ade501b6", "MeterName": "Compute Hours", "MeterRates": { "0": 0.839 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4_v2 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "0001-01-01T00:00:00", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "c63c9359-a1a9-40d4-a878-5190485648b3", "MeterName": "Standard MS3 Database (Hours)", "MeterRates": { "0": 0.0 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "MySQL Database on Azure", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-05-04T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "50b2951b-45e8-4aae-8aa8-daba9d4ff0c6", "MeterName": "Premium P18 Secondary Geo Database Days", "MeterRates": { "0": 383.404 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "SQL Database", "MeterTags": [], "Unit": "Days" }, { "EffectiveDate": "2015-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "844e6b74-425f-4e72-a98c-7a424bd7d41d", "MeterName": "Compute Hours", "MeterRates": { "0": 0.944 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "A6 HDInsight (Non-Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "32749b8d-4029-43d7-9027-d917b1680607", "MeterName": "Compute Hours", "MeterRates": { "0": 0.28 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "85373a0c-6ece-41bd-8d07-34477114df1b", "MeterName": "Compute Hours", "MeterRates": { "0": 0.449 }, "MeterRegion": "EU West", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12 VM", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Azure App Service", "MeterId": "098d5dab-fbc6-44bf-ace3-3bb399658cee", "MeterName": "Premium Small App Service Hours", "MeterRates": { "0": 0.378 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2013-12-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "fe6418a1-ea5e-48b6-8728-63fa1e156695", "MeterName": "Compute Hours", "MeterRates": { "0": 1.594 }, "MeterRegion": "JA West", "MeterStatus": "Active", "MeterSubCategory": "A7 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-03-25T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Storage", "MeterId": "e2479b74-a48f-43f9-b1ce-f176d5900aad", "MeterName": "Standard IO - Queue (GB)", "MeterRates": { "0": 0.132 }, "MeterRegion": "CA East", "MeterStatus": "Active", "MeterSubCategory": "Read-Access Geo Redundant", "MeterTags": [], "Unit": "GB" }, { "EffectiveDate": "2016-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Data Services", "MeterId": "46a9341f-64e4-4601-a22c-33669b243676", "MeterName": "DWU", "MeterRates": { "0": 2.4194 }, "MeterRegion": "BR South", "MeterStatus": "Active", "MeterSubCategory": "SQL Data Warehouse", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "9c757631-cc2a-4087-a522-ce951fffbe49", "MeterName": "Compute Hours", "MeterRates": { "0": 0.26 }, "MeterRegion": "US South Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D2_v2 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-10-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Cloud Services", "MeterId": "cfc14ce6-3709-4415-bc3a-e80560a1c4d6", "MeterName": "Compute Hours", "MeterRates": { "0": 1.248 }, "MeterRegion": "AU East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D4 Cloud Services", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-09-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "041b9704-e167-440e-98d6-fdc6fafc8493", "MeterName": "Premium Managed Disk/P30 (Units)", "MeterRates": { "0": 67.59 }, "MeterRegion": "IN Central", "MeterStatus": "Active", "MeterSubCategory": "HDInsight Storage", "MeterTags": [], "Unit": "Units" }, { "EffectiveDate": "2016-09-07T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "ed50efb6-6057-4d51-9a12-55c6d77aafbc", "MeterName": "Compute Hours", "MeterRates": { "0": 0.792 }, "MeterRegion": "UK South", "MeterStatus": "Active", "MeterSubCategory": "A4 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "15edb42b-9b5f-44e9-bf0c-1d19b1eb8cec", "MeterName": "Compute Hours", "MeterRates": { "0": 0.652 }, "MeterRegion": "US North Central", "MeterStatus": "Active", "MeterSubCategory": "Standard_D12_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-02-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "14f1872f-2861-4df2-a649-42bd849935cb", "MeterName": "Compute Hours", "MeterRates": { "0": 0.168 }, "MeterRegion": "JA East", "MeterStatus": "Active", "MeterSubCategory": "Standard_D1_v2 VM (Windows)", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2015-07-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Business Analytics", "MeterId": "564fa413-2705-4df8-bff8-128084de21b6", "MeterName": "Data Movement Cloud", "MeterRates": { "0": 0.25 }, "MeterRegion": "", "MeterStatus": "Active", "MeterSubCategory": "Data Factory", "MeterTags": [], "Unit": "Hours" }, { "EffectiveDate": "2016-11-01T00:00:00Z", "IncludedQuantity": 0.0, "MeterCategory": "Virtual Machines", "MeterId": "6b660c58-a5f3-434a-8fe4-c9981b178c35", "MeterName": "Compute Hours", "MeterRates": { "0": 0.091 }, "MeterRegion": "US West", "MeterStatus": "Active", "MeterSubCategory": "Standard_A2_v2 VM", "MeterTags": [], "Unit": "Hours" } ], "OfferTerms": [ { "EffectiveDate": "2015-01-01T00:00:00Z", "ExcludedMeterIds": [], "Name": "Monetary Commitment", "TieredDiscount": { "6000": 0.05 } } ] } ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500000001025013535474530033445 0ustar kamikami00000000000000{ "id": "/subscriptions/99999999-9999-9999-9999-999999999999/providers/Microsoft.Compute", "namespace": "Microsoft.Compute", "resourceTypes": [ { "resourceType": "availabilitySets", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2015-06-15", "2015-05-01-preview", "2014-12-01-preview" ] }, { "resourceType": "virtualMachines", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2015-06-15", "2015-05-01-preview", "2014-12-01-preview" ] }, { "resourceType": "virtualMachines/extensions", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2015-06-15", "2015-05-01-preview", "2014-12-01-preview" ] }, { "resourceType": "virtualMachines/diagnosticSettings", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2014-04-01" ] }, { "resourceType": "virtualMachines/metricDefinitions", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2014-04-01" ] }, { "resourceType": "locations", "locations": [], "apiVersions": [ "2015-06-15", "2015-05-01-preview", "2014-12-01-preview" ] }, { "resourceType": "locations/operations", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2015-06-15", "2015-05-01-preview", "2014-12-01-preview" ] }, { "resourceType": "locations/vmSizes", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2015-06-15", "2015-05-01-preview", "2014-12-01-preview" ] }, { "resourceType": "locations/usages", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2015-06-15", "2015-05-01-preview", "2014-12-01-preview" ] }, { "resourceType": "locations/publishers", "locations": [ "East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West" ], "apiVersions": [ "2015-06-15", "2015-05-01-preview" ] } ], "registrationState": "Registered" }././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_disks.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500000000460513535474530033454 0ustar kamikami00000000000000{ "value": [ { "properties": { "accountType": "Standard_LRS", "osType": "Linux", "creationData": { "createOption": "FromImage", "imageReference": { "id": "/Subscriptions/99999999-9999-9999-9999-999999999999/Providers/Microsoft.Compute/Locations/eastus/Publishers/OpenLogic/ArtifactTypes/VMImage/Offers/CentOS/Skus/7.3/Versions/latest" } }, "diskSizeGB": 31, "timeCreated": "2017-03-09T10:12:37.0256203+00:00", "ownerId": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Compute/virtualMachines/test-vm-1", "provisioningState": "Succeeded", "diskState": "Attached" }, "type": "Microsoft.Compute/disks", "location": "eastus", "tags": {}, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-disk-1", "name": "test-disk-1" }, { "properties": { "accountType": "Standard_LRS", "osType": "Linux", "creationData": { "createOption": "FromImage", "imageReference": { "id": "/Subscriptions/99999999-9999-9999-9999-999999999999/Providers/Microsoft.Compute/Locations/eastus/Publishers/OpenLogic/ArtifactTypes/VMImage/Offers/CentOS/Skus/7.3/Versions/latest" } }, "diskSizeGB": 31, "timeCreated": "2017-03-09T11:40:37.092158+00:00", "provisioningState": "Updating", "diskState": "Unattached" }, "type": "Microsoft.Compute/disks", "location": "eastus", "tags": {}, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-disk-2", "name": "test-disk-2" }, { "properties": { "accountType": "Standard_LRS", "osType": "Linux", "creationData": { "createOption": "Empty" }, "diskSizeGB": 10, "timeCreated": "2017-03-09T10:08:42.6418313+00:00", "provisioningState": "Succeeded", "diskState": "Unattached" }, "type": "Microsoft.Compute/disks", "location": "eastus", "tags": {}, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/disks/test-disk-3", "name": "test-disk-3" } ] }././@LongLink0000000000000000000000000000022100000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_locations_eastus_vmSizes.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500000000112413535474530033445 0ustar kamikami00000000000000{ "value": [ { "name": "Standard_A0", "numberOfCores": 1, "osDiskSizeInMB": 1047552, "resourceDiskSizeInMB": 20480, "memoryInMB": 768, "maxDataDiskCount": 1 }, { "name": "Standard_A1", "numberOfCores": 1, "osDiskSizeInMB": 1047552, "resourceDiskSizeInMB": 71680, "memoryInMB": 1792, "maxDataDiskCount": 2 }, { "name": "Standard_A2", "numberOfCores": 2, "osDiskSizeInMB": 1047552, "resourceDiskSizeInMB": 138240, "memoryInMB": 3584, "maxDataDiskCount": 4 } ] } ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_snapshots.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500000000546013535474530033454 0ustar kamikami00000000000000{ "value": [ { "properties": { "accountType": "Standard_LRS", "creationData": { "createOption": "Copy", "sourceUri": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-disk-1" }, "diskSizeGB": 1, "timeCreated": "2017-03-09T14:28:27.8655868+00:00", "provisioningState": "Creating", "diskState": "Unattached" }, "type": "Microsoft.Compute/snapshots", "location": "eastus", "tags": { "test_snap": "test" }, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/snapshots/test-snap-1", "name": "test-snap-1" }, { "properties": { "accountType": "Standard_LRS", "creationData": { "createOption": "Copy", "sourceUri": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-disk-2" }, "diskSizeGB": 2, "timeCreated": "2017-02-02T17:52:40.2213321+00:00", "provisioningState": "Updating", "diskState": "Unattached" }, "type": "Microsoft.Compute/snapshots", "location": "eastus", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/snapshots/test-snap-2", "name": "test-snap-2" }, { "properties": { "accountType": "Standard_LRS", "creationData": { "createOption": "Copy", "sourceUri": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/disks/test-disk-3" }, "diskSizeGB": 2, "timeCreated": "2017-02-02T17:52:44.4557501+00:00", "provisioningState": "Failed", "diskState": "Unattached" }, "type": "Microsoft.Compute/snapshots", "location": "eastus", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/snapshots/test-snap-3", "name": "test-snap-3" }, { "properties": { "accountType": "Standard_LRS", "creationData": { "createOption": "Copy", "sourceUri": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/disks/test-disk-4" }, "diskSizeGB": 2, "timeCreated": "2017-02-02T17:52:50.0027361+00:00", "provisioningState": "Failed", "diskState": "Unattached" }, "type": "Microsoft.Compute/snapshots", "location": "eastus", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/snapshots/test-snap-4", "name": "test-snap-4" } ] }././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500000000320013535474530033442 0ustar kamikami00000000000000{ "value": [ { "properties": { "vmId": "CCEEBF63-E92B-4A50-9949-6E44BFC61D3F", "hardwareProfile": { "vmSize": "Standard_A1" }, "storageProfile": { "imageReference": { "publisher": "OpenLogic", "offer": "CentOS", "sku": "7.3", "version": "latest" }, "osDisk": { "osType": "Linux", "name": "test-node-disk-1", "createOption": "FromImage", "caching": "ReadWrite", "managedDisk": { "storageAccountType": "Standard_LRS", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-node-disk-1" } }, "dataDisks": [] }, "osProfile": { "computerName": "test-node-1", "adminUsername": "user", "linuxConfiguration": { "disablePasswordAuthentication": false }, "secrets": [] }, "networkProfile": { "networkInterfaces": [ { "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/networkInterfaces/test-node-1-nic" } ] }, "provisioningState": "Running" }, "type": "Microsoft.Compute/virtualMachines", "location": "eastus", "tags": {}, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/virtualMachines/test-node-1", "name": "test-node-1" } ] }././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_networkInterfaces.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500000000405313570310635033443 0ustar kamikami00000000000000{ "value": [ { "name": "test-nic", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic", "etag": "Z/\"99999999-9999-9999-9999-999999999999\"", "location": "eastus", "tags": { "tag_key1": "tag_val1" }, "properties": { "provisioningState": "Succeeded", "resourceGuid": "99999999-9999-9999-9999-999999999999", "ipConfigurations": [ { "name": "ipconfig1", "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic/ipConfigurations/ipconfig1", "etag": "Z/\"99999999-9999-9999-9999-999999999999\"", "type": "Microsoft.Network/networkInterfaces/ipConfigurations", "properties": { "provisioningState": "Succeeded", "privateIPAddress": "172.20.2.4", "privateIPAllocationMethod": "Dynamic", "publicIPAddress": { "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/publicIPAddresses/test-ip" }, "subnet": { "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/rg1-vnet/subnets/default" }, "primary": false, "privateIPAddressVersion": "IPv4", "isInUseWithService": false } } ], "dnsSettings": { "dnsServers": [ ], "appliedDnsServers": [ ], "internalDomainNameSuffix": "test.bx.internal.cloudapp.net" }, "macAddress": "00-0D-3A-1B-C7-21", "enableAcceleratedNetworking": false, "enableIPForwarding": false, "primary": true, "virtualMachine": { "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Compute/virtualMachines/test-vm-1" } }, "type": "Microsoft.Network/networkInterfaces" } ] } ././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Network_virtualnetworks.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Mic0000664000175000017500000000342413570310635033444 0ustar kamikami00000000000000{ "value": [ { "name": "test_network", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/test_network", "etag": "W/\"99999999-9999-9999-9999-999999999999\"", "type": "Microsoft.Network/virtualNetworks", "location": "westus2", "tags": { "tag_key1": "tag_val1" }, "properties": { "provisioningState": "Succeeded", "resourceGuid": "99999999-9999-9999-9999-999999999999", "addressSpace": { "addressPrefixes": [ "10.39.0.0/16" ] }, "dhcpOptions": { "dnsServers": [ "172.11.111.11", "172.11.111.12", "8.8.8.8", "8.8.4.4" ] }, "subnets": [ { "name": "Azure_VPC_Subnet", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/test_network/subnets/Azure_VPC_Subnet", "etag": "W/\"99999999-9999-9999-9999-999999999990\"", "properties": { "provisioningState": "Succeeded", "addressPrefix": "10.17.26.0/19", "ipConfigurations": [ { "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic/ipConfigurations/ipconfig1" } ], "delegations": [ ] }, "type": "Microsoft.Network/virtualNetworks/subnets" } ], "virtualNetworkPeerings": [ ], "enableDdosProtection": false, "enableVmProtection": false } } ] } ././@LongLink0000000000000000000000000000024000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_disks_test_disk_1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000160213535474530033505 0ustar kamikami00000000000000{ "properties": { "accountType": "Standard_LRS", "osType": "Linux", "creationData": { "createOption": "FromImage", "imageReference": { "id": "/Subscriptions/99999999-9999-9999-9999-999999999999/Providers/Microsoft.Compute/Locations/eastus/Publishers/OpenLogic/ArtifactTypes/VMImage/Offers/CentOS/Skus/7.3/Versions/latest" } }, "diskSizeGB": 31, "timeCreated": "2017-03-09T10:12:37.0256203+00:00", "ownerId": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Compute/virtualMachines/test-vm-1", "provisioningState": "Succeeded", "diskState": "Attached" }, "type": "Microsoft.Compute/disks", "location": "eastus", "tags": {}, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-disk-1", "name": "test-disk-1" }././@LongLink0000000000000000000000000000024400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_snapshots_test_snap_1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000123613535474530033510 0ustar kamikami00000000000000{ "properties": { "accountType": "Standard_LRS", "creationData": { "createOption": "Copy", "sourceUri": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-disk-1" }, "diskSizeGB": 1, "timeCreated": "2017-03-09T14:28:27.8655868+00:00", "provisioningState": "Creating", "diskState": "Unattached" }, "type": "Microsoft.Compute/snapshots", "location": "eastus", "tags": { "test_snap": "test" }, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/snapshots/test-snap-1", "name": "test-snap-1" }././@LongLink0000000000000000000000000000025200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000303213570310635033476 0ustar kamikami00000000000000{ "properties": { "vmId": "99999999-9999-9999-9999-999999999999", "hardwareProfile": { "vmSize": "Standard_A1" }, "storageProfile": { "osDisk": { "osType": "Linux", "name": "OSD-9999", "createOption": "Attach", "caching": "ReadWrite", "managedDisk": { "storageAccountType": "Standard_LRS", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/OSD-9999" } }, "dataDisks": [ { "lun": 0, "name": "DD0-9999", "createOption": "Attach", "caching": "None", "managedDisk": { "storageAccountType": "Standard_LRS", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/DD0-9999" }, "diskSizeGB": 8 } ] }, "networkProfile": { "networkInterfaces": [ { "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/0000/providers/Microsoft.Network/networkInterfaces/test-nic", "properties": { "primary": true } } ] }, "provisioningState": "Succeeded" }, "type": "Microsoft.Compute/virtualMachines", "location": "eastus", "tags": { "tag_key1": "tag_val1" }, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/0000/providers/Microsoft.Compute/virtualMachines/test_vm", "name": "test_vm" } ././@LongLink0000000000000000000000000000026700000000000011222 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_1_InstanceView.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000105713535474530033511 0ustar kamikami00000000000000{ "vmAgent": { "vmAgentVersion": "2.2.5", "statuses": [ { "code": "ProvisioningState/succeeded", "level": "Info", "displayStatus": "Ready", "message": "Guest Agent is running", "time": "2017-03-09T15:11:03+00:00" } ], "extensionHandlers": [] }, "statuses": [ { "code": "ProvisioningState/updating", "level": "Info", "displayStatus": "Updating" }, { "code": "PowerState/running", "level": "Info", "displayStatus": "VM running" } ] }././@LongLink0000000000000000000000000000026000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Network_networkInterfaces_test_node_1_nic.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000272613535474530033515 0ustar kamikami00000000000000{ "name": "test-node-1-nic", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/networkInterfaces/test-node-1-nic", "etag": "W/\"5E19562E-8E84-493D-A29E-A84F5AC21D76\"", "location": "eastus", "tags": {}, "properties": { "provisioningState": "Succeeded", "resourceGuid": "AD512C3D-9A7B-4012-8C5D-227A9EA5E6F4", "ipConfigurations": [ { "name": "myip1", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/networkInterfaces/test-node-1-nic/ipConfigurations/myip1", "etag": "W/\"5E19562E-8E84-493D-A29E-A84F5AC21D76\"", "properties": { "provisioningState": "Succeeded", "privateIPAddress": "10.0.0.1", "privateIPAllocationMethod": "Dynamic", "subnet": { "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/virtualNetworks/000000/subnets/000000" }, "primary": true } } ], "dnsSettings": { "dnsServers": [], "appliedDnsServers": [] }, "macAddress": "11-11-11-11-11-11", "enableIPForwarding": false, "primary": true, "virtualMachine": { "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/virtualMachines/test-node-1" } }, "type": "Microsoft.Network/networkInterfaces" }././@LongLink0000000000000000000000000000022400000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_111111_providers_Microsoft_Compute_disks.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000114413535474530033506 0ustar kamikami00000000000000{ "value": [ { "properties": { "accountType": "Standard_LRS", "osType": "Linux", "creationData": { "createOption": "Empty" }, "diskSizeGB": 10, "timeCreated": "2017-03-09T10:08:42.6418313+00:00", "provisioningState": "Succeeded", "diskState": "Unattached" }, "type": "Microsoft.Compute/disks", "location": "eastus", "tags": {}, "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/disks/test-disk-3", "name": "test-disk-3" } ] }././@LongLink0000000000000000000000000000023000000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_111111_providers_Microsoft_Compute_snapshots.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000260513535474530033511 0ustar kamikami00000000000000{ "value": [ { "properties": { "accountType": "Standard_LRS", "creationData": { "createOption": "Copy", "sourceUri": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/disks/test-disk-3" }, "diskSizeGB": 2, "timeCreated": "2017-02-02T17:52:44.4557501+00:00", "provisioningState": "Failed", "diskState": "Unattached" }, "type": "Microsoft.Compute/snapshots", "location": "eastus", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/snapshots/test-snap-3", "name": "test-snap-3" }, { "properties": { "accountType": "Standard_LRS", "creationData": { "createOption": "Copy", "sourceUri": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/disks/test-disk-4" }, "diskSizeGB": 2, "timeCreated": "2017-02-02T17:52:50.0027361+00:00", "provisioningState": "Failed", "diskState": "Unattached" }, "type": "Microsoft.Compute/snapshots", "location": "eastus", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/111111/providers/Microsoft.Compute/snapshots/test-snap-4", "name": "test-snap-4" } ] }././@LongLink0000000000000000000000000000025200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_networkInterfaces_test_nic.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000351513570310635033504 0ustar kamikami00000000000000{ "name": "test-nic", "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic", "etag": "Z/\"99999999-9999-9999-9999-999999999999\"", "location": "eastus", "tags": { "tag_key1": "tag_val1" }, "properties": { "provisioningState": "Succeeded", "resourceGuid": "99999999-9999-9999-9999-999999999999", "ipConfigurations": [ { "name": "ipconfig1", "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/networkInterfaces/test-nic/ipConfigurations/ipconfig1", "etag": "Z/\"99999999-9999-9999-9999-999999999999\"", "type": "Microsoft.Network/networkInterfaces/ipConfigurations", "properties": { "provisioningState": "Succeeded", "privateIPAddress": "172.20.2.4", "privateIPAllocationMethod": "Dynamic", "publicIPAddress": { "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/publicIPAddresses/test-ip" }, "subnet": { "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Network/virtualNetworks/rg1-vnet/subnets/default" }, "primary": true, "privateIPAddressVersion": "IPv4", "isInUseWithService": false } } ], "dnsSettings": { "dnsServers": [ ], "appliedDnsServers": [ ], "internalDomainNameSuffix": "test.bx.internal.cloudapp.net" }, "macAddress": "00-0D-3A-1B-C7-21", "enableAcceleratedNetworking": false, "enableIPForwarding": false, "primary": true, "virtualMachine": { "id": "/subscriptions/subid/resourceGroups/REVIZOR/providers/Microsoft.Compute/virtualMachines/test-vm-1" } }, "type": "Microsoft.Network/networkInterfaces" } ././@LongLink0000000000000000000000000000026000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_publicIPAddresses_test_public_ip.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000114413570310635033500 0ustar kamikami00000000000000{ "name": "testDNS-ip", "id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/publicIPAddresses/test-ip", "location": "westus", "zones": [ "1" ], "properties": { "provisioningState": "Succeeded", "publicIPAddressVersion": "IPv4", "publicIPAllocationMethod": "Static", "idleTimeoutInMinutes": 10, "ipConfiguration": { "id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.Network/networkInterfaces/testDNS649/ipConfigurations/ipconfig1" } }, "sku": { "name": "Standard" }, "type": "Microsoft.Network/publicIPAddresses" } ././@LongLink0000000000000000000000000000030700000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_REVIZOR_providers_Microsoft_Network_virtualNetworks_test_network_CheckIPAddressAvailability.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroup0000664000175000017500000000023513570310635033500 0ustar kamikami00000000000000{ "available": false, "availableIPAddresses": [ "10.32.36.102", "10.32.36.103", "10.32.36.104", "10.32.36.105", "10.32.36.106" ] } ././@LongLink0000000000000000000000000000024200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_subid_resourceGroups_rg1_providers_Microsoft_Network_publicIPAddresses_test_ip.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/azure_arm/_subscriptions_subid_resourceGroups_r0000664000175000017500000000000313570310635034314 0ustar kamikami00000000000000{} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/0000775000175000017500000000000013600223624024162 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_block_products_json.json0000664000175000017500000000064513535474530031774 0ustar kamikami00000000000000[{"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}, {"cost": 0.25, "id": "b412f354-5056-4bf0-a42f-6ddd998aa092", "description": "Block 2GB Virtual Server"}, {"cost": 0.35, "id": "0cd183d3-0287-4b1a-8288-b3ea8302ed58", "description": "Block 4GB Virtual Server"}, {"cost": 0.45, "id": "b9b87a5b-2885-4a2e-b434-44a163ca6251", "description": "Block 8GB Virtual Server"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_block_templates_json.json0000664000175000017500000000263013535474530032123 0ustar kamikami00000000000000[{"public": true, "id": "c66b8145-f768-45ef-9878-395bf8b1b7ff", "description": "CentOS 5 (Latest Release)", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "1fc24f51-6d7d-4fa9-9a6e-0d6f36b692e2", "description": "Ubuntu 8.10 64bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "b6f152db-988c-4194-b292-d6dd2aa2dbab", "description": "Debian 5.0 64bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "4b697e48-282b-4140-8cf8-142e2a2711ee", "description": "Ubuntu 8.04 LTS 64bit", "created": "2009/07/31 15:58:20 -0700"}, {"public": true, "id": "a6a141bf-592a-4fa6-b130-4c14f69e82d0", "description": "Ubuntu 8.04 LTS 32Bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "b181033f-aea7-4e6c-8bb4-11169775c0f8", "description": "Ubuntu 9.04 64bit", "created": "2010/01/26 11:31:19 -0800"}, {"public": true, "id": "b5371c5a-9da2-43ee-a745-99a4723f624c", "description": "ArchLinux 2009.08 64bit", "created": "2010/02/13 18:07:01 -0800"}, {"public": true, "id": "a00baa8f-b5d0-4815-8238-b471c4c4bf72", "description": "Ubuntu 9.10 64bit", "created": "2010/02/17 22:06:21 -0800"}, {"public": true, "id": "03807e08-a13d-44e4-b011-ebec7ef2c928", "description": "Ubuntu 10.04 LTS 64bit", "created": "2010/05/04 14:43:30 -0700"}, {"public": true, "id": "8b60e6de-7cbc-4c8e-b7df-5e2f9c4ffd6b", "description": "Ubuntu 10.04 LTS 32bit", "created": "2010/05/04 14:43:30 -0700"}] ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94d0000664000175000017500000000061513535474530032366 0ustar kamikami00000000000000{"ips": [{"address": "67.214.214.212"}], "memory": 1073741824, "template": "centos", "id": "99df878c-6e5c-4945-a635-d94da9fd3146", "storage": 21474836480, "hostname": "apitest.c44905.c44905.blueboxgrid.com", "description": "1 GB RAM + 20 GB Disk", "cpu": 0.5, "status": "running", "product": {"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}} ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94d0000664000175000017500000000003413535474530032361 0ustar kamikami00000000000000{"text":"Block destroyed."} ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94d0000664000175000017500000000006013535474530032360 0ustar kamikami00000000000000{ "status": "ok", "text": "Reboot initiated." } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_json.json0000664000175000017500000000035313535474530030230 0ustar kamikami00000000000000[{"ips":[{"address":"67.214.214.212"}],"memory":1073741824,"id":"99df878c-6e5c-4945-a635-d94da9fd3146","storage":21474836480,"hostname":"foo.apitest.blueboxgrid.com","description":"1 GB RAM + 20 GB Disk","cpu":0.5,"status":"running"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/bluebox/api_blocks_json_post.json0000664000175000017500000000053413535474530031276 0ustar kamikami00000000000000{"ips":[{"address":"67.214.214.212"}],"memory":1073741824,"id":"99df878c-6e5c-4945-a635-d94da9fd3146","storage":21474836480,"hostname":"foo.apitest.blueboxgrid.com","description":"1 GB RAM + 20 GB Disk","cpu":0.5,"status":"queued", "product": {"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/0000775000175000017500000000000013600223624024512 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/create_cloud_ip.json0000664000175000017500000000105613535474530030543 0ustar kamikami00000000000000{ "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "id": "cip-jsjc5", "interface": null, "load_balancer": null, "public_ip": "109.107.37.234", "resource_type": "cloud_ip", "reverse_dns": "cip-109-107-37-234.gb1.brightbox.com", "server": null, "server_group": null, "status": "unmapped", "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-jsjc5" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/create_server.json0000664000175000017500000000316613535474530030257 0ustar kamikami00000000000000{"id": "srv-3a97e", "url": "servers/(server_id)", "name": "My web server", "status": "active", "hostname": "srv-3a97e.gb1.brightbox.com", "created_at": "", "deleted_at": "", "started_at": "", "account": {"id": "acc-3jd8s", "url": "accounts/(account_id)", "name": "Brightbox Systems Ltd.", "status": "verified", "ram_limit": 20480, "ram_used": 2048, "limits_cloudips": 5}, "image": {"id": "img-9vxqi", "url": "images/(image_id)", "name": "Brightbox Lucid 32", "status": "available", "description": "Jeremy's debian ec2 image", "source": "jeremy_debian-32_ec2", "source_type": "upload", "arch": "32-bit", "created_at": "", "owner": "acc-bright"}, "server_type": {"id": "typ-a97e6", "url": "server_types/(server_type_id)", "handle": "nano", "name": "Brightbox Nano", "status": "", "cores": 2, "ram": 2048, "disk_size": ""}, "zone": {"id": "zon-8ja0a", "url": "zones/(zone_id)", "handle": "gb1-a"}, "snapshots": [{"id": "img-9vxqi", "url": "images/(image_id)", "name": "Brightbox Lucid 32", "status": "available", "description": "Jeremy's debian ec2 image", "source": "jeremy_debian-32_ec2", "source_type": "upload", "arch": "32-bit", "created_at": "", "owner": "acc-bright"}], "cloud_ips": [{"id": "cip-ja8ub", "url": "cloud_ips/(cloud_ip_id)", "public_ip": "109.107.42.129", "status": "mapped", "reverse_dns": "cip-109-107-42-129.gb1.brightbox.com"}], "interfaces": [{"id": "int-mc3a9", "url": "interfaces/(interface_id)", "mac_address": "02:24:19:6e:18:36", "ipv4_address": "10.110.24.54"}]}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/create_server_gb1_a.json0000664000175000017500000000470013535474530031303 0ustar kamikami00000000000000{ "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "cloud_ips": [], "console_token": null, "console_token_expires": null, "console_url": null, "created_at": "2012-04-12T10:58:49Z", "deleted_at": null, "fqdn": "srv-p61uj.gb1.brightbox.com", "hostname": "srv-p61uj", "id": "srv-p61uj", "image": { "arch": "x86_64", "created_at": "2012-04-11T01:36:19Z", "description": "Standard server with cloud-init", "id": "img-n4yek", "name": "Ubuntu Precise 12.04 LTS server", "owner": "acc-tqs4c", "resource_type": "image", "source": "precise-amd64-17903.gz", "status": "deprecated", "url": "https://api.gb1.brightbox.com/1.0/images/img-n4yek", "username": "ubuntu" }, "interfaces": [ { "id": "int-ctud9", "ipv4_address": "10.240.156.30", "ipv6_address": "2a02:1348:14c:2707:24:19ff:fef0:9c1e", "mac_address": "02:24:19:f0:9c:1e", "resource_type": "interface", "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-ctud9" } ], "name": "Test Node", "resource_type": "server", "server_groups": [ { "created_at": "2011-08-24T08:41:56Z", "default": true, "description": "All new servers are added to this group unless specified otherwise.", "id": "grp-irgkb", "name": "default", "resource_type": "server_group", "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" } ], "server_type": { "cores": 2, "disk_size": 20480, "handle": "nano", "id": "typ-4nssg", "name": "Brightbox Nano Instance", "ram": 512, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-4nssg" }, "snapshots": [], "started_at": null, "status": "creating", "url": "https://api.gb1.brightbox.com/1.0/servers/srv-p61uj", "user_data": null, "zone": { "handle": "gb1-a", "id": "zon-6mxqw", "resource_type": "zone", "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/create_server_gb1_b.json0000664000175000017500000000470113535474530031305 0ustar kamikami00000000000000{ "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "cloud_ips": [], "console_token": null, "console_token_expires": null, "console_url": null, "created_at": "2012-04-12T11:01:51Z", "deleted_at": null, "fqdn": "srv-nnumd.gb1.brightbox.com", "hostname": "srv-nnumd", "id": "srv-nnumd", "image": { "arch": "x86_64", "created_at": "2012-04-11T01:36:19Z", "description": "Standard server with cloud-init", "id": "img-n4yek", "name": "Ubuntu Precise 12.04 LTS server", "owner": "acc-tqs4c", "resource_type": "image", "source": "precise-amd64-17903.gz", "status": "deprecated", "url": "https://api.gb1.brightbox.com/1.0/images/img-n4yek", "username": "ubuntu" }, "interfaces": [ { "id": "int-2chhk", "ipv4_address": "10.232.142.194", "ipv6_address": "2a02:1348:14d:23b0:24:19ff:fee8:8ec2", "mac_address": "02:24:19:e8:8e:c2", "resource_type": "interface", "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-2chhk" } ], "name": "Test Node", "resource_type": "server", "server_groups": [ { "created_at": "2011-08-24T08:41:56Z", "default": true, "description": "All new servers are added to this group unless specified otherwise.", "id": "grp-irgkb", "name": "default", "resource_type": "server_group", "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" } ], "server_type": { "cores": 2, "disk_size": 20480, "handle": "nano", "id": "typ-4nssg", "name": "Brightbox Nano Instance", "ram": 512, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-4nssg" }, "snapshots": [], "started_at": null, "status": "creating", "url": "https://api.gb1.brightbox.com/1.0/servers/srv-nnumd", "user_data": null, "zone": { "handle": "gb1-b", "id": "zon-remk1", "resource_type": "zone", "url": "https://api.gb1.brightbox.com/1.0/zones/zon-remk1" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/list_cloud_ips.json0000664000175000017500000000636013535474530030441 0ustar kamikami00000000000000[ { "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "id": "cip-tlrp3", "interface": null, "load_balancer": null, "public_ip": "109.107.35.16", "resource_type": "cloud_ip", "reverse_dns": "cip-109-107-35-16.gb1.brightbox.com", "server": null, "server_group": null, "status": "unmapped", "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-tlrp3" }, { "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "id": "cip-w8vbt", "interface": null, "load_balancer": null, "public_ip": "109.107.35.76", "resource_type": "cloud_ip", "reverse_dns": "cip-109-107-35-76.gb1.brightbox.com", "server": null, "server_group": null, "status": "unmapped", "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-w8vbt" }, { "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "id": "cip-uswab", "interface": { "id": "int-ztqbx", "ipv4_address": "10.240.228.234", "ipv6_address": "2a02:1348:14c:393a:24:19ff:fef0:e4ea", "mac_address": "02:24:19:f0:e4:ea", "resource_type": "interface", "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-ztqbx" }, "load_balancer": null, "public_ip": "109.107.35.105", "resource_type": "cloud_ip", "reverse_dns": "cip-109-107-35-105.gb1.brightbox.com", "server": { "created_at": "2012-01-30T14:42:28Z", "deleted_at": null, "fqdn": "srv-742vn.gb1.brightbox.com", "hostname": "srv-742vn", "id": "srv-742vn", "name": "Kernel builder", "resource_type": "server", "started_at": "2012-03-28T15:26:43Z", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/servers/srv-742vn" }, "server_group": null, "status": "mapped", "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-uswab" }, { "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "id": "cip-ui4n1", "interface": null, "load_balancer": null, "public_ip": "109.107.37.135", "resource_type": "cloud_ip", "reverse_dns": "cip-109-107-37-135.gb1.brightbox.com", "server": null, "server_group": null, "status": "unmapped", "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-ui4n1" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/list_images.json0000664000175000017500000000562013535474530027723 0ustar kamikami00000000000000[ { "ancestor": { "arch": "i686", "created_at": "2010-10-04T19:03:37Z", "description": "Creates a blank disk", "id": "img-6lybc", "name": "Blank Image", "owner": "acc-tqs4c", "resource_type": "image", "source": "blank_10G", "status": "deleted", "url": "https://api.gb1.brightbox.com/1.0/images/img-6lybc", "username": null }, "arch": "i686", "compatibility_mode": false, "created_at": "2010-10-02T19:03:37Z", "description": "login: root using stored ssh key", "disk_size": 1086, "id": "img-99q79", "min_ram": null, "name": "CentOS 5.5 server", "official": true, "owner": "acc-tqs4c", "public": true, "resource_type": "image", "source": "srv-s4mfq", "source_type": "upload", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/images/img-99q79", "username": null, "virtual_size": 10244 }, { "ancestor": { "arch": "i686", "created_at": "2010-10-04T19:03:37Z", "description": "Creates a blank disk", "id": "img-6lybc", "name": "Blank Image", "owner": "acc-tqs4c", "resource_type": "image", "source": "blank_10G", "status": "deleted", "url": "https://api.gb1.brightbox.com/1.0/images/img-6lybc", "username": null }, "arch": "x86_64", "compatibility_mode": false, "created_at": "2010-10-03T19:03:37Z", "description": "login: root using stored ssh key", "disk_size": 1133, "id": "img-pnqnc", "min_ram": null, "name": "CentOS 5.5 server", "official": true, "owner": "acc-tqs4c", "public": true, "resource_type": "image", "source": "srv-53fez", "source_type": "upload", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/images/img-pnqnc", "username": null, "virtual_size": 10240 }, { "ancestor": null, "arch": "i686", "compatibility_mode": false, "created_at": "2012-01-22T05:36:24Z", "description": "Standard server with cloud-init", "disk_size": 671, "id": "img-joo06", "min_ram": null, "name": "Ubuntu Oneiric 11.10 server", "official": false, "owner": "acc-tqs4c", "public": true, "resource_type": "image", "source": "oneiric-i386-20178.gz", "source_type": "upload", "status": "deprecated", "url": "https://api.gb1.brightbox.com/1.0/images/img-joo06", "username": "ubuntu", "virtual_size": 1025 } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/list_server_types.json0000664000175000017500000000443613535474530031214 0ustar kamikami00000000000000[ { "cores": 2, "disk_size": 20480, "handle": "nano", "id": "typ-4nssg", "name": "Brightbox Nano Instance", "ram": 512, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-4nssg" }, { "cores": 8, "disk_size": 163840, "handle": "medium", "id": "typ-qdiwq", "name": "Brightbox Medium Instance", "ram": 4096, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-qdiwq" }, { "cores": 4, "disk_size": 81920, "handle": "small", "id": "typ-urtky", "name": "Brightbox Small Instance", "ram": 2048, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-urtky" }, { "cores": 8, "disk_size": 327680, "handle": "large", "id": "typ-mlbt7", "name": "Brightbox Large Instance", "ram": 8192, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-mlbt7" }, { "cores": 4, "disk_size": 40960, "handle": "mini", "id": "typ-iqisj", "name": "Brightbox Mini Instance", "ram": 1024, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-iqisj" }, { "cores": 8, "disk_size": 655360, "handle": "xl", "id": "typ-wdicw", "name": "Brightbox XL Instance", "ram": 16384, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-wdicw" }, { "cores": 8, "disk_size": 1310720, "handle": "xxl", "id": "typ-lr76m", "name": "Brightbox XXL Instance", "ram": 32768, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-lr76m" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/list_servers.json0000664000175000017500000001273113535474530030150 0ustar kamikami00000000000000 [ { "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "cloud_ips": [ { "id": "cip-tlrp3", "public_ip": "109.107.35.16", "resource_type": "cloud_ip", "reverse_dns": "cip-109-107-35-16.gb1.brightbox.com", "status": "mapped", "url": "https://api.gb1.brightbox.com/1.0/cloud_ips/cip-tlrp3" } ], "created_at": "2010-10-14T10:02:38Z", "deleted_at": null, "fqdn": "srv-xvpn7.gb1.brightbox.com", "hostname": "srv-xvpn7", "id": "srv-xvpn7", "image": { "arch": "i686", "created_at": "2010-10-11T15:23:51Z", "description": "", "id": "img-arm8f", "name": "Snapshot of srv-vf2a4 11 Oct 15:23", "owner": "acc-tqs4c", "resource_type": "image", "source": "srv-vf2a4", "status": "deleted", "url": "https://api.gb1.brightbox.com/1.0/images/img-arm8f", "username": null }, "interfaces": [ { "id": "int-519up", "ipv4_address": "10.74.210.210", "mac_address": "02:24:19:4a:d2:d2", "resource_type": "interface", "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-519up" } ], "name": "Ubuntu Image Builder Box", "resource_type": "server", "server_groups": [ { "created_at": "2011-08-24T08:41:56Z", "default": true, "description": "All new servers are added to this group unless specified otherwise.", "id": "grp-irgkb", "name": "default", "resource_type": "server_group", "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" } ], "server_type": { "cores": 4, "disk_size": 81920, "handle": "small", "id": "typ-urtky", "name": "Brightbox Small Instance", "ram": 2048, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-urtky" }, "snapshots": [], "started_at": "2012-03-28T15:25:56Z", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/servers/srv-xvpn7", "zone": { "handle": "gb1-a", "id": "zon-6mxqw", "resource_type": "zone", "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" } }, { "account": { "id": "acc-tqs4c", "name": "bbctest", "resource_type": "account", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/account" }, "cloud_ips": [], "created_at": "2012-01-30T14:42:28Z", "deleted_at": null, "fqdn": "srv-742vn.gb1.brightbox.com", "hostname": "srv-742vn", "id": "srv-742vn", "image": { "arch": "x86_64", "created_at": "2012-01-30T13:25:09Z", "description": "", "id": "img-j93gd", "name": "Snapshot of srv-k0pug 30 Jan 13:25", "owner": "acc-tqs4c", "resource_type": "image", "source": "srv-k0pug", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/images/img-j93gd", "username": null }, "interfaces": [ { "id": "int-ztqbx", "ipv4_address": "10.240.228.234", "ipv6_address": "2a02:1348:14c:393a:24:19ff:fef0:e4ea", "mac_address": "02:24:19:f0:e4:ea", "resource_type": "interface", "url": "https://api.gb1.brightbox.com/1.0/interfaces/int-ztqbx" } ], "name": "Kernel builder", "resource_type": "server", "server_groups": [ { "created_at": "2011-08-24T08:41:56Z", "default": true, "description": "All new servers are added to this group unless specified otherwise.", "id": "grp-irgkb", "name": "default", "resource_type": "server_group", "url": "https://api.gb1.brightbox.com/1.0/server_groups/grp-irgkb" } ], "server_type": { "cores": 8, "disk_size": 163840, "handle": "medium", "id": "typ-qdiwq", "name": "Brightbox Medium Instance", "ram": 4096, "resource_type": "server_type", "status": "available", "url": "https://api.gb1.brightbox.com/1.0/server_types/typ-qdiwq" }, "snapshots": [], "started_at": "2012-03-28T15:26:43Z", "status": "active", "url": "https://api.gb1.brightbox.com/1.0/servers/srv-742vn", "zone": { "handle": "gb1-a", "id": "zon-6mxqw", "resource_type": "zone", "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" } } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/list_zones.json0000664000175000017500000000053013535474530027607 0ustar kamikami00000000000000[ { "handle": "gb1-a", "id": "zon-6mxqw", "resource_type": "zone", "url": "https://api.gb1.brightbox.com/1.0/zones/zon-6mxqw" }, { "handle": "gb1-b", "id": "zon-remk1", "resource_type": "zone", "url": "https://api.gb1.brightbox.com/1.0/zones/zon-remk1" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/brightbox/token.json0000664000175000017500000000010713535474530026536 0ustar kamikami00000000000000{"access_token":"k1bjflpsaj8wnrbrwzad0eqo36nxiha", "expires_in": 3600} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudscale/0000775000175000017500000000000013600223624024640 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudscale/create_node.json0000664000175000017500000000202713535474530030017 0ustar kamikami00000000000000{ "href": "https://api.cloudscale.ch/v1/servers/47cec963-fcd2-482f-bdb6-24461b2d47b1", "uuid": "47cec963-fcd2-482f-bdb6-24461b2d47b1", "name": "db-master", "status": "changing", "flavor": { "slug": "flex-4", "name": "Flex-4", "vcpu_count": 2, "memory_gb": 4 }, "image": { "slug": "debian-8", "name": "Debian 8 (2016-10-20)", "operating_system": "Debian" }, "volumes": [ { "type": "ssd", "device_path": "", "size_gb": 50 } ], "interfaces": [ { "type": "public", "addresses": [ { "version": 4, "address": "185.98.122.176", "prefix_length": 24, "gateway": "185.98.122.1", "reverse_ptr": "185-98-122-176.cust.cloudscale.ch" }, { "version": 6, "address": "2a06:c01:1:1902::7ab0:176", "prefix_length": 64, "gateway": "fe80::1", "reverse_ptr": "185-98-122-176.cust.cloudscale.ch" } ] } ], "anti_affinity_with": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudscale/list_images.json0000664000175000017500000000013113535474530030041 0ustar kamikami00000000000000[{"slug":"ubuntu-16.10","name":"Ubuntu 16.10 (2016-10-17)","operating_system":"Ubuntu"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudscale/list_nodes.json0000664000175000017500000000217613535474530027717 0ustar kamikami00000000000000[ { "href": "https://api.cloudscale.ch/v1/servers/47cec963-fcd2-482f-bdb6-24461b2d47b1", "uuid": "47cec963-fcd2-482f-bdb6-24461b2d47b1", "name": "db-master", "status": "running", "flavor": { "slug": "flex-4", "name": "Flex-4", "vcpu_count": 2, "memory_gb": 4 }, "image": { "slug": "debian-8", "name": "Debian 8 (2016-10-20)", "operating_system": "Debian" }, "volumes": [ { "type": "ssd", "device_path": "/dev/vda", "size_gb": 50 } ], "interfaces": [ { "type": "public", "addresses": [ { "version": 4, "address": "185.98.122.176", "prefix_length": 24, "gateway": "185.98.122.1", "reverse_ptr": "185-98-122-176.cust.cloudscale.ch" }, { "version": 6, "address": "2a06:c01:1:1902::7ab0:176", "prefix_length": 64, "gateway": "fe80::1", "reverse_ptr": "185-98-122-176.cust.cloudscale.ch" } ] } ], "anti_affinity_with": [] } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudscale/list_sizes.json0000664000175000017500000000020313535474530027731 0ustar kamikami00000000000000[{"slug":"flex-2","name":"Flex-2","vcpu_count":1,"memory_gb":2}, {"slug":"flex-4","name":"Flex-4","vcpu_count":2,"memory_gb": 4}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/0000775000175000017500000000000013600223624024651 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/drives_clone.txt0000664000175000017500000001335613535474530030111 0ustar kamikami00000000000000status active use dbserver,general name SQL Server Standard 2008 R2 - Windows Server Standard 2008 R2 - 64bit English pub clone bits 64 url http://www.microsoft.com/sqlserver/2008/en/us/ read:bytes 4096 description Please refer to the install notes for a full guide to initial configuration. write:bytes 21474840576 drive a814def5-1789-49a0-bf88-7abe7bb1682a install_notes ***You must update the default Administrator password for Windows Server Standard 2008 and the Super Administrator password (sa) for SQL Server Standard 2008***\n\nPre-installed Windows Server 2008 Standard R2 64bit English on 15/07/2010\n=========================================================================\n\n1. Minimum Hardware Requirements\n--------------------------------\n\nThe recommended minimum hardware requirements for the use of SQL Server Standard 2008 R2 with Windows Server Standard 2008 R2 as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/library/ms143506.aspx\n\n\n2. Update your administrator password\n-------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n3. Expanding your drive\n-----------------------\n\nThe system is fully installed, but you will need to extend the\ndisk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n4. Enabling Remote Access\n-------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection according to your Security Configuration\n\n\n5. Pinging Service\n------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules"\n\n\nSQL Server 2008 R2 on 15/07/2010\n================================\n\n1. Change the Super Administrator Password (sa). \n--------------------------------------------------------------------\n\nThe default password has been set to "CloudSigma1"\n\na) Open "Microsoft SQL Server Management Studio"\n\nb) Connect to the Server Using "Windows Indentificaiton"\n\nc) From the Object Explorer select "Security" then "Longins"\n\nd) Right-click on sa and select "Properties"\n\ne) Enter the new password into "Password" and "Confirm Password" and press "OK"\n\n\n2. The following features were installed:\n-----------------------------------------------------\n\na) Main features\n\n-Database Engine Services\n-SQL Server Replication\n-Full-Text Search\n-Analysis Services\n-Reporting Services\n\nb) Shared Features\n\n-Business Intelligengce Development Studio\n-Client Tools Connectivity\n-Integration Services\n-Clinet Tools Backwards Compatibility\n-Clinet Tools SDK\n-SQL Server Books Online\n-Mangement Tools - Basic\n-Management Tools - Complete\n-SQL Client Connectivity SDK\n-Microsoft Sync Framework\n\n3 The following services were configured:\n--------------------------------------------------------\n\n\nService: SQL Server Agent\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Manual\n\nService: SQL Server Database Engine\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Automatic\n\nService: SQL Server Analysis Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Reporting Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Integration Services 10.1\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n \nService: SQL Full-text filter Daemon Lanuch\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nService: SQL Server Browser\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nFor detailed server installation configuration refer to the following installation log files on the system:\nC:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20100716_162426\Summary_WIN-K0F21FV1C1V_20100716_162426.txt\n volume 000431a5-46d9-4a67-9c03-3c3402a41992 host 00043e69-ac57-45b1-8692-75db24064fb9 os windows user 93b34fd9-7986-4b25-8bfd-98a50383605d read:requests 1 licenses msft_p73_04837 msft_tfa_00009 type disk write:requests 5242881 size 21474836480 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/drives_info.txt0000664000175000017500000002012013535474530027727 0ustar kamikami00000000000000status active use general name test node bits 64 url http://www.centos.org/ read:bytes 4096 description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. write:bytes 21474840576 os linux drive 3d18db4b-f9bd-4313-b034-12ae181efa88 install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 1 free true type disk write:requests 5242881 size 53687091200 status active use general name test node bits 64 url http://www.centos.org/ read:bytes 4096 description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. write:bytes 21474840576 os linux drive 3d18db4b-f9bd-4313-b034-12ae181efa99 install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 1 free true type disk write:requests 5242881 size 103687091200 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/drives_single_info.txt0000664000175000017500000001004713535474530031277 0ustar kamikami00000000000000status active use general name test node bits 64 url http://www.centos.org/ read:bytes 4096 description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. write:bytes 21474840576 os linux drive d18119ce_7afa_474a_9242_e0384b160220 install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 1 free true type disk write:requests 5242881 size 53687091200 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/drives_standard_info.txt0000664000175000017500000042054113535474530031622 0ustar kamikami00000000000000type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Yoper is a multipurpose high performance operating system which has been carefully optimised for PC's with either 686 or higher processor types. The binaries that come with Yoper have been built from scratch using the original sources combined with the best features of major distros, measuring up to the demanding proliferation of network communications and more intensive digital multimedia, graphics and audio capabilities which are ushering in a new era of business productivity enabled by a new generation of sophisticated microprocessors, and business application tools. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 102401 name Yoper 2010 Linux with XFCE Install CD url http://yoper-linux.org/ read:bytes 4096 claim:type shared drive 7e3e7628-d1e6-47c6-858d-7b54aac5c916 write:bytes 419434496 read:requests 1 os linux type cdrom size 2621440000 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description Ultimate Edition, first released in December 2006, is a fork of Ubuntu. The goal of the project is to create a complete, seamlessly integrated, visually stimulating, and easy-to-install operating system. Single-button upgrade is one of several special characteristics of this distribution. Other main features include custom desktop and theme with 3D effects, support for a wide range of networking options, including WiFi and Bluetooth, and integration of many extra applications and package repositories. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 640001 name Ultimate 2.6 Linux 64bit Install CD url http://ultimateedition.info/ read:bytes 440279040 claim:type shared drive 526ed5cb-6fbe-46fb-a064-7707c844d774 write:bytes 2621444096 read:requests 107490 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description FreeBSD is a UN*X-like operating system for the i386, IA-64, PC-98, Alpha/AXP, and UltraSPARC platforms based on U.C. Berkeley's "4.4BSD-Lite" release, with some "4.4BSD-Lite2" enhancements. It is also based indirectly on William Jolitz's port of U.C. Berkeley's "Net/2" to the i386, known as "386BSD", though very little of the 386BSD code remains. FreeBSD is used by companies, Internet Service Providers, researchers, computer professionals, students and home users all over the world in their work, education and recreation. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 168961 name FreeBSD 8.0 Linux 64bit Install CD url http://www.freebsd.org/ read:bytes 479866880 claim:type shared drive 95380e4c-4f69-432d-be2b-1965a282bdb9 write:bytes 692064256 read:requests 117155 os other type cdrom size 218103808 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description The Fedora 13 x86_64 (64bit) network installation CD favourite true install_notes The Fedora 13 network installaton cd will install, through the network, the latest Fedora packages; since it includes the "updates" repo.\n\nThe minimal install option offers great ground to build on top of a very nice base. This configuration is recommended for most servers.\n\nBuild your own and share them wth us! volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 53249 name Fedora 13 Linux x86 64bit netinst Install CD url http://fedoraproject.org/ read:bytes 1444963840 claim:type shared drive 14b1e97f-5bba-4cf1-aec4-7b7b573826c2 write:bytes 218107904 read:requests 352119 os linux type cdrom size 452984832 use security readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description The Untangle Lite package offers a collection of free, open-source software applications to run on the Untangle Server. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server.\n volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 110593 name Untangle 7.4 Linux 64bit Install CD url http://www.untangle.com/ read:bytes 4096 claim:type shared drive 06c39099-9f75-40f4-b2e1-6012c87f3579 write:bytes 452988928 read:requests 1 os linux type cdrom size 138412032 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type preinstalled status active description Puppy Linux is extraordinarily small, yet quite full featured. Puppy boots into a 64MB ramdisk, and that's it, the whole caboodle runs in RAM. Unlike live CD distributions that have to keep pulling stuff off the CD, Puppy in its entirety loads into RAM. This means that all applications start in the blink of an eye and respond to user input instantly. Puppy Linux has the ability to boot off a flash card or any USB memory device, CDROM, Zip disk or LS/120/240 Superdisk, floppy disks, internal hard drive. It can even use a multisession formatted CD-R/DVD-R to save everything back to the CD/DVD with no hard drive required at all! favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 33793 name Puppy 5.1 Linux Install CD url www.puppylinux.org read:bytes 276828160 claim:type shared drive 60111502-6ff3-43e1-9485-5be775f81657 write:bytes 138416128 read:requests 67585 os linux type cdrom size 171966464 use router,general,networking readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type preinstalled status active description Vyatta project is a Linux-based router and firewall offering a free community edition and two commercial editions with support. Vyatta has changed the networking world by developing the first commercially supported, open-source router & firewall solution. Vyatta combines the features, performance and reliability of an enterprise router & firewall with the cost savings, flexibility and security of open source. favourite true install_notes \nCD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 41985 name Vyatta 6.1 Live CD url www.yyatta.com read:bytes 687869952 claim:type shared drive 8159ab9b-9703-48f6-a206-ac26efe8fdc2 write:bytes 171970560 read:requests 167937 os linux type cdrom size 721420288 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description ZenLive Linux is a live cd derived from Zenwalk distribution. Zenwalk Linux (formerly Minislack) is a Slackware-based Linux distribution with focus on Internet applications, multimedia and programming tools. ZenLive Linux LiveCD is a complete system with software for Internet browsing, mail, chat, multimedia and office, as well as for programming in C, Perl, Python and Ruby. The main objectives of Zenwalk Linux are to be simple and fast, provide one application per task, be a complete development and desktop environment and to be small enough to fit on a 400MB ISO image. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 176129 name Zenlive 6.4 Linux Install CD url http://www.zenwalk.org/ read:bytes 721424384 claim:type shared drive fcc2aa68-24ce-438e-8386-1d4e66336155 write:bytes 721424384 read:requests 176129 os linux type cdrom claimed 00059836-5512-4ce2-bf66-4daab2d994e4:guest:2e82c87e-61a1-443c-bc81-5c3167df5c11:ide:0:0 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:3234b1fc-415f-4019-ada1-27781aea8750:ide:0:0 size 4198498304 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description CentOS as a group is a community of open source contributors and users. Typical CentOS users are organisations and individuals that do not need strong commercial support in order to achieve successful operation. CentOS is 100% compatible rebuild of the Red Hat Enterprise Linux, in full compliance with Red Hat's redistribution requirements. CentOS is for people who need an enterprise class operating system stability without the cost of certification and support. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 1025025 name CentOS 5.5 Linux 32bit Install DVD url http://www.centos.org read:bytes 16706375680 claim:type shared drive 6e0e2282-c29a-4d19-97e6-7ddb7cdf0dd2 write:bytes 4198502400 read:requests 4078705 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd,livecd status active description Ubuntu is a complete desktop Linux operating system, freely available with both community and professional support. The Ubuntu community is built on the ideas enshrined in the Ubuntu Manifesto: that software should be available free of charge, that software tools should be usable by people in their local language and despite any disabilities, and that people should have the freedom to customise and alter their software in whatever way they see fit."Ubuntu&quot; is an ancient African word, meaning"humanity to others&quot;. The Ubuntu distribution brings the spirit of Ubuntu to the software world. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 179201 name Ubuntu 10.04 Linux 32bit Install CD url http://www.ubuntu.com/ read:bytes 1298436608 claim:type shared drive 0e305bb9-f512-4d4a-894c-4a733cae570f write:bytes 734007296 read:requests 295036 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd,livecd status active description Chakra is a user-friendly and powerful distribution and live CD based on Arch Linux. It features a graphical installer, automatic hardware detection and configuration, the latest KDE desktop, and a variety of tools and extras. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 204801 name Chakra Alpha 5 Linux 64bit Install and Live CD url http://chakra-project.org/ read:bytes 185200640 claim:type shared drive c0856590-c2b1-4725-9448-bba7c74d35dc write:bytes 838864896 read:requests 45215 os linux type cdrom claimed 00043e69-ac57-45b1-8692-75db24064fb9:guest:4c014a4e-615e-489e-b22a-bf966bce83d7:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:0a9d4833-fc5f-4825-9626-5a3e6555d329:ide:0:0 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:71d09667-fd6b-491a-949f-6a7ab9c70907:ide:0:0 0008d252-5102-43a0-82c6-18e8e2dd2bff:guest:c8264872-67a1-4452-a736-8dc6ef9eb07d:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:6efe92c3-0126-4ddb-9140-73706c804c3b:ide:0:0 000932a7-c74f-4de3-bfc4-227435f78998:guest:158c515f-1649-44f0-895c-f0de39575a1c:ide:0:0 00079b57-1b29-4a89-a8d0-1d648fc20804:guest:7d62f26e-2062-469e-846a-b926dffb00b1:ide:0:0 size 4697620480 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description - favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 1146881 name Debian Linux 5.0 Install CD url http://www.debian.org/ read:bytes 4612921344 claim:type shared drive 794a068d-228c-4758-81f0-e1bc955a6cce write:bytes 4697624576 read:requests 985768 os linux type cdrom size 2751463424 use dev,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type livecd status active description Scientific Linux is a recompiled Red Hat Enterprise Linux put together by various labs and universities around the world. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 674125 name Scientific Linux 5.5 64bit Live CD url https://www.scientificlinux.org/ read:bytes 10903552 claim:type shared drive 7aa74ca3-4c64-4b08-9972-eddeb38a650d write:bytes 2761216000 read:requests 2662 os linux type cdrom size 612368384 use networking,other readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description Nexenta OS is a free and open source operating system combining the OpenSolaris kernel with GNU application userland. Nexenta OS runs on Intel/AMD 32-/64-bit hardware and is distributed as a single installable CD. Upgrades and binary packages not included on the CD can be installed from Nexenta OS repository using Advanced Packaging Tool. In addition, source based software components can be downloaded from network repositories available at Debian/GNU Linux and Ubuntu Linux. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 149357 name NexentaStor 3.0.3 Linux 32bit/64bit Install CD url http://www.nexenta.org/ read:bytes 2822144 claim:type shared drive 2c3369a5-22eb-4462-8137-35a62b7a93cf write:bytes 611766272 read:requests 689 os other type cdrom size 301989888 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Zenwalk Linux (formerly Minislack) is a Slackware-based GNU/Linux operating system with a goal of being slim and fast by using only one application per task and with focus on graphical desktop and multimedia usage. Zenwalk features the latest Linux technology along with a complete programming environment and libraries to provide an ideal platform for application programmers. Zenwalk's modular approach also provides a simple way to convert Zenwalk Linux into a finely-tuned modern server (e.g. LAMP, messaging, file sharing). favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 73342 name Zenwalk Core 6.4 Install CD url http://yoper-linux.org/ read:bytes 1576960 claim:type shared drive 3d58f1c6-9ec4-4963-917e-9917d39e5003 write:bytes 300408832 read:requests 385 os linux type cdrom size 67108864 use general,security readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type preinstalled status active description IPFire is a linux-distribution that focusses on easy setup, good handling and a high niveau of security. It is operable via an intuitive webinterface, which offers a lot of playground for beginners and even experienced administrators. IPFire is maintained by experienced developers, who are really concerned about security and regulary updates to keep it secure. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 16385 name IPFire 2.7 Core 40 Linux 32bit Install CD url http://www.ipfire.org/ read:bytes 4096 claim:type shared drive 231aa9af-f2ef-407c-9374-76a1215b94d3 write:bytes 67112960 read:requests 1 os linux type cdrom size 734003200 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Legacy OS (formerly TEENpup Linux) is a distribution based on Puppy Linux. Although the original concept was to create a flavour of Puppy Linux with more applications and a more appealing desktop aimed at teenage users, Legacy OS has now grown to become a general purpose distribution. It comes with a large number of applications, browser plugins and media codecs as standard software. Despite these enhancements Legacy OS is still perfectly suitable for installation on older and low-resource computers, as well as modern hardware. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 179201 name Legacy OS Linux 32bit Install CD url http://pupweb.org/wikka/TeenPup read:bytes 4096 claim:type shared drive 39f24226-dc6c-40e2-abc8-e8f2da976671 write:bytes 734007296 read:requests 1 os linux type cdrom size 209715200 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description Yohsuke Ooi has announced the release of Momonga Linux 7, a Japanese community distribution loosely modelled on Fedora. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 51201 name Momonga 7 Linux 64bit Net Install CD url http://www.momonga-linux.org/ read:bytes 4096 claim:type shared drive f424888b-e66e-43f4-99c1-2991a5b82894 write:bytes 209719296 read:requests 1 os linux type cdrom size 713031680 use general,security,systemrecovery readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type livecd status active description CAINE (Computer Aided INvestigative Environment) is an Ubuntu-based GNU/Linux live distribution created as a project of Digital Forensics for Interdepartmental Centre for Research on Security (CRIS), supported by the University of Modena and Reggio Emilia in Italy. The CAINE forensic framework contains a collection of tools wrapped up into a user-friendly environment. It introduces novel features - it aims to fill the interoperability gap across different forensic tools, it provides a homogeneous GUI that guides digital investigators during the acquisition and analysis of electronic evidence, and it offers a semi-automatic process for the documentation and report compilation. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 174081 name Caine 2.0 Linux 32bit Live CD url http://www.caine-live.net/ read:bytes 4096 claim:type shared drive 9768a0d1-e90c-44eb-8da7-06bca057cb93 write:bytes 713035776 read:requests 1 os linux type cdrom size 708837376 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Kongoni GNU/Linux is a Slackware-based, desktop-oriented GNU/Linux distribution and live CD. Its main features include a graphical installer, a Kongoni Integrated Setup System (KISS), and an easy-to-use Ports Installation GUI (PIG). The distribution's package management borrows its main concepts from BSD ports, with an intuitive graphical package installer that compiles and installs programs from source code on the user's system. Kongoni, which means gnu (also known as wildebeest) in Shona, includes only software that complies with Free Software Foundation's definition of software freedom. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 173057 name Kongoni 1.12.3 Linux 32bit Live CD url http://www.kongoni.org/ read:bytes 4096 claim:type shared drive 6ac51b9d-a1db-44fc-b325-30bdefd0dd0a write:bytes 708841472 read:requests 1 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type livecd status active description Debris Linux is a minimalist, desktop-oriented distribution and live CD based on Ubuntu. It includes the GNOME desktop and a small set of popular desktop applications, such as GNOME Office, Firefox web browser, Pidgin instant messenger, and ufw firewall manager. Debris Linux ships with a custom kernel, a custom system installer called DebI, and a script that makes it easy to save and restore any customisations made while in live mode. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Debris 2.0 Linux Live CD url http://debrislinux.org/ read:bytes 0 claim:type shared drive 258e1026-36bf-4368-ba7c-52836de4f757 write:bytes 0 read:requests 0 os linux type cdrom size 1887436800 use systemrecovery,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type livecd status active description Toorox is a Linux Live-DVD based on Gentoo that starts as a bootable media using KNOPPIX technology. While the system is booting, all necessary drivers will be included automatically (lshwd). Toorox is only using the memory and an existing swap partition at runtime, so your hard disks won't be touched by default. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server.\n volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Toorox 05.2010 Linux 64bit Live CD url http://toorox.de/ read:bytes 0 claim:type shared drive 8fa3bc29-47e8-496a-89c6-02872a0d2642 write:bytes 0 read:requests 0 os linux type cdrom size 2516582400 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description FreeBSD is a UN*X-like operating system for the i386, IA-64, PC-98, Alpha/AXP, and UltraSPARC platforms based on U.C. Berkeley's"4.4BSD-Lite&quot; release, with some"4.4BSD-Lite2&quot; enhancements. It is also based indirectly on William Jolitz's port of U.C. Berkeley's"Net/2&quot; to the i386, known as"386BSD&quot;, though very little of the 386BSD code remains. FreeBSD is used by companies, Internet Service Providers, researchers, computer professionals, students and home users all over the world in their work, education and recreation. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name FreeBSD 7.3 Linux 64bit Install CD url http://www.freebsd.org/ read:bytes 13836288 claim:type shared drive 92444414-dc65-451d-9018-2b1ab8db4ceb write:bytes 0 read:requests 3378 os other type cdrom size 1073741824 use systemrecovery,security readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd,livecd status active description KANOTIX is a Linux distribution based on the latest stable release of Debian GNU/Linux. It is built on top of a latest kernel which is carefully patched with fixes and drivers for most modern hardware. Although it can be used as a live CD, it also includes a graphical installer for hard disk installation. The user-friendly nature of the distribution is further enhanced by a custom-built control centre and specialist scripts. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Kanotix 4-2.6 Linux with KDE 64bit Install and Live CD url http://www.kanotix.com/ read:bytes 232169472 claim:type shared drive c7c33c07-5e28-42c8-9800-eb40e2aef287 write:bytes 0 read:requests 56682 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description TinyMe is a Unity Linux-based mini-distribution. It exists to ease installation of Unity Linux on older computers, to provide a minimal installation for developers, and to deliver a fast Linux installation for where only the bare essentials are needed. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name TinyMe 2010 Linux Install CD url http://tinymelinux.com/ read:bytes 0 claim:type shared drive 87b3f98c-c95c-454d-a002-bef63f5bbc1a write:bytes 0 read:requests 0 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description moonOS is a complete, Ubuntu-based distribution featuring the LXDE and Enlightenment 17 desktop managers and imaginative, original artwork. A project created and designed by Cambodian artist Chanrithy Thim, moonOS is intended as an operating system for any desktop, laptop or virtual machine. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name MoonOS 3 Linux 32bit Install CD url http://www.moonos.org/ read:bytes 0 claim:type shared drive d2651d5b-3760-41be-a8b0-6fe5ca208825 write:bytes 0 read:requests 0 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description - favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Yoper 2010 Linux with KDE3 Install CD url http://yoper-linux.org/ read:bytes 0 claim:type shared drive 50e0ca32-c04a-47e3-be37-1cd6f0ad9ff8 write:bytes 0 read:requests 0 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Easy Peasy is an Ubuntu based operating system for netbooks. It's optimized for netbooks and favors the best software available by delivering Firefox with Flash and Java, Skype, Google Picasa, Songbird etc. out of the box. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name EasyPeasy 1.6 Linux Install CD url http://www.geteasypeasy.com/ read:bytes 195153920 claim:type shared drive daac6531-8f59-4c96-baa0-6545350d5a5e write:bytes 0 read:requests 47645 os linux type cdrom size 1572864000 use email,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description Calculate Linux is a Gentoo-based family of three distinguished distributions. Calculate Directory Server (CDS) is a solution that supports Windows and Linux clients via LDAP + SAMBA, providing proxy, mail and Jabbers servers with streamlined user management. Calculate Linux Desktop (CLD) is a workstation and client distribution with KDE, GNOME or Xfce desktop that includes a wizard to configure a connection to Calculate Directory Server. Calculate Linux Scratch (CLS) is live CD with a build framework for creating a custom distribution. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Calculate 10.4 Linux 64bit Install CD url http://www.calculate-linux.org/ read:bytes 16932864 claim:type shared drive 20f5b0dd-5c63-40aa-97b8-5b34e5107a25 write:bytes 0 read:requests 4134 os linux type cdrom size 734003200 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description KahelOS is a Linux distribution based on Arch Linux. Its desktop edition comes with pre-configured GNOME as the default desktop environment, GNOME Office productivity suite, Epiphany web browser, GIMP image manipulation program, and other popular GTK+ and GNOME applications. Like Arch Linux, KahelOS maintains a rolling-release model of updating software packages using its parent's repositories. A server edition is also available. Both the desktop and server editions come in the form of installation CDs with text-based installers, but no live media. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name KahelOS 05-01-2010 Linux 64bit Install CD url http://www.kahelos.org/ read:bytes 0 claim:type shared drive 1ddaedbf-ceb8-43b5-a587-e9e635d97f50 write:bytes 0 read:requests 0 os linux type cdrom size 524288000 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd,livecd status active description PCLinuxOS is a user-friendly, Mandriva-based Linux distribution with out-of-the-box support for many popular graphics and sound cards, as well as other peripheral devices. The bootable live CD provides an easy-to-use graphical installer and the distribution sports a wide range of popular applications for the typical desktop user, including browser plugins and full multimedia playback. The intuitive system configuration tools include Synaptic for package management, Addlocale to add support to many languages, Getopenoffice to install the latest OpenOffice.org, and Mylivecd to create a customised live CD. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name PCLinuxOS 2010.1 Linux with KDE Install and Live CD url http://www.pc-os.org/ read:bytes 0 claim:type shared drive 3e0f427e-10eb-4277-bc3b-48f054908a09 write:bytes 0 read:requests 0 os linux type cdrom size 524288000 use multimedia,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type livecd status active description Peppermint was designed for enhanced mobility, efficiency and ease of use. While other operating systems are taking 10 minutes to load, you are already connected, communicating and getting things done. And, unlike other operating systems, Peppermint is ready to use out of the box. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Peppermint 1.0 Linux Live CD url http://peppermintos.com/ read:bytes 0 claim:type shared drive 92ffa2f6-f663-49d9-98ec-dc0b474369c4 write:bytes 0 read:requests 0 os linux type cdrom size 419430400 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type livecd status active description PureOS and PureOSlight are GNU/Linux live CDs based on Debian's testing repository. These are desktop distributions that can be used as live media (CD or USB) or as full-featured operating systems installed on a hard disk. PureOS is a 700 MB live CD with KDE, Iceweasel, Icedove, OpenOffice.org, Songbird, VLC and K3B. PureOSlight is a small 300 MB live CD with Xfce, Iceweasel, Icedove, AbiWord, Gnumeric and Exaile. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name PureOS 2.0 Linux Live CD url http://www.pureos.org/ read:bytes 100663296 claim:type shared drive ed6421b5-41c2-4ba3-a3c9-7c330d36e5b3 write:bytes 0 read:requests 24576 os linux type cdrom size 104857600 use dev,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description ReactOS® is a free, modern operating system based on the design of Windows® XP/2003. Written completely from scratch, it aims to follow the Windows-NT® architecture designed by Microsoft from the hardware level right through to the application level. This is not a Linux based system, and shares none of the unix architecture. The main goal of the ReactOS project is to provide an operating system which is binary compatible with Windows. This will allow your Windows applications and drivers to run as they would on your Windows system. Additionally, the look and feel of the Windows operating system is used, such that people accustomed to the familiar user interface of Windows® would find using ReactOS straightforward. The ultimate goal of ReactOS is to allow you to remove Windows® and install ReactOS without the end user noticing the change. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name ReactOS 0.3.11 Alpha Install CD url http://www.reactos.org/ read:bytes 0 claim:type shared drive 327fd7dd-a2ca-4437-b87e-7610fccc3202 write:bytes 0 read:requests 0 os other type cdrom size 1887436800 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Ubuntu Studio is a variant of Ubuntu aimed at the GNU/Linux audio, video and graphic enthusiast as well as professional. The distribution provides a collection of open-source applications available for multimedia creation. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Ubuntu Studio 10.04 Linux 32bit Install CD url http://www.ubuntu.com/ read:bytes 499675136 claim:type shared drive c6a368d1-cae6-43d9-8af6-b42142aed4b9 write:bytes 0 read:requests 121991 os linux type cdrom size 1073741824 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff bits 32 drive_type livecd status active description Vector Linux is a small, fast, Intel based Linux operating system for PC style computers. The creators of Vector Linux had a single credo: keep it simple, keep it small and let the end user decide what their operating system is going to be. What has evolved from this concept is perhaps the best little Linux operating system available anywhere. For the casual computer user you have a lightening fast desktop with graphical programs to handle your daily activities from web surfing, sending and receiving email, chatting on ICQ or IRC to running an ftp server. The power user will be pleased because all the tools are there to compile their own programs, use the system as a server or perhaps the gateway for their home or office computer network. Administrators will be equally as pleased because the small size and memory requirements of the operating system can be deployed on older machines maybe long forgotten. favourite true free true volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Vector 6.0 Linux with KDE Live CD url http://www.vectorlinux.com/ read:bytes 0 claim:type shared drive 0aa0b75d-ce40-4877-9882-8a81443911fe write:bytes 0 read:requests 0 os linux type cdrom size 713031680 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Greenie Linux is an Ubuntu-based distribution customised for Slovak and Czech users. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Greenie 7 Linux 32bit Install CD url http://www.greenie.sk/ read:bytes 0 claim:type shared drive bdddc973-e84f-4cbc-a2c9-a9fce73bc462 write:bytes 0 read:requests 0 os linux type cdrom size 67108864 use networking,gateway readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd,livecd status active description pfSense is a free, open source customized distribution of FreeBSD tailored for use as a firewall and router. In addition to being a powerful, flexible firewalling and routing platform, it includes a long list of related features and a package system allowing further expandability without adding bloat and potential security vulnerabilities to the base distribution. pfSense is a popular project with more than 1 million downloads since its inception, and proven in countless installations ranging from small home networks protecting a PC and an Xbox to large corporations, universities and other organizations protecting thousands of network devices.  favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name PfSense 1.2.3 Linux 32bit Live and Install CD url http://www.pfsense.org read:bytes 68657152 claim:type shared drive db46ea0d-26f3-4cd0-8a55-54da2af10363 write:bytes 0 read:requests 16762 os linux type cdrom size 46137344 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type installcd status active description Mandrake Linux was created in 1998 with the goal of making Linux easier to use for everyone. At that time, Linux was already well-known as a powerful and stable operating system that demanded strong technical knowledge and extensive use of the "command line"; MandrakeSoft saw this as an opportunity to integrate the best graphical desktop environments and contribute its own graphical configuration utilities and quickly became famous for setting the standard in ease-of-use and functionality. Mandriva Linux, formerly known as Mandrakelinux, is a friendly Linux Operating System which specializes in ease-of-use for both servers and the home/office. It is freely available in many languages throughout the world. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Mandriva Spring 2010 Linux 64bit Net Install CD url http://mandriva.com/ read:bytes 19488768 claim:type shared drive 857456e4-e16c-4a6f-9bfc-f5be3e58bde5 write:bytes 0 read:requests 4758 os linux type cdrom size 1606418432 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description UHU-Linux is the leading distribution of Linux in Hungary. It is primarily intended for Hungarian users, thus special care is taken to support the Hungarian language as much as possible. Ease of installation and sane default settings both help new users of Linux and make veterans feel comfortable. Usability as the main goal involves having all the cutting-edge yet stable releases of Open Source packages, with dpkg as the package manager. Development is completely open and everyone is invited to join. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 392193 name Uhu Linux 2.2 32bit Install CD url http://uhulinux.hu/ read:bytes 354873344 claim:type shared drive 9d99705b-818a-49f8-8c77-0cd4a42cdea6 write:bytes 1606422528 read:requests 86639 os linux type cdrom size 734003200 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description Chakra, a fast, user-friendly and extremely powerful Live CD and/or distrolet based on the award winning KDE Software Compilation and on the GNU/Linux distribution for connoisseurs: Arch Linux. Currently in alpha stage, it features a graphical installer, automatic hardware configuration, and of course some more tools and extras. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. volume 00106cda-0e17-40c8-a576-b516f0eb67bc host 00109617-2c6b-424b-9cfa-5b572c17bafe user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 179201 name Chakra 2.0 Linux Live CD url http://www.chakra-project.org/ read:bytes 4096 claim:type shared drive fdfa8104-05fb-4210-aba5-fe78c4e6ee8c write:bytes 734007296 read:requests 1 os linux type cdrom size 662700032 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 32 drive_type installcd status active description UberStudent ("uber" meaning "productive" in Latin) is an Ubuntu-based distribution on a DVD designed for learning and teaching academic computing at the higher education and advanced secondary levels. UberStudent comes with software for everyday computing tasks, plus a core set of programs and features designed to teach and make easier the tasks and habits common to high-performing students of all academic disciplines. Lifelong learners, as well as any sort of knowledge worker, will equally benefit. UberStudent is supported by a free Moodle virtual learning environment. favourite true install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0013fc75-b170-4d62-abaf-804b8fc466cc host 001318df-35c6-439f-8e72-8d57c36ca86b user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 161793 name UberStudent 1.0 Linux with LXDE 32bit Install CD url http://www.uberstudent.org/ read:bytes 4096 claim:type shared drive 854a9706-fb14-4868-80df-53d712f1531a write:bytes 662704128 read:requests 1 os linux type disk size 3221225472 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type preinstalled status active description This is a pre-installed ready Fedora system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. The Fedora Project is an openly-developed project designed by Red Hat, open for general participation, led by a meritocracy, following a set of project objectives. The goal of The Fedora Project is to work with the Linux community to build a complete, general purpose operating system exclusively from open source software. Development will be done in a public forum. The project will produce time-based releases of Fedora about 2-3 times a year, with a public release schedule. The Red Hat engineering team will continue to participate in building Fedora and will invite and encourage more outside participation than in past releases. By using this more open process, we hope to provide an operating system more in line with the ideals of free software and more appealing to the open source community. favourite true install_notes ***You must update the default root/superuser password for Fedora 13 on first login.***\n\nPre-installed Fedora 13 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Complete the personalisation of your new server\n---------------------------------------------------------------------\nUpon first start-up you should be presented with the welcome screen after the initial boot process has completed. You will now have the opportunity to personalise your system installation. \na) Click the 'forward' button to get started.\n\nb) You will now see the license information for this system. Fedora 13 has an open source GNU license. Assuming this is acceptable you should click the 'forward' button again.\n\nc) You can now create your own user account, enter your name and set the password. Please note:\n\nTHIS IS NOT THE ADMINISTRATIVE ACCOUNT. YOU SHOULD RESET THE ROOT/SUPERUSER PASSWORD AS OUTLINED IN STEP 4 BELOW AFTER COMPLETING STEP 3.\n\nd) After clicking forward again you will have the opportunity to set the time servers that will set your servers time. You can just leave the default values unless you have some specific needs. Once you are happy please click the 'forward' button.\n\ne) Finally you have the option to submit your hardware profile to the Fedora Project to help with their development. This is entirely your personal choice. Either way once you are ready click the 'finish' button.\n\n4. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: cloudsigma\nThe default root/superuser password is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\nsu root\n\nWhen prompted use the password 'cloudsigma' (don't type the quote marks). The prompt should change to show you now using the root/superuser account.\n\nc) Now type the command:\n\npasswd\n\nd) When prompted enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\ne) CoudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\nf) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n5. Expanding your drive\n--------------------------------\n\nThe system is fully installed and designed to expand to fill the initial size of the drive. After first login you should find that the system has used the full disk size as its partition.\n\n\n6. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n7. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. volume 0003ca60-6b03-4da9-a409-84d8d7afa738 host 00031836-a624-4b22-bc7d-41ff8977087b user 00000000-0000-0000-0000-000000000001 autoexpanding true write:requests 786433 name Fedora 13 Linux 64bit Preinstalled System url http://fedoraproject.org/ read:bytes 40962080768 claim:type shared drive d18119ce-7afa-474a-9242-e0384b160220 write:bytes 3221229568 read:requests 10000508 os linux type disk size 4294967296 use dbserver,webserver,email,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type preinstalled status active favourite true install_notes ***You must update the default root/superuser password for Debian 5.0 on first login.***\n\nPre-installed Debian 5.0 64bit Linux on 02/08/2010\n========================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n------------------------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n-------------------------------------------------------\n\nThe default accounta are: root and cloudsigma\nThe default passwords for both accounts is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'cloudsigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. volume 0003ca60-6b03-4da9-a409-84d8d7afa738 host 00031836-a624-4b22-bc7d-41ff8977087b user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 1048577 name Debian 5.0 Preinstalled without X url www.debian.org read:bytes 35180666880 claim:type shared drive fd49670e-17e8-4b0e-b03e-d6a65c138445 write:bytes 4294971392 read:requests 8589030 os linux type disk size 21474836480 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type preinstalled status active description This is a pre-installed ready CentOS system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. favourite true install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. volume 000431a5-46d9-4a67-9c03-3c3402a41992 host 00043e69-ac57-45b1-8692-75db24064fb9 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 5242881 name CentOS 5.5 Linux 64bit Preinstalled System url http://www.centos.org/ read:bytes 251925499904 claim:type shared drive 1ea7dead-9d52-4e79-9a9b-435db7cc972c write:bytes 21474840576 read:requests 61505249 os linux type disk size 2684354560 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type preinstalled status active description This is a pre-installed ready Ubuntu system that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. Ubuntu Linux is a complete desktop Linux operating system, freely available with both community and professional support. The Ubuntu community is built on the ideas enshrined in the Ubuntu Manifesto: that software should be available free of charge, that software tools should be usable by people in their local language and despite any disabilities, and that people should have the freedom to customise and alter their software in whatever way they see fit. "Ubuntu" is an ancient African word, meaning "humanity to others". The Ubuntu Linux distribution brings the spirit of Ubuntu to the software world. favourite true install_notes ***You must update the default root/superuser password for Ubuntu 10.04 on first login.***\n\nPre-installed Ubuntu 10.04 64bit Linux on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: cloudsigma\nThe default root/superuser password is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\nsudo su\n\nWhen prompted use the password 'cloudsigma' (don't type the quote marks). The prompt should change to show you now using the root/superuser account.\n\nc) Now type the command:\n\npasswd\n\nd) When prompted enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\ne) CoudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\nf) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed and designed to expand to fill the initial size of the drive. After first login you should find that the system has used the full disk size as its partition.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. volume 00059deb-640a-464e-9509-6a3ec6cfd549 host 00059836-5512-4ce2-bf66-4daab2d994e4 user 00000000-0000-0000-0000-000000000001 autoexpanding true write:requests 655361 name Ubuntu Linux 10.04 Desktop 64bit Preinstalled System url http://www.ubuntu.com/ read:bytes 24617140224 claim:type shared drive 99a75966-209f-41d5-817c-7a3916354540 write:bytes 2684358656 read:requests 6010044 os linux type disk size 8589934592 use dbserver,webserver,email,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type preinstalled status active favourite true install_notes ***You must update the default root/superuser password for Ubuntu 10.04 on first login.***\n\nPre-installed Ubuntu 10.04 64bit Linux on 01/09/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: cloudsigma\nThe default root/superuser password is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\nsudo su\n\nWhen prompted use the password 'cloudsigma' (don't type the quote marks). The prompt should change to show you now using the root/superuser account.\n\nc) Now type the command:\n\npasswd\n\nd) When prompted enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\ne) CoudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\nf) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed and designed to expand to fill the initial size of the drive. After first login you should find that the system has used the full disk size as its partition.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. volume 000848ef-af56-4fe4-b724-5338a9fa6aa6 host 0008d252-5102-43a0-82c6-18e8e2dd2bff user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 2097153 name Ubuntu 10.04 Server Edition Linux 64bit url http://www.ubuntu.com/server read:bytes 71391387648 claim:type shared drive 0b060e09-d98b-44cc-95a4-7e3a22ba1b53 write:bytes 8589938688 read:requests 17429538 os linux type disk size 21474836480 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type preinstalled status active description This is a pre-installed ready CentOS system including AppFirst monitoring software that can be deployed to your account instantly. Please refer to the install notes for a full guide to initial configuration. CentOS is an Enterprise-class Linux Distribution derived from sources freely provided to the public by a prominent North American Enterprise Linux vendor. CentOS conforms fully with the upstream vendors redistribution policy and aims to be 100% binary compatible. favourite true install_notes ***You must update the default root/superuser password for CentOS 5.5 on first login.***\n\nPre-installed CentOS 5.5 64bit Linux with AppFirst Monitoring on 24/07/2010\n============================================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n----------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n----------------------------------------------------\n\nThe default account is: root\nThe default root/superuser password is set to: CloudSigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\ne) When prompted enter the password 'CloudSigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nf) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ng) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs.\n\n\n6. AppFirst\n-------------------------\nThis disk image includes AppFirst monitoring software already installed. This software is able to provide in-depth server and application performance feedback. In order to take advantage of this software you need to have an AppFirst account.\n\nFull details of AppFirst's services including a 14-day free trial are available at http://www.appfirst.com . volume 00106cda-0e17-40c8-a576-b516f0eb67bc host 00109617-2c6b-424b-9cfa-5b572c17bafe user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 5242881 name CentOS 5.5 Linux 64bit Preinstalled System with AppFirst Monitoring read:bytes 838707331072 claim:type shared drive c157e1eb-aa9c-4dd7-80b8-6fd4a238f2a9 write:bytes 21474840576 read:requests 204762532 os linux type disk size 8589934592 use dbserver,webserver,email,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free true bits 64 drive_type preinstalled status active favourite true install_notes ***You must update the default root/superuser password for Debian 5.0 on first login.***\n\nPre-installed Debian 5.0 64bit Linux on 02/08/2010\n========================================\n\n1. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements based on user feedback are:\n\nCPU: 1GHz\nRAM: 1GHz\n\nWe recommend specifying a larger size for a better user experience.\n\n\n2. Access your server for the first time using VNC\n------------------------------------------------------------------\nInitially you will need to access your server via VNC to complete the setup. \n\na) Start up your new server.\n\nb) Please use one of the recommended VNC clients, you will find a full list by following the 'Connect to your server via VNC now' link on general tab of the server detail window.\n\nb) Use the IP address and VNC password as provided on the general tab of the server detail window.\n\nc) After a few seconds you should see your server appear.\n\n\n3. Update your root/superuser password\n-------------------------------------------------------\n\nThe default accounta are: root and cloudsigma\nThe default passwords for both accounts is set to: cloudsigma .\n\nPlease CHANGE this IMMEDIATELY after first connecting with VNC.\n\na) Open a terminal or use the command line.\n\nb) Type the command:\n\npasswd\n\nc) When prompted enter the password 'cloudsigma' (no quotes should be typed) again and press return. You will then be prompted to enter a new password. We recommend a password of at least 8 characters including upper case and lower case letters as well as numbers.\n\nd) CloudSigma does not have access to your server account passwords. It is imperative that you securely store and manage your own passwords for your servers.\n\ne) Please note your root/superuser password is different from your VNC password. You can change your VNC password from the web console at any time.\n\n\n4. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive if you chose a disk size greater than 20GB. There are a number of tools which you can use to achieve this included GParted, the CD of which is also available in the drives library.\n\n\n4. Enabling Remote Access\n--------------------------------------\n\nVNC access is always enabled in our cloud allowing emergency recovery. We recommend using SSH to access your server for command line actions. By default this is turned off initially for security reasons. You will need to enable and install SSH if you wish to use it for access moving forward.\n\n\n5. Networking\n-------------------\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs. volume 001118bb-dbdb-4ab0-b7db-d4cceb160098 host 00115b1d-6fe9-40b2-a013-426a6a584ff7 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 2097153 name Debian 5.0 Preinstalled url www.debian.org read:bytes 71179878400 claim:type shared drive 9b732c4e-32a3-4369-b5f7-9a0325195baa write:bytes 8589938688 read:requests 17377900 os linux type cdrom claimed 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:7055acf3-8d9a-4a99-a24f-dda1aaf37944:ide:0:0 00115b1d-6fe9-40b2-a013-426a6a584ff7:guest:0a486768-08c1-419d-ad9c-1c8143df3496:ide:0:0 size 2248146944 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff bits 64 email drives@elastichosts.com drive_type installcd status active description - favourite false free false volume 0007aee7-bd5b-4551-9d8f-a958051235a9 host 00079b57-1b29-4a89-a8d0-1d648fc20804 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Windows Web Server 2008 Trial Install CD url http://www.microsoft.com read:bytes 55097581056 claim:type shared drive 7aead6d3-c3e6-4940-85c7-f5ee61f6ef2b write:bytes 0 read:requests 22364695 os windows type cdrom claimed 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:6100e29c-708d-4a5b-821b-6a9faa3ba013:ide:0:1 00031836-a624-4b22-bc7d-41ff8977087b:guest:fcde7569-e034-452c-9909-7c485f5d168f:ide:0:0 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:1ac4641e-aa67-47f2-a77d-e9c5982d68b2:ide:0:0 0012c12d-72b1-4dfc-ae0f-aeab09881545:guest:300989f8-da5c-42a6-91f8-97e87b85b748:ide:0:1 00016115-af87-452b-a3bf-3affc8a7d934:guest:f679b4ba-a4de-4254-90d1-27396aac8712:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:65e59c8b-579b-4977-b60c-b3b7eb404026:ide:0:0 00016115-af87-452b-a3bf-3affc8a7d934:guest:76eaf2fe-554a-4d3f-a3ef-a1214e878793:ide:0:0 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:030cfdda-9c6c-4622-a68c-2e3588fbe828:ide:0:0 00109617-2c6b-424b-9cfa-5b572c17bafe:guest:64a5375a-31cc-414f-9e14-006b5c39b51f:ide:0:0 00059836-5512-4ce2-bf66-4daab2d994e4:guest:83da4fb5-037f-4985-a0f6-f696fa7ff727:ide:0:0 0014dbec-e818-4cf4-b467-d4f0dad10246:guest:90f4a2d3-9b76-4444-a1b2-72bbd06fe3e2:ide:0:0 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:cbb4ecc9-654f-4410-aeb4-b9ca602faa01:ide:0:0 0008d252-5102-43a0-82c6-18e8e2dd2bff:guest:e7ea14b2-aaa0-48b4-b1ac-7c8351c2edf4:ide:0:0 001318df-35c6-439f-8e72-8d57c36ca86b:guest:67f96fa3-8d41-4f8b-8199-4111617d3150:ide:0:1 000663ee-9fb6-4461-90f6-01327a4aff07:guest:245dd0b0-18eb-4e24-b219-9549bafdea87:ide:0:0 000663ee-9fb6-4461-90f6-01327a4aff07:guest:b52e106f-f14c-4312-8597-bcfedf4b0e70:ide:0:0 size 2663383040 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free false bits 64 email drives@elastichosts.com drive_type installcd status active description - favourite false install_notes pass:123456 volume 0007aee7-bd5b-4551-9d8f-a958051235a9 host 00079b57-1b29-4a89-a8d0-1d648fc20804 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Windows Server 2008 Trial Install CD url http://www.microsoft.com/windowsserver2008/en/us/default.aspx read:bytes 78315713024 claim:type shared drive f89af28e-ff00-4fc9-a7ed-22e7fa5a88db write:bytes 0 read:requests 32289210 os windows status active name Gentoo Install Minimal amd64 20100408 readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 437561856 write:bytes 119558144 claim:type shared drive 73162606-78ca-4b0a-8f7a-70aa70563d90 free none volume 00018aab-c080-4ed3-b52f-459933d34ec9 host 00016115-af87-452b-a3bf-3affc8a7d934 os linux user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 79760 claimed 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:d74c8d2b-a169-486c-adbd-89ca50dccafa:ide:0:1 type cdrom write:requests 29189 size 209715200 status active name Peppermint Ice Linux 32bit Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 1986560 description Peppermint OS is an Ubuntu-based Linux distribution that aims to be lightning fast and easy on system resources. By employing Mozilla's Prism technology Peppermint integrates seamlessly with Cloud and web-based applications. The distribution's other features include automatic updates, easy step-by-step installation, sleek and user-friendly interface, and increased mobility by integrating directly with Cloud-based applications. write:bytes 437698560 claim:type shared drive f9d92afc-27ff-4139-84c7-ac6655e6f6f1 install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00018aab-c080-4ed3-b52f-459933d34ec9 host 00016115-af87-452b-a3bf-3affc8a7d934 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 485 free none type cdrom write:requests 106860 size 436207616 status active name Super Gamer Linux 32bit and 64bit Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 137039872 description SuperGamer is a live DVD based on VectorLinux, intended to showcase gaming on Linux. The distribution is optimised for a gaming computer environment, with some tweaks to help speed up running from the live DVD. Extra games are added along with some demo editions of proprietary games. All games are native Linux games, but users wishing to run Windows games may install WINE or a related emulator, such as Cedega. write:bytes 8446324736 claim:type shared drive d72701b2-01b9-4ac3-9afa-d0afdb6bcf2f install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00018aab-c080-4ed3-b52f-459933d34ec9 host 00016115-af87-452b-a3bf-3affc8a7d934 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 33457 free none type cdrom write:requests 2062091 size 8413773824 status active name ZeroShell 1.3 Linux Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 856064 description Zeroshell is a Linux distribution for servers and embedded devices aimed at providing the main network services a LAN requires. It is available in the form of Live CD or Compact Flash image and you can configure and administer it using your web browser. write:bytes 153247744 claim:type shared drive 44358ce4-0f30-4e48-86d1-e93330961a8a install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC.\n volume 00023324-4c49-4567-a017-c85c8a6b8313 host 0002c6df-a1d2-4d1d-96f0-f95405a28183 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 209 free none type cdrom write:requests 37414 size 155189248 status active name Astaro Security Gateway Firewall Server 8.0 Linux Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 365871104 description Astaro offers an integrated software solution that provides superior performance in an all-in-one firewall. Its hardened operating system, stateful packet inspection, content filtering (virus & surf protection), application proxies and IPsec based VPN provides a powerful solution to today's security issues. It is designed to maximize your networks security without compromising its performance enabling telecommuters, branch offices, customers and suppliers to safely share critical business information. Our proprietary user interface, WebAdmin allows ease of use and manageability of all open source firewall components, as well as the Up2Date service via the Internet. It is easy to install with all components on one CD achieving simple implementation and integration to existing network environments. write:bytes 369696768 claim:type shared drive 916b0e39-b234-407b-89ab-e8108f05726f install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00023324-4c49-4567-a017-c85c8a6b8313 host 0002c6df-a1d2-4d1d-96f0-f95405a28183 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 89324 claimed 000096ce-ff07-413d-912a-aa1a33963802:guest:20911753-98a6-4951-af34-89e157452c84:ide:0:0 00115b1d-6fe9-40b2-a013-426a6a584ff7:guest:75a96f35-c3fd-492a-a48b-34dcd10987d6:ide:0:0 free none type cdrom write:requests 90258 size 369098752 status active name Chakra 0.2.2 Linux 64bit Install and Live CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 5451776 description Chakra GNU/Linux is a user-friendly and powerful distribution and live CD based on Arch Linux. It features a graphical installer, automatic hardware detection and configuration, the latest KDE desktop, and a variety of tools and extras. write:bytes 724774912 claim:type shared drive 0e8c8ac2-f791-4764-a964-c6d2679ae49a install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend using it as an installation CD and not just a live CD.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 0000acbf-fa0a-44a6-8018-2f106f96a45f host 000096ce-ff07-413d-912a-aa1a33963802 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 1331 free none type cdrom write:requests 176947 size 721420288 status active name Clonezilla Live 1.2.6 64bit readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 876544 description Clonezilla Live is a Debian-based live CD containing Clonezilla, a partition and disk cloning software similar to Norton Ghost. It saves and restores only used blocks in hard drive. With Clonezilla, one can clone a 5 GB system to 40 clients in about 10 minutes. write:bytes 134045696 claim:type shared drive cec8330f-59c7-4e20-9577-54df28d598e7 install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n3. Start the server.\n4. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n5. You will be able to start using your new server via VNC. volume 0000acbf-fa0a-44a6-8018-2f106f96a45f host 000096ce-ff07-413d-912a-aa1a33963802 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 214 free none type cdrom write:requests 32726 size 134217728 status active name Absolute Linux 13.1.2 Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 93573632 description Absolute Linux is a light-weight modification of Slackware Linux. It includes several utilities that make configuration and maintenance easier and it has many common desktop and Internet applications installed and configured with tight integration of menus, applications and MIME types. Absolute Linux uses IceWM and ROX for its window and file managers. write:bytes 728211456 claim:type shared drive b745638c-87ff-4836-8623-e48e67286494 install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 000431a5-46d9-4a67-9c03-3c3402a41992 host 00043e69-ac57-45b1-8692-75db24064fb9 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 39232 free none type cdrom write:requests 177786 size 725614592 status active name Sabayon_Linux_5.4_amd64_K.iso readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 12877824 write:bytes 2160496640 claim:type shared drive 75119285-7c20-43f4-9d3b-e6af3f1823e3 free none volume 000431a5-46d9-4a67-9c03-3c3402a41992 host 00043e69-ac57-45b1-8692-75db24064fb9 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 3144 type cdrom write:requests 527465 size 2151677952 status active name FreeBSD 8.1 Linux 64bit Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 60035072 description About FreeBSD FreeBSD is a UN*X-like operating system for the i386, IA-64, PC-98, Alpha/AXP, and UltraSPARC platforms based on U.C. Berkeley's "4.4BSD-Lite" release, with some "4.4BSD-Lite2" enhancements. It is also based indirectly on William Jolitz's port of U.C. Berkeley's "Net/2" to the i386, known as "386BSD", though very little of the 386BSD code remains. FreeBSD is used by companies, Internet Service Providers, researchers, computer professionals, students and home users all over the world in their work, education and recreation. write:bytes 2315309056 claim:type shared drive fb940d5b-b9a0-4f9c-8cb7-94c3378d1676 install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00059deb-640a-464e-9509-6a3ec6cfd549 host 00059836-5512-4ce2-bf66-4daab2d994e4 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 14657 free none type cdrom write:requests 565261 size 2306867200 status active name BackTrack 4 Release 1 Linux Live CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 4008857600 description A SLAX-based live CD with a comprehensive collection of security and forensics tools BackTrack 4 R1, a Linux-based penetration testing arsenal for security professionals. write:bytes 2023919616 claim:type shared drive ef152c9c-1460-44f5-b192-8e0524909709 install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00059deb-640a-464e-9509-6a3ec6cfd549 host 00059836-5512-4ce2-bf66-4daab2d994e4 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 978725 free none type cdrom write:requests 494121 size 2017460224 status active name Vector 6.0 Linux 32bit Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 3035136 description VECTORLINUX is a small, fast, Intel Linux operating system based on one of the original Linux distributions, Slackware. The enormously popular Slackware is the true "Unix" of Linux distributions and is used by major corporations, universities and home users alike. It's popularity stems from the fact that it is a robust, versatile and almost unbreakable system. Slackware has been traditionally known to be about as user friendly as a coiled rattlesnake and that's where Vector Linux comes into play. We have produced a bloat free, easy to install, configure and maintain Slackware based system that is second to none. write:bytes 729059328 claim:type shared drive c2a757b9-dfd0-432c-bb29-b380b4dd6fb6 free none volume 00059deb-640a-464e-9509-6a3ec6cfd549 host 00059836-5512-4ce2-bf66-4daab2d994e4 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 741 type cdrom write:requests 177993 size 729808896 status active name PCBSD 8.1 Linux 64bit Install CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 15228928 description PC-BSD has as its goals to be an easy-to-install-and-use desktop operating system, based on FreeBSD. To accomplish this, it currently has a graphical installation, which will enable even UNIX novices to easily install and get it running. It will also come with KDE pre-built, so that the desktop can be used immediately. Currently in development is a graphical software installation program, which will make installing pre-built software as easy as other popular operating systems. write:bytes 3794726912 claim:type shared drive 802fbcab-2723-469c-b775-6fdeb21287da install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 3718 free none type cdrom write:requests 926447 size 3783262208 status active name nst-2.13.0.x86_64.iso readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 7503872 write:bytes 1436717056 claim:type shared drive 9d04c648-712d-4076-bd99-70088d85fe01 free none volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 1832 type cdrom write:requests 350761 size 1430257664 status active name Peppermint-Ice-10012010.iso readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 2613248 write:bytes 452710400 claim:type shared drive 2e79eeee-b4ad-4dcf-a072-86dcede6af1b free none volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 638 type cdrom write:requests 110525 size 452984832 status active name Sabayon_Linux_5.4_amd64_K.iso readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 14082048 write:bytes 2161713152 claim:type shared drive 07e2a6df-8389-4130-a003-edacc19a9ee3 free none volume 00065289-b9c8-4548-8d83-e1891f831f51 host 000663ee-9fb6-4461-90f6-01327a4aff07 user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 3438 type cdrom write:requests 527762 size 2151677952 type cdrom claimed 00031836-a624-4b22-bc7d-41ff8977087b:guest:ffe02269-b653-47ad-ab21-a02805b24904:ide:0:0 000096ce-ff07-413d-912a-aa1a33963802:guest:1f378a18-1b59-40e7-8e9a-7f81d7eda6b8:ide:0:0 00079b57-1b29-4a89-a8d0-1d648fc20804:guest:8c13b69d-6d11-4151-975b-a2f084c7ada7:ide:0:0 00166b98-6431-40ad-94b0-244881ff87d5:guest:1705b116-aac2-449a-b0de-3dd4ab7e765f:ide:0:0 000932a7-c74f-4de3-bfc4-227435f78998:guest:30d887ee-ed96-4c32-a1a8-5ab49abd2a7e:ide:0:1 00154bbf-adf4-475d-9fe6-71c1e987d1bd:guest:bcea8695-baeb-476e-8089-475ce8948646:ide:0:1 0002c6df-a1d2-4d1d-96f0-f95405a28183:guest:df1368af-05a3-4ad5-8017-54be3ea70232:ide:0:0 00109617-2c6b-424b-9cfa-5b572c17bafe:guest:3569d646-7ae5-410f-b66e-64bba1381cba:ide:0:0 size 2663383040 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff bits 64 drive_type installcd status active description - favourite false free false volume 0009c669-9ea6-4825-b788-b40902bb1902 host 000932a7-c74f-4de3-bfc4-227435f78998 encryption:cipher aes-xts-plain user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 0 name Windows Server 2008 Trial Install CD url http://www.microsoft.com/windowsserver2008/en/us/default.aspx read:bytes 5261708288 claim:type shared drive 7e23b099-dd35-446b-8d90-2953643b664f write:bytes 0 read:requests 1883649 os windows status active name Unity Linux 64bit Install and Live CD readers ffffffff-ffff-ffff-ffff-ffffffffffff favourite none read:bytes 147034112 description The community-oriented Unity Linux is a minimalist distribution and live CD based on Mandriva Linux. The project's main goal is to create a base operating system from which more complete, user-oriented distribution can easily be built - either by other distribution projects or by the users themselves. Unity Linux uses Openbox as the default window manager. Its package management is handled via Smart and RPM 5 which can download and install additional software packages from the project's online repository. write:bytes 290488320 claim:type shared drive d235dada-407c-4105-b4ef-636eb7604404 install_notes CD Installation instructions:\n1. Add this CD to a server that you wish to install this software onto.\n2. Make sure there is a hard drive also attached to the same server on which this software can be installed if you intend to use this as an installation and not live CD only.\n3. Make sure that this CD is selected as the boot drive. You can do this from the 'Drives' tab on the main server detail window.\n4. Start the server.\n5. Connect to the server using VNC. You will find the IP address and password on the 'Summary' tab of the main server detail window and in the server list view.\n6. You will be able to complete the software installation via VNC and start using your new server. volume 00106cda-0e17-40c8-a576-b516f0eb67bc host 00109617-2c6b-424b-9cfa-5b572c17bafe user 00000000-0000-0000-0000-000000000001 autoexpanding false read:requests 35897 free none type cdrom write:requests 70920 size 289406976 type disk licenses msft_p73_04837 msft_tfa_00009 size 21474836480 use dbserver,general readers ffffffff-ffff-ffff-ffff-ffffffffffff free false bits 64 drive_type preinstalled status active description Please refer to the install notes for a full guide to initial configuration. favourite false install_notes ***You must update the default Administrator password for Windows Server Standard 2008 and the Super Administrator password (sa) for SQL Server Standard 2008***\n\nPre-installed Windows Server 2008 Standard R2 64bit English on 15/07/2010\n=========================================================================\n\n1. Minimum Hardware Requirements\n--------------------------------\n\nThe recommended minimum hardware requirements for the use of SQL Server Standard 2008 R2 with Windows Server Standard 2008 R2 as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/library/ms143506.aspx\n\n\n2. Update your administrator password\n-------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n3. Expanding your drive\n-----------------------\n\nThe system is fully installed, but you will need to extend the\ndisk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n4. Enabling Remote Access\n-------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection according to your Security Configuration\n\n\n5. Pinging Service\n------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules"\n\n\nSQL Server 2008 R2 on 15/07/2010\n================================\n\n1. Change the Super Administrator Password (sa). \n--------------------------------------------------------------------\n\nThe default password has been set to "CloudSigma1"\n\na) Open "Microsoft SQL Server Management Studio"\n\nb) Connect to the Server Using "Windows Indentificaiton"\n\nc) From the Object Explorer select "Security" then "Longins"\n\nd) Right-click on sa and select "Properties"\n\ne) Enter the new password into "Password" and "Confirm Password" and press "OK"\n\n\n2. The following features were installed:\n-----------------------------------------------------\n\na) Main features\n\n-Database Engine Services\n-SQL Server Replication\n-Full-Text Search\n-Analysis Services\n-Reporting Services\n\nb) Shared Features\n\n-Business Intelligengce Development Studio\n-Client Tools Connectivity\n-Integration Services\n-Clinet Tools Backwards Compatibility\n-Clinet Tools SDK\n-SQL Server Books Online\n-Mangement Tools - Basic\n-Management Tools - Complete\n-SQL Client Connectivity SDK\n-Microsoft Sync Framework\n\n3 The following services were configured:\n--------------------------------------------------------\n\n\nService: SQL Server Agent\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Manual\n\nService: SQL Server Database Engine\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Automatic\n\nService: SQL Server Analysis Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Reporting Services\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n\nService: SQL Server Integration Services 10.1\nUser: NT AUTHORITY\NETWORK SERVICE\nStartup Type: Disabled\n \nService: SQL Full-text filter Daemon Lanuch\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nService: SQL Server Browser\nUser: NT AUTHORITY\LOCALSERVICE\nStartup Type: Disabled\n\nFor detailed server installation configuration refer to the following installation log files on the system:\nC:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20100716_162426\Summary_WIN-K0F21FV1C1V_20100716_162426.txt\n volume 00023324-4c49-4567-a017-c85c8a6b8313 host 0002c6df-a1d2-4d1d-96f0-f95405a28183 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 5242881 name SQL Server Standard 2008 R2 - Windows Server Standard 2008 R2 - 64bit English pub url http://www.microsoft.com/sqlserver/2008/en/us/ read:bytes 49172439040 claim:type shared drive 7b013f8c-dd4c-4701-b1ca-936506dc37ca write:bytes 21474840576 read:requests 12004990 os windows type disk licenses msft_lwa_00135 size 13958643712 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free false bits 64 drive_type preinstalled status active description Please refer to the install notes for a full guide to initial configuration. favourite false install_notes ***You must update the default Administrator password for Windows Web Server 2008***\n\nPre-installed Windows Server 2008 Web R2 64bit English on 24/07/2010\n============================================================\n\n1. Connecting to your server via VNC\n--------------------------------------------------\n\na) Having installed a compatible VNC client, open a VNC connection to your server.\n\nb) Enter your IP address and VNC password as displayed on your Server Summary Window.\n\nc) Start to configure your server.\n\n\n2. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/windowsserver/cc196364.aspx\n\nWe recommend specifying a higher level of RAM for a better user experience.\n\n\n3. Update your administrator password\n----------------------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" from the "Start" menu and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n4. Configuring your Networking\n------------------------------------------\n\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs.\n\n\n5. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n6. Enabling Remote Access\n--------------------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection type according to your Security Configuration\n\n\n7. Pinging Service\n-------------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules" volume 00120946-d7a4-486e-867e-8348bebe0b95 host 0012c12d-72b1-4dfc-ae0f-aeab09881545 user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 3407873 name Windows Server Web 2008 R2 64bit English url http://www.microsoft.com/windowsserver2008/en/us/default.aspx read:bytes 145252270080 claim:type shared drive 71697799-c611-41b9-93be-f79152aefbe5 write:bytes 13958647808 read:requests 35461980 os windows type disk licenses msft_p73_04837 size 13958643712 use general readers ffffffff-ffff-ffff-ffff-ffffffffffff free false bits 64 drive_type preinstalled status active description Please refer to the install notes for a full guide to initial configuration. favourite false install_notes ***You must update the default Administrator password for Windows Server Standard 2008***\n\nPre-installed Windows Server 2008 Standard R2 64bit English on 24/07/2010\n============================================================\n\n1. Connecting to your server via VNC\n--------------------------------------------------\n\na) Having installed a compatible VNC client, open a VNC connection to your server.\n\nb) Enter your IP address and VNC password as displayed on your Server Summary Window.\n\nc) Start to configure your server.\n\n\n2. Minimum Hardware Requirements\n--------------------------------------------------\n\nThe recommended minimum hardware requirements as publishes by Microsoft can be found through the following link:\n\nhttp://msdn.microsoft.com/en-us/windowsserver/cc196364.aspx\n\nWe recommend specifying a higher level of RAM for a better user experience.\n\n\n3. Update your administrator password\n----------------------------------------------------\n\nThe default administrator password is set to: CloudSigma1\n\nPlease CHANGE this IMMEDIATELY after first logging on.\n\na) Open the "Control Panel" from the "Start" menu and select "User Accounts"\n\nb) Select "Change your Windows Password"\n\nc) The Administrator user icon will be shown on the right, select again "Change your Password", and on this screen update your details accordingly\n\n\n4. Configuring your Networking\n------------------------------------------\n\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\n\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users.\n\nIt is important that you secure access to your server according to your needs.\n\n\n5. Expanding your drive\n--------------------------------\n\nThe system is fully installed, but you will need to extend the disk partition to cover the whole of your drive. To do this:\n\na) Open the "Computer Management" tool from "Administrative Tools" on the "Start" menu.\n\nb) Select "Storage" then "Disk Management" in the left hand pane\n\nc) Right-click on the 12.90 GB NTFS primary partition, and select "Extend Volume"\n\nd) Enter the amount of disk space that you want to increase the Volume size by (the default will be the maximum available)\n\nYou will need to repeat this procedure if you ever resize this drive in the future.\n\n\n6. Enabling Remote Access\n--------------------------------------\n\nAfter logging in to VNC for the first time to configure your new Windows server, we recommend that if you are logging in from a Windows Desktop that you enable Remote Desktop for better access performance. To do this, follow these instructions:\n\na) Select "Start" | "Applications" | "Control Panel"\n\nb) Select "System and Security"\n\nc) Under "System" select "Allow Remote Access"\n\nd) Select the corresponding connection type according to your Security Configuration\n\n\n7. Pinging Service\n-------------------------\n\nThe Pinging service has been turned on by default, if you wish to disable it please follow these instructions:\n\na) Select the "Windows Firewall with Advanced Security" tool from "Administrative Tools" on the "Start" menu.\n\nb) On the left hand pane, select "Inbound Rules"\n\nc) On the middle pane, select the rules "File and Printer Sharing (Echo Request - ICMPv4-In)" and "File and Printer Sharing (Echo Request - ICMPv6-In)"\n\nd) From the right-hand pane, select "Disable Rules" volume 0013fc75-b170-4d62-abaf-804b8fc466cc host 001318df-35c6-439f-8e72-8d57c36ca86b user 00000000-0000-0000-0000-000000000001 autoexpanding false write:requests 3407873 name Windows Server Standard 2008 R2 64bit English url http://www.microsoft.com/windowsserver2008/en/us/default.aspx read:bytes 257073537024 claim:type shared drive 0611be3f-0607-4b3c-8bad-a0af392d928a write:bytes 13958647808 read:requests 62762094 os windows apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/resources_ip_create.txt0000664000175000017500000000041113535474530031446 0ustar kamikami00000000000000resource 1.2.3.4 netmask 255.255.255.0 nameserver 91.203.56.1 user f2e19d5c-eaa1-44e5-94aa-dc194594bd7b type ip gateway 91.203.56.1 resource 1.2.3.5 netmask 255.255.255.0 nameserver 91.203.56.1 user f2e19d5c-eaa1-44e5-94aa-dc194594bd7b type ip gateway 91.203.56.1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/resources_ip_list.txt0000664000175000017500000000004113535474530031155 0ustar kamikami00000000000000ip 1.2.3.4 ip 1.2.3.5 ip 1.2.3.6 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/servers_create.txt0000664000175000017500000000107013535474530030437 0ustar kamikami00000000000000ide:0:0:write:requests 466 rx 760681 vnc:password testpass ide:0:0 f0202f1c-0b4f-4cfc-8ae3-e30951d09ef0 ide:0:0:read:requests 7467 ide:0:0:read:bytes 165395968 vnc:ip 178.22.66.28 tx:packets 32 tx 2568 boot ide:0:0 smp 1 started 1286568422 nic:0:model virtio status active mem 640 rx:packets 12662 user 93b34fd9-7986-4b25-8bfd-98a50383605d ide:0:0:media disk name cloudsigma node persistent true nic:0:block tcp/22 tcp/23 tcp/25 tcp/43594 tcp/43595 server 62fe7cde-4fb9-4c63-bd8c-e757930066a0 nic:0:dhcp 1.2.3.4 nic:1:dhcp 1.2.3.5 ide:0:0:write:bytes 7358464 cpu 1100 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/servers_info.txt0000664000175000017500000000107013535474530030127 0ustar kamikami00000000000000ide:0:0:write:requests 466 rx 760681 vnc:password testpass ide:0:0 f0202f1c-0b4f-4cfc-8ae3-e30951d09ef0 ide:0:0:read:requests 7467 ide:0:0:read:bytes 165395968 vnc:ip 178.22.66.28 tx:packets 32 tx 2568 boot ide:0:0 smp 1 started 1286568422 nic:0:model virtio status active mem 640 rx:packets 12662 user 93b34fd9-7986-4b25-8bfd-98a50383605d ide:0:0:media disk name cloudsigma node persistent true nic:0:block tcp/22 tcp/23 tcp/25 tcp/43594 tcp/43595 server 62fe7cde-4fb9-4c63-bd8c-e757930066a0 nic:0:dhcp 1.2.3.4 nic:1:dhcp 1.2.3.5 ide:0:0:write:bytes 7358464 cpu 1100 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma/servers_set.txt0000664000175000017500000000107013535474530027767 0ustar kamikami00000000000000ide:0:0:write:requests 466 rx 760681 vnc:password testpass ide:0:0 f0202f1c-0b4f-4cfc-8ae3-e30951d09ef0 ide:0:0:read:requests 7467 ide:0:0:read:bytes 165395968 vnc:ip 178.22.66.28 tx:packets 32 tx 2568 boot ide:0:0 smp 2 started 1286568422 nic:0:model virtio status active mem 640 rx:packets 12662 user 93b34fd9-7986-4b25-8bfd-98a50383605d ide:0:0:media disk name cloudsigma node persistent true nic:0:block tcp/22 tcp/23 tcp/25 tcp/43594 tcp/43595 server 62fe7cde-4fb9-4c63-bd8c-e757930066a0 nic:0:dhcp 1.2.3.4 nic:1:dhcp 1.2.3.5 ide:0:0:write:bytes 7358464 cpu 1100 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/0000775000175000017500000000000013600223624025311 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/balance.json0000664000175000017500000000005013535474530027577 0ustar kamikami00000000000000{"balance": "10.00", "currency": "USD"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/capabilities.json0000664000175000017500000000073213535474530030652 0ustar kamikami00000000000000{ "drives": { "dssd": { "max_size": 8858013190752, "min_size": 536870912 } }, "servers": { "cpu": { "max": 80000, "min": 250 }, "cpu_per_smp": { "max": 2200, "min": 1000 }, "mem": { "max": 137438953472, "min": 268435456 }, "smp": { "max": 40, "min": 1 } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/create_subscription.json0000664000175000017500000000140713535474530032270 0ustar kamikami00000000000000{ "objects": [ { "amount": "1", "auto_renew": false, "descendants": [], "discount_amount": "0", "discount_percent": "0", "end_time": "2014-03-01T12:00:00+00:00", "id": "228816", "period": "1 month", "price": "10.26666666666666666666666667", "remaining": "1", "resource": "vlan", "resource_uri": "/api/2.0/subscriptions/228816/", "start_time": "2014-01-31T17:06:19.388295+00:00", "status": "active", "subscribed_object": "2494079f-8376-40bf-9b37-34d633b8a7b7", "uuid": "0dd25c5c-6c01-498f-b009-e07d76552a1a" } ], "price": "10.26666666666666666666666667" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/currentusage.json0000664000175000017500000000356313535474530030735 0ustar kamikami00000000000000{ "balance": { "balance": "378.74599035374868510600", "currency": "USD" }, "usage": { "cpu": { "burst": 0, "subscribed": 0, "using": 0 }, "dssd": { "burst": 13958643712, "subscribed": 0, "using": 13958643712 }, "ip": { "burst": 0, "subscribed": 0, "using": 0 }, "mem": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_7jq_00341": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_7nq_00302": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_lwa_00135": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_p71_01031": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_p73_04837": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_p73_04837_core": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_tfa_00009": { "burst": 0, "subscribed": 0, "using": 0 }, "msft_tfa_00523": { "burst": 0, "subscribed": 0, "using": 0 }, "sms": { "burst": 0, "subscribed": 0, "using": 0 }, "ssd": { "burst": 0, "subscribed": 0, "using": 0 }, "tx": { "burst": 0, "subscribed": 5368709120, "using": 0 }, "vlan": { "burst": 0, "subscribed": 0, "using": 0 } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_avail_groups.json0000664000175000017500000000103713535474530032267 0ustar kamikami00000000000000[ [ "ad2b0b9c-8b66-45bc-a0f8-3a8514b78406", "e464a01b-ad2a-4bed-a4dd-30d1687560fd", "2246e488-a1b9-4da2-af30-0b6c73a1529c", "51a6b22f-2884-48d9-87f8-c85cb6f43c99", "a67c932d-6766-470b-b1c5-17856e4a5b4e", "3af58efd-8442-466f-80bf-48c5a2ee84b6", "ab35089c-0a89-435f-aedd-eaa05fae0ef1", "9972280b-3d74-4b0d-85de-caa0ef0117a6", "c47bca85-0199-438c-9ae4-d308357cf22d", "3e166706-188c-4f38-b8d5-7fc10a5019a1", "ba47e1e9-1848-48bd-8786-9cc45744214c" ] ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_clone.json0000664000175000017500000000160013535474530030670 0ustar kamikami00000000000000{ "objects": [ { "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "cloned drive", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", "runtime": { "snapshots_allocated_size": 0, "storage_type": null }, "size": 2097152000, "snapshots": [], "status": "creating", "storage_type": null, "tags": [], "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_create.json0000664000175000017500000000160013535474530031033 0ustar kamikami00000000000000{ "objects": [ { "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "test drive 5", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", "runtime": { "snapshots_allocated_size": 0, "storage_type": null }, "size": 2097152000, "snapshots": [], "status": "creating", "storage_type": null, "tags": [], "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_detail.json0000664000175000017500000002615213535474530031043 0ustar kamikami00000000000000{ "meta": { "limit": 20, "offset": 0, "total_count": 4 }, "objects": [ { "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": { "arch": "64", "category": "general", "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", "favourite": "False", "image_type": "preinst", "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", "os": "linux", "paid": "False", "url": "http://www.debian.org/" }, "mounted_on": [], "name": "test node 2-drive", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/9d1d2cf3-08c1-462f-8485-f4b073560809/", "runtime": { "snapshots_allocated_size": 0, "storage_type": "dssd" }, "size": 13958643712, "snapshots": [], "status": "unmounted", "storage_type": "dssd", "tags": [], "uuid": "9d1d2cf3-08c1-462f-8485-f4b073560809" }, { "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": { "arch": "64", "category": "general", "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", "favourite": "False", "image_type": "preinst", "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", "os": "linux", "paid": "False", "url": "http://www.debian.org/" }, "mounted_on": [], "name": "test node 3-drive", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/c9799969-0016-4298-a72c-93cabc067c6e/", "runtime": { "snapshots_allocated_size": 0, "storage_type": "dssd" }, "size": 13958643712, "snapshots": [], "status": "unmounted", "storage_type": "dssd", "tags": [], "uuid": "c9799969-0016-4298-a72c-93cabc067c6e" }, { "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": { "arch": "64", "category": "general", "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", "favourite": "False", "image_type": "preinst", "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", "os": "linux", "paid": "False", "url": "http://www.debian.org/" }, "mounted_on": [], "name": "test node 2-drive", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/967c8bbd-ca32-42db-a9b8-95e270e0aae1/", "runtime": { "snapshots_allocated_size": 0, "storage_type": "dssd" }, "size": 13958643712, "snapshots": [], "status": "unmounted", "storage_type": "dssd", "tags": [], "uuid": "967c8bbd-ca32-42db-a9b8-95e270e0aae1" }, { "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": { "arch": "64", "category": "general", "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", "favourite": "False", "image_type": "preinst", "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", "os": "linux", "paid": "False", "url": "http://www.debian.org/" }, "mounted_on": [ { "resource_uri": "/api/2.0/servers/e06cf7b3-ea46-4d38-87e0-3f918c4648d3/", "uuid": "e06cf7b3-ea46-4d38-87e0-3f918c4648d3" } ], "name": "test node 2-drive", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/3e166706-188c-4f38-b8d5-7fc10a5019a1/", "runtime": { "snapshots_allocated_size": 0, "storage_type": "dssd" }, "size": 13958643712, "snapshots": [], "status": "mounted", "storage_type": "dssd", "tags": [], "uuid": "3e166706-188c-4f38-b8d5-7fc10a5019a1" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_get.json0000664000175000017500000000123613535474530030354 0ustar kamikami00000000000000{ "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "test drive 5", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", "runtime": { "snapshots_allocated_size": 0, "storage_type": null }, "size": 2097152000, "snapshots": [], "status": "unmounted", "storage_type": null, "tags": [], "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/drives_resize.json0000664000175000017500000000160013535474530031071 0ustar kamikami00000000000000{ "objects": [ { "affinities": [], "allow_multimount": false, "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "test drive 5", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/drives/b02311e2-a83c-4c12-af10-b30d51c86913/", "runtime": { "snapshots_allocated_size": 0, "storage_type": null }, "size": 1164967936, "snapshots": [], "status": "creating", "storage_type": null, "tags": [], "uuid": "b02311e2-a83c-4c12-af10-b30d51c86913" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_no_rules.json0000664000175000017500000000076013535474530033617 0ustar kamikami00000000000000{ "objects": [ { "meta": {}, "name": "test policy 1", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/fwpolicies/ae9e5982-33fd-4e89-a467-4480256ccdb6/", "rules": [], "servers": [], "uuid": "ae9e5982-33fd-4e89-a467-4480256ccdb6" } ] } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_create_with_rules.jso0000664000175000017500000000154413535474530034001 0ustar kamikami00000000000000{ "objects": [ { "meta": {}, "name": "test policy 2", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/fwpolicies/324819a5-7a5b-4231-957d-662a7429fb8c/", "rules": [ { "action": "accept", "comment": null, "direction": "out", "dst_ip": "127.0.0.1/32", "dst_port": null, "ip_proto": "tcp", "src_ip": "127.0.0.1/32", "src_port": null } ], "servers": [], "uuid": "324819a5-7a5b-4231-957d-662a7429fb8c" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/fwpolicies_detail.json0000664000175000017500000000576013535474530031715 0ustar kamikami00000000000000{ "meta": { "limit": 0, "offset": 0, "total_count": 2 }, "objects": [ { "meta": {}, "name": "test policy", "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "resource_uri": "/api/2.0/fwpolicies/0e339282-0cb5-41ac-a9db-727fb62ff2dc/", "rules": [], "servers": [], "uuid": "0e339282-0cb5-41ac-a9db-727fb62ff2dc" }, { "meta": {}, "name": "My awesome policy", "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "resource_uri": "/api/2.0/fwpolicies/0c754845-f2ed-4347-8758-4315f7fa9c22/", "rules": [ { "action": "drop", "comment": "Drop traffic from the VM to IP address 23.0.0.0/32", "direction": "out", "dst_ip": "23.0.0.0/32", "dst_port": null, "ip_proto": "tcp", "src_ip": null, "src_port": null }, { "action": "accept", "comment": "Allow SSH traffic to the VM from our office in Dubai", "direction": "in", "dst_ip": null, "dst_port": "22", "ip_proto": "tcp", "src_ip": "172.66.32.0/24", "src_port": null }, { "action": "drop", "comment": "Drop all other SSH traffic to the VM", "direction": "in", "dst_ip": null, "dst_port": "22", "ip_proto": "tcp", "src_ip": null, "src_port": null }, { "action": "drop", "comment": "Drop all UDP traffic to the VM, not originating from 172.66.32.55", "direction": "in", "dst_ip": null, "dst_port": null, "ip_proto": "udp", "src_ip": "!172.66.32.55/32", "src_port": null }, { "action": "drop", "comment": "Drop any traffic, to the VM with destination port not between 1-1024", "direction": "in", "dst_ip": null, "dst_port": "!1:1024", "ip_proto": "tcp", "src_ip": null, "src_port": null } ], "servers": [], "uuid": "0c754845-f2ed-4347-8758-4315f7fa9c22" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/libdrives.json0000664000175000017500000010255613535474530030213 0ustar kamikami00000000000000{ "meta": { "limit": 20, "offset": 0, "total_count": 89 }, "objects": [ { "affinities": [], "allow_multimount": false, "arch": "32", "category": [ "security" ], "description": "IPCop 2.0.2 - i486 - CD.\r\nThe IPCop Firewall is a Linux firewall distribution.", "favourite": true, "image_type": "install", "install_notes": "1. Attach the CD.\\n Please be aware that the CD needs to be attached to the server to IDE. \\n \\n 2. Attach a Drive.\\n Please be aware that the minimum drive size where you are going to install the OS should be 5 GB. \\n \\n 3. Connecting to your server via VNC.\\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 4. Minimum Hardware Requirements.\\n The recommended minimum hardware requirements as publishes by ipcop.org are: 32MB RAM and 386MHz CPU \\n We recommend specifying a higher level of RAM for a better user experience.\\n", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "IPCop 2.0.2", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/6eca8d96-44bc-4637-af97-77ccd7ba4144/", "size": 1000000000, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.ipcop.org/", "uuid": "6eca8d96-44bc-4637-af97-77ccd7ba4144" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "FreeBSD-8.4-RELEASE-amd64-disc1", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD.\\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \\n\r\n\\n\r\n2. Attach a Drive.\\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \\n\r\n\\n\r\n3. Connecting to your server via VNC.\\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \\n\r\n\\n\r\n4. Minimum Hardware Requirements.\\n\r\nThe recommended minimum hardware requirements as publishes by freebsd.org are: 0.5 GB RAM and 0.5\\n GHz CPU We recommend specifying a higher level of RAM for a better user experience.\\n\r\n", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "FreeBSD 8.4", "os": "other", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/c143724d-4d40-4871-bc2c-5120b4263ab3/", "size": 536870912, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.freebsd.org/", "uuid": "c143724d-4d40-4871-bc2c-5120b4263ab3" }, { "affinities": [], "allow_multimount": false, "arch": "32", "category": [ "general" ], "description": "Ubuntu 12.04 Desktop - 32bit - Install CD", "favourite": true, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Ubuntu 12.04 Desktop", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/703e693e-056d-4cd6-9531-36ec045fee7c/", "size": 1000000000, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.ubuntu.com/", "uuid": "703e693e-056d-4cd6-9531-36ec045fee7c" }, { "affinities": [], "allow_multimount": false, "arch": "32", "category": [ "general" ], "description": "Ubuntu 12.04 Server - 32bit - Install CD", "favourite": true, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. \r\n", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Ubuntu 12.04 Server", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/36b01118-55f4-454f-92ee-578eb6d99867/", "size": 1000000000, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.ubuntu.com/", "uuid": "36b01118-55f4-454f-92ee-578eb6d99867" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Windows Server 2012 Standard - 64bit Install CD", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD \\n Please be aware that the CD needs to be attached to the server to IDE. \\n \\n 2. Attach a Drive \\n Please be aware that the minimum drive size where you are going to install the OS should be 32 GB. \\n \\n 3. Connecting to your server via VNC \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 4. Minimum Hardware Requirements \\n The recommended minimum hardware requirements as publishes by Microsoft can be found through the following link: http://msdn.microsoft.com/library/dn303418.aspx We recommend specifying a higher level of RAM for a better user experience. \\n \\n 5. Enter your license key. \\n", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Windows Server Standard 2012", "os": "windows", "owner": null, "paid": true, "resource_uri": "/api/2.0/libdrives/b4273b6d-b227-4966-9e6e-5d48cebfcaa5/", "size": 3694116864, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.microsoft.com/", "uuid": "b4273b6d-b227-4966-9e6e-5d48cebfcaa5" }, { "affinities": [], "allow_multimount": false, "arch": "32", "category": [ "general" ], "description": "Knoppix 6 - 32bit - CD", "favourite": false, "image_type": "live", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Knoppix.net are: 512MB RAM and 512MHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Knoppix 6.4.3", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/ed47dc6d-4efd-4c05-b2f8-ab32ccf6de3b/", "size": 3670016000, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://knoppix.net/", "uuid": "ed47dc6d-4efd-4c05-b2f8-ab32ccf6de3b" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "This image is produced by SixSq specifically to work with SlipStream.", "favourite": false, "image_type": "preinst", "install_notes": "", "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "ubuntu-10.04-toMP", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/5236b9ee-f735-42fd-a236-17558f9e12d3/", "size": 3221225472, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "5236b9ee-f735-42fd-a236-17558f9e12d3" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "CentOS 6.4 Server - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/30.", "favourite": false, "image_type": "preinst", "install_notes": "1. Clone the Image.\\n\r\nThe image needs to be cloned and then attached to the server.\\n\r\n\\n\r\n2. Connecting to your server via VNC.\\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI.\\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window.\\n\r\nc) Start to configure your server.\\n\r\n\\n\r\n3. Minimum Hardware Requirements.\\n\r\nThe recommended minimum hardware requirements as publishes by centos.org: 0.5GB RAM and 0.5GHz CPU\\n\r\n\\n\r\n4. Update your administrator password.\\n\r\nBy default and for security reasons \"root\" login is completely disabled (including for ssh)\\n\r\nUser \"cloudsigma\" with password \"cloudsigma\" is available for access.\\n\r\nPlease be aware that on the first login you will be asked to change the current password \"cloudsigma\" and set a secure password.\\n\r\nFor \"root\" please use the command \"sudo su\"\\n\r\n\\n\r\n5. Setup your CentOS.\\n\r\n\\n\r\n6. Configuring your Networking.\\n\r\na) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will assign the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings.\\n\r\nb) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs.\\n", "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "CentOS 6.4 Server", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/cc08cd15-0c17-429f-bd56-15fefaca9d88/", "size": 10737418240, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.centos.org/", "uuid": "cc08cd15-0c17-429f-bd56-15fefaca9d88" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Debian 6.0.7 - amd64 Pre-Installed English with SSH and VirtIO support. Last update on 2013/09/28.", "favourite": false, "image_type": "preinst", "install_notes": "Intall notes:\t1. Clone the Image. \\n The image needs to be cloned and then attached to the server. \\n \\n 2. Connecting to your server via VNC. \\n a) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n b) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n c) Start to configure your server. \\n \\n 3. Minimum Hardware Requirements. \\n The recommended minimum hardware requirements as publishes by Debian.org: 1GB RAM and 1GHrz CPU \\n \\n 4. Update your administrator password. \\n Please be aware that on startup you will be asked to enter the current password \"password123\" and set a secure password. \\n \\n 5. Setup your Debian. \\n By default the timezone and the language are set to Switzerland. \\n \\n 6. Configuring your Networking. \\n a) IP networking can be left as DHCP. Even if you are using a static IP address with this server our management layer will apply the same IP address via DHCP. Using DHCP ensures you will have no issues receiving the correct networking settings. We recommend using DHCP initially if only to receive all the correct networking settings. \\n b) CloudSigma employs an open networking infrastructure. All ports are open for inbound and outbound traffic with the exception of port 25 (SMTP) which is blocked for trial users. It is important that you secure access to your server according to your needs. \\n", "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "Debian 6.0.7 Desktop", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/e848e216-76bb-4c1d-a376-54e4bdf54fe4/", "size": 10737418240, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.debian.org/", "uuid": "e848e216-76bb-4c1d-a376-54e4bdf54fe4" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "CentOS 6.3 - 64bit - DVD\r\n", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5 GB RAM and 0.5 GHz CPU We recommend specifying a higher level of RAM for a better user experience.", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "CentOS 6.3 DVD", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/65c99e46-296c-4d3f-ad1f-88dc06772624/", "size": 4289396736, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "65c99e46-296c-4d3f-ad1f-88dc06772624" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "CentOS 6.4 - 64bit - DVD\r\n", "favourite": false, "image_type": "install", "install_notes": "1. Attach the DVD. \\n\r\nPlease be aware that the DVD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5GB RAM and 0.5GHz CPU We recommend specifying a higher level of RAM for a better user experience.", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "CentOS 6.4 DVD", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/608e784a-5bff-4d25-afeb-bf7f998f56ef/", "size": 4353392640, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "608e784a-5bff-4d25-afeb-bf7f998f56ef" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Ubuntu 10.04.3 LTS Server Edition 64bit - CD", "favourite": true, "image_type": "install", "install_notes": "\r\n1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu,com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Ubuntu 10.04.3 Server", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/b69cbf27-d2a8-44f7-bc5a-3facc70021a8/", "size": 1000000000, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://ubuntu.com/", "uuid": "b69cbf27-d2a8-44f7-bc5a-3facc70021a8" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Slackware-13.37 - 64bit - Install DVD", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Slackware.com are: 128MB RAM and 512MHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Slackware 13.37", "os": "linux", "owner": null, "paid": true, "resource_uri": "/api/2.0/libdrives/e209e588-8c06-44ce-8d57-c10df32c5876/", "size": 4613734400, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "e209e588-8c06-44ce-8d57-c10df32c5876" }, { "affinities": [], "allow_multimount": false, "arch": "32", "category": [ "general" ], "description": "RedHat Enterprise 6.0 - 32bit - Install DVD", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by RedHat.com are: 2GB RAM and 2GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "RedHat Enterprise 6.0", "os": "linux", "owner": null, "paid": true, "resource_uri": "/api/2.0/libdrives/a0638d80-bc5b-48a3-a7ba-dec2416239bf/", "size": 2936012800, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.redhat.com/", "uuid": "a0638d80-bc5b-48a3-a7ba-dec2416239bf" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "CentOS 6.3 SlipStream. This image is produced by SixSq specifically to work with SlipStream.", "favourite": false, "image_type": "preinst", "install_notes": "CentOS 6.3 SlipStream", "jobs": [], "licenses": [], "media": "disk", "meta": {}, "mounted_on": [], "name": "CentOS 6.3 for SlipStream", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/ac51c08f-d22b-4da8-9591-d343947f7455/", "size": 7516192768, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "ac51c08f-d22b-4da8-9591-d343947f7455" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Debian 6 - 64bit - CD", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Debian 6", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/98f810a3-b8f0-4441-89cd-02be4f2614d7/", "size": 676331520, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "98f810a3-b8f0-4441-89cd-02be4f2614d7" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Ubuntu 12.10 Server - 64bit - Install CD", "favourite": true, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Ubuntu.com are: 0.5GB RAM and 0.5GHrz CPU We recommend specifying a higher level of RAM for a better user experience. \r\n", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Ubuntu 12.10 Server", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/6afbda4b-1027-4405-9ae9-c7d32f097d31/", "size": 1000000000, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.ubuntu.com/", "uuid": "6afbda4b-1027-4405-9ae9-c7d32f097d31" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Debian 7.1 - 64bit - CD", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience.", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Debian 7.1", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/958bf26c-f25b-457d-aedb-a5cfb36bdeef/", "size": 536870912, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "958bf26c-f25b-457d-aedb-a5cfb36bdeef" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "CentOS 6.2 - 64bit - DVD\r\n", "favourite": false, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by centos.org are: 0.5 GB RAM and 0.5 GHz CPU We recommend specifying a higher level of RAM for a better user experience.\r\n", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "CentOS 6.2 DVD", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/d7cdd30f-2197-47ac-a878-c285c1e67426/", "size": 4423139328, "status": "unmounted", "storage_type": null, "tags": [], "url": "", "uuid": "d7cdd30f-2197-47ac-a878-c285c1e67426" }, { "affinities": [], "allow_multimount": false, "arch": "64", "category": [ "general" ], "description": "Debian 5.0 - 64bit - CD", "favourite": true, "image_type": "install", "install_notes": "1. Attach the CD. \\n\r\nPlease be aware that the CD needs to be attached to the server to IDE. \r\n\\n\r\n \\n\r\n2. Attach a Drive. \\n\r\nPlease be aware that the minimum drive size where you are going to install the OS should be 5 GB. \r\n\\n\r\n \\n\r\n3. Connecting to your server via VNC. \\n\r\na) Having installed a compatible VNC client, open a VNC connection to your server through the UI. \\n\r\nb) Enter your VNC url and VNC password as displayed on your Server Properties Window. \\n\r\nc) Start to configure your server. \r\n\\n\r\n \\n\r\n4. Minimum Hardware Requirements. \\n\r\nThe recommended minimum hardware requirements as publishes by Debian.org are: 1GB RAM and 1GHrz CPU We recommend specifying a higher level of RAM for a better user experience. ", "jobs": [], "licenses": [], "media": "cdrom", "meta": {}, "mounted_on": [], "name": "Debian 5.0", "os": "linux", "owner": null, "paid": false, "resource_uri": "/api/2.0/libdrives/794a068d-228c-4758-81f0-e1bc955a6cce/", "size": 4697620480, "status": "unmounted", "storage_type": null, "tags": [], "url": "http://www.debian.org/", "uuid": "794a068d-228c-4758-81f0-e1bc955a6cce" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/pricing.json0000664000175000017500000023171613535474530027664 0ustar kamikami00000000000000{ "current": { "cpu": 5, "dssd": 1, "ip": 1, "mem": 7, "msft_7jq_00341": 1, "msft_7nq_00302": 1, "msft_lwa_00135": 1, "msft_p71_01031": 1, "msft_p73_04837": 1, "msft_p73_04837_core": 1, "msft_tfa_00009": 1, "msft_tfa_00523": 1, "sms": 1, "ssd": 1, "tx": 8, "vlan": 1 }, "meta": { "limit": 0, "offset": 0, "total_count": 316 }, "next": { "cpu": 5, "dssd": 1, "ip": 1, "mem": 7, "msft_7jq_00341": 1, "msft_7nq_00302": 1, "msft_lwa_00135": 1, "msft_p71_01031": 1, "msft_p73_04837": 1, "msft_p73_04837_core": 1, "msft_tfa_00009": 1, "msft_tfa_00523": 1, "sms": 1, "ssd": 1, "tx": 10, "vlan": 1 }, "objects": [ { "currency": "CHF", "id": "18", "level": 1, "multiplier": 2783138807808000, "price": "0.26600000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "EUR", "id": "20", "level": 1, "multiplier": 2783138807808000, "price": "0.21000000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "GBP", "id": "22", "level": 1, "multiplier": 2783138807808000, "price": "0.18200000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "USD", "id": "24", "level": 1, "multiplier": 2783138807808000, "price": "0.28000000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "CHF", "id": "26", "level": 1, "multiplier": 2783138807808000, "price": "0.76000000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "EUR", "id": "28", "level": 1, "multiplier": 2783138807808000, "price": "0.60000000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "GBP", "id": "30", "level": 1, "multiplier": 2783138807808000, "price": "0.52000000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "USD", "id": "32", "level": 1, "multiplier": 2783138807808000, "price": "0.80000000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "CHF", "id": "34", "level": 1, "multiplier": 2592000, "price": "4.75000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "EUR", "id": "36", "level": 1, "multiplier": 2592000, "price": "3.75000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "GBP", "id": "38", "level": 1, "multiplier": 2592000, "price": "3.25000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "USD", "id": "40", "level": 1, "multiplier": 2592000, "price": "5.00000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "USD", "id": "8", "level": 1, "multiplier": 3600000, "price": "0.00790500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "42", "level": 1, "multiplier": 2592000, "price": "19.00000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "USD", "id": "104", "level": 2, "multiplier": 3600000, "price": "0.00816000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "44", "level": 1, "multiplier": 2592000, "price": "15.00000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "USD", "id": "108", "level": 3, "multiplier": 3600000, "price": "0.00841500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "46", "level": 1, "multiplier": 2592000, "price": "13.00000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "USD", "id": "112", "level": 4, "multiplier": 3600000, "price": "0.00867000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "48", "level": 1, "multiplier": 2592000, "price": "20.00000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "CHF", "id": "2", "level": 1, "multiplier": 3600000, "price": "0.00875500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "54", "level": 1, "multiplier": 1073741824, "price": "0.01950000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "101", "level": 2, "multiplier": 3600000, "price": "0.00901000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "105", "level": 3, "multiplier": 3600000, "price": "0.00935000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "109", "level": 4, "multiplier": 3600000, "price": "0.00960500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "113", "level": 5, "multiplier": 3600000, "price": "0.01028500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "117", "level": 6, "multiplier": 3600000, "price": "0.01088000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "121", "level": 7, "multiplier": 3600000, "price": "0.01207000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "125", "level": 8, "multiplier": 3600000, "price": "0.01385500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "10", "level": 1, "multiplier": 3865470566400, "price": "0.01256000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "133", "level": 10, "multiplier": 3865470566400, "price": "0.02080000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "137", "level": 11, "multiplier": 3865470566400, "price": "0.02192000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "141", "level": 12, "multiplier": 3865470566400, "price": "0.02288000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "116", "level": 5, "multiplier": 3600000, "price": "0.00926500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "120", "level": 6, "multiplier": 3600000, "price": "0.00977500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "124", "level": 7, "multiplier": 3600000, "price": "0.01088000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "16", "level": 1, "multiplier": 3865470566400, "price": "0.01128000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "136", "level": 10, "multiplier": 3865470566400, "price": "0.01872000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "140", "level": 11, "multiplier": 3865470566400, "price": "0.01968000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "144", "level": 12, "multiplier": 3865470566400, "price": "0.02064000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "148", "level": 13, "multiplier": 3865470566400, "price": "0.02136000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "152", "level": 14, "multiplier": 3865470566400, "price": "0.02184000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "156", "level": 15, "multiplier": 3865470566400, "price": "0.02232000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "160", "level": 16, "multiplier": 3865470566400, "price": "0.02280000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "4", "level": 1, "multiplier": 3600000, "price": "0.00612000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "102", "level": 2, "multiplier": 3600000, "price": "0.00637500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "106", "level": 3, "multiplier": 3600000, "price": "0.00654500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "110", "level": 4, "multiplier": 3600000, "price": "0.00671500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "114", "level": 5, "multiplier": 3600000, "price": "0.00714000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "128", "level": 8, "multiplier": 3600000, "price": "0.01249500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "132", "level": 9, "multiplier": 3600000, "price": "0.01411000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "60", "level": 10, "multiplier": 3600000, "price": "0.01623500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "64", "level": 11, "multiplier": 3600000, "price": "0.01734000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "68", "level": 12, "multiplier": 3600000, "price": "0.01844500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "72", "level": 13, "multiplier": 3600000, "price": "0.01921000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "76", "level": 14, "multiplier": 3600000, "price": "0.01980500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "80", "level": 15, "multiplier": 3600000, "price": "0.02031500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "118", "level": 6, "multiplier": 3600000, "price": "0.00756500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "122", "level": 7, "multiplier": 3600000, "price": "0.00841500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "126", "level": 8, "multiplier": 3600000, "price": "0.00969000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "130", "level": 9, "multiplier": 3600000, "price": "0.01096500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "58", "level": 10, "multiplier": 3600000, "price": "0.01266500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "62", "level": 11, "multiplier": 3600000, "price": "0.01351500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "66", "level": 12, "multiplier": 3600000, "price": "0.01428000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "145", "level": 13, "multiplier": 3865470566400, "price": "0.02376000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "149", "level": 14, "multiplier": 3865470566400, "price": "0.02424000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "153", "level": 15, "multiplier": 3865470566400, "price": "0.02480000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "157", "level": 16, "multiplier": 3865470566400, "price": "0.02536000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "50", "level": 1, "multiplier": 1073741824, "price": "0.03250000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "253", "level": 2, "multiplier": 1073741824, "price": "0.03420000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "257", "level": 3, "multiplier": 1073741824, "price": "0.03750000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "261", "level": 4, "multiplier": 1073741824, "price": "0.04250000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "265", "level": 5, "multiplier": 1073741824, "price": "0.04750000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "269", "level": 6, "multiplier": 1073741824, "price": "0.05170000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "273", "level": 7, "multiplier": 1073741824, "price": "0.05580000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "277", "level": 8, "multiplier": 1073741824, "price": "0.05920000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "281", "level": 9, "multiplier": 1073741824, "price": "0.06250000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "209", "level": 10, "multiplier": 1073741824, "price": "0.06500000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "213", "level": 11, "multiplier": 1073741824, "price": "0.06750000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "217", "level": 12, "multiplier": 1073741824, "price": "0.07000000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "221", "level": 13, "multiplier": 1073741824, "price": "0.07330000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "225", "level": 14, "multiplier": 1073741824, "price": "0.07830000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "229", "level": 15, "multiplier": 1073741824, "price": "0.08330000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "233", "level": 16, "multiplier": 1073741824, "price": "0.08830000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "84", "level": 16, "multiplier": 3600000, "price": "0.02091000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "5", "level": 0, "multiplier": 3600000, "price": "0.01105000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "13", "level": 0, "multiplier": 3865470566400, "price": "0.01352000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "53", "level": 0, "multiplier": 1073741824, "price": "0.04225000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "255", "level": 2, "multiplier": 1073741824, "price": "0.02050000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "129", "level": 9, "multiplier": 3600000, "price": "0.01564000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "57", "level": 10, "multiplier": 3600000, "price": "0.01810500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "61", "level": 11, "multiplier": 3600000, "price": "0.01929500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "65", "level": 12, "multiplier": 3600000, "price": "0.02048500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "69", "level": 13, "multiplier": 3600000, "price": "0.02142000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "73", "level": 14, "multiplier": 3600000, "price": "0.02193000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "77", "level": 15, "multiplier": 3600000, "price": "0.02261000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "81", "level": 16, "multiplier": 3600000, "price": "0.02320500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "259", "level": 3, "multiplier": 1073741824, "price": "0.02250000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "85", "level": 17, "multiplier": 3600000, "price": "0.02558500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "263", "level": 4, "multiplier": 1073741824, "price": "0.02550000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "89", "level": 18, "multiplier": 3600000, "price": "0.02805000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "267", "level": 5, "multiplier": 1073741824, "price": "0.02850000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "271", "level": 6, "multiplier": 1073741824, "price": "0.03100000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "210", "level": 10, "multiplier": 1073741824, "price": "0.04550000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "212", "level": 10, "multiplier": 1073741824, "price": "0.05850000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "275", "level": 7, "multiplier": 1073741824, "price": "0.03350000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "214", "level": 11, "multiplier": 1073741824, "price": "0.04730000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "216", "level": 11, "multiplier": 1073741824, "price": "0.06080000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "279", "level": 8, "multiplier": 1073741824, "price": "0.03550000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "218", "level": 12, "multiplier": 1073741824, "price": "0.04900000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "220", "level": 12, "multiplier": 1073741824, "price": "0.06300000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "283", "level": 9, "multiplier": 1073741824, "price": "0.03750000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "222", "level": 13, "multiplier": 1073741824, "price": "0.05130000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "224", "level": 13, "multiplier": 1073741824, "price": "0.06600000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "211", "level": 10, "multiplier": 1073741824, "price": "0.03900000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "226", "level": 14, "multiplier": 1073741824, "price": "0.05480000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "228", "level": 14, "multiplier": 1073741824, "price": "0.07050000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "215", "level": 11, "multiplier": 1073741824, "price": "0.04050000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "230", "level": 15, "multiplier": 1073741824, "price": "0.05830000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "232", "level": 15, "multiplier": 1073741824, "price": "0.07500000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "219", "level": 12, "multiplier": 1073741824, "price": "0.04200000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "234", "level": 16, "multiplier": 1073741824, "price": "0.06180000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "236", "level": 16, "multiplier": 1073741824, "price": "0.07950000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "223", "level": 13, "multiplier": 1073741824, "price": "0.04400000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "238", "level": 17, "multiplier": 1073741824, "price": "0.06530000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "240", "level": 17, "multiplier": 1073741824, "price": "0.08400000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "227", "level": 14, "multiplier": 1073741824, "price": "0.04700000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "242", "level": 18, "multiplier": 1073741824, "price": "0.07000000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "244", "level": 18, "multiplier": 1073741824, "price": "0.09000000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "231", "level": 15, "multiplier": 1073741824, "price": "0.05000000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "246", "level": 19, "multiplier": 1073741824, "price": "0.07580000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "248", "level": 19, "multiplier": 1073741824, "price": "0.09750000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "52", "level": 1, "multiplier": 1073741824, "price": "0.02280000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "56", "level": 1, "multiplier": 1073741824, "price": "0.02930000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "235", "level": 16, "multiplier": 1073741824, "price": "0.05300000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "250", "level": 20, "multiplier": 1073741824, "price": "0.08280000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "252", "level": 20, "multiplier": 1073741824, "price": "0.10650000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "239", "level": 17, "multiplier": 1073741824, "price": "0.05600000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "254", "level": 2, "multiplier": 1073741824, "price": "0.02390000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "256", "level": 2, "multiplier": 1073741824, "price": "0.03080000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "243", "level": 18, "multiplier": 1073741824, "price": "0.06000000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "258", "level": 3, "multiplier": 1073741824, "price": "0.02630000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "260", "level": 3, "multiplier": 1073741824, "price": "0.03380000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "247", "level": 19, "multiplier": 1073741824, "price": "0.06500000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "262", "level": 4, "multiplier": 1073741824, "price": "0.02980000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "264", "level": 4, "multiplier": 1073741824, "price": "0.03830000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "GBP", "id": "251", "level": 20, "multiplier": 1073741824, "price": "0.07100000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "266", "level": 5, "multiplier": 1073741824, "price": "0.03330000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "268", "level": 5, "multiplier": 1073741824, "price": "0.04280000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "270", "level": 6, "multiplier": 1073741824, "price": "0.03620000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "272", "level": 6, "multiplier": 1073741824, "price": "0.04650000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "274", "level": 7, "multiplier": 1073741824, "price": "0.03910000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "276", "level": 7, "multiplier": 1073741824, "price": "0.05030000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "278", "level": 8, "multiplier": 1073741824, "price": "0.04140000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "280", "level": 8, "multiplier": 1073741824, "price": "0.05330000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "282", "level": 9, "multiplier": 1073741824, "price": "0.04380000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "284", "level": 9, "multiplier": 1073741824, "price": "0.05630000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "180", "level": 2, "multiplier": 3865470566400, "price": "0.01152000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "93", "level": 19, "multiplier": 3600000, "price": "0.03162000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "CHF", "id": "97", "level": 20, "multiplier": 3600000, "price": "0.03638000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "184", "level": 3, "multiplier": 3865470566400, "price": "0.01176000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "306", "level": 0, "multiplier": 2592000, "price": "15.69000000000000000000", "resource": "msft_7nq_00302", "unit": "" }, { "currency": "CHF", "id": "297", "level": 0, "multiplier": 2592000, "price": "8.50000000000000000000", "resource": "msft_p71_01031", "unit": "" }, { "currency": "CHF", "id": "301", "level": 0, "multiplier": 2592000, "price": "1.60000000000000000000", "resource": "msft_p73_04837_core", "unit": "" }, { "currency": "CHF", "id": "307", "level": 0, "multiplier": 2592000, "price": "0.98000000000000000000", "resource": "msft_tfa_00523", "unit": "" }, { "currency": "EUR", "id": "295", "level": 0, "multiplier": 2592000, "price": "350.00000000000000000000", "resource": "msft_tfa_00009", "unit": "count/month" }, { "currency": "EUR", "id": "313", "level": 0, "multiplier": 2592000, "price": "0.73010000000000000000", "resource": "msft_tfa_00523", "unit": "" }, { "currency": "GBP", "id": "314", "level": 0, "multiplier": 2592000, "price": "38.51520000000000000000", "resource": "msft_7jq_00341", "unit": "" }, { "currency": "GBP", "id": "315", "level": 0, "multiplier": 2592000, "price": "10.04160000000000000000", "resource": "msft_7nq_00302", "unit": "" }, { "currency": "GBP", "id": "288", "level": 0, "multiplier": 2592000, "price": "15.00000000000000000000", "resource": "msft_lwa_00135", "unit": "count/month" }, { "currency": "GBP", "id": "300", "level": 0, "multiplier": 2592000, "price": "5.44000000000000000000", "resource": "msft_p71_01031", "unit": "" }, { "currency": "GBP", "id": "292", "level": 0, "multiplier": 2592000, "price": "27.00000000000000000000", "resource": "msft_p73_04837", "unit": "count/month" }, { "currency": "GBP", "id": "304", "level": 0, "multiplier": 2592000, "price": "1.02400000000000000000", "resource": "msft_p73_04837_core", "unit": "" }, { "currency": "GBP", "id": "296", "level": 0, "multiplier": 2592000, "price": "300.00000000000000000000", "resource": "msft_tfa_00009", "unit": "count/month" }, { "currency": "GBP", "id": "316", "level": 0, "multiplier": 2592000, "price": "0.62720000000000000000", "resource": "msft_tfa_00523", "unit": "" }, { "currency": "USD", "id": "188", "level": 4, "multiplier": 3865470566400, "price": "0.01200000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "192", "level": 5, "multiplier": 3865470566400, "price": "0.01248000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "196", "level": 6, "multiplier": 3865470566400, "price": "0.01296000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "200", "level": 7, "multiplier": 3865470566400, "price": "0.01392000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "204", "level": 8, "multiplier": 3865470566400, "price": "0.01536000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "208", "level": 9, "multiplier": 3865470566400, "price": "0.01680000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "164", "level": 17, "multiplier": 3865470566400, "price": "0.02472000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "168", "level": 18, "multiplier": 3865470566400, "price": "0.02664000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "172", "level": 19, "multiplier": 3865470566400, "price": "0.02952000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "176", "level": 20, "multiplier": 3865470566400, "price": "0.03336000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "178", "level": 2, "multiplier": 3865470566400, "price": "0.00896000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "182", "level": 3, "multiplier": 3865470566400, "price": "0.00912000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "186", "level": 4, "multiplier": 3865470566400, "price": "0.00936000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "190", "level": 5, "multiplier": 3865470566400, "price": "0.00976000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "194", "level": 6, "multiplier": 3865470566400, "price": "0.01008000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "198", "level": 7, "multiplier": 3865470566400, "price": "0.01080000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "202", "level": 8, "multiplier": 3865470566400, "price": "0.01200000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "206", "level": 9, "multiplier": 3865470566400, "price": "0.01304000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "162", "level": 17, "multiplier": 3865470566400, "price": "0.01920000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "166", "level": 18, "multiplier": 3865470566400, "price": "0.02072000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "170", "level": 19, "multiplier": 3865470566400, "price": "0.02296000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "174", "level": 20, "multiplier": 3865470566400, "price": "0.02592000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "179", "level": 2, "multiplier": 3865470566400, "price": "0.00768000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "183", "level": 3, "multiplier": 3865470566400, "price": "0.00784000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "187", "level": 4, "multiplier": 3865470566400, "price": "0.00800000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "191", "level": 5, "multiplier": 3865470566400, "price": "0.00832000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "195", "level": 6, "multiplier": 3865470566400, "price": "0.00864000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "1", "level": 0, "multiplier": 3600000, "price": "0.01700000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "3", "level": 0, "multiplier": 3600000, "price": "0.01360000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "11", "level": 0, "multiplier": 3865470566400, "price": "0.01664000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "51", "level": 0, "multiplier": 1073741824, "price": "0.05200000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "EUR", "id": "19", "level": 0, "multiplier": 2783138807808000, "price": "0.16000000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "EUR", "id": "27", "level": 0, "multiplier": 2783138807808000, "price": "0.16000000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "EUR", "id": "35", "level": 0, "multiplier": 2592000, "price": "4.00000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "EUR", "id": "43", "level": 0, "multiplier": 2592000, "price": "8.00000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "GBP", "id": "21", "level": 0, "multiplier": 2783138807808000, "price": "0.01352000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "GBP", "id": "29", "level": 0, "multiplier": 2783138807808000, "price": "0.01352000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "GBP", "id": "37", "level": 0, "multiplier": 2592000, "price": "3.25000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "GBP", "id": "45", "level": 0, "multiplier": 2592000, "price": "6.50000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "CHF", "id": "9", "level": 0, "multiplier": 3865470566400, "price": "0.02080000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "49", "level": 0, "multiplier": 1073741824, "price": "0.06500000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "17", "level": 0, "multiplier": 2783138807808000, "price": "0.20000000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "CHF", "id": "25", "level": 0, "multiplier": 2783138807808000, "price": "0.45000000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "CHF", "id": "33", "level": 0, "multiplier": 2592000, "price": "5.00000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "CHF", "id": "41", "level": 0, "multiplier": 2592000, "price": "9.50000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "USD", "id": "7", "level": 0, "multiplier": 3600000, "price": "0.01640000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "15", "level": 0, "multiplier": 3865470566400, "price": "0.01840000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "USD", "id": "55", "level": 0, "multiplier": 1073741824, "price": "0.05850000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "23", "level": 0, "multiplier": 2783138807808000, "price": "0.18000000000000000000", "resource": "dssd", "unit": "GB/month" }, { "currency": "USD", "id": "31", "level": 0, "multiplier": 2783138807808000, "price": "0.47400000000000000000", "resource": "ssd", "unit": "GB/month" }, { "currency": "USD", "id": "39", "level": 0, "multiplier": 2592000, "price": "4.50000000000000000000", "resource": "ip", "unit": "IP" }, { "currency": "USD", "id": "47", "level": 0, "multiplier": 2592000, "price": "10.00000000000000000000", "resource": "vlan", "unit": "VLAN" }, { "currency": "CHF", "id": "177", "level": 2, "multiplier": 3865470566400, "price": "0.01280000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "181", "level": 3, "multiplier": 3865470566400, "price": "0.01304000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "185", "level": 4, "multiplier": 3865470566400, "price": "0.01328000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "189", "level": 5, "multiplier": 3865470566400, "price": "0.01392000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "193", "level": 6, "multiplier": 3865470566400, "price": "0.01440000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "197", "level": 7, "multiplier": 3865470566400, "price": "0.01552000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "201", "level": 8, "multiplier": 3865470566400, "price": "0.01712000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "205", "level": 9, "multiplier": 3865470566400, "price": "0.01872000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "161", "level": 17, "multiplier": 3865470566400, "price": "0.02744000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "165", "level": 18, "multiplier": 3865470566400, "price": "0.02960000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "169", "level": 19, "multiplier": 3865470566400, "price": "0.03280000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "173", "level": 20, "multiplier": 3865470566400, "price": "0.03704000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "237", "level": 17, "multiplier": 1073741824, "price": "0.09330000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "241", "level": 18, "multiplier": 1073741824, "price": "0.10000000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "245", "level": 19, "multiplier": 1073741824, "price": "0.10830000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "CHF", "id": "249", "level": 20, "multiplier": 1073741824, "price": "0.11830000000000000000", "resource": "tx", "unit": "GB" }, { "currency": "USD", "id": "88", "level": 17, "multiplier": 3600000, "price": "0.02303500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "92", "level": 18, "multiplier": 3600000, "price": "0.02524500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "96", "level": 19, "multiplier": 3600000, "price": "0.02847500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "USD", "id": "100", "level": 20, "multiplier": 3600000, "price": "0.03281000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "70", "level": 13, "multiplier": 3600000, "price": "0.01496000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "74", "level": 14, "multiplier": 3600000, "price": "0.01538500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "78", "level": 15, "multiplier": 3600000, "price": "0.01581000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "82", "level": 16, "multiplier": 3600000, "price": "0.01623500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "86", "level": 17, "multiplier": 3600000, "price": "0.01793500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "90", "level": 18, "multiplier": 3600000, "price": "0.01955000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "94", "level": 19, "multiplier": 3600000, "price": "0.02210000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "98", "level": 20, "multiplier": 3600000, "price": "0.02550000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "EUR", "id": "12", "level": 1, "multiplier": 3865470566400, "price": "0.00880000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "134", "level": 10, "multiplier": 3865470566400, "price": "0.01456000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "138", "level": 11, "multiplier": 3865470566400, "price": "0.01528000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "142", "level": 12, "multiplier": 3865470566400, "price": "0.01608000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "146", "level": 13, "multiplier": 3865470566400, "price": "0.01664000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "150", "level": 14, "multiplier": 3865470566400, "price": "0.01696000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "154", "level": 15, "multiplier": 3865470566400, "price": "0.01736000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "EUR", "id": "158", "level": 16, "multiplier": 3865470566400, "price": "0.01776000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "6", "level": 1, "multiplier": 3600000, "price": "0.00527000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "103", "level": 2, "multiplier": 3600000, "price": "0.00544000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "107", "level": 3, "multiplier": 3600000, "price": "0.00561000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "111", "level": 4, "multiplier": 3600000, "price": "0.00578000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "115", "level": 5, "multiplier": 3600000, "price": "0.00612000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "119", "level": 6, "multiplier": 3600000, "price": "0.00654500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "123", "level": 7, "multiplier": 3600000, "price": "0.00722500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "127", "level": 8, "multiplier": 3600000, "price": "0.00833000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "131", "level": 9, "multiplier": 3600000, "price": "0.00943500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "59", "level": 10, "multiplier": 3600000, "price": "0.01088000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "63", "level": 11, "multiplier": 3600000, "price": "0.01156000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "67", "level": 12, "multiplier": 3600000, "price": "0.01232500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "71", "level": 13, "multiplier": 3600000, "price": "0.01283500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "75", "level": 14, "multiplier": 3600000, "price": "0.01326000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "79", "level": 15, "multiplier": 3600000, "price": "0.01360000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "83", "level": 16, "multiplier": 3600000, "price": "0.01394000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "87", "level": 17, "multiplier": 3600000, "price": "0.01538500000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "91", "level": 18, "multiplier": 3600000, "price": "0.01683000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "95", "level": 19, "multiplier": 3600000, "price": "0.01904000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "99", "level": 20, "multiplier": 3600000, "price": "0.02193000000000000000", "resource": "cpu", "unit": "GHz/hour" }, { "currency": "GBP", "id": "14", "level": 1, "multiplier": 3865470566400, "price": "0.00752000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "199", "level": 7, "multiplier": 3865470566400, "price": "0.00928000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "203", "level": 8, "multiplier": 3865470566400, "price": "0.01024000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "207", "level": 9, "multiplier": 3865470566400, "price": "0.01120000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "135", "level": 10, "multiplier": 3865470566400, "price": "0.01248000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "139", "level": 11, "multiplier": 3865470566400, "price": "0.01312000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "143", "level": 12, "multiplier": 3865470566400, "price": "0.01376000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "147", "level": 13, "multiplier": 3865470566400, "price": "0.01424000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "151", "level": 14, "multiplier": 3865470566400, "price": "0.01456000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "155", "level": 15, "multiplier": 3865470566400, "price": "0.01488000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "159", "level": 16, "multiplier": 3865470566400, "price": "0.01520000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "163", "level": 17, "multiplier": 3865470566400, "price": "0.01648000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "167", "level": 18, "multiplier": 3865470566400, "price": "0.01776000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "171", "level": 19, "multiplier": 3865470566400, "price": "0.01968000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "GBP", "id": "175", "level": 20, "multiplier": 3865470566400, "price": "0.02224000000000000000", "resource": "mem", "unit": "GB/hour" }, { "currency": "CHF", "id": "305", "level": 0, "multiplier": 2592000, "price": "60.18000000000000000000", "resource": "msft_7jq_00341", "unit": "" }, { "currency": "CHF", "id": "285", "level": 0, "multiplier": 2592000, "price": "25.00000000000000000000", "resource": "msft_lwa_00135", "unit": "count/month" }, { "currency": "CHF", "id": "289", "level": 0, "multiplier": 2592000, "price": "45.00000000000000000000", "resource": "msft_p73_04837", "unit": "count/month" }, { "currency": "CHF", "id": "293", "level": 0, "multiplier": 2592000, "price": "500.00000000000000000000", "resource": "msft_tfa_00009", "unit": "count/month" }, { "currency": "USD", "id": "308", "level": 0, "multiplier": 2592000, "price": "58.07370000000000000000", "resource": "msft_7jq_00341", "unit": "" }, { "currency": "USD", "id": "309", "level": 0, "multiplier": 2592000, "price": "15.14085000000000000000", "resource": "msft_7nq_00302", "unit": "" }, { "currency": "USD", "id": "286", "level": 0, "multiplier": 2592000, "price": "22.50000000000000000000", "resource": "msft_lwa_00135", "unit": "count/month" }, { "currency": "USD", "id": "298", "level": 0, "multiplier": 2592000, "price": "8.20250000000000000000", "resource": "msft_p71_01031", "unit": "" }, { "currency": "USD", "id": "290", "level": 0, "multiplier": 2592000, "price": "40.50000000000000000000", "resource": "msft_p73_04837", "unit": "count/month" }, { "currency": "USD", "id": "302", "level": 0, "multiplier": 2592000, "price": "1.54400000000000000000", "resource": "msft_p73_04837_core", "unit": "" }, { "currency": "USD", "id": "294", "level": 0, "multiplier": 2592000, "price": "450.00000000000000000000", "resource": "msft_tfa_00009", "unit": "count/month" }, { "currency": "USD", "id": "310", "level": 0, "multiplier": 2592000, "price": "0.94570000000000000000", "resource": "msft_tfa_00523", "unit": "" }, { "currency": "EUR", "id": "311", "level": 0, "multiplier": 2592000, "price": "44.83410000000000000000", "resource": "msft_7jq_00341", "unit": "" }, { "currency": "EUR", "id": "312", "level": 0, "multiplier": 2592000, "price": "11.68905000000000000000", "resource": "msft_7nq_00302", "unit": "" }, { "currency": "EUR", "id": "287", "level": 0, "multiplier": 2592000, "price": "17.50000000000000000000", "resource": "msft_lwa_00135", "unit": "count/month" }, { "currency": "EUR", "id": "299", "level": 0, "multiplier": 2592000, "price": "6.33250000000000000000", "resource": "msft_p71_01031", "unit": "" }, { "currency": "EUR", "id": "291", "level": 0, "multiplier": 2592000, "price": "31.50000000000000000000", "resource": "msft_p73_04837", "unit": "count/month" }, { "currency": "EUR", "id": "303", "level": 0, "multiplier": 2592000, "price": "1.19200000000000000000", "resource": "msft_p73_04837_core", "unit": "" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_attach_policy.json0000664000175000017500000000231113535474530032610 0ustar kamikami00000000000000{ "context": true, "cpu": 2000, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 536870912, "meta": {}, "name": "test_server_updated", "nics": [ { "boot_order": null, "firewall_policy": { "resource_uri": "/api/2.0/fwpolicies/461dfb8c-e641-43d7-a20e-32e2aa399086/", "uuid": "461dfb8c-e641-43d7-a20e-32e2aa399086" }, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:58:83:c4:07:fc", "model": "virtio", "runtime": null, "vlan": null } ], "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "requirements": [], "resource_uri": "/api/2.0/servers/d6bde7f2-69ca-4825-909b-fcc08ea928ef/", "runtime": null, "smp": 1, "status": "stopped", "tags": [], "uuid": "d6bde7f2-69ca-4825-909b-fcc08ea928ef", "vnc_password": "updated_password" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_avail_groups.json0000664000175000017500000000042713535474530032466 0ustar kamikami00000000000000[ [ "63456dc4-36f9-4a3f-b478-4d376b8ff5a9", "ede05e68-c997-4aad-816a-39469fd1a562" ], [ "ad8caf99-45c4-45fc-8ba7-acb8a68be66f", "4b9e1487-0b80-4f65-9c3e-e840dde27ccd" ], [ "658bafdf-8fbf-4fc6-be4f-74ecc7f0e8a5" ] ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_clone.json0000664000175000017500000000332413535474530031072 0ustar kamikami00000000000000{ "context": true, "cpu": 1000, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [ { "boot_order": 1, "dev_channel": "0:0", "device": "ide", "drive": { "resource_uri": "/api/2.0/drives/f1e42abe-f7db-4dcc-b37e-e53aca7a3ba9/", "uuid": "f1e42abe-f7db-4dcc-b37e-e53aca7a3ba9" } } ], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 2147483648, "meta": { "description": "ddd", "ssh_public_key": "" }, "name": "test cloned node", "nics": [ { "boot_order": null, "firewall_policy": { "resource_uri": "/api/2.0/fwpolicies/461dfb8c-e641-43d7-a20e-32e2aa399086/", "uuid": "461dfb8c-e641-43d7-a20e-32e2aa399086" }, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:76:4c:96:e1:98", "model": "virtio", "runtime": null, "vlan": null } ], "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "requirements": [], "resource_uri": "/api/2.0/servers/470ea5b9-3beb-4506-9cac-e3c63002480b/", "runtime": null, "smp": 1, "status": "cloning", "tags": [ { "resource_uri": "/api/2.0/tags/e60bb2d2-08d4-4255-adac-5faf87efcdd2/", "uuid": "e60bb2d2-08d4-4255-adac-5faf87efcdd2" } ], "uuid": "470ea5b9-3beb-4506-9cac-e3c63002480b", "vnc_password": "xxxx" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_close_vnc.json0000664000175000017500000000015313535474530031742 0ustar kamikami00000000000000{ "action": "close_vnc", "result": "success", "uuid": "2e64e5e4-f31d-471a-ac1b-1ae079652e40" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create.json0000664000175000017500000000255513535474530031242 0ustar kamikami00000000000000{ "objects": [ { "context": true, "cpu": 1000, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 536870912, "meta": {}, "name": "test node", "nics": [ { "boot_order": null, "firewall_policy": null, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:08:76:b1:ce:41", "model": "virtio", "runtime": null, "vlan": null } ], "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "requirements": [], "resource_uri": "/api/2.0/servers/9de75ed6_fd33_45e2_963f_d405f31fd911/", "runtime": null, "smp": 1, "status": "started", "tags": [], "uuid": "9de75ed6_fd33_45e2_963f_d405f31fd911", "vnc_password": "testserver" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_create_with_vlan.json0000664000175000017500000000447213535474530033315 0ustar kamikami00000000000000{ "objects": [ { "context": true, "cpu": 1100, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [ { "boot_order": 1, "dev_channel": "0:0", "device": "ide", "drive": { "resource_uri": "/api/2.0/drives/7c0efbb2-b1e8-4e77-9d72-9f9f9d75ae7b/", "uuid": "7c0efbb2-b1e8-4e77-9d72-9f9f9d75ae7b" }, "runtime": null } ], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 671088640, "meta": {}, "name": "test node vlan", "nics": [ { "boot_order": null, "firewall_policy": null, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:94:75:3c:16:34", "model": "virtio", "runtime": null, "vlan": null }, { "boot_order": null, "firewall_policy": null, "ip_v4_conf": null, "ip_v6_conf": null, "mac": "22:84:c4:af:f3:fc", "model": "virtio", "runtime": null, "vlan": { "resource_uri": "/api/2.0/vlans/39ae851d-433f-4ac2-a803-ffa24cb1fa3e/", "uuid": "39ae851d-433f-4ac2-a803-ffa24cb1fa3e" } } ], "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "requirements": [], "resource_uri": "/api/2.0/servers/c8b034fb-9e66-4892-be12-a36121d4b704/", "runtime": null, "smp": 1, "status": "stopped", "tags": [], "uuid": "9de75ed6_fd33_45e2_963f_d405f31fd911", "vnc_password": "testserver" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_all_stopped.json0000664000175000017500000000645313535474530033630 0ustar kamikami00000000000000{ "meta": { "limit": 20, "offset": 0, "total_count": 2 }, "objects": [ { "context": true, "cpu": 1000, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 1073741824, "meta": { "description": "test description 2", "ssh_public_key": "" }, "name": "test no drives", "nics": [ { "boot_order": null, "firewall_policy": null, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:98:ce:04:50:df", "model": "virtio", "runtime": null, "vlan": null } ], "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "requirements": [], "resource_uri": "/api/2.0/servers/9de75ed6-fd33-45e2-963f-d405f31fd911/", "runtime": null, "smp": 1, "status": "stopped", "tags": [], "uuid": "9de75ed6-fd33-45e2-963f-d405f31fd911", "vnc_password": "bar" }, { "context": true, "cpu": 2000, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [ { "boot_order": 1, "dev_channel": "0:0", "device": "ide", "drive": { "resource_uri": "/api/2.0/drives/3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9/", "uuid": "3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9" } } ], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 2147483648, "meta": { "description": "test1" }, "name": "test-1", "nics": [ { "boot_order": null, "firewall_policy": null, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:22:4e:1e:e0:7e", "model": "virtio", "runtime": null, "vlan": null } ], "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "requirements": [], "resource_uri": "/api/2.0/servers/9414bbeb-e908-4e55-ae3f-2eb61adc50d8/", "runtime": null, "smp": 1, "status": "stopped", "tags": [], "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8", "vnc_password": "foo" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_detail_mixed_state.json0000664000175000017500000001305113535474530033620 0ustar kamikami00000000000000{ "meta": { "limit": 20, "offset": 0, "total_count": 2 }, "objects": [ { "context": true, "cpu": 1000, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 1073741824, "meta": { "description": "test description 2", "ssh_public_key": "" }, "name": "test no drives", "nics": [ { "boot_order": null, "firewall_policy": null, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:98:ce:04:50:df", "model": "virtio", "runtime": { "interface_type": "public", "io": { "bytes_recv": "1323", "bytes_sent": "21535", "packets_recv": "3", "packets_sent": "278" }, "ip_v4": { "resource_uri": "/api/2.0/ips/185.12.5.181/", "uuid": "185.12.5.181" }, "ip_v6": null }, "vlan": null }, { "boot_order": null, "firewall_policy": null, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:2c:03:99:32:be", "model": "virtio", "runtime": { "interface_type": "public", "io": { "bytes_recv": "0", "bytes_sent": "0", "packets_recv": "0", "packets_sent": "0" }, "ip_v4": { "resource_uri": "/api/2.0/ips/178.22.68.55/", "uuid": "178.22.68.55" }, "ip_v6": null }, "vlan": null } ], "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "requirements": [], "resource_uri": "/api/2.0/servers/9de75ed6-fd33-45e2-963f-d405f31fd911/", "runtime": { "active_since": "2013-11-05T10:15:42+00:00", "nics": [ { "interface_type": "public", "io": { "bytes_recv": "1323", "bytes_sent": "21535", "packets_recv": "3", "packets_sent": "278" }, "ip_v4": { "resource_uri": "/api/2.0/ips/185.12.5.181/", "uuid": "185.12.5.181" }, "ip_v6": null, "mac": "22:98:ce:04:50:df" } ] }, "smp": 1, "status": "running", "tags": [], "uuid": "9de75ed6-fd33-45e2-963f-d405f31fd911", "vnc_password": "foo" }, { "context": true, "cpu": 2000, "cpu_model": null, "cpus_instead_of_cores": false, "drives": [ { "boot_order": 1, "dev_channel": "0:0", "device": "ide", "drive": { "resource_uri": "/api/2.0/drives/3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9/", "uuid": "3f74acec-ba3c-4efd-ab9e-5d95a4c5fca9" } } ], "enable_numa": false, "hv_relaxed": false, "hv_tsc": false, "mem": 2147483648, "meta": { "description": "test1" }, "name": "test-1", "nics": [ { "boot_order": null, "firewall_policy": null, "ip_v4_conf": { "conf": "dhcp", "ip": null }, "ip_v6_conf": null, "mac": "22:22:4e:1e:e0:7e", "model": "virtio", "runtime": null, "vlan": null } ], "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "requirements": [], "resource_uri": "/api/2.0/servers/9414bbeb-e908-4e55-ae3f-2eb61adc50d8/", "runtime": null, "smp": 1, "status": "stopped", "tags": [], "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8", "vnc_password": "bar" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/servers_open_vnc.json0000664000175000017500000000024213535474530031575 0ustar kamikami00000000000000{ "action": "open_vnc", "result": "success", "uuid": "2e64e5e4-f31d-471a-ac1b-1ae079652e40", "vnc_url": "vnc://direct.lvs.cloudsigma.com:41111" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/start_already_started.json0000664000175000017500000000022613535474530032603 0ustar kamikami00000000000000[{"error_point": null, "error_type": "permission", "error_message": "Cannot start guest in state \"started\". Guest should be in state \"stopped\""}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/start_success.json0000664000175000017500000000013113535474530031077 0ustar kamikami00000000000000{"action": "start", "result": "success", "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_already_stopped.json0000664000175000017500000000025313535474530032443 0ustar kamikami00000000000000[{"error_point": null, "error_type": "permission", "error_message": "Cannot stop guest in state \"stopped\". Guest should be in state \"['started', 'running_legacy']\""}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/stop_success.json0000664000175000017500000000013013535474530030726 0ustar kamikami00000000000000{"action": "stop", "result": "success", "uuid": "9414bbeb-e908-4e55-ae3f-2eb61adc50d8"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/subscriptions.json0000664000175000017500000001042013535474530031123 0ustar kamikami00000000000000{ "meta": { "limit": 20, "offset": 0, "total_count": 5 }, "objects": [ { "amount": "1", "auto_renew": true, "descendants": [], "discount_amount": null, "discount_percent": null, "end_time": "2014-02-20T11:12:34.930946+00:00", "id": "7272", "last_notification": null, "period": "345 days, 0:00:00", "price": "0E-20", "remaining": "1", "resource": "vlan", "resource_uri": "/api/2.0/subscriptions/7272/", "start_time": "2013-03-12T11:12:34.930946+00:00", "status": "active", "subscribed_object": "96537817-f4b6-496b-a861-e74192d3ccb0", "uuid": "509f8e27-1e64-49bb-aa5a-baec074b0210" }, { "amount": "1", "auto_renew": true, "descendants": [], "discount_amount": null, "discount_percent": null, "end_time": "2014-02-20T11:12:41.837474+00:00", "id": "7273", "last_notification": null, "period": "345 days, 0:00:00", "price": "0E-20", "remaining": "1", "resource": "ip", "resource_uri": "/api/2.0/subscriptions/7273/", "start_time": "2013-03-12T11:12:41.837474+00:00", "status": "active", "subscribed_object": "185.12.6.183", "uuid": "c2423c1a-8768-462c-bdc3-4ca09c1e650b" }, { "amount": "17179869184", "auto_renew": true, "descendants": [], "discount_amount": null, "discount_percent": null, "end_time": "2014-02-20T14:04:14.142181+00:00", "id": "3985", "last_notification": null, "period": "365 days, 0:00:00", "price": "0E-20", "remaining": "17179869184", "resource": "mem", "resource_uri": "/api/2.0/subscriptions/3985/", "start_time": "2013-02-20T14:04:14.142181+00:00", "status": "active", "subscribed_object": null, "uuid": "9bb117d3-4bc5-4e2d-a907-b20abd48eaf9" }, { "amount": "8000", "auto_renew": true, "descendants": [], "discount_amount": null, "discount_percent": null, "end_time": "2014-02-20T14:04:29.040258+00:00", "id": "3986", "last_notification": null, "period": "365 days, 0:00:00", "price": "0E-20", "remaining": "8000", "resource": "cpu", "resource_uri": "/api/2.0/subscriptions/3986/", "start_time": "2013-02-20T14:04:29.040258+00:00", "status": "active", "subscribed_object": null, "uuid": "a265c47f-1a00-4095-acfc-2193622bfbd8" }, { "amount": "32212254720", "auto_renew": true, "descendants": [], "discount_amount": null, "discount_percent": null, "end_time": "2014-02-20T14:04:44.088984+00:00", "id": "3987", "last_notification": null, "period": "365 days, 0:00:00", "price": "0E-20", "remaining": "32212254720", "resource": "dssd", "resource_uri": "/api/2.0/subscriptions/3987/", "start_time": "2013-02-20T14:04:44.088984+00:00", "status": "active", "subscribed_object": null, "uuid": "8965ff95-4924-40a9-b923-a58615149732" }, { "amount": "32212254720", "auto_renew": true, "descendants": [], "discount_amount": null, "discount_percent": null, "end_time": "", "id": "5555", "last_notification": null, "period": "365 days, 0:00:00", "price": "0E-20", "remaining": "32212254720", "resource": "dssd", "resource_uri": "/api/2.0/subscriptions/3987/", "start_time": null, "status": "active", "subscribed_object": null, "uuid": "8965ff95-4924-40a9-b923-a58615149732" } ], "price": "0E-20" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create.json0000664000175000017500000000072013535474530030477 0ustar kamikami00000000000000{ "objects": [ { "meta": {}, "name": "test tag 3", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/tags/c0008127-6dbf-4cf3-85f5-203f4c3967fa/", "resources": [], "uuid": "c0008127-6dbf-4cf3-85f5-203f4c3967fa" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_create_with_resources.json0000664000175000017500000000157613535474530033636 0ustar kamikami00000000000000{ "objects": [ { "meta": {}, "name": "test tag 3", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/tags/c0008127-6dbf-4cf3-85f5-203f4c3967fa/", "resources": [ { "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "res_type": "vlans", "resource_uri": "/api/2.0/vlans/96537817-f4b6-496b-a861-e74192d3ccb0/", "uuid": "1" } ], "uuid": "c0008127-6dbf-4cf3-85f5-203f4c3967fa" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_detail.json0000664000175000017500000000173613535474530030506 0ustar kamikami00000000000000{ "meta": { "limit": 20, "offset": 0, "total_count": 2 }, "objects": [ { "meta": {}, "name": "test tag 2", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/tags/a010ec41-2ead-4630-a1d0-237fa77e4d4d/", "resources": [], "uuid": "a010ec41-2ead-4630-a1d0-237fa77e4d4d" }, { "meta": {}, "name": "test tag 1", "owner": { "resource_uri": "/api/2.0/user/69fcfc03-d635-4f99-a8b3-e1b73637cb5d/", "uuid": "69fcfc03-d635-4f99-a8b3-e1b73637cb5d" }, "resource_uri": "/api/2.0/tags/e60bb2d2-08d4-4255-adac-5faf87efcdd2/", "resources": [], "uuid": "e60bb2d2-08d4-4255-adac-5faf87efcdd2" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_get.json0000664000175000017500000000053513535474530030017 0ustar kamikami00000000000000{ "meta": {}, "name": "test tag 2", "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "resource_uri": "/api/2.0/tags/a010ec41-2ead-4630-a1d0-237fa77e4d4d/", "resources": [], "uuid": "a010ec41-2ead-4630-a1d0-237fa77e4d4d" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/tags_update.json0000664000175000017500000000215113535474530030516 0ustar kamikami00000000000000{ "meta": {}, "name": "test tag 3", "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "resource_uri": "/api/2.0/tags/900ac9c6-2f98-48a4-b406-5494b4ea4663/", "resources": [ { "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "res_type": "servers", "resource_uri": "/api/2.0/servers/79f7853b-04bd-44f5-a2c2-fa56f6861994/", "uuid": "79f7853b-04bd-44f5-a2c2-fa56f6861994" }, { "owner": { "resource_uri": "/api/2.0/user/5b4a69a3-8e78-4c45-a8ba-8b13f0895e23/", "uuid": "5b4a69a3-8e78-4c45-a8ba-8b13f0895e23" }, "res_type": "drives", "resource_uri": "/api/2.0/drives/8c48e0bd-e17b-49ca-8926-654107d2b7e7/", "uuid": "8c48e0bd-e17b-49ca-8926-654107d2b7e7" } ], "uuid": "900ac9c6-2f98-48a4-b406-5494b4ea4663" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json0000664000175000017500000000012313535474530031123 0ustar kamikami00000000000000[{"error_point": null, "error_type": "backend", "error_message": "unknown error"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/0000775000175000017500000000000013600223624024656 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/addNicToVirtualMachine_default.json0000664000175000017500000000007513535474530033613 0ustar kamikami00000000000000{ "addnictovirtualmachineresponse" : {"jobid":"addnictovm"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/associateIpAddress_default.json0000664000175000017500000000013713535474530033043 0ustar kamikami00000000000000{ "associateipaddressresponse" : {"id":"10987171-8cc9-4d0a-b98f-1698c09ddd2d","jobid":11111} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/attachVolume_default.json0000664000175000017500000000007113535474530031722 0ustar kamikami00000000000000{ "attachvolumeresponse" : {"jobid":"attachvolumejob"} } ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_defaul0000664000175000017500000000007713535474530034252 0ustar kamikami00000000000000{ "authorizesecuritygroupingressresponse" : {"jobid":17200} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createAffinityGroup_default.json0000664000175000017500000000006613535474530033244 0ustar kamikami00000000000000{"createaffinitygroupresponse": { "jobid" : 1300004}} ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createEgressFirewallRule_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createEgressFirewallRule_default.jso0000664000175000017500000000010713535474530034042 0ustar kamikami00000000000000{ "createegressfirewallruleresponse" : {"jobid":1149341,"id":172465} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_default.json0000664000175000017500000000010113535474530033041 0ustar kamikami00000000000000{ "createfirewallruleresponse" : {"jobid":1149341,"id":172465} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_firewallicmp.json0000664000175000017500000000010113535474530034073 0ustar kamikami00000000000000{ "createfirewallruleresponse" : {"jobid":1149343,"id":172466} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createNetworkACLList_default.json0000664000175000017500000000020113535474530033252 0ustar kamikami00000000000000{ "createnetworkacllistresponse" : {"id":"5692ffdc-d98e-4c7e-a53e-817835e97694","jobid":"0e6707fa-15d9-4cd4-8e16-fd58232321e1"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createNetworkACL_default.json0000664000175000017500000000013713535474530032426 0ustar kamikami00000000000000{ "createnetworkaclresponse" : {"id":"54bd8cc6-5db0-4f64-8495-a0dfaf3fb4d5","jobid":"111112"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createNetwork_default.json0000664000175000017500000001064513535474530032113 0ustar kamikami00000000000000{ "createnetworkresponse" : { "network" : {"id":"a804d341-996e-4d9a-b2b0-226c648dc6e3","name":"test","displaytext":"test","broadcastdomaintype":"Lswitch","traffictype":"Guest","gateway":"10.1.1.1","netmask":"255.255.255.0","cidr":"10.1.1.0/24","zoneid":"2","zonename":"BETA-SBP-DC-1","networkofferingid":"c348cabe-0208-49e0-91ad-32b88c55fd8c","networkofferingname":"SourceNatNiciraNvpNetwork","networkofferingdisplaytext":"Offering for a Nicira Nvp isolated network with SourceNat","networkofferingconservemode":true,"networkofferingavailability":"Optional","issystem":false,"state":"Allocated","related":"a804d341-996e-4d9a-b2b0-226c648dc6e3","dns1":"8.8.8.8","dns2":"8.8.8.4","type":"Isolated","acltype":"Account","account":"rkuipers_admin","projectid":"d5f1209d-3a28-4dfb-8cc1-884e5d5e1d56","domainid":"4b6e626c-9d50-4480-bf77-daae632c7ffd","domain":"rkuipers","service":[{"name":"Firewall","capability":[{"name":"SupportedProtocols","value":"tcp,udp,icmp","canchooseservicecapability":false},{"name":"SupportedTrafficDirection","value":"ingress, egress","canchooseservicecapability":false},{"name":"MultipleIps","value":"true","canchooseservicecapability":false},{"name":"SupportedEgressProtocols","value":"tcp,udp,icmp, all","canchooseservicecapability":false},{"name":"TrafficStatistics","value":"per public ip","canchooseservicecapability":false}]},{"name":"StaticNat"},{"name":"Lb","capability":[{"name":"LbSchemes","value":"Public","canchooseservicecapability":false},{"name":"SupportedStickinessMethods","value":"[{\"methodname\":\"LbCookie\",\"paramlist\":[{\"paramname\":\"cookie-name\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"mode\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"nocache\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"indirect\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"postonly\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"domain\",\"required\":false,\"isflag\":false,\"description\":\" \"}],\"description\":\"This is loadbalancer cookie based stickiness method.\"},{\"methodname\":\"AppCookie\",\"paramlist\":[{\"paramname\":\"cookie-name\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"length\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"holdtime\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"request-learn\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"prefix\",\"required\":false,\"isflag\":true,\"description\":\" \"},{\"paramname\":\"mode\",\"required\":false,\"isflag\":false,\"description\":\" \"}],\"description\":\"This is App session based sticky method. Define session stickiness on an existing application cookie. It can be used only for a specific http traffic\"},{\"methodname\":\"SourceBased\",\"paramlist\":[{\"paramname\":\"tablesize\",\"required\":false,\"isflag\":false,\"description\":\" \"},{\"paramname\":\"expire\",\"required\":false,\"isflag\":false,\"description\":\" \"}],\"description\":\"This is source based Stickiness method, it can be used for any type of protocol.\"}]","canchooseservicecapability":false},{"name":"SupportedLBIsolation","value":"dedicated","canchooseservicecapability":false},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn,source","canchooseservicecapability":false},{"name":"SupportedProtocols","value":"tcp, udp","canchooseservicecapability":false}]},{"name":"SourceNat","capability":[{"name":"RedundantRouter","value":"true","canchooseservicecapability":false},{"name":"SupportedSourceNatTypes","value":"peraccount","canchooseservicecapability":false}]},{"name":"Dns","capability":[{"name":"AllowDnsSuffixModification","value":"true","canchooseservicecapability":false}]},{"name":"Connectivity"},{"name":"Vpn","capability":[{"name":"SupportedVpnTypes","value":"pptp,l2tp,ipsec","canchooseservicecapability":false},{"name":"VpnTypes","value":"removeaccessvpn","canchooseservicecapability":false}]},{"name":"Dhcp","capability":[{"name":"DhcpAccrossMultipleSubnets","value":"true","canchooseservicecapability":false}]},{"name":"UserData"},{"name":"PortForwarding"}],"networkdomain":"rkuipers.local","physicalnetworkid":"e48527a6-6882-4c5f-bce9-c02ecd5ef8c1","restartrequired":false,"specifyipranges":false,"vpcid":"22e8388c-21bf-4b84-8f20-e92a7f550898","canusefordeploy":true,"ispersistent":false,"tags":[],"displaynetwork":true} } }././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createPortForwardingRule_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createPortForwardingRule_default.jso0000664000175000017500000000014713535474530034077 0ustar kamikami00000000000000{ "createportforwardingruleresponse" : {"id":"bc7ea3ee-a2c3-4b86-a53f-01bdaa1b2e32","jobid":"11113"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json0000664000175000017500000000204113535474530032373 0ustar kamikami00000000000000{ "createsshkeypairresponse" : { "keypair" : {"name":"test-keypair","fingerprint":"51:9f:81:30:ec:82:0c:e5:8c:81:ac:14:27:d0:e5:e2","privatekey":"-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDMaSZY4v228AWWcXYLoojgaZ+K8SbuI8YoPDEi9UWcww5mWSTx\nVl6Ksb8YPFxL6+3/unlfr4zK1LksxgN8XRuZr+YBFGphUB6a5EcyshkXi3mfAE7d\n6a26ah6ySXFK9GmZoXcJqQ1xLC9rKGPL7tWgHmbX1lCbN6QinV0mZVEHNwIDAQAB\nAoGACXQngN7mqwpIx99xfTJEMFTSOyPSEBt5c6zs/NfpI0nmJZej3MGI19NGqkFI\nZ35+4F/ocyN0WIEkG00BJkRMHWdPNd+YnVSuVgEyGCD8hDvBbUEQrmdZ0VfQt+2q\nd52g573s6D6Skk/SZHGi3yHca4H52c3EpLJzThxUmJSSqmECQQD0loEIiQzQaap3\n/Gce7nZeLCSNXf0Q5aKFQv/X22srw6YvJ9/25cLahiFtQUadId9VUXSYTgEKX0ST\nB2CZ4UJxAkEA1fK/PT+YIHaiQIiCK/xTnoIuTvdXmH0IozolRxGAKpQZNvaMpKgn\nvXU84/yztekEPG0pKmCm7CZUZoGdfiJoJwJALwUsAy8NtpdJvU1ZqbmgKdSEpmS2\nPORYjRPnSWEWRlCThyc8SCO9hPMaQ/2zjIuxep5xMsJ0MsFD1pwpdwu2EQJBAMrG\nEZ7ZQTOzfMAxIT7THeWjeIR7RNhP2PnrSB19Zr30M5m2P0Jn5ZJZJWbnwOPuf4dN\n5rA1fr9e7KtiuYQs1A0CQQCT06qHdHaQr78A6YTEbDVr0M57qVrdsm5xyXzCmpMy\n9LxXAACghjHbjF//FEOjNG21IutbCg6cNIRz5EM8+MD+\n-----END RSA PRIVATE KEY-----\n"} } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json0000664000175000017500000000033113535474530033275 0ustar kamikami00000000000000{"createsecuritygroupresponse":{"securitygroup":{"account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","id":"895f9e41-4d89-468e-9b69-19a8f0d3a889","domain":"runseb@gmail.com","name":"MySG"}}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createSnapshot_default.json0000664000175000017500000000007413535474530032254 0ustar kamikami00000000000000{ "createsnapshotresponse" : {"jobid":1300001,"id":190547} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createTags_default.json0000664000175000017500000000014113535474530031346 0ustar kamikami00000000000000{ "createtagsresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"createtagsjob"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createTemplate_default.json0000664000175000017500000000007313535474530032227 0ustar kamikami00000000000000{ "createtemplateresponse" : {"jobid":1300003,"id":10260} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVPC_default.json0000664000175000017500000000016613535474530031107 0ustar kamikami00000000000000{ "createvpcresponse" : {"id":"c78499e1-b3a2-4a2a-9759-c2bcb1b79cd4","jobid":"f618f672-c714-4031-8c79-bb1300a2163c"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVolume_default.json0000664000175000017500000000014513535474530031723 0ustar kamikami00000000000000{ "createvolumeresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"createvolumejob"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVolume_withcustomdisksize.json0000664000175000017500000000014513535474530034253 0ustar kamikami00000000000000{ "createvolumeresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"createvolumejob"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVolume_withvolumetype.json0000664000175000017500000000014513535474530033404 0ustar kamikami00000000000000{ "createvolumeresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"createvolumejob"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVpnConnection_default.json0000664000175000017500000000012413535474530033234 0ustar kamikami00000000000000{ "createvpnconnectionresponse" : { "jobid" : "createVpnConnection" } } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVpnCustomerGateway_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVpnCustomerGateway_default.jso0000664000175000017500000000013613535474530034105 0ustar kamikami00000000000000{ "createvpncustomergatewayresponse" : { "jobid" : "createVpnCustomerGateway" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/createVpnGateway_default.json0000664000175000017500000000020613535474530032537 0ustar kamikami00000000000000{ "createvpngatewayresponse": { "id": "5ef6794e-cec8-4018-9fef-c4dacbadee14", "jobid": "createVpnGateway" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteAffinityGroup_default.json0000664000175000017500000000006613535474530033243 0ustar kamikami00000000000000{"deleteaffinitygroupresponse": { "jobid" : 1300005}} ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteEgressFirewallRule_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteEgressFirewallRule_default.jso0000664000175000017500000000007313535474530034043 0ustar kamikami00000000000000{ "deleteegressfirewallruleresponse" : {"jobid":1149342} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteFirewallRule_default.json0000664000175000017500000000006513535474530033051 0ustar kamikami00000000000000{ "deletefirewallruleresponse" : {"jobid":1149342} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteNetwork_default.json0000664000175000017500000000006713535474530032107 0ustar kamikami00000000000000{ "deletenetworkresponse" : {"jobid":"deleteNetwork"} }././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deletePortForwardingRule_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deletePortForwardingRule_default.jso0000664000175000017500000000007313535474530034074 0ustar kamikami00000000000000{ "deleteportforwardingruleresponse" : {"jobid":"11114"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json0000664000175000017500000000007113535474530032373 0ustar kamikami00000000000000{ "deletesshkeypairresponse" : { "success" : "true"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json0000664000175000017500000000007413535474530033300 0ustar kamikami00000000000000{ "deletesecuritygroupresponse" : { "success" : "true"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteSnapshot_default.json0000664000175000017500000000006013535474530032246 0ustar kamikami00000000000000{ "deletesnapshotresponse" : {"jobid":1300002} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteTags_default.json0000664000175000017500000000014013535474530031344 0ustar kamikami00000000000000{ "deletetagsresponse" : {"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","jobid":"deletetagsjob"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteVPC_default.json0000664000175000017500000000005713535474530031105 0ustar kamikami00000000000000{ "deletevpcresponse" : {"jobid":"deleteVPC"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteVolume_default.json0000664000175000017500000000006413535474530031722 0ustar kamikami00000000000000{ "deletevolumeresponse" : { "success" : "true"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteVpnConnection_default.json0000664000175000017500000000010413535474530033231 0ustar kamikami00000000000000{ "deletevpnconnectionresponse" : {"jobid":"deleteVpnConnection"} } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteVpnCustomerGateway_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteVpnCustomerGateway_default.jso0000664000175000017500000000013613535474530034104 0ustar kamikami00000000000000{ "deletevpncustomergatewayresponse" : { "jobid" : "deleteVpnCustomerGateway" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deleteVpnGateway_default.json0000664000175000017500000000007613535474530032543 0ustar kamikami00000000000000{ "deletevpngatewayresponse" : {"jobid":"deleteVpnGateway"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_default.json0000664000175000017500000000007713535474530033424 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":17164,"id":2602} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail.json0000664000175000017500000000016013535474530034121 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"errorcode" : 431, "errortext" : "Unable to find service offering: 104"} } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployfail2.jso0000664000175000017500000000007713535474530034034 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":17177,"id":2602} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployip.json0000664000175000017500000000011313535474530033614 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":"deployvmwithid","id":65385} } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploykeyname.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploykeyname.j0000664000175000017500000000010713535474530034120 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"id":"fc4fd31a","jobid":"11116"} } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploynetworks.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploynetworks.0000664000175000017500000000010213535474530034164 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":1149366,"id":65385} } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.j0000664000175000017500000000014013535474530034132 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":11117,"id":"19253fbf-abb7-4013-a8a1-97df3b93f206"} }././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploysecuritygroup.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deploysecurityg0000664000175000017500000000014313535474530034255 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"id":"fc4fd31a-16d3-49db-814a-56b39b9ef986","jobid":"11115"} } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_rootdisksize.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_rootdisksize.js0000664000175000017500000000011713535474530034167 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":"deployrootdisksize","id":65285} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_stoppedvm.json0000664000175000017500000000011413535474530034011 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":"deployvmstopped","id":65385} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/destroyVirtualMachine_default.json0000664000175000017500000000006613535474530033617 0ustar kamikami00000000000000{ "destroyvirtualmachineresponse" : {"jobid":17166} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/detachVolume_default.json0000664000175000017500000000007113535474530031706 0ustar kamikami00000000000000{ "detachvolumeresponse" : {"jobid":"detachvolumejob"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/disassociateIpAddress_default.json0000664000175000017500000000007013535474530033537 0ustar kamikami00000000000000{ "disassociateipaddressresponse" : {"jobid":"11112"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/dummy_rsa.pub0000664000175000017500000000062213535474530027401 0ustar kamikami00000000000000ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCw3Fw6AdX+3Ul3lRJIPE0Hd5oBaHnCVB1Wl325FVeJZeQiKF9Z0sw+/StWuo2ZA5ra6/A8X7tITiO7goUncdd7xLT3r3UCwKGNZXrTn8e2Kutqd9S7EN+SUh63kZmcEQsFCuC3hg0O8TzG5ROQxukYc+7PAvcYk7+KV8r3B5eh2lvp5tHTpCX/63pm4zHm5rnE38DnESeh4Dh2R8hkhnoxo9ixQCdETbufUTo5abCkKbcf8/1+qA5A13uXqBsx/KtmZX0SvyQW3hKFPGXSaYxAE/u+DZU8Myr/dDKLrGPYt6e5CSXlQLFcnz99akuVdqOP9ygPGcgwlAajOZgt+Vwn sebgoa@sebmini.local apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listAffinityGroupTypes_default.json0000664000175000017500000000014113535474530033773 0ustar kamikami00000000000000{ "listaffinitygrouptypesresponse" : {"count": 1, "affinityGroupType": [{"type": "MyAGType"}] }} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listAffinityGroups_default.json0000664000175000017500000000017013535474530033133 0ustar kamikami00000000000000{ "listaffinitygroupsresponse" : {"count": 1, "affinitygroup" : [{"id":"11112", "name": "MyAG", "type": "MyAGType"}] }} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_default.json0000664000175000017500000000037613535474530032727 0ustar kamikami00000000000000{ "listdiskofferingsresponse" : { "count":1 ,"diskoffering" : [ {"id":"6345e3b7-227e-4209-8f8c-1f94219696e6","name":"Disk offer 1","displaytext":"Disk offer 1 display name","disksize":10,"created":"2012-04-24T16:35:55+0200","iscustomized":false} ] } } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withcustomdisksize.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withcustomdisksize0000664000175000017500000000037513535474530034306 0ustar kamikami00000000000000{ "listdiskofferingsresponse" : { "count":1 ,"diskoffering" : [ {"id":"6345e3b7-227e-4209-8f8c-1f94219696e6","name":"Disk offer 1","displaytext":"Disk offer 1 display name","disksize":10,"created":"2012-04-24T16:35:55+0200","iscustomized":true} ] } } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withvolumetype.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listDiskOfferings_withvolumetype.jso0000664000175000017500000000037613535474530034232 0ustar kamikami00000000000000{ "listdiskofferingsresponse" : { "count":1 ,"diskoffering" : [ {"id":"6345e3b7-227e-4209-8f8c-1f94219696e6","name":"Disk offer 1","displaytext":"Disk offer 1 display name","disksize":10,"created":"2012-04-24T16:35:55+0200","iscustomized":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listEgressFirewallRules_default.json0000664000175000017500000000042513535474530034116 0ustar kamikami00000000000000{ "listegressfirewallrulesresponse" : { "count":1 ,"firewallrule" : [ {"id":"7d4e2924-49b6-4a5a-9a98-69f2f0f73c69","protocol":"tcp","startport":"80","endport":"80","networkid":"874be2ca-20a7-4360-80e9-7356c0018c0b","state":"Active","cidrlist":"192.168.0.0/16","tags":[]} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_default.json0000664000175000017500000000035113535474530032743 0ustar kamikami00000000000000{"listfirewallrulesresponse": {"count": 1, "firewallrule": [ { "cidrlist": "192.168.0.0/16", "id": 171597, "ipaddress": "1.1.1.116", "protocol": "tcp", "startport": "33", "endport": "34", "ipaddressid": 34000, "state": "Active" }]}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_firewallicmp.json0000664000175000017500000000034413535474530033777 0ustar kamikami00000000000000{"listfirewallrulesresponse": {"count": 1, "firewallrule": [ { "cidrlist": "192.168.0.0/16", "icmpcode": 0, "icmptype": 8, "id": 52394, "ipaddress": "1.1.1.116", "ipaddressid": 34000, "protocol": "icmp", "state": "Active" } ]}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listIpForwardingRules_default.json0000664000175000017500000000050013535474530033565 0ustar kamikami00000000000000{ "listipforwardingrulesresponse" : { "count":1 ,"ipforwardingrule" : [ {"id":"772fd410-6649-43ed-befa-77be986b8906","protocol":"tcp","virtualmachineid":"2600","virtualmachinename":"test","virtualmachinedisplayname":"test","ipaddressid":34000,"ipaddress":"1.1.1.116","startport":33,"endport":34,"state":"Active"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworkACLLists_default.json0000664000175000017500000000031213535474530033150 0ustar kamikami00000000000000{ "listnetworkacllistsresponse" : { "count":4 ,"networkacllist" : [ {"id":"54bd8cc6-5db0-4f64-8495-a0dfaf3fb4d5","name":"test","description":"test","vpcid":"cf698ec3-edd0-466c-a8f6-f9096700b6ec"} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworkACLs_default.json0000664000175000017500000000046613535474530032326 0ustar kamikami00000000000000{ "listnetworkaclsresponse" : { "count":1 ,"networkacl" : [ {"id":"54bd8cc6-5db0-4f64-8495-a0dfaf3fb4d5","protocol":"tcp","startport":"80","endport":"80","traffictype":"Ingress","state":"Active","cidrlist":"0.0.0.0/0","tags":[],"aclid":"4b1a2ef9-b53a-4e1b-9a45-0408b3ce3494","number":1,"action":"Allow"} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworkOfferings_default.json0000664000175000017500000000653613535474530033472 0ustar kamikami00000000000000{ "listnetworkofferingsresponse" : { "count":2 ,"networkoffering" : [ {"id":"c348cabe-0208-49e0-91ad-32b88c55fd8c","name":"SourceNatNiciraNvpNetwork","displaytext":"Offering for a Nicira Nvp isolated network with SourceNat","tags":"BETA-SBP-DC-1-pSTT","traffictype":"Guest","isdefault":true,"specifyvlan":false,"conservemode":true,"specifyipranges":false,"availability":"Optional","networkrate":-1,"state":"Enabled","guestiptype":"Isolated","serviceofferingid":"01f93707-3a35-44a6-84e9-ea767287a6b2","service":[{"name":"Firewall","provider":[{"name":"VirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"ElasticIp","value":"false","canchooseservicecapability":false},{"name":"AssociatePublicIP","value":"false","canchooseservicecapability":false}]},{"name":"Lb","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedLBIsolation","value":"dedicated","canchooseservicecapability":false},{"name":"ElasticLb","value":"false","canchooseservicecapability":false},{"name":"InlineMode","value":"false","canchooseservicecapability":false}]},{"name":"SourceNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedSourceNatTypes","value":"peraccount","canchooseservicecapability":false},{"name":"RedundantRouter","value":"false","canchooseservicecapability":false}]},{"name":"Dns","provider":[{"name":"VirtualRouter"}]},{"name":"Connectivity","provider":[{"name":"NiciraNvp"}]},{"name":"Vpn","provider":[{"name":"VirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VirtualRouter"}]},{"name":"UserData","provider":[{"name":"VirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VirtualRouter"}]}],"forvpc":false,"ispersistent":false,"egressdefaultpolicy":false}, {"id":"7c09e208-2af5-43d6-9f0b-53868ef788ea","name":"OAT offering for OAT purposes","displaytext":"OAT offering for OAT purposes","tags":"BETA-SBP-DC-1-pSTT","traffictype":"Guest","isdefault":false,"specifyvlan":false,"conservemode":true,"specifyipranges":false,"availability":"Optional","networkrate":-1,"state":"Enabled","guestiptype":"Isolated","serviceofferingid":"01f93707-3a35-44a6-84e9-ea767287a6b2","service":[{"name":"Firewall","provider":[{"name":"VirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"ElasticIp","value":"false","canchooseservicecapability":false},{"name":"AssociatePublicIP","value":"false","canchooseservicecapability":false}]},{"name":"Lb","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedLBIsolation","value":"dedicated","canchooseservicecapability":false},{"name":"ElasticLb","value":"false","canchooseservicecapability":false},{"name":"InlineMode","value":"false","canchooseservicecapability":false}]},{"name":"SourceNat","provider":[{"name":"VirtualRouter"}],"capability":[{"name":"SupportedSourceNatTypes","value":"peraccount","canchooseservicecapability":false},{"name":"RedundantRouter","value":"false","canchooseservicecapability":false}]},{"name":"Dns","provider":[{"name":"VirtualRouter"}]},{"name":"Connectivity","provider":[{"name":"NiciraNvp"}]},{"name":"Vpn","provider":[{"name":"VirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VirtualRouter"}]},{"name":"UserData","provider":[{"name":"VirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VirtualRouter"}]}],"forvpc":false,"ispersistent":false,"egressdefaultpolicy":true,"maxconnections":4096} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworks_default.json0000664000175000017500000000213213535474530031776 0ustar kamikami00000000000000{ "listnetworksresponse" : {"count": 1, "network": [{"domain": "ROOT", "acltype": "Domain", "specifyipranges": true, "related": "00304a04-c7ea-4e77-a786-18bc64347bf7", "zoneid": "1128bd56-b4d9-4ac6-a7b9-c715b187ce11", "domainid": "4a8857b8-7235-4e31-a7ef-b8b44d180850", "displaytext": "guestNetworkForBasicZone", "id": "00304a04-c7ea-4e77-a786-18bc64347bf7", "canusefordeploy": true, "physicalnetworkid": "07f747f5-b445-487f-b2d7-81a5a512989e", "networkdomain": "cs1cloud.internal", "service": [{"name": "SecurityGroup"}, {"name": "UserData"}, {"name": "Dhcp"}], "state": "Setup", "type": "Shared", "zonename": "CH-GV2", "networkofferingavailability": "Optional", "networkofferingid": "45964a3a-8a1c-4438-a377-0ff1e264047a", "tags": [], "networkofferingdisplaytext": "Exoscale Offering for Shared Security group enabled networks", "subdomainaccess": true, "traffictype": "Guest", "restartrequired": false, "broadcastdomaintype": "Vlan", "name": "guestNetworkForBasicZone", "dns2": "80.245.17.230", "dns1": "80.245.17.229", "networkofferingname": "ExoscaleSharedNetworkOfferingWithSGService", "issystem": false}]} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail.json0000664000175000017500000000246513535474530032513 0ustar kamikami00000000000000{ "listnetworksresponse" : { "network" : [ {"id":860,"name":"Virtual Network","displaytext":"A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.","broadcastdomaintype":"Vlan","traffictype":"Guest","zoneid":1,"networkofferingid":6,"networkofferingname":"DefaultVirtualizedNetworkOffering","networkofferingdisplaytext":"Virtual Vlan","networkofferingavailability":"Required","isshared":false,"issystem":false,"state":"Implemented","related":860,"broadcasturi":"vlan://1459","dns1":"1.1.1.1","dns2":"1.1.1.2","type":"Virtual","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","isdefault":true,"service":[{"name":"Gateway"},{"name":"Firewall","capability":[{"name":"MultipleIps","value":"true"},{"name":"TrafficStatistics","value":"per public ip"},{"name":"StaticNat","value":"true"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedSourceNatTypes","value":"per account"}]},{"name":"UserData"},{"name":"Dns"},{"name":"Dhcp"},{"name":"Lb","capability":[{"name":"TrafficStatistics","value":"per public ip"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn"}]}],"networkdomain":"cs363local","securitygroupenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployfail2.json0000664000175000017500000000246513535474530032575 0ustar kamikami00000000000000{ "listnetworksresponse" : { "network" : [ {"id":860,"name":"Virtual Network","displaytext":"A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router.","broadcastdomaintype":"Vlan","traffictype":"Guest","zoneid":1,"networkofferingid":6,"networkofferingname":"DefaultVirtualizedNetworkOffering","networkofferingdisplaytext":"Virtual Vlan","networkofferingavailability":"Required","isshared":false,"issystem":false,"state":"Implemented","related":860,"broadcasturi":"vlan://1459","dns1":"1.1.1.1","dns2":"1.1.1.2","type":"Virtual","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","isdefault":true,"service":[{"name":"Gateway"},{"name":"Firewall","capability":[{"name":"MultipleIps","value":"true"},{"name":"TrafficStatistics","value":"per public ip"},{"name":"StaticNat","value":"true"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedSourceNatTypes","value":"per account"}]},{"name":"UserData"},{"name":"Dns"},{"name":"Dhcp"},{"name":"Lb","capability":[{"name":"TrafficStatistics","value":"per public ip"},{"name":"SupportedProtocols","value":"tcp,udp"},{"name":"SupportedLbAlgorithms","value":"roundrobin,leastconn"}]}],"networkdomain":"cs363local","securitygroupenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworks_deployip.json0000664000175000017500000000757313535474530032215 0ustar kamikami00000000000000{"listnetworksresponse": { "count": 3, "network": [ { "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://1002", "displaytext": "network:192.168.2.0/24", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "endip": "192.168.2.233", "gateway": "192.168.2.254", "id": 1823, "isdefault": false, "isshared": true, "issystem": false, "name": "ROOT", "netmask": "255.255.255.0", "networkdomain": "cs1cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Direct", "networkofferingid": 7, "networkofferingname": "DefaultDirectNetworkOffering", "related": 1823, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Dhcp" } ], "startip": "192.168.2.1", "state": "Setup", "traffictype": "Guest", "type": "Direct", "vlan": "1002", "zoneid": 1 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://2909", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1547, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1547, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 2 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://3564", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1374, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1374, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 1 } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworks_deploynetworks.json0000664000175000017500000000757313535474530033461 0ustar kamikami00000000000000{"listnetworksresponse": { "count": 3, "network": [ { "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://1002", "displaytext": "network:192.168.2.0/24", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "endip": "192.168.2.233", "gateway": "192.168.2.254", "id": 1823, "isdefault": false, "isshared": true, "issystem": false, "name": "ROOT", "netmask": "255.255.255.0", "networkdomain": "cs1cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Direct", "networkofferingid": 7, "networkofferingname": "DefaultDirectNetworkOffering", "related": 1823, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Dhcp" } ], "startip": "192.168.2.1", "state": "Setup", "traffictype": "Guest", "type": "Direct", "vlan": "1002", "zoneid": 1 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://2909", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1547, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1547, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 2 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://3564", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1374, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1374, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 1 } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworks_rootdisksize.json0000664000175000017500000000757313535474530033121 0ustar kamikami00000000000000{"listnetworksresponse": { "count": 3, "network": [ { "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://1002", "displaytext": "network:192.168.2.0/24", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "endip": "192.168.2.233", "gateway": "192.168.2.254", "id": 1823, "isdefault": false, "isshared": true, "issystem": false, "name": "ROOT", "netmask": "255.255.255.0", "networkdomain": "cs1cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Direct", "networkofferingid": 7, "networkofferingname": "DefaultDirectNetworkOffering", "related": 1823, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Dhcp" } ], "startip": "192.168.2.1", "state": "Setup", "traffictype": "Guest", "type": "Direct", "vlan": "1002", "zoneid": 1 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://2909", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1547, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1547, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 2 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://3564", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1374, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1374, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 1 } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNetworks_stoppedvm.json0000664000175000017500000000757313535474530032411 0ustar kamikami00000000000000{"listnetworksresponse": { "count": 3, "network": [ { "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://1002", "displaytext": "network:192.168.2.0/24", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "endip": "192.168.2.233", "gateway": "192.168.2.254", "id": 1823, "isdefault": false, "isshared": true, "issystem": false, "name": "ROOT", "netmask": "255.255.255.0", "networkdomain": "cs1cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Direct", "networkofferingid": 7, "networkofferingname": "DefaultDirectNetworkOffering", "related": 1823, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Dhcp" } ], "startip": "192.168.2.1", "state": "Setup", "traffictype": "Guest", "type": "Direct", "vlan": "1002", "zoneid": 1 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://2909", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1547, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1547, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 2 }, { "account": "testuser", "broadcastdomaintype": "Vlan", "broadcasturi": "vlan://3564", "displaytext": "testuser-network", "dns1": "8.8.8.8", "dns2": "8.8.8.8", "domain": "ROOT", "domainid": 1623, "id": 1374, "isdefault": true, "isshared": false, "issystem": false, "name": "testuser-network", "networkdomain": "cs586cloud.internal", "networkofferingavailability": "Optional", "networkofferingdisplaytext": "Virtual Vlan", "networkofferingid": 6, "networkofferingname": "DefaultVirtualizedNetworkOffering", "related": 1374, "securitygroupenabled": false, "service": [ { "name": "UserData" }, { "capability": [ { "name": "AllowDnsSuffixModification", "value": "true" } ], "name": "Dns" }, { "capability": [ { "name": "SupportedProtocols", "value": "tcp, udp" }, { "name": "SupportedLbAlgorithms", "value": "roundrobin,leastconn,source" } ], "name": "Lb" }, { "name": "Gateway" }, { "name": "Dhcp" }, { "capability": [ { "name": "SupportedVpnTypes", "value": "pptp,l2tp,ipsec" } ], "name": "Vpn" }, { "capability": [ { "name": "MultipleIps", "value": "true" }, { "name": "SupportedSourceNatTypes", "value": "per account" }, { "name": "SupportedProtocols", "value": "tcp,udp,icmp" }, { "name": "TrafficStatistics", "value": "per public ip" }, { "name": "PortForwarding", "value": "true" }, { "name": "StaticNat", "value": "true" } ], "name": "Firewall" } ], "state": "Implemented", "traffictype": "Guest", "type": "Virtual", "zoneid": 1 } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listNics_default.json0000664000175000017500000000041713535474530031062 0ustar kamikami00000000000000{ "listnicsresponse" : { "count":1 ,"nic" : [ {"id":"15418e74-25e8-42d3-9bd7-eb55e57825fe","networkid":"de45b0ed-b5ae-4374-ac7c-aff3fb2aefa2","netmask":"255.255.255.0","gateway":"10.1.1.1","ipaddress":"10.1.1.136","isdefault":true,"macaddress":"02:00:00:b9:01:1a"} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listOsTypes_default.json0000664000175000017500000002440013535474530031572 0ustar kamikami00000000000000{ "listostypesresponse" : { "count":146 ,"ostype" : [ {"id":69,"oscategoryid":7,"description":"Asianux 3(32-bit)"}, {"id":70,"oscategoryid":7,"description":"Asianux 3(64-bit)"}, {"id":1,"oscategoryid":1,"description":"CentOS 4.5 (32-bit)"}, {"id":2,"oscategoryid":1,"description":"CentOS 4.6 (32-bit)"}, {"id":3,"oscategoryid":1,"description":"CentOS 4.7 (32-bit)"}, {"id":4,"oscategoryid":1,"description":"CentOS 4.8 (32-bit)"}, {"id":5,"oscategoryid":1,"description":"CentOS 5.0 (32-bit)"}, {"id":6,"oscategoryid":1,"description":"CentOS 5.0 (64-bit)"}, {"id":7,"oscategoryid":1,"description":"CentOS 5.1 (32-bit)"}, {"id":8,"oscategoryid":1,"description":"CentOS 5.1 (64-bit)"}, {"id":9,"oscategoryid":1,"description":"CentOS 5.2 (32-bit)"}, {"id":10,"oscategoryid":1,"description":"CentOS 5.2 (64-bit)"}, {"id":11,"oscategoryid":1,"description":"CentOS 5.3 (32-bit)"}, {"id":12,"oscategoryid":1,"description":"CentOS 5.3 (64-bit)"}, {"id":13,"oscategoryid":1,"description":"CentOS 5.4 (32-bit)"}, {"id":14,"oscategoryid":1,"description":"CentOS 5.4 (64-bit)"}, {"id":111,"oscategoryid":1,"description":"CentOS 5.5 (32-bit)"}, {"id":112,"oscategoryid":1,"description":"CentOS 5.5 (64-bit)"}, {"id":73,"oscategoryid":2,"description":"Debian GNU/Linux 4(32-bit)"}, {"id":74,"oscategoryid":2,"description":"Debian GNU/Linux 4(64-bit)"}, {"id":72,"oscategoryid":2,"description":"Debian GNU/Linux 5(64-bit)"}, {"id":15,"oscategoryid":2,"description":"Debian GNU/Linux 5.0 (32-bit)"}, {"id":132,"oscategoryid":2,"description":"Debian GNU/Linux 6(32-bit)"}, {"id":133,"oscategoryid":2,"description":"Debian GNU/Linux 6(64-bit)"}, {"id":102,"oscategoryid":6,"description":"DOS"}, {"id":118,"oscategoryid":4,"description":"Fedora 10"}, {"id":117,"oscategoryid":4,"description":"Fedora 11"}, {"id":116,"oscategoryid":4,"description":"Fedora 12"}, {"id":115,"oscategoryid":4,"description":"Fedora 13"}, {"id":120,"oscategoryid":4,"description":"Fedora 8"}, {"id":119,"oscategoryid":4,"description":"Fedora 9"}, {"id":83,"oscategoryid":9,"description":"FreeBSD (32-bit)"}, {"id":84,"oscategoryid":9,"description":"FreeBSD (64-bit)"}, {"id":92,"oscategoryid":6,"description":"Microsoft Small Bussiness Server 2003"}, {"id":138,"oscategoryid":7,"description":"None"}, {"id":78,"oscategoryid":8,"description":"Novell Netware 5.1"}, {"id":77,"oscategoryid":8,"description":"Novell Netware 6.x"}, {"id":68,"oscategoryid":7,"description":"Open Enterprise Server"}, {"id":16,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.0 (32-bit)"}, {"id":17,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.0 (64-bit)"}, {"id":18,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.1 (32-bit)"}, {"id":19,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.1 (64-bit)"}, {"id":20,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.2 (32-bit)"}, {"id":21,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.2 (64-bit)"}, {"id":22,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.3 (32-bit)"}, {"id":23,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.3 (64-bit)"}, {"id":24,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.4 (32-bit)"}, {"id":25,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.4 (64-bit)"}, {"id":134,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.5 (32-bit)"}, {"id":135,"oscategoryid":3,"description":"Oracle Enterprise Linux 5.5 (64-bit)"}, {"id":104,"oscategoryid":7,"description":"OS/2"}, {"id":60,"oscategoryid":7,"description":"Other (32-bit)"}, {"id":103,"oscategoryid":7,"description":"Other (64-bit)"}, {"id":75,"oscategoryid":7,"description":"Other 2.6x Linux (32-bit)"}, {"id":76,"oscategoryid":7,"description":"Other 2.6x Linux (64-bit)"}, {"id":200,"oscategoryid":1,"description":"Other CentOS (32-bit)"}, {"id":201,"oscategoryid":1,"description":"Other CentOS (64-bit)"}, {"id":98,"oscategoryid":7,"description":"Other Linux (32-bit)"}, {"id":99,"oscategoryid":7,"description":"Other Linux (64-bit)"}, {"id":139,"oscategoryid":7,"description":"Other PV (32-bit)"}, {"id":140,"oscategoryid":7,"description":"Other PV (64-bit)"}, {"id":202,"oscategoryid":5,"description":"Other SUSE Linux(32-bit)"}, {"id":203,"oscategoryid":5,"description":"Other SUSE Linux(64-bit)"}, {"id":59,"oscategoryid":10,"description":"Other Ubuntu (32-bit)"}, {"id":100,"oscategoryid":10,"description":"Other Ubuntu (64-bit)"}, {"id":131,"oscategoryid":10,"description":"Red Hat Enterprise Linux 2"}, {"id":66,"oscategoryid":4,"description":"Red Hat Enterprise Linux 3(32-bit)"}, {"id":67,"oscategoryid":4,"description":"Red Hat Enterprise Linux 3(64-bit)"}, {"id":106,"oscategoryid":4,"description":"Red Hat Enterprise Linux 4(64-bit)"}, {"id":26,"oscategoryid":4,"description":"Red Hat Enterprise Linux 4.5 (32-bit)"}, {"id":27,"oscategoryid":4,"description":"Red Hat Enterprise Linux 4.6 (32-bit)"}, {"id":28,"oscategoryid":4,"description":"Red Hat Enterprise Linux 4.7 (32-bit)"}, {"id":29,"oscategoryid":4,"description":"Red Hat Enterprise Linux 4.8 (32-bit)"}, {"id":30,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.0 (32-bit)"}, {"id":31,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.0 (64-bit)"}, {"id":32,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.1 (32-bit)"}, {"id":33,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.1 (64-bit)"}, {"id":34,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.2 (32-bit)"}, {"id":35,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.2 (64-bit)"}, {"id":36,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.3 (32-bit)"}, {"id":37,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.3 (64-bit)"}, {"id":38,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.4 (32-bit)"}, {"id":39,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.4 (64-bit)"}, {"id":113,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.5 (32-bit)"}, {"id":114,"oscategoryid":4,"description":"Red Hat Enterprise Linux 5.5 (64-bit)"}, {"id":136,"oscategoryid":4,"description":"Red Hat Enterprise Linux 6.0 (32-bit)"}, {"id":137,"oscategoryid":4,"description":"Red Hat Enterprise Linux 6.0 (64-bit)"}, {"id":85,"oscategoryid":9,"description":"SCO OpenServer 5"}, {"id":86,"oscategoryid":9,"description":"SCO UnixWare 7"}, {"id":79,"oscategoryid":9,"description":"Sun Solaris 10(32-bit)"}, {"id":80,"oscategoryid":9,"description":"Sun Solaris 10(64-bit)"}, {"id":142,"oscategoryid":9,"description":"Sun Solaris 11 (32-bit)"}, {"id":141,"oscategoryid":9,"description":"Sun Solaris 11 (64-bit)"}, {"id":82,"oscategoryid":9,"description":"Sun Solaris 8(Experimental)"}, {"id":81,"oscategoryid":9,"description":"Sun Solaris 9(Experimental)"}, {"id":109,"oscategoryid":5,"description":"SUSE Linux Enterprise 10(32-bit)"}, {"id":110,"oscategoryid":5,"description":"SUSE Linux Enterprise 10(64-bit)"}, {"id":96,"oscategoryid":5,"description":"SUSE Linux Enterprise 8(32-bit)"}, {"id":97,"oscategoryid":5,"description":"SUSE Linux Enterprise 8(64-bit)"}, {"id":107,"oscategoryid":5,"description":"SUSE Linux Enterprise 9(32-bit)"}, {"id":108,"oscategoryid":5,"description":"SUSE Linux Enterprise 9(64-bit)"}, {"id":41,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 10 SP1 (32-bit)"}, {"id":42,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 10 SP1 (64-bit)"}, {"id":43,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 10 SP2 (32-bit)"}, {"id":44,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 10 SP2 (64-bit)"}, {"id":45,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 10 SP3 (64-bit)"}, {"id":46,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 11 (32-bit)"}, {"id":47,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 11 (64-bit)"}, {"id":40,"oscategoryid":5,"description":"SUSE Linux Enterprise Server 9 SP4 (32-bit)"}, {"id":121,"oscategoryid":10,"description":"Ubuntu 10.04 (32-bit)"}, {"id":126,"oscategoryid":10,"description":"Ubuntu 10.04 (64-bit)"}, {"id":125,"oscategoryid":10,"description":"Ubuntu 8.04 (32-bit)"}, {"id":130,"oscategoryid":10,"description":"Ubuntu 8.04 (64-bit)"}, {"id":124,"oscategoryid":10,"description":"Ubuntu 8.10 (32-bit)"}, {"id":129,"oscategoryid":10,"description":"Ubuntu 8.10 (64-bit)"}, {"id":123,"oscategoryid":10,"description":"Ubuntu 9.04 (32-bit)"}, {"id":128,"oscategoryid":10,"description":"Ubuntu 9.04 (64-bit)"}, {"id":122,"oscategoryid":10,"description":"Ubuntu 9.10 (32-bit)"}, {"id":127,"oscategoryid":10,"description":"Ubuntu 9.10 (64-bit)"}, {"id":95,"oscategoryid":6,"description":"Windows 2000 Advanced Server"}, {"id":105,"oscategoryid":6,"description":"Windows 2000 Professional"}, {"id":61,"oscategoryid":6,"description":"Windows 2000 Server"}, {"id":55,"oscategoryid":6,"description":"Windows 2000 Server SP4 (32-bit)"}, {"id":65,"oscategoryid":6,"description":"Windows 3.1"}, {"id":48,"oscategoryid":6,"description":"Windows 7 (32-bit)"}, {"id":49,"oscategoryid":6,"description":"Windows 7 (64-bit)"}, {"id":63,"oscategoryid":6,"description":"Windows 95"}, {"id":62,"oscategoryid":6,"description":"Windows 98"}, {"id":64,"oscategoryid":6,"description":"Windows NT 4"}, {"id":204,"oscategoryid":6,"description":"Windows PV"}, {"id":87,"oscategoryid":6,"description":"Windows Server 2003 DataCenter Edition(32-bit)"}, {"id":88,"oscategoryid":6,"description":"Windows Server 2003 DataCenter Edition(64-bit)"}, {"id":50,"oscategoryid":6,"description":"Windows Server 2003 Enterprise Edition(32-bit)"}, {"id":51,"oscategoryid":6,"description":"Windows Server 2003 Enterprise Edition(64-bit)"}, {"id":89,"oscategoryid":6,"description":"Windows Server 2003 Standard Edition(32-bit)"}, {"id":90,"oscategoryid":6,"description":"Windows Server 2003 Standard Edition(64-bit)"}, {"id":91,"oscategoryid":6,"description":"Windows Server 2003 Web Edition"}, {"id":52,"oscategoryid":6,"description":"Windows Server 2008 (32-bit)"}, {"id":53,"oscategoryid":6,"description":"Windows Server 2008 (64-bit)"}, {"id":54,"oscategoryid":6,"description":"Windows Server 2008 R2 (64-bit)"}, {"id":56,"oscategoryid":6,"description":"Windows Vista (32-bit)"}, {"id":101,"oscategoryid":6,"description":"Windows Vista (64-bit)"}, {"id":93,"oscategoryid":6,"description":"Windows XP (32-bit)"}, {"id":94,"oscategoryid":6,"description":"Windows XP (64-bit)"}, {"id":57,"oscategoryid":6,"description":"Windows XP SP2 (32-bit)"}, {"id":58,"oscategoryid":6,"description":"Windows XP SP3 (32-bit)"} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listPortForwardingRules_default.json0000664000175000017500000000066713535474530034157 0ustar kamikami00000000000000{ "listportforwardingrulesresponse" : { "count":1 ,"portforwardingrule" : [ {"id":"bc7ea3ee-a2c3-4b86-a53f-01bdaa1b2e32","privateport":"33","privateendport":"34","protocol":"tcp","publicport":"33","publicendport":"34","virtualmachineid":"2600","virtualmachinename":"testlib","virtualmachinedisplayname":"testlib","ipaddressid":"96dac96f-0b5d-42c1-b5de-8a97f3e34c43","ipaddress":"1.1.1.116","state":"Active","cidrlist":"","tags":[]} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json0000664000175000017500000000303413535474530031755 0ustar kamikami00000000000000{ "listprojectsresponse": { "count": 1, "project": [ { "id": "e7ce14a8-abb7-48b9-931f-5f426febed6d", "name": "ExampleProjectName", "displaytext": "ExampleProject", "account": "CB0512", "cpuavailable": 18, "cpulimit": 32, "cputotal": 14, "domain": "ExampleDomain", "domainid": "dc0314d4-09aa-4e8f-8a54-419ecf344635", "ipavailable": 8, "iplimit": 8, "iptotal": 0, "memoryavailable": 72000, "memorylimit": 128000, "memorytotal": 56000, "networkavailable": 0, "networklimit": "Unlimited", "networktotal": 0, "primarystorageavailable": 1204, "primarystoragelimit": 1600, "primarystoragetotal": 396, "secondarystorageavailable": 3817, "secondarystoragelimit": 4000, "secondarystoragetotal": 183, "snapshotavailable": 17, "snapshotlimit": 20, "snapshottotal": 3, "state": "Active", "tags": [], "templateavailable": 17, "templatelimit": 20, "templatetotal": 3, "vmavailable": 1, "vmlimit": 8, "vmrunning": 7, "vmtotal": 7, "volumeavailable": 1, "volumelimit": 16, "volumetotal": 15, "vpcavailable": 20, "vpclimit": 0, "vpctotal": 0 } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_default.json0000664000175000017500000000244413535474530033535 0ustar kamikami00000000000000{ "listpublicipaddressesresponse" : { "publicipaddress" : [ {"id":34000,"ipaddress":"1.1.1.116","virtualmachineid":"2600","allocated":"2011-06-23T05:20:39+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33999,"ipaddress":"1.1.1.48","allocated":"2011-06-23T05:20:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33998,"ipaddress":"1.1.1.47","allocated":"2011-06-23T05:20:30+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33970,"ipaddress":"1.1.1.19","allocated":"2011-06-20T04:08:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":true,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"} ] } } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_firewallicmp.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_firewallicmp.j0000664000175000017500000000244413535474530034047 0ustar kamikami00000000000000{ "listpublicipaddressesresponse" : { "publicipaddress" : [ {"id":34000,"ipaddress":"1.1.1.116","virtualmachineid":"2600","allocated":"2011-06-23T05:20:39+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33999,"ipaddress":"1.1.1.48","allocated":"2011-06-23T05:20:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33998,"ipaddress":"1.1.1.47","allocated":"2011-06-23T05:20:30+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33970,"ipaddress":"1.1.1.19","allocated":"2011-06-20T04:08:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":true,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listResourceLimits_default.json0000664000175000017500000000237013535474530033137 0ustar kamikami00000000000000{ "listresourcelimitsresponse" : { "count":8 ,"resourcelimit" : [ {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"0","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"1","max":-1}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"2","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"3","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"4","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"5","max":-1}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"6","max":20}, {"account":"fakeuser@mycompany.com","domainid":"bd0b5c60-cd1e-4bf0-8d90-72c4b0de7520","domain":"fakeuser@mycompany.com","resourcetype":"7","max":20} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listRouters_default.json0000664000175000017500000000327213535474530031633 0ustar kamikami00000000000000{ "listroutersresponse" : { "count":1 ,"router" : [ {"id":"634c57f2-5ea2-487b-a5d3-5bb5550de691","zoneid":"2","zonename":"TEST-ZONE","dns1":"8.8.8.8","dns2":"8.8.8.4","networkdomain":"cloudify-mgmt.local","gateway":"178.237.34.1","name":"r-21786-VM","publicip":"178.237.34.110","publicmacaddress":"06:49:62:00:02:cf","publicnetmask":"255.255.255.0","publicnetworkid":"38204176-846f-4d24-bb3e-725e5756b62a","guestipaddress":"10.10.10.1","guestmacaddress":"02:00:57:2b:00:03","guestnetmask":"255.255.255.192","guestnetworkid":"3cfab464-d6b5-4944-bd77-24afae1190b2","templateid":"77f1ad92-4b83-4481-b7ca-5c6b1a9fa82f","created":"2014-09-30T11:29:46+0200","state":"Running","account":"test","domainid":"ee90435a-bba8-427f-90f9-02f9bf9e03aa","domain":"test","serviceofferingid":"01f93707-3a35-44a6-84e9-ea767287a6b2","serviceofferingname":"System Offering For Software Router","isredundantrouter":false,"redundantstate":"UNKNOWN","version":"4.3.0","vpcid":"3ec197ca-167f-40f0-b306-edf97a0490bf","role":"VIRTUAL_ROUTER","nic":[{"id":"b62719ae-c5dc-423d-928d-892aeee1798a","networkid":"38204176-846f-4d24-bb3e-725e5756b62a","netmask":"255.255.255.0","gateway":"178.237.34.1","ipaddress":"178.237.34.110","isolationuri":"vlan://50","broadcasturi":"vlan://50","traffictype":"Public","isdefault":true,"macaddress":"06:49:62:00:02:cf"},{"id":"cf9f148e-2e7b-4894-8071-50f35778e5f0","networkid":"3cfab464-d6b5-4944-bd77-24afae1190b2","netmask":"255.255.255.192","ipaddress":"10.10.10.1","isolationuri":"lswitch:3a682dc2-2c86-439a-97cf-e594957e9e72","broadcasturi":"lswitch:3a682dc2-2c86-439a-97cf-e594957e9e72","traffictype":"Guest","type":"Isolated","isdefault":false,"macaddress":"02:00:57:2b:00:03"}],"requiresupgrade":false} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json0000664000175000017500000000023113535474530032265 0ustar kamikami00000000000000{"listsshkeypairsresponse":{"count":1,"sshkeypair":[{"name":"cs-keypair","fingerprint":"00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"}]}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one.json0000664000175000017500000000023113535474530032261 0ustar kamikami00000000000000{"listsshkeypairsresponse":{"count":1,"sshkeypair":[{"name":"cs-keypair","fingerprint":"00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"}]}} ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one_doesnt_exist.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_get_one_doesnt_exist0000664000175000017500000000004413535474530034103 0ustar kamikami00000000000000{ "listsshkeypairsresponse" : { } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_no_keys.json0000664000175000017500000000003713535474530032314 0ustar kamikami00000000000000{"listsshkeypairsresponse":{}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json0000664000175000017500000000257713535474530033206 0ustar kamikami00000000000000{ "listsecuritygroupsresponse" : { "count":2 ,"securitygroup" : [ {"id":"ebfa2339","name":"default","description":"Default Security Group","account":"gmail.com","domainid":"ab53d864","domain":"gmail.com","ingressrule":[{"ruleid":"b83428c0-7f4c-44d1-bc96-4e1720168fdf","protocol":"tcp","startport":22,"endport":22,"cidr":"0.0.0.0/0"},{"ruleid":"bcb528e7-1a77-48f5-9bac-65cdcbc760e8","protocol":"tcp","startport":9200,"endport":9200,"cidr":"0.0.0.0/0"},{"ruleid":"80cca966-aa85-4bf0-9cb3-6b318b5d577f","protocol":"tcp","startport":9200,"endport":9300,"securitygroupname":"default","account":"runseb@gmail.com"},{"ruleid":"04f1264d-d0af-4c51-bcf9-4776166bba7d","protocol":"tcp","startport":8080,"endport":8080,"cidr":"0.0.0.0/0"}],"egressrule":[],"tags":[]}, {"id":"efae588b-5d74-4d0f-aeb8-96250d45fdee","name":"mongodb","description":"A SG for replica sets","account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","domain":"runseb@gmail.com","ingressrule":[{"ruleid":"ed30a29e-4456-4df6-ba26-26b350da0bd9","protocol":"tcp","startport":27017,"endport":27017,"securitygroupname":"default","account":"runseb@gmail.com"},{"ruleid":"4b5722f0-fc04-4263-93e7-c93564e5619c","protocol":"tcp","startport":22,"endport":22,"cidr":"0.0.0.0/0"},{"ruleid":"2430f851-189f-4d10-9bcd-b2276bc7d6a3","protocol":"tcp","startport":27017,"endport":27017,"cidr":"0.0.0.0/0"}],"egressrule":[],"tags":[]} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_no_groups.json0000664000175000017500000000004613535474530033562 0ustar kamikami00000000000000{ "listsecuritygroupsresponse" : {} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_default.json0000664000175000017500000000234313535474530033431 0ustar kamikami00000000000000{ "listserviceofferingsresponse" : { "serviceoffering" : [ {"id":105,"name":"Compute Micro PRD","displaytext":"1CPU, 384MB, 80GB HDD","cpunumber":1,"cpuspeed":1200,"memory":384,"created":"2011-06-01T03:38:05+0000","storagetype":"shared","offerha":false,"domainid":14,"domain":"AA000062"}, {"id":70,"name":"Compute XLarge PRD","displaytext":"8CPU, 13.6GB RAM, 160GB Storage","cpunumber":8,"cpuspeed":1200,"memory":13928,"created":"2011-02-08T07:06:19+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":69,"name":"Compute Large PRD","displaytext":"4CPU, 6.8GB RAM, 160GB Storage","cpunumber":4,"cpuspeed":1200,"memory":6964,"created":"2011-02-08T07:05:47+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":68,"name":"Compute Medium PRD","displaytext":"2CPU, 3.4GB RAM, 160GB Storage","cpunumber":2,"cpuspeed":1200,"memory":3484,"created":"2011-02-08T07:05:03+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"}, {"id":67,"name":"Compute Small PRD","displaytext":"1CPU, 1.7GB RAM, 160GB Storage","cpunumber":1,"cpuspeed":1200,"memory":1744,"created":"2011-02-08T07:03:44+0000","storagetype":"shared","offerha":true,"domainid":14,"domain":"AA000062"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_deployip.json0000664000175000017500000000162613535474530033635 0ustar kamikami00000000000000{ "listserviceofferingsresponse" : {"count": 3, "serviceoffering": [ {"cpunumber": 2, "cpuspeed": 1600, "created": "2011-09-09T13:14:19+0900", "defaultuse": false, "displaytext": "M4", "id": 21, "issystem": false, "limitcpuuse": true, "memory": 4096, "name": "M4", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 800, "created": "2011-09-09T13:17:52+0900", "defaultuse": false, "displaytext": "XS", "id": 24, "issystem": false, "limitcpuuse": true, "memory": 512, "name": "XS", "networkrate": 100, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 1600, "created": "2011-09-14T22:51:23+0900", "defaultuse": false, "displaytext": "S2", "id": 30, "issystem": false, "limitcpuuse": true, "memory": 2048, "name": "S2", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}]}} ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_deploynetworks.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_deploynetworks.0000664000175000017500000000162613535474530034207 0ustar kamikami00000000000000{ "listserviceofferingsresponse" : {"count": 3, "serviceoffering": [ {"cpunumber": 2, "cpuspeed": 1600, "created": "2011-09-09T13:14:19+0900", "defaultuse": false, "displaytext": "M4", "id": 21, "issystem": false, "limitcpuuse": true, "memory": 4096, "name": "M4", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 800, "created": "2011-09-09T13:17:52+0900", "defaultuse": false, "displaytext": "XS", "id": 24, "issystem": false, "limitcpuuse": true, "memory": 512, "name": "XS", "networkrate": 100, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 1600, "created": "2011-09-14T22:51:23+0900", "defaultuse": false, "displaytext": "S2", "id": 30, "issystem": false, "limitcpuuse": true, "memory": 2048, "name": "S2", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}]}} ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_rootdisksize.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_rootdisksize.js0000664000175000017500000000162613535474530034204 0ustar kamikami00000000000000{ "listserviceofferingsresponse" : {"count": 3, "serviceoffering": [ {"cpunumber": 2, "cpuspeed": 1600, "created": "2011-09-09T13:14:19+0900", "defaultuse": false, "displaytext": "M4", "id": 21, "issystem": false, "limitcpuuse": true, "memory": 4096, "name": "M4", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 800, "created": "2011-09-09T13:17:52+0900", "defaultuse": false, "displaytext": "XS", "id": 24, "issystem": false, "limitcpuuse": true, "memory": 512, "name": "XS", "networkrate": 100, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 1600, "created": "2011-09-14T22:51:23+0900", "defaultuse": false, "displaytext": "S2", "id": 30, "issystem": false, "limitcpuuse": true, "memory": 2048, "name": "S2", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}]}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listServiceOfferings_stoppedvm.json0000664000175000017500000000162613535474530034031 0ustar kamikami00000000000000{ "listserviceofferingsresponse" : {"count": 3, "serviceoffering": [ {"cpunumber": 2, "cpuspeed": 1600, "created": "2011-09-09T13:14:19+0900", "defaultuse": false, "displaytext": "M4", "id": 21, "issystem": false, "limitcpuuse": true, "memory": 4096, "name": "M4", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 800, "created": "2011-09-09T13:17:52+0900", "defaultuse": false, "displaytext": "XS", "id": 24, "issystem": false, "limitcpuuse": true, "memory": 512, "name": "XS", "networkrate": 100, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}, {"cpunumber": 1, "cpuspeed": 1600, "created": "2011-09-14T22:51:23+0900", "defaultuse": false, "displaytext": "S2", "id": 30, "issystem": false, "limitcpuuse": true, "memory": 2048, "name": "S2", "networkrate": 500, "offerha": false, "storagetype": "shared", "tags": "Shared.auto"}]}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listSnapshots_default.json0000664000175000017500000000163413535474530032152 0ustar kamikami00000000000000{"listsnapshotsresponse" : { "count":3 ,"snapshot" : [ {"id":188402,"account":"User1","domainid":2345,"domain":"70000001000","snapshottype":"MANUAL","volumeid":89341,"volumename":"ROOT-12344","volumetype":"ROOT","created":"2014-09-17T19:55:48+0900","name":"i-123-87654-VM_ROOT-12344_20140917105548","intervaltype":"MANUAL","state":"BackedUp"}, {"id":188401,"account":"User1","domainid":2345,"domain":"70000001100","snapshottype":"MANUAL","volumeid":89342,"volumename":"ROOT-12345","volumetype":"ROOT","created":"2014-09-17T19:44:41+0900","name":"i-123-87654-VM_ROOT-12345_20140917104441","intervaltype":"MANUAL","state":"BackedUp"}, {"id":188400,"account":"User1","domainid":2345,"domain":"70000001100","snapshottype":"MANUAL","volumeid":89343,"volumename":"ROOT-71128","volumetype":"ROOT","created":"2014-09-17T19:34:58+0900","name":"i-882-71128-VM_ROOT-71128_20140917103458","intervaltype":"MANUAL","state":"BackedUp"}]}}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listTemplates_default.json0000664000175000017500000001406713535474530032132 0ustar kamikami00000000000000{ "listtemplatesresponse" : { "template" : [ {"id":576,"name":"ESX[beta] Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","displaytext":"ESX[beta] Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","ispublic":true,"created":"2011-06-01T01:25:12+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":126,"ostypename":"Ubuntu 10.04 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":702743552,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":443,"name":"XEN Basic Windows Svr 2008 R2 x64 R2.1","displaytext":"XEN Basic Windows Svr 2008 R2 x64 R2.1","ispublic":true,"created":"2011-03-25T01:29:46+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":54,"ostypename":"Windows Server 2008 R2 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":474,"name":"XEN Basic Windows Svr 2003 SP2 STD","displaytext":"XEN Basic Windows Svr 2003 SP2 STD","ispublic":true,"created":"2011-04-07T10:38:45+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":89,"ostypename":"Windows Server 2003 Standard Edition(32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":444,"name":"ESX[beta] Windows 2003 x32 R2.0","displaytext":"ESX[beta] Windows 2003 x32 R2.0","ispublic":true,"created":"2011-03-25T01:34:00+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":89,"ostypename":"Windows Server 2003 Standard Edition(32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":876909056,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":447,"name":"ESX[beta] Windows 2008 x32 R2.0","displaytext":"ESX[beta] Windows 2008 x32 R2.0","ispublic":true,"created":"2011-03-25T01:45:23+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":52,"ostypename":"Windows Server 2008 (32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":3391547904,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":462,"name":"ESX[beta] Centos 5.5 x64 R2.0","displaytext":"ESX[beta] Centos 5.5 x64 R2.0","ispublic":true,"created":"2011-03-28T05:06:36+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":2263178240,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":425,"name":"XEN Windows 2008 x32 R2.0","displaytext":"XEN Windows 2008 x32 R2.0","ispublic":true,"created":"2011-03-22T03:22:21+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":52,"ostypename":"Windows Server 2008 (32-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171798691840,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":461,"name":"ESX[beta] Basic Windows 2008 R2 x64","displaytext":"ESX[beta] Basic Windows 2008 R2 x64","ispublic":true,"created":"2011-03-26T22:48:48+0000","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":true,"crossZones":false,"ostypeid":54,"ostypename":"Windows Server 2008 R2 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":3230146048,"templatetype":"USER","hypervisor":"VMware","domain":"ROOT","domainid":1,"isextractable":false}, {"id":575,"name":"Xen Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","displaytext":"Xen Ubuntu 10.04.2 CHEF Small \\ Micro Optimised","ispublic":true,"created":"2011-06-01T01:06:21+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":85899345920,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":481,"name":"XEN Centos 5.4 x64 R2.0","displaytext":"XEN Centos 5.4 x64 R2.0","ispublic":true,"created":"2011-04-14T01:43:49+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171966464000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":421,"name":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","displaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","ispublic":true,"created":"2011-03-22T02:54:06+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":167772160000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":423,"name":"XEN Basic Centos 5.5 x64 PV r2.2","displaytext":"XEN Basic Centos 5.5 x64 PV r2.2","ispublic":true,"created":"2011-03-22T02:59:31+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":167772160000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false}, {"id":422,"name":"XEN OpenSUSE x64 11.4 R2.0","displaytext":"XEN OpenSUSE x64 11.4 R2.0","ispublic":true,"created":"2011-03-22T02:58:25+0000","isready":true,"passwordenabled":false,"format":"VHD","isfeatured":true,"crossZones":false,"ostypeid":12,"ostypename":"CentOS 5.3 (64-bit)","account":"admin","zoneid":1,"zonename":"Sydney","size":171966464000,"templatetype":"USER","hypervisor":"XenServer","domain":"ROOT","domainid":1,"isextractable":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listTemplates_deployip.json0000664000175000017500000000202513535474530032322 0ustar kamikami00000000000000{ "listtemplatesresponse" : {"count": 2, "template": [ {"account": "admin", "created": "2014-06-06T20:08:49+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "OVA", "hypervisor": "VMware", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 2, "zonename": "zone2"}, {"account": "admin", "created": "2014-06-06T20:08:48+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "OVA", "hypervisor": "VMware", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 1, "zonename": "zone1"} ]} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listTemplates_deploynetworks.json0000664000175000017500000000202513535474530033566 0ustar kamikami00000000000000{ "listtemplatesresponse" : {"count": 2, "template": [ {"account": "admin", "created": "2014-06-06T20:08:49+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "OVA", "hypervisor": "VMware", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 2, "zonename": "zone2"}, {"account": "admin", "created": "2014-06-06T20:08:48+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "OVA", "hypervisor": "VMware", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 1, "zonename": "zone1"} ]} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listTemplates_notemplates.json0000664000175000017500000000004113535474530033024 0ustar kamikami00000000000000{ "listtemplatesresponse" : {} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listTemplates_rootdisksize.json0000664000175000017500000000202313535474530033224 0ustar kamikami00000000000000{ "listtemplatesresponse" : {"count": 2, "template": [ {"account": "admin", "created": "2014-06-06T20:08:49+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "QCOW2", "hypervisor": "KVM", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 2, "zonename": "zone2"}, {"account": "admin", "created": "2014-06-06T20:08:48+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "QCOW2", "hypervisor": "KVM", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 1, "zonename": "zone1"} ]} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listTemplates_stoppedvm.json0000664000175000017500000000202513535474530032516 0ustar kamikami00000000000000{ "listtemplatesresponse" : {"count": 2, "template": [ {"account": "admin", "created": "2014-06-06T20:08:49+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "OVA", "hypervisor": "VMware", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 2, "zonename": "zone2"}, {"account": "admin", "created": "2014-06-06T20:08:48+0900", "crossZones": false, "displaytext": "CentOS 6.5", "domain": "ROOT", "domainid": 1, "format": "OVA", "hypervisor": "VMware", "id": 8028, "isextractable": true, "isfeatured": true, "ispublic": true, "isready": true, "name": "CentOS 6.5 64-bit", "ostypeid": 112, "ostypename": "CentOS 5.5 (64-bit)", "passwordenabled": true, "size": 16106127360, "status": "Download Complete", "templatetype": "USER", "zoneid": 1, "zonename": "zone1"} ]} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVPCOfferings_default.json0000664000175000017500000000146113535474530032461 0ustar kamikami00000000000000{ "listvpcofferingsresponse" : { "count":1 ,"vpcoffering" : [ {"id":"cd7dbd68-4333-4507-b80d-9840cab32841","name":"Default VPC offering with Netscaler","displaytext":"Default VPC offering with Netscaler","isdefault":false,"state":"Enabled","service":[{"name":"Vpn","provider":[{"name":"VpcVirtualRouter"}]},{"name":"NetworkACL","provider":[{"name":"VpcVirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dns","provider":[{"name":"VpcVirtualRouter"}]},{"name":"UserData","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Lb","provider":[{"name":"Netscaler"},{"name":"InternalLbVm"}]},{"name":"SourceNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VpcVirtualRouter"}]}]} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVPCs_default.json0000664000175000017500000000204513535474530031000 0ustar kamikami00000000000000{ "listvpcsresponse" : { "count":1 ,"vpc" : [ {"id":"6adc8ad1-a8a1-4a4e-af75-2c3643297041","name":"test","displaytext":"test","state":"Enabled","zoneid":"2","zonename":"TEST-DC-1","service":[{"name":"Vpn","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Connectivity","provider":[{"name":"NiciraNvp"}]},{"name":"NetworkACL","provider":[{"name":"VpcVirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dns","provider":[{"name":"VpcVirtualRouter"}]},{"name":"UserData","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Lb","provider":[{"name":"VpcVirtualRouter"},{"name":"InternalLbVm"}]},{"name":"SourceNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VpcVirtualRouter"}]}],"cidr":"10.1.1.0/16","vpcofferingid":"ef58092b-8547-4d41-8dc3-cdaa471e12b1","account":"test_admin","domainid":"ee90435a-bba8-427f-90f9-02f9bf9e03aa","domain":"test","network":[],"restartrequired":false,"networkdomain":"test.local","tags":[]} ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVirtualMachines_default.json0000664000175000017500000000334113535474530033263 0ustar kamikami00000000000000{ "listvirtualmachinesresponse" : { "virtualmachine" : [ {"id":2600,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:06:42+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"1.78%","networkkbsread":2,"networkkbswrite":2,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3891,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.116","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer", "tags": [{"key": "testkey", "value": "testvalue"}, {"key": "foo", "value": "bar"}]}, {"id":2601,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:09:44+0000","state":"Starting","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"jobid":17147,"jobstatus":0,"nic":[{"id":3892,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.203","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVirtualMachines_noipaddress.json0000664000175000017500000000417213535474530034155 0ustar kamikami00000000000000{ "listvirtualmachinesresponse" : { "virtualmachine" : [ { "id":2600, "name":"test", "displayname":"test", "account":"fakeaccount", "domainid":801, "domain":"AA000062-libcloud-dev", "created":"2011-06-23T05:06:42+0000", "state":"Running", "haenable":false, "zoneid":1, "zonename":"Sydney", "templateid":421, "templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0", "templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0", "passwordenabled":false, "serviceofferingid":105, "serviceofferingname":"Compute Micro PRD", "cpunumber":1, "cpuspeed":1200, "memory":384, "cpuused":"1.78%", "networkkbsread":2, "networkkbswrite":2, "guestosid":12, "rootdeviceid":0, "rootdevicetype":"IscsiLUN", "securitygroup":[], "nic":[ { "id":3891, "networkid":860, "netmask":"255.255.240.0", "gateway":"1.1.2.1", "ipaddress":"1.1.1.116", "traffictype":"Guest", "type":"Virtual", "isdefault":true }, { "id":3892, "networkid":861, "type":"Virtual", "isdefault":false } ], "hypervisor":"XenServer", "tags": [ {"key": "testkey", "value": "testvalue"}, {"key": "foo", "value": "bar"}] }, { "id":2601, "name":"test", "displayname":"test", "account":"fakeaccount", "domainid":801, "domain":"AA000062-libcloud-dev", "created":"2011-06-23T05:09:44+0000", "state":"Starting", "haenable":false, "zoneid":1, "zonename":"Sydney", "templateid":421, "templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0", "templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0", "passwordenabled":false, "serviceofferingid":105, "serviceofferingname": "Compute Micro PRD", "cpunumber":1, "cpuspeed":1200, "memory":384, "guestosid":12, "rootdeviceid":0, "rootdevicetype":"IscsiLUN", "securitygroup":[], "jobid":17147, "jobstatus":0, "nic":[ { "id":3892, "networkid":860, "netmask":"255.255.240.0", "gateway":"1.1.2.1", "ipaddress":"1.1.1.203", "traffictype":"Guest", "type":"Virtual", "isdefault":true } ], "hypervisor":"XenServer" } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVolumes_default.json0000664000175000017500000000140413535474530031615 0ustar kamikami00000000000000{ "listvolumesresponse" : { "count":1 ,"volume" : [ {"id":"fe1ada16-57a0-40ae-b577-01a153690fb4","name":"ROOT-69942","zoneid":"7dbc4787-ec2f-498d-95f0-848c8c81e5da","zonename":"MTV-Zone1","type":"ROOT","deviceid":0,"virtualmachineid":"3239ade9-fd25-405c-8eda-59f0313a3fb0","vmname":"apb-cent32-bld","vmdisplayname":"apb-cent32-bld","vmstate":"Stopped","size":139264,"created":"2013-04-16T16:25:57-0700","state":"Ready","account":"andrew","domainid":"41a4917b-7952-499d-ba7f-4c57464d3dc8","domain":"ROOT","storagetype":"local","hypervisor":"KVM","storage":"c2422.halxg.cloudera.com","destroyed":false,"serviceofferingid":"7cc4f8c3-7c56-4155-9916-9f42072ea712","serviceofferingname":"Tiny","serviceofferingdisplaytext":"Tiny (1 core, 1GB RAM)","isextractable":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVolumes_rootdisksize.json0000664000175000017500000000137113535474530032725 0ustar kamikami00000000000000{ "listvolumesresponse" : { "count":1 ,"volume" : [ {"id":"fe1ada16-57a0-40ae-b577-01a153690fb4","name":"ROOT-69941","zoneid":"7dbc4787-ec2f-498d-95f0-848c8c81e5da","zonename":"test","type":"ROOT","deviceid":0,"virtualmachineid":"3239ade9-fd25-405c-8eda-59f0313a3fb0","vmname":"rootdisksize","vmdisplayname":"rootdisksize","vmstate":"Stopped","size":53687091200,"created":"2013-04-16T16:25:57-0700","state":"Ready","account":"testuser","domainid":"41a4917b-7952-499d-ba7f-4c57464d3dc8","domain":"ROOT","storagetype":"local","hypervisor":"KVM","storage":"c24232.test.com","destroyed":false,"serviceofferingid":"7cc4f8c3-7c56-4155-9916-9f42072ea712","serviceofferingname":"Tiny","serviceofferingdisplaytext":"Tiny (1 core, 1GB RAM)","isextractable":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVpnConnections_default.json0000664000175000017500000000170713535474530033137 0ustar kamikami00000000000000{ "listvpnconnectionsresponse": { "count": 1, "vpnconnection": [ { "account": "some_admin", "cidrlist": "10.2.2.0/24", "created": "2015-02-20T13:32:58+0100", "domain": "some_domain", "domainid": "9b397dea-25ef-4c5d-b47d-627eaebe8ed8", "dpd": false, "esplifetime": 3600, "esppolicy": "3des-md5", "gateway": "10.2.2.1", "id": "8f482d9a-6cee-453b-9e78-b0e1338ffce9", "ikelifetime": 86400, "ikepolicy": "3des-md5", "ipsecpsk": "xxx", "passive": false, "publicip": "1.2.3.4", "s2scustomergatewayid": "ea67eaae-1c2a-4e65-b910-441e77f69bea", "s2svpngatewayid": "cffa0cab-d1da-42a7-92f6-41379267a29f", "state": "Connected" } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVpnCustomerGateways_default.json0000664000175000017500000000127413535474530034162 0ustar kamikami00000000000000{ "listvpncustomergatewaysresponse": { "count": 1, "vpncustomergateway": [ { "account": "some_account", "cidrlist": "10.2.2.0/24", "domain": "some_domain", "domainid": "9b397dea-25ef-4c5d-b47d-627eaebe8ed8", "dpd": false, "esplifetime": 3600, "esppolicy": "3des-md5", "gateway": "10.2.2.1", "id": "ea67eaae-1c2a-4e65-b910-441e77f69bea", "ikelifetime": 86400, "ikepolicy": "3des-md5", "ipsecpsk": "some_psk", "name": "some_name" } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listVpnGateways_default.json0000664000175000017500000000067213535474530032441 0ustar kamikami00000000000000{ "listvpngatewaysresponse": { "count": 1, "vpngateway": [ { "account": "some_account", "domain": "some_domain", "domainid": "9b397dea-25ef-4c5d-b47d-627eaebe8ed8", "id": "cffa0cab-d1da-42a7-92f6-41379267a29f", "publicip": "1.2.3.4", "vpcid": "4d25e181-8850-4d52-8ecb-a6f35bbbabde" } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_default.json0000664000175000017500000000017413535474530031264 0ustar kamikami00000000000000{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail.json0000664000175000017500000000017413535474530031770 0ustar kamikami00000000000000{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_deployfail2.json0000664000175000017500000000017413535474530032052 0ustar kamikami00000000000000{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_deployip.json0000664000175000017500000000066213535474530031467 0ustar kamikami00000000000000{ "listzonesresponse" : { "count":2 ,"zone" : [ {"id":1,"name":"zone1","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"6a3bfa26-67cd-3ff2-867e-20e86b211bb1","dhcpprovider":"VirtualRouter"}, {"id":2,"name":"zone2","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"8366e550-542d-373d-88e3-ca7c90bc8e6c","dhcpprovider":"VirtualRouter"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_deploynetworks.json0000664000175000017500000000066213535474530032733 0ustar kamikami00000000000000{ "listzonesresponse" : { "count":2 ,"zone" : [ {"id":1,"name":"zone1","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"6a3bfa26-67cd-3ff2-867e-20e86b211bb1","dhcpprovider":"VirtualRouter"}, {"id":2,"name":"zone2","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"8366e550-542d-373d-88e3-ca7c90bc8e6c","dhcpprovider":"VirtualRouter"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_rootdisksize.json0000664000175000017500000000066213535474530032373 0ustar kamikami00000000000000{ "listzonesresponse" : { "count":2 ,"zone" : [ {"id":1,"name":"zone1","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"6a3bfa26-67cd-3ff2-867e-20e86b211bb1","dhcpprovider":"VirtualRouter"}, {"id":2,"name":"zone2","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"8366e550-542d-373d-88e3-ca7c90bc8e6c","dhcpprovider":"VirtualRouter"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_stoppedvm.json0000664000175000017500000000066213535474530031663 0ustar kamikami00000000000000{ "listzonesresponse" : { "count":2 ,"zone" : [ {"id":1,"name":"zone1","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"6a3bfa26-67cd-3ff2-867e-20e86b211bb1","dhcpprovider":"VirtualRouter"}, {"id":2,"name":"zone2","networktype":"Advanced","securitygroupsenabled":false,"allocationstate":"Enabled","zonetoken":"8366e550-542d-373d-88e3-ca7c90bc8e6c","dhcpprovider":"VirtualRouter"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_withcustomdisksize.json0000664000175000017500000000017413535474530033614 0ustar kamikami00000000000000{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/listZones_withvolumetype.json0000664000175000017500000000017413535474530032745 0ustar kamikami00000000000000{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11111.json0000664000175000017500000000166613535474530032316 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"cb13887","userid":"11110","cmd":"org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"ipaddress":{"id":"10987171-8cc9-4d0a-b98f-1698c09ddd2d","ipaddress":"7.5.6.1","allocated":"2013-09-05T06:19:59-0400","zoneid":"d06193b2-7980-4ad1-b5d8-7b2f2eda63c3","zonename":"SanJose","issourcenat":false,"account":"admin","domainid":"0ce03bf9-540d-47da-b3f3-75df64fddf2f","domain":"ROOT","forvirtualnetwork":true,"vlanid":"0cf2e30a-1d75-4108-8a50-259e0590faf9","vlanname":"67","isstaticnat":false,"issystem":false,"associatednetworkid":"edd15baf-b5af-4805-8484-3478ad236372","associatednetworkname":"defaultown","networkid":"9a3b3ed4-40f4-4def-aecb-8b9f54536693","state":"Allocating","physicalnetworkid":"3a997df4-ea89-4b53-b523-010857a9087b","tags":[]}},"created":"2013-09-05T06:19:59-0400","jobid":"11111"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_111112.json0000664000175000017500000000114113535474530032364 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"5d7d4c5e-7e0b-4ac2-8550-713180d8a342","userid":"5fb4b286-ac58-44a7-acae-d47dbbac78d1","cmd":"org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"networkacl":{"id":"54bd8cc6-5db0-4f64-8495-a0dfaf3fb4d5","protocol":"tcp","startport":"1","endport":"1","traffictype":"Egress","state":"Active","cidrlist":"0.0.0.0/0","tags":[],"aclid":"0420fe87-b781-4579-a083-4890fb718d7e","number":20,"action":"Allow"}},"created":"2014-10-09T11:05:50+0200","jobid":"111112"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11112.json0000664000175000017500000000056313535474530032312 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"cb13887c-7c6a-464d-aa8f-c6971f9dd458","userid":"11110e27-5a51-4109-9598-7df34141761a","cmd":"org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2013-09-05T06:36:44-0400","jobid":"11112"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11113.json0000664000175000017500000000131013535474530032302 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"cb13887c","userid":"11110","cmd":"org.apache.cloudstack.api.command.user.firewall.CreatePortForwardingRuleCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"portforwardingrule":{"id":"bc7ea3ee-a2c3-4b86-a53f-01bdaa1b2e32","privateport":"33","privateendport":"33","protocol":"tcp","publicport":"33","publicendport":"33","virtualmachineid":"8879e159-d4a6-4a1d-bc75-074c097bef2a","virtualmachinename":"testlib","virtualmachinedisplayname":"libcloud","ipaddressid":"96dac96f-0b5d-42c1-b5de-8a97f3e34c43","ipaddress":"7.5.1.7","state":"Active","cidrlist":"","tags":[]}},"created":"2013-09-05T07:33:43-0400","jobid":"11113"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11114.json0000664000175000017500000000057213535474530032314 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"cb13887c-7c6a-464d-aa8f-c6971f9dd458","userid":"11110e27-5a51-4109-9598-7df34141761a","cmd":"org.apache.cloudstack.api.command.user.firewall.DeletePortForwardingRuleCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2013-09-05T09:09:01-0400","jobid":"11114"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11115.json0000664000175000017500000000310113535474530032304 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"b8c0baab","userid":"968f6b4e","cmd":"com.cloud.api.commands.DeployVMCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":"fc4fd31a-16d3-49db-814a-56b39b9ef986","name":"test","displayname":"test","account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","domain":"runseb@gmail.com","created":"2013-09-05T15:45:11+0200","state":"Running","haenable":false,"zoneid":"1128bd56-b4d9-4ac6-a7b9-c715b187ce11","zonename":"CH-GV2","templateid":"a17b40d6-83e4-4f2a-9ef0-dce6af575789","templatename":"Linux Ubuntu 12.04 LTS 64-bit","templatedisplaytext":"Linux Ubuntu 12.04 LTS 64-bit 10GB Disk","passwordenabled":true,"serviceofferingid":"71004023-bb72-4a97-b1e9-bc66dfce9470","serviceofferingname":"Micro","cpunumber":1,"cpuspeed":2198,"memory":512,"guestosid":"113038d0-a8cd-4d20-92be-ea313f87c3ac","rootdeviceid":0,"rootdevicetype":"Filesystem","securitygroup":[{"id":"efae588b-5d74-4d0f-aeb8-96250d45fdee","name":"default","description":"A SG for replica sets"},{"id":"ebfa2339-e9ae-4dcb-b73c-a76cd3fce39e","name":"mongodb","description":"Default Security Group"}],"password":"iQ7hbmrjw","nic":[{"id":"09a806c7-ab1e-452d-a779-dda974ea7e41","networkid":"00304a04-c7ea-4e77-a786-18bc64347bf7","netmask":"255.255.254.0","gateway":"185.19.28.1","ipaddress":"185.19.28.98","traffictype":"Guest","type":"Shared","isdefault":true,"macaddress":"06:54:5a:00:00:95"}],"hypervisor":"KVM","tags":[]}},"created":"2013-09-05T15:45:11+0200","jobid":"10046ad6-917f-4c25-add3-e08cd98e0e87"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11116.json0000664000175000017500000000304713535474530032316 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"b8c0baab-18a1-44c0-ab67-e24049212925","userid":"968f6b4e-b382-4802-afea-dd731d4cf9b9","cmd":"com.cloud.api.commands.DeployVMCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":"94fa7e76-9a39-4e5a-8f84-40e496650780","name":"test","displayname":"test","account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","domain":"runseb@gmail.com","created":"2012-09-05T16:05:50+0200","state":"Running","haenable":false,"zoneid":"1128bd56-b4d9-4ac6-a7b9-c715b187ce11","zonename":"CH-GV2","templateid":"a17b40d6-83e4-4f2a-9ef0-dce6af575789","templatename":"Linux Ubuntu 12.04 LTS 64-bit","templatedisplaytext":"Linux Ubuntu 12.04 LTS 64-bit 10GB Disk","passwordenabled":true,"serviceofferingid":"71004023-bb72-4a97-b1e9-bc66dfce9470","serviceofferingname":"Micro","cpunumber":1,"cpuspeed":2198,"memory":512,"guestosid":"113038d0-a8cd-4d20-92be-ea313f87c3ac","rootdeviceid":0,"rootdevicetype":"Filesystem","securitygroup":[{"id":"ebfa2339-e9ae-4dcb-b73c-a76cd3fce39e","name":"default","description":"Default Security Group"}],"password":"zU3gwurmi","nic":[{"id":"2bd513cf-7453-4594-87c2-2d8b17ae8fad","networkid":"00304a04-c7ea-4e77-a786-18bc64347bf7","netmask":"255.255.254.0","gateway":"185.19.28.1","ipaddress":"185.19.28.96","traffictype":"Guest","type":"Shared","isdefault":true,"macaddress":"06:84:e0:00:00:93"}],"hypervisor":"KVM","tags":[],"keypair":"foobar"}},"created":"2013-09-05T16:05:51+0200","jobid":"a0c97348-4d21-43ba-879e-9d8340ec0805"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json0000664000175000017500000000476113535474530032323 0ustar kamikami00000000000000{ "queryasyncjobresultresponse": { "accountid": "86d47ca2-726b-4b85-a18a-77d6b0d79829", "userid": "20cd68f5-0633-48a5-826e-e4e2a00dd6b8", "cmd": "org.apache.cloudstack.api.command.user.vm.DeployVMCmd", "jobstatus": 1, "jobprocstatus": 0, "jobresultcode": 0, "jobresulttype": "object", "jobresult": { "virtualmachine": { "id": "19253fbf-abb7-4013-a8a1-97df3b93f206", "name": "TestNode", "projectid": "b90442d1-079b-4066-ab7d-41f8f3a5078b", "project": "Test Project", "domainid": "dc0314d4-09aa-4e8f-8a54-419ecf344635", "domain": "Test Domain", "created": "2014-03-06T15:39:44-0600", "state": "Running", "haenable": false, "zoneid": "d630b15a-a9e1-4641-bee8-355005b7a14d", "zonename": "TestZone", "templateid": "a032e8a0-3411-48b7-9e78-ff66823e6561", "templatename": "OL-6.3.1-64-13.11.01", "templatedisplaytext": "OL-6.3.1-64-13.11.01", "passwordenabled": true, "serviceofferingid": "519f8667-26d0-40e5-a1cd-da04be1fd9b5", "serviceofferingname": "Test Service Offering", "cpunumber": 1, "cpuspeed": 2000, "memory": 2000, "guestosid": "b8506c91-6d8e-4086-8659-f6296a7b71ac", "rootdeviceid": 0, "rootdevicetype": "ROOT", "securitygroup": [], "password": "mW6crjxag", "nic": [ { "id": "1c144283-979a-4359-b695-3334dc403457", "networkid": "1bf4acce-19a5-4830-ab1d-444f8acb9986", "networkname": "Public", "netmask": "255.255.252.0", "gateway": "10.1.2.2", "ipaddress": "10.2.2.8", "isolationuri": "vlan://2950", "broadcasturi": "vlan://2950", "traffictype": "Guest", "type": "Shared", "isdefault": true, "macaddress": "06:ef:30:00:04:22" } ], "hypervisor": "VMware", "tags": [], "affinitygroup": [], "displayvm": true, "isdynamicallyscalable": false, "jobid": "e23b9f0c-b7ae-4ffe-aea0-c9cf436cc315", "jobstatus": 0 } }, "created": "2014-03-06T15:39:44-0600", "jobid": "e23b9f0c-b7ae-4ffe-aea0-c9cf436cc315" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149341.json0000664000175000017500000000046613535474530032475 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1149341,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"firewallrule":{"id":172465,"protocol":"tcp","startport":"33","endport":"34","ipaddressid":34000,"ipaddress":"1.1.1.116","state":"Active","cidrlist":"192.168.0.0/16"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149342.json0000664000175000017500000000023613535474530032471 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1149342,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149343.json0000664000175000017500000000046113535474530032472 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1149343,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"firewallrule":{"id":172466,"protocol":"icmp","ipaddressid":34000,"ipaddress":"1.1.1.116","state":"Active","cidrlist":"192.168.0.0/16","icmptype":8,"icmpcode":0}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149366.json0000664000175000017500000000226513535474530032503 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid": 1149366, "jobprocstatus": 0, "jobresult": {"virtualmachine": {"account": "testuser", "cpunumber": 2, "cpuspeed": 1600, "created": "2014-07-06T16:40:39+0900", "displayname": "deploynetworks", "domain": "ROOT", "domainid": 1623, "guestosid": 112, "haenable": false, "hypervisor": "VMware", "id": 65385, "memory": 4096, "name": "deploynetworks", "nic": [{"gateway": "10.1.0.1", "id": 87320, "ipaddress": "10.1.0.29", "isdefault": true, "macaddress": "02:00:78:4a:01:9e", "netmask": "255.255.252.0", "networkid": 1374, "traffictype": "Guest", "type": "Virtual"}, {"gateway": "192.168.2.254", "id": 87319, "ipaddress": "192.168.2.55", "isdefault": false, "macaddress": "06:e6:50:00:70:0e", "netmask": "255.255.255.0", "networkid": 1823, "traffictype": "Guest", "type": "Direct"}], "password": "password", "passwordenabled": true, "rootdeviceid": 0, "rootdevicetype": "VMFS", "securitygroup": [], "serviceofferingid": 21, "serviceofferingname": "M4", "state": "Running" , "templatedisplaytext": "CentOS 6.5", "templateid": 8028, "templatename": "CentOS 6.5 64-bit", "zoneid": 1, "zonename": "zone1"}}, "jobresultcode": 0, "jobresulttype": "object", "jobstatus": 1} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300001.json0000664000175000017500000000074213535474530032450 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1300001,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"snapshot":{"id":190547,"account":"User1","domainid":2345,"domain":"70000001000","snapshottype":"MANUAL","volumeid":"fe1ada16-57a0-40ae-b577-01a153690fb4","volumename":"ROOT-12345","volumetype":"ROOT","created":"2014-09-22T19:09:47+0900","name":"i-123-87654-VM_ROOT-23456_20140917105548","intervaltype":"MANUAL","state":"CreatedOnPrimary"}}} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300002.json0000664000175000017500000000023513535474530032446 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1300002,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300003.json0000664000175000017500000000130013535474530032441 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1300003,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"template":{"id":10260,"name":"test-libcloud-template","displaytext":"test-libcloud-template","ispublic":false,"created":"2014-09-22T19:14:28+0900","isready":true,"passwordenabled":false,"format":"OVA","isfeatured":false,"crossZones":false,"ostypeid":99,"ostypename":"Other Linux (64-bit)","account":"User1","zoneid":2,"zonename":"zone1","status":"Download Complete","size":16106127360,"templatetype":"USER","hypervisor":"VMware","domain":"70000001100","domainid":1105,"isextractable":true,"checksum":"d8fc299515d138b13680014d05031d8b","sourcetemplateid":10259}}} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300004.json0000664000175000017500000000032613535474530032451 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1300004,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"affinitygroup" : {"id":"11113", "name": "MyAG2", "type": "MyAGType"} }} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300005.json0000664000175000017500000000024113535474530032446 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":1300005,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success" : true }} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1300006.json0000664000175000017500000000474013535474530032457 0ustar kamikami00000000000000{ "queryasyncjobresultresponse": { "accountid": "86d47ca2-726b-4b85-a18a-77d6b0d79829", "userid": "20cd68f5-0633-48a5-826e-e4e2a00dd6b8", "jobstatus": 1, "jobprocstatus": 0, "jobresultcode": 0, "jobresulttype": "object", "jobresult": { "virtualmachine": { "id": "19253fbf-abb7-4013-a8a1-97df3b93f206", "name": "TestNode", "projectid": "b90442d1-079b-4066-ab7d-41f8f3a5078b", "project": "Test Project", "domainid": "dc0314d4-09aa-4e8f-8a54-419ecf344635", "domain": "Test Domain", "created": "2014-03-06T15:39:44-0600", "state": "Running", "haenable": false, "zoneid": "d630b15a-a9e1-4641-bee8-355005b7a14d", "zonename": "TestZone", "templateid": "a032e8a0-3411-48b7-9e78-ff66823e6561", "templatename": "OL-6.3.1-64-13.11.01", "templatedisplaytext": "OL-6.3.1-64-13.11.01", "passwordenabled": true, "serviceofferingid": "519f8667-26d0-40e5-a1cd-da04be1fd9b5", "serviceofferingname": "Test Service Offering", "cpunumber": 1, "cpuspeed": 2000, "memory": 2000, "guestosid": "b8506c91-6d8e-4086-8659-f6296a7b71ac", "rootdeviceid": 0, "rootdevicetype": "ROOT", "securitygroup": [], "password": "mW6crjxag", "nic": [ { "id": "1c144283-979a-4359-b695-3334dc403457", "networkid": "1bf4acce-19a5-4830-ab1d-444f8acb9986", "networkname": "Public", "netmask": "255.255.252.0", "gateway": "10.1.2.2", "ipaddress": "10.2.2.8", "isolationuri": "vlan://2950", "broadcasturi": "vlan://2950", "traffictype": "Guest", "type": "Shared", "isdefault": true, "macaddress": "06:ef:30:00:04:22" } ], "hypervisor": "VMware", "tags": [], "affinitygroup" : [{"id":"11112", "name": "MyAG", "type": "MyAGType"}], "displayvm": true, "isdynamicallyscalable": false, "jobid": "e23b9f0c-b7ae-4ffe-aea0-c9cf436cc315", "jobstatus": 0 } }, "created": "2014-03-06T15:39:44-0600", "jobid": "e23b9f5c-b7ae-4ffe-aea0-c9cf436dc315" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json0000664000175000017500000000163313535474530032326 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17164,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"192.168.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17165.json0000664000175000017500000000172013535474530032324 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17165,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17166.json0000664000175000017500000000172213535474530032327 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Destroyed","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17177.json0000664000175000017500000000010213535474530032320 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17177,"jobstatus":2} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json0000664000175000017500000000172113535474530032332 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Starting","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json0000664000175000017500000000172013535474530032333 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Stopped","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json0000664000175000017500000000135313535474530032314 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"00000000-0000-0000-0000-000000000000","userid":"111111-1111-1111-1111-111111111111","cmd":"org.apache.cloudstack.api.command.user.securitygroup.AuthorizeSecurityGroupIngressCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"securitygroup":{"id":"222222-2222-2222-2222-222222222222","name":"test_sg","description":"Test security group","account":"smith@example.com","domainid":"333333-3333-3333-3333-333333333333","domain":"smith@example.com","ingressrule":[{"ruleid":"444444-4444-4444-4444-444444444444","protocol":"udp","startport":0,"endport":65535,"cidr":"0.0.0.0/0"}],"egressrule":[],"tags":[]}},"created":"2015-09-15T15:00:00+0200","jobid":"17200"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_88776.json0000664000175000017500000000022113535474530032337 0ustar kamikami00000000000000{ "queryasyncjobresultresponse": {"jobprocstatus": 0, "jobstatus": 1, "jobresult": {"virtualmachine": {"serviceofferingid": "eee-fff-ggg-hhh"}}}}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_88777.json0000664000175000017500000000021213535474530032340 0ustar kamikami00000000000000{ "queryasyncjobresultresponse": {"jobprocstatus": 0, "jobstatus": 1, "jobresult": {"virtualmachine": {"templateid": "aaa-bbb-ccc-ddd"}}}}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_addnictovm.json0000664000175000017500000000455213535474530033777 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : { "accountid" : "02c9bf08-6f36-44b1-a57f-df0708f90de4", "userid" : "6ef2b921-4ecf-4651-8188-f9868db73e73", "cmd" : "org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd", "jobstatus" : 1, "jobprocstatus" : 0, "jobresultcode" : 0, "jobresulttype" : "object", "jobresult" : { "virtualmachine" : { "id" : "903897b7-9241-4f93-bd08-3453c36a3c99", "name" : "test", "account" : "rkuipers_admin", "domainid" : "4b6e626c-9d50-4480-bf77-daae632c7ffd", "domain" : "rkuipers", "created" : "2014-10-03T17:24:37+0200", "state" : "Stopped", "haenable" : false, "zoneid" : "2", "zonename" : "BETA-SBP-DC-1", "guestosid" : "278699da-edfc-11e2-a249-005056ba4c5e", "securitygroup" : [], "nic" : [{ "id": "15418e74-25e8-42d3-9bd7-eb55e57825fe", "networkid": "de45b0ed-b5ae-4374-ac7c-aff3fb2aefa2", "networkname": "rkuipers-default", "netmask": "255.255.255.0", "gateway": "10.1.1.1", "ipaddress": "10.1.1.136", "isolationuri": "lswitch:d3eaa05c-4392-4918-93ab-c4a979a7988a", "broadcasturi": "lswitch:d3eaa05c-4392-4918-93ab-c4a979a7988a", "traffictype": "Guest", "type": "Isolated", "isdefault": true, "macaddress": "02:00:00:b9:01:1a" }, { "id": "f71e48da-fe40-458d-9033-ea27a3a92de1", "networkid": "f59ee08a-66b5-40c6-baa7-392394c6cea9", "networkname": "node_cellar_network", "netmask": "255.255.255.0", "gateway": "10.1.1.1", "ipaddress": "10.1.1.253", "isolationuri": "lswitch:bad1ca9f-b039-4ad1-b5fc-1f3147fad7fa", "broadcasturi": "lswitch:bad1ca9f-b039-4ad1-b5fc-1f3147fad7fa", "traffictype": "Guest", "type": "Isolated", "isdefault": false, "macaddress": "02:00:4f:84:00:1d" } ], "hypervisor" : "XenServer", "tags" : [], "affinitygroup" : [], "displayvm" : true, "isdynamicallyscalable" : false } }, "created" : "2014-10-03T18:30:59+0200", "jobid" : "e521e748-1271-4587-8433-2d094704bfe9" } } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_attachvolumejob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_attachvolumejob.0000664000175000017500000000217313535474530034141 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.AttachVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","deviceid":5,"virtualmachineid":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmname":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmdisplayname":"gre-kickstart","vmstate":"Running","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Ready","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"KVM","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering 1","diskofferingdisplaytext":"Disk offering 1 display name","storage":"Shared Storage CL01","attached":"2012-06-05T09:17:38+0200","destroyed":false,"isextractable":false}},"created":"2012-06-05T09:17:38+0200","jobid":"e07d6b9b-2b6c-45bd-840b-3c4c3d890168"} } ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnConnection.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnConnect0000664000175000017500000000227113535474530034134 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : { "cmd" : "org.apache.cloudstack.api.command.user.vpn.CreateVpnConnectionCmd", "jobid" : "createVpnConnection", "userid" : "user_id", "accountid" : "account_id", "jobprocstatus" : 0, "created" : "2015-02-23T08:36:09+0100", "jobstatus" : 1, "jobresult" : { "vpnconnection" : { "esplifetime" : 3600, "cidrlist" : "10.0.0.0/24", "gateway" : "10.0.0.1", "ikelifetime" : 86400, "state" : "Connected", "ikepolicy" : "3des-md5", "domain" : "domain", "dpd" : false, "id" : "f45c3af8-f909-4f16-9d40-ed4409c575f8", "s2svpngatewayid" : "515aefbc-448b-484b-8d6a-ff3b67637bf1", "s2scustomergatewayid" : "201fc1d1-05e1-4e9c-a025-d72e954dd856", "account" : "account", "domainid" : "domain_id", "esppolicy" : "3des-md5", "created" : "2015-02-23T08:36:09+0100", "passive" : false, "ipsecpsk" : "ipsecpsk", "publicip" : "1.2.3.4" } }, "jobresultcode" : 0, "jobresulttype" : "object" } } ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnCustomerGateway.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnCustome0000664000175000017500000000167613535474530034172 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : { "cmd" : "org.apache.cloudstack.api.command.user.vpn.CreateVpnCustomerGatewayCmd", "jobid" : "createVpnCustomerGateway", "userid" : "user_id", "accountid" : "account_id", "jobprocstatus" : 0, "created" : "2015-02-23T08:25:01+0100", "jobstatus" : 1, "jobresult" : { "vpncustomergateway" : { "esplifetime" : 3600, "cidrlist" : "10.0.0.0/24", "account" : "account", "gateway" : "10.0.0.1", "ikelifetime" : 86400, "name" : "VPN-10.0.0.1", "domainid" : "domain_id", "esppolicy" : "3des-md5", "ikepolicy" : "3des-md5", "domain" : "domain", "dpd" : false, "id" : "cef3c766-116a-4e83-9844-7d08ab7d3fd4", "ipsecpsk" : "ipsecpsk" } }, "jobresultcode" : 0, "jobresulttype" : "object" } } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnGateway.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createVpnGateway0000664000175000017500000000155413535474530034147 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : { "cmd" : "org.apache.cloudstack.api.command.user.vpn.CreateVpnGatewayCmd", "jobid" : "b26272a4-f5e4-4ebe-a7d3-eaaf3ec8280c", "userid" : "2f517f5b-cac9-48b5-aafc-e9d7ca879784", "accountid" : "4009e75e-5311-43f2-bc92-b92676455eed", "jobprocstatus" : 0, "created" : "2015-02-20T15:53:54+0100", "jobstatus" : 1, "jobresult" : { "vpngateway" : { "domain" : "some_domain", "vpcid" : "4d25e181-8850-4d52-8ecb-a6f35bbbabde", "account" : "some_account", "domainid" : "9b397dea-25ef-4c5d-b47d-627eaebe8ed8", "id" : "5ef6794e-cec8-4018-9fef-c4dacbadee14", "publicip" : "2.3.4.5" } }, "jobresultcode" : 0, "jobresulttype" : "object" } } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createtagsjob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createtagsjob.js0000664000175000017500000000056113535474530034123 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"dcfd4b83-2ae6-43d1-a2eb-af87066ecbc9","userid":"c3d3cb3c-0f13-429a-b900-5bacc346df32","cmd":"com.cloud.api.commands.CreateTagsCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-02-07T20:10:40+0100","jobid":"2a7426a5-e25e-4400-900d-09bca3c0a039"} }././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createvolumejob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createvolumejob.0000664000175000017500000000163413535474530034141 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.CreateVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Allocated","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"None","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering","diskofferingdisplaytext":"Disk offering display name","storage":"none","destroyed":false,"isextractable":false}},"created":"2012-06-05T08:47:54+0200","jobid":"35416f6d-1b5b-4ceb-a7d4-aab0deede71b"} } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteNetwork.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteNetwork.js0000664000175000017500000000061413535474530034121 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"02c9bf08-6f36-44b1-a57f-df0708f90de4","userid":"6ef2b921-4ecf-4651-8188-f9868db73e73","cmd":"org.apache.cloudstack.api.command.user.network.DeleteNetworkCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-06-11T10:09:00+0200","jobid":"65789636-d2c8-484c-9d13-47ad3de384ed"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVPC.json0000664000175000017500000000060413535474530033454 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"5d7d4c5e-7e0b-4ac2-8550-713180d8a342","userid":"5fb4b286-ac58-44a7-acae-d47dbbac78d1","cmd":"org.apache.cloudstack.api.command.user.vpc.DeleteVPCCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-09-25T00:11:31+0200","jobid":"cfa5c4f5-d312-4b18-9197-385ef169726e"} }././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnConnection.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnConnect0000664000175000017500000000067313535474530034137 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : { "cmd" : "org.apache.cloudstack.api.command.user.vpn.DeleteVpnConnectionCmd", "jobid" : "deleteVpnConnection", "userid" : "user_id", "accountid" : "account_id", "jobprocstatus" : 0, "created" : "2015-02-23T08:17:41+0100", "jobstatus" : 1, "jobresult" : { "success" : true }, "jobresultcode" : 0, "jobresulttype" : "object" } } ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnCustomerGateway.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnCustome0000664000175000017500000000070513535474530034161 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : { "cmd" : "org.apache.cloudstack.api.command.user.vpn.DeleteVpnCustomerGatewayCmd", "jobid" : "deleteVpnCustomerGateway", "userid" : "user_id", "accountid" : "account_id", "jobprocstatus" : 0, "created" : "2015-02-23T08:20:47+0100", "jobstatus" : 1, "jobresult" : { "success" : true }, "jobresultcode" : 0, "jobresulttype" : "object" } } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnGateway.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVpnGateway0000664000175000017500000000101713535474530034140 0ustar kamikami00000000000000{ "queryasyncjobresultresponse": { "accountid": "4009e75e-5311-43f2-bc92-b92676455eed", "cmd": "org.apache.cloudstack.api.command.user.vpn.DeleteVpnGatewayCmd", "created": "2015-02-20T16:32:40+0100", "jobid": "0648122e-fb16-495b-96d0-86e16b742557", "jobprocstatus": 0, "jobresult": { "success": true }, "jobresultcode": 0, "jobresulttype": "object", "jobstatus": 1, "userid": "2f517f5b-cac9-48b5-aafc-e9d7ca879784" } } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deletetagsjob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deletetagsjob.js0000664000175000017500000000056113535474530034122 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"dcfd4b83-2ae6-43d1-a2eb-af87066ecbc9","userid":"c3d3cb3c-0f13-429a-b900-5bacc346df32","cmd":"com.cloud.api.commands.DeleteTagsCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-02-08T13:43:24+0100","jobid":"02425faf-4cf4-44c2-9241-cb8b1eabc957"} }././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployrootdisksize.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployrootdisksi0000664000175000017500000000227313535474530034304 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":"deployrootdisksize", "jobprocstatus": 0, "jobresult": {"virtualmachine": {"account": "testuser", "cpunumber": 2, "cpuspeed": 1600, "created": "2014-07-06T16:40:39+0900", "displayname": "rootdisksize", "domain": "ROOT", "domainid": 1623, "guestosid": 112, "haenable": false, "hypervisor": "KVM", "id": 65285, "memory": 4096, "name": "rootdisksize", "nic": [{"gateway": "10.1.0.1", "id": 87320, "ipaddress": "10.1.0.128", "isdefault": true, "macaddress": "02:00:78:4a:01:9e", "netmask": "255.255.252.0", "networkid": 1374, "traffictype": "Guest", "type": "Virtual"}, {"gateway": "192.168.2.254", "id": 87319, "ipaddress": "192.168.2.55", "isdefault": false, "macaddress": "06:e6:50:00:70:0e", "netmask": "255.255.255.0", "networkid": 1823, "traffictype": "Guest", "type": "Direct"}], "password": "password", "passwordenabled": true, "rootdeviceid": 0, "rootdevicetype": "VMFS", "securitygroup": [], "serviceofferingid": 21, "serviceofferingname": "M4", "state": "Stopped" , "templatedisplaytext": "CentOS 6.5", "templateid": 8028, "templatename": "CentOS 6.5 64-bit", "zoneid": 1, "zonename": "zone1"}}, "jobresultcode": 0, "jobresulttype": "object", "jobstatus": 1} } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployvmstopped.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployvmstopped.0000664000175000017500000000226513535474530034212 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":"deployvmstopped", "jobprocstatus": 0, "jobresult": {"virtualmachine": {"account": "testuser", "cpunumber": 2, "cpuspeed": 1600, "created": "2014-07-06T16:40:39+0900", "displayname": "deployip", "domain": "ROOT", "domainid": 1623, "guestosid": 112, "haenable": false, "hypervisor": "VMware", "id": 65385, "memory": 4096, "name": "stopped_vm", "nic": [{"gateway": "10.1.0.1", "id": 87320, "ipaddress": "10.1.0.128", "isdefault": true, "macaddress": "02:00:78:4a:01:9e", "netmask": "255.255.252.0", "networkid": 1374, "traffictype": "Guest", "type": "Virtual"}, {"gateway": "192.168.2.254", "id": 87319, "ipaddress": "192.168.2.55", "isdefault": false, "macaddress": "06:e6:50:00:70:0e", "netmask": "255.255.255.0", "networkid": 1823, "traffictype": "Guest", "type": "Direct"}], "password": "password", "passwordenabled": true, "rootdeviceid": 0, "rootdevicetype": "VMFS", "securitygroup": [], "serviceofferingid": 21, "serviceofferingname": "M4", "state": "Stopped" , "templatedisplaytext": "CentOS 6.5", "templateid": 8028, "templatename": "CentOS 6.5 64-bit", "zoneid": 1, "zonename": "zone1"}}, "jobresultcode": 0, "jobresulttype": "object", "jobstatus": 1} } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployvmwithid.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deployvmwithid.j0000664000175000017500000000226213535474530034173 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":"deployvmwithip", "jobprocstatus": 0, "jobresult": {"virtualmachine": {"account": "testuser", "cpunumber": 2, "cpuspeed": 1600, "created": "2014-07-06T16:40:39+0900", "displayname": "deployip", "domain": "ROOT", "domainid": 1623, "guestosid": 112, "haenable": false, "hypervisor": "VMware", "id": 65385, "memory": 4096, "name": "deployip", "nic": [{"gateway": "10.1.0.1", "id": 87320, "ipaddress": "10.1.0.128", "isdefault": true, "macaddress": "02:00:78:4a:01:9e", "netmask": "255.255.252.0", "networkid": 1374, "traffictype": "Guest", "type": "Virtual"}, {"gateway": "192.168.2.254", "id": 87319, "ipaddress": "192.168.2.55", "isdefault": false, "macaddress": "06:e6:50:00:70:0e", "netmask": "255.255.255.0", "networkid": 1823, "traffictype": "Guest", "type": "Direct"}], "password": "password", "passwordenabled": true, "rootdeviceid": 0, "rootdevicetype": "VMFS", "securitygroup": [], "serviceofferingid": 21, "serviceofferingname": "M4", "state": "Running" , "templatedisplaytext": "CentOS 6.5", "templateid": 8028, "templatename": "CentOS 6.5 64-bit", "zoneid": 1, "zonename": "zone1"}}, "jobresultcode": 0, "jobresulttype": "object", "jobstatus": 1} } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_detachvolumejob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_detachvolumejob.0000664000175000017500000000165713535474530034133 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.DetachVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"5931d2ca-4e90-4915-88a8-32b38b3991a3","name":"gre-test-volume","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","size":10737418240,"created":"2012-06-15T14:56:40+0200","state":"Ready","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"KVM","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"OS disk for Windows","diskofferingdisplaytext":"OS disk for Windows","storage":"Shared Storage CL01","destroyed":false,"isextractable":false}},"created":"2012-06-15T15:08:39+0200","jobid":"ca6c856d-1f36-4e27-989e-09cad2dad808"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_removenic.json0000664000175000017500000000455713535474530033643 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : { "accountid" : "02c9bf08-6f36-44b1-a57f-df0708f90de4", "userid" : "6ef2b921-4ecf-4651-8188-f9868db73e73", "cmd" : "org.apache.cloudstack.api.command.user.vm.RemoveNicFromVMCmd", "jobstatus" : 1, "jobprocstatus" : 0, "jobresultcode" : 0, "jobresulttype" : "object", "jobresult" : { "virtualmachine" : { "id" : "903897b7-9241-4f93-bd08-3453c36a3c99", "name" : "test", "account" : "rkuipers_admin", "domainid" : "4b6e626c-9d50-4480-bf77-daae632c7ffd", "domain" : "rkuipers", "created" : "2014-10-03T17:24:37+0200", "state" : "Stopped", "haenable" : false, "zoneid" : "2", "zonename" : "BETA-SBP-DC-1", "guestosid" : "278699da-edfc-11e2-a249-005056ba4c5e", "securitygroup" : [], "nic" : [{ "id": "15418e74-25e8-42d3-9bd7-eb55e57825fe", "networkid": "de45b0ed-b5ae-4374-ac7c-aff3fb2aefa2", "networkname": "rkuipers-default", "netmask": "255.255.255.0", "gateway": "10.1.1.1", "ipaddress": "10.1.1.136", "isolationuri": "lswitch:d3eaa05c-4392-4918-93ab-c4a979a7988a", "broadcasturi": "lswitch:d3eaa05c-4392-4918-93ab-c4a979a7988a", "traffictype": "Guest", "type": "Isolated", "isdefault": true, "macaddress": "02:00:00:b9:01:1a" }, { "id": "f71e48da-fe40-458d-9033-ea27a3a92de1", "networkid": "f59ee08a-66b5-40c6-baa7-392394c6cea9", "networkname": "node_cellar_network", "netmask": "255.255.255.0", "gateway": "10.1.1.1", "ipaddress": "10.1.1.253", "isolationuri": "lswitch:bad1ca9f-b039-4ad1-b5fc-1f3147fad7fa", "broadcasturi": "lswitch:bad1ca9f-b039-4ad1-b5fc-1f3147fad7fa", "traffictype": "Guest", "type": "Isolated", "isdefault": false, "macaddress": "02:00:4f:84:00:1d" } ], "hypervisor" : "XenServer", "tags" : [], "affinitygroup" : [], "displayvm" : true, "isdynamicallyscalable" : false } }, "created" : "2014-10-03T18:40:30+0200", "jobid" : "23fc6bfc-e354-41c8-bf8b-c0db8227feb4" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json0000664000175000017500000000006513535474530033417 0ustar kamikami00000000000000{ "rebootvirtualmachineresponse" : {"jobid":17165} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_default.json0000664000175000017500000000021013535474530032750 0ustar kamikami00000000000000{ "registersshkeypairresponse": { "keypair": { "name": "foobar", "fingerprint": "c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_error.json0000664000175000017500000000014713535474530032466 0ustar kamikami00000000000000{ "registersshkeypairresponse" : {"uuidList":[],"errorcode":431,"errortext":"Public key is invalid"} } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/removeNicFromVirtualMachine_default.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/removeNicFromVirtualMachine_default.0000664000175000017500000000010113535474530033775 0ustar kamikami00000000000000{ "removenicfromvirtualmachineresponse" : {"jobid":"removenic"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/restoreVirtualMachine_default.json0000664000175000017500000000007013535474530033604 0ustar kamikami00000000000000{ "restorevirtualmachineresponse" : { "jobid" : 88777} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/scaleVirtualMachine_default.json0000664000175000017500000000006613535474530033215 0ustar kamikami00000000000000{ "scalevirtualmachineresponse" : { "jobid" : 88776} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json0000664000175000017500000000006413535474530033261 0ustar kamikami00000000000000{ "startvirtualmachineresponse" : {"jobid":17188} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json0000664000175000017500000000006313535474530033110 0ustar kamikami00000000000000{ "stopvirtualmachineresponse" : {"jobid":17199} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/cloudstack/updateVMAffinityGroup_default.json0000664000175000017500000000007013535474530033521 0ustar kamikami00000000000000{"updatevmaffinitygroupresponse": { "jobid" : 1300006}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/0000775000175000017500000000000013600223624025145 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/create_image.json0000664000175000017500000000036413535474530030463 0ustar kamikami00000000000000{ "action": { "id": 36805022, "status": "in-progress", "type": "snapshot", "started_at": "2014-11-14T16:34:39Z", "completed_at": null, "resource_id": 3164450, "resource_type": "droplet", "region": "nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/create_key_pair.json0000664000175000017500000000031613535474530031201 0ustar kamikami00000000000000{ "ssh_key": { "id": 7717, "fingerprint": "f5:d1:78:ed:28:72:5f:e1:ac:94:fd:1f:e0:a3:48:6d", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQsxRiUKn example", "name": "test1" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/error.json0000664000175000017500000000006213535474530027202 0ustar kamikami00000000000000{"id":"","message":"Unable to authenticate you."} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/ex_power_on_node.json0000664000175000017500000000036413535474530031407 0ustar kamikami00000000000000{ "action": { "id": 36804758, "status": "in-progress", "type": "power_on", "started_at": "2014-11-14T16:31:19Z", "completed_at": null, "resource_id": 3164450, "resource_type": "droplet", "region": "nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/ex_shutdown_node.json0000664000175000017500000000036413535474530031432 0ustar kamikami00000000000000{ "action": { "id": 36077293, "status": "in-progress", "type": "shutdown", "started_at": "2014-11-04T17:08:03Z", "completed_at": null, "resource_id": 3067649, "resource_type": "droplet", "region": "nyc2" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/get_image.json0000664000175000017500000000035513535474530027777 0ustar kamikami00000000000000{ "image": { "id": 12345, "name": "My snapshot", "distribution": "Ubuntu", "slug": null, "public": false, "regions": [ "nyc2" ], "created_at": "2014-11-04T22:23:02Z", "min_disk_size": 20 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/list_key_pairs.json0000664000175000017500000000037613535474530031102 0ustar kamikami00000000000000{ "ssh_keys": [ { "id": 7717, "fingerprint": "f5:d1:78:ed:28:72:5f:e1:ac:94:fd:1f:e0:a3:48:6d", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDGk5 example", "name": "test1" } ], "meta": { "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean/list_nodes_page_1.json0000664000175000017500000000371213535474530031435 0ustar kamikami00000000000000{ "droplets": [ { "id": 3164444, "name": "example.com", "memory": 512, "vcpus": 1, "disk": 20, "locked": false, "status": "active", "kernel": { "id": 2233, "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic", "version": "3.13.0-37-generic" }, "created_at": "2014-11-14T16:29:21Z", "features": [ "backups", "ipv6", "virtio" ], "backup_ids": [ 7938002 ], "snapshot_ids": [ ], "image": { "id": 6918990, "name": "14.04 x64", "distribution": "Ubuntu", "slug": "ubuntu-14-04-x64", "public": true, "regions": [ "nyc1", "ams1", "sfo1", "nyc2", "ams2", "sgp1", "lon1", "nyc3", "ams3", "nyc3" ], "created_at": "2014-10-17T20:24:33Z", "min_disk_size": 20 }, "size_slug": "512mb", "networks": { "v4": [ { "ip_address": "104.236.32.182", "netmask": "255.255.192.0", "gateway": "104.236.0.1", "type": "public" } ], "v6": [ { "ip_address": "2604:A880:0800:0010:0000:0000:02DD:4001", "netmask": 64, "gateway": "2604:A880:0800:0010:0000:0000:0000:0001", "type": "public" } ] }, "region": { "name": "New York 3", "slug": "nyc3", "sizes": [ ], "features": [ "virtio", "private_networking", "backups", "ipv6", "metadata" ], "available": null } } ], "links": { "pages": { "last":"https://api.digitalocean.com/v2/droplets?page=2", "next":"https://api.digitalocean.com/v2/droplets?page=2" } }, "meta": { "total":2 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/0000775000175000017500000000000013600223624025554 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/attach_floating_ip.json0000664000175000017500000000125513535474530032304 0ustar kamikami00000000000000{"action":{"id":397123123,"status":"in-progress","type":"assign_ip","started_at":"2018-03-19T14:16:04Z","completed_at":null,"resource_id":1812306133,"resource_type":"floating_ip","region":{"name":"Amsterdam 3","slug":"ams3","sizes":["512mb","1gb","2gb","4gb","8gb","c-16","s-1vcpu-3gb","c-2","c-4","c-8","m-1vcpu-8gb","m-16gb","m-32gb","m-64gb","m-128gb","m-224gb","s-1vcpu-1gb","s-3vcpu-1gb","s-1vcpu-2gb","s-2vcpu-2gb","s-2vcpu-4gb","s-4vcpu-8gb","s-6vcpu-16gb","16gb","s-8vcpu-32gb","32gb","s-12vcpu-48gb","48gb","s-16vcpu-64gb","64gb","s-20vcpu-96gb"],"features":["private_networking","backups","ipv6","metadata","install_agent","storage"],"available":true},"region_slug":"ams3"}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/attach_volume.json0000664000175000017500000000116413535474530031317 0ustar kamikami00000000000000{ "action": { "region_slug": "nyc1", "region": { "available": true, "features": [ "private_networking", "backups", "ipv6", "metadata" ], "sizes": [ "512mb", "1gb", "2gb", "4gb", "8gb", "16gb", "32gb", "48gb", "64gb" ], "slug": "nyc1", "name": "New York 1" }, "resource_type": "backend", "resource_id": null, "completed_at": null, "started_at": "2016-06-06T21:01:30Z", "type": "attach_volume", "status": "in-progress", "id": 110956293 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/create_floating_ip.json0000664000175000017500000000110513535474530032275 0ustar kamikami00000000000000{"floating_ip":{"ip":"167.138.123.111","droplet":null,"region":{"name":"New York 1","slug":"nyc1","sizes":["64gb","512mb","1gb","2gb","4gb","8gb","16gb","32gb","48gb","c-16","s-1vcpu-3gb","c-2","c-4","c-8","m-1vcpu-8gb","m-16gb","m-32gb","m-64gb","m-128gb","m-224gb","s-1vcpu-1gb","s-3vcpu-1gb","s-1vcpu-2gb","s-2vcpu-2gb","s-2vcpu-4gb","s-4vcpu-8gb","s-6vcpu-16gb","s-8vcpu-32gb","s-12vcpu-48gb","s-16vcpu-64gb","s-20vcpu-96gb","s-24vcpu-128gb"],"features":["private_networking","backups","ipv6","metadata","install_agent","storage"],"available":true},"locked":false},"links":{}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/create_image.json0000664000175000017500000000036413535474530031072 0ustar kamikami00000000000000{ "action": { "id": 36805022, "status": "in-progress", "type": "snapshot", "started_at": "2014-11-14T16:34:39Z", "completed_at": null, "resource_id": 3164450, "resource_type": "droplet", "region": "nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/create_key_pair.json0000664000175000017500000000031613535474530031610 0ustar kamikami00000000000000{ "ssh_key": { "id": 7717, "fingerprint": "f5:d1:78:ed:28:72:5f:e1:ac:94:fd:1f:e0:a3:48:6d", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQsxRiUKn example", "name": "test1" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/create_node.json0000664000175000017500000000041613535474530030733 0ustar kamikami00000000000000{ "action": { "id":39290099, "status":"completed", "type":"create", "started_at":"2014-12-19T19:14:36Z", "completed_at":"2014-12-19T19:15:23Z", "resource_id":12345, "resource_type":"droplet", "region":"nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/create_volume.json0000664000175000017500000000113713535474530031316 0ustar kamikami00000000000000{ "volume": { "created_at": "2016-06-06T20:51:04Z", "size_gigabytes": 4, "description": "Block store for examples", "name": "example", "droplet_ids": [], "region": { "available": true, "features": [ "private_networking", "backups", "ipv6", "metadata" ], "sizes": [ "512mb", "1gb", "2gb", "4gb", "8gb", "16gb", "32gb", "48gb", "64gb" ], "slug": "nyc1", "name": "New York 1" }, "id": "62766883-2c28-11e6-b8e6-000f53306ae1" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/create_volume_snapshot.json0000664000175000017500000000050013535474530033226 0ustar kamikami00000000000000{ "snapshot": { "id": "c0def940-9324-11e6-9a56-000f533176b1", "name": "test-snapshot", "regions": [ "nyc1" ], "created_at": "2016-10-15T22:14:34Z", "resource_id": "8371d4fe-92b0-11e6-9a56-000f533176b1", "resource_type": "volume", "min_disk_size": 1, "size_gigabytes": 0 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/detach_floating_ip.json0000664000175000017500000000125713535474530032272 0ustar kamikami00000000000000{"action":{"id":397123123,"status":"in-progress","type":"unassign_ip","started_at":"2018-03-19T14:19:33Z","completed_at":null,"resource_id":9946493837,"resource_type":"floating_ip","region":{"name":"Amsterdam 3","slug":"ams3","sizes":["512mb","1gb","2gb","4gb","8gb","c-16","s-1vcpu-3gb","c-2","c-4","c-8","m-1vcpu-8gb","m-16gb","m-32gb","m-64gb","m-128gb","m-224gb","s-1vcpu-1gb","s-3vcpu-1gb","s-1vcpu-2gb","s-2vcpu-2gb","s-2vcpu-4gb","s-4vcpu-8gb","s-6vcpu-16gb","16gb","s-8vcpu-32gb","32gb","s-12vcpu-48gb","48gb","s-16vcpu-64gb","64gb","s-20vcpu-96gb"],"features":["private_networking","backups","ipv6","metadata","install_agent","storage"],"available":true},"region_slug":"ams3"}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/detach_volume.json0000664000175000017500000000116413535474530031303 0ustar kamikami00000000000000{ "action": { "region_slug": "nyc1", "region": { "available": true, "features": [ "private_networking", "backups", "ipv6", "metadata" ], "sizes": [ "512mb", "1gb", "2gb", "4gb", "8gb", "16gb", "32gb", "48gb", "64gb" ], "slug": "nyc1", "name": "New York 1" }, "resource_type": "backend", "resource_id": null, "completed_at": null, "started_at": "2016-06-06T21:02:20Z", "type": "detach_volume", "status": "in-progress", "id": 110956599 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/error.json0000664000175000017500000000006213535474530027611 0ustar kamikami00000000000000{"id":"","message":"Unable to authenticate you."} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/error_invalid_image.json0000664000175000017500000000013713535474530032464 0ustar kamikami00000000000000{"id":"unprocessable_entity","message":"You specified an invalid image for Droplet creation."} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_change_kernel.json0000664000175000017500000000037113535474530031744 0ustar kamikami00000000000000{ "action": { "id": 36077295, "status": "in-progress", "type": "kernel_change", "started_at": "2014-11-04T17:08:03Z", "completed_at": null, "resource_id": 3067650, "resource_type": "droplet", "region": "ams2" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_enable_ipv6.json0000664000175000017500000000042213535474530031346 0ustar kamikami00000000000000{ "action": { "id": 36804954, "status": "in-progress", "type": "enable_ipv6", "started_at": "2014-11-14T16:34:24Z", "completed_at": null, "resource_id": 3164450, "resource_type": "droplet", "region": "ams2", "region_slug": "ams2" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_hard_reboot.json0000664000175000017500000000036713535474530031454 0ustar kamikami00000000000000{ "action": { "id": 36077294, "status": "in-progress", "type": "power_cycle", "started_at": "2014-11-04T17:08:03Z", "completed_at": null, "resource_id": 3067651, "resource_type": "droplet", "region": "ams3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_power_on_node.json0000664000175000017500000000036413535474530032016 0ustar kamikami00000000000000{ "action": { "id": 36804758, "status": "in-progress", "type": "power_on", "started_at": "2014-11-14T16:31:19Z", "completed_at": null, "resource_id": 3164450, "resource_type": "droplet", "region": "nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_rebuild_node.json0000664000175000017500000000037013535474530031611 0ustar kamikami00000000000000{ "action": { "id": 36804758, "status": "in-progress", "type": "rebuild", "started_at": "2014-11-14T16:31:19Z", "completed_at": null, "resource_id": 3164450, "resource_type": "droplet", "region_slug": "nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_rename_node.json0000664000175000017500000000037413535474530031436 0ustar kamikami00000000000000{ "action": { "id":918910, "status":"in-progress", "type":"rename", "started_at":"2014-12-21T02:19:17Z", "completed_at":null, "resource_id":12345, "resource_type":"droplet", "region":"nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_resize_node.json0000664000175000017500000000036713535474530031472 0ustar kamikami00000000000000{ "action": { "id": 36804758, "status": "in-progress", "type": "resize", "started_at": "2014-11-14T16:31:19Z", "completed_at": null, "resource_id": 3164450, "resource_type": "droplet", "region_slug": "nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/ex_shutdown_node.json0000664000175000017500000000036413535474530032041 0ustar kamikami00000000000000{ "action": { "id": 36077293, "status": "in-progress", "type": "shutdown", "started_at": "2014-11-04T17:08:03Z", "completed_at": null, "resource_id": 3067649, "resource_type": "droplet", "region": "nyc2" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/get_image.json0000664000175000017500000000035513535474530030406 0ustar kamikami00000000000000{ "image": { "id": 12345, "name": "My snapshot", "distribution": "Ubuntu", "slug": null, "public": false, "regions": [ "nyc2" ], "created_at": "2014-11-04T22:23:02Z", "min_disk_size": 20 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_floating_ips.json0000664000175000017500000000473513535474530032204 0ustar kamikami00000000000000{"floating_ips":[{"ip":"133.166.122.204","droplet":{"status":"active","kernel": null,"volume_ids": [],"locked": false,"name":"vdloo-magweb","backup_ids": [],"created_at":"2018-03-01T10:15:06Z","snapshot_ids": [],"size_slug":"2gb","id": 84155775,"next_backup_window": null,"vcpus": 2,"features": [],"image": {"regions": ["ams3"],"min_disk_size": 80,"public": false,"name":"hypernode","distribution":"Ubuntu","created_at":"2018-05-23T14:16:34Z","size_gigabytes": 1.02,"type":"snapshot","slug": null,"id": 12367123},"memory": 4096,"region": {"available": true,"slug":"ams3","features": ["private_networking","backups","ipv6","metadata","install_agent","storage"],"name":"Amsterdam 3","sizes": ["64gb","512mb","1gb","2gb","4gb","8gb","16gb","32gb","36gb","c-16","s-1vcpu-3gb","c-2","c-4","c-8","m-1vcpu-8gb","m-16gb","m-32gb","m-64gb","m-128gb","m-224gb","s-1vcpu-1gb","s-3vcpu-1gb","s-1vcpu-2gb","s-2vcpu-2gb","s-2vcpu-4gb","s-4vcpu-8gb","s-6vcpu-16gb","s-8vcpu-32gb","s-12vcpu-36gb","s-16vcpu-64gb","s-20vcpu-96gb","s-24vcpu-128gb"]},"disk": 80,"networks": {"v4": [{"ip_address":"145.65.193.36","netmask":"255.255.280.0","type":"public","gateway":"145.65.192.1"}],"v6": []},"tags": [],"size": {"price_monthly": 20.0,"available": true,"vcpus": 2,"regions": ["ams2","ams3","blr1","fra1","lon1","nyc1","nyc2","nyc3","sfo1","sfo2","sgp1","tor1"],"memory": 4096,"transfer": 3.0,"disk": 80,"price_hourly": 0.02976,"slug":"2gb"}},"region":{"name":"Amsterdam 3","slug":"ams3","sizes":["64gb","512mb","1gb","2gb","4gb","8gb","16gb","32gb","36gb","c-16","s-1vcpu-3gb","c-2","c-4","c-8","m-1vcpu-8gb","m-16gb","m-32gb","m-64gb","m-128gb","m-224gb","s-1vcpu-1gb","s-3vcpu-1gb","s-1vcpu-2gb","s-2vcpu-2gb","s-2vcpu-4gb","s-4vcpu-8gb","s-6vcpu-16gb","s-8vcpu-32gb","s-12vcpu-36gb","s-16vcpu-64gb","s-20vcpu-96gb","s-24vcpu-128gb"],"features":["private_networking","backups","ipv6","metadata","install_agent","storage"],"available":true},"locked":false},{"ip":"154.138.103.175","droplet":null,"region":{"name":"Amsterdam 3","slug":"ams3","sizes":["64gb","512mb","1gb","2gb","4gb","8gb","16gb","32gb","36gb","c-16","s-1vcpu-3gb","c-2","c-4","c-8","m-1vcpu-8gb","m-16gb","m-32gb","m-64gb","m-128gb","m-224gb","s-1vcpu-1gb","s-3vcpu-1gb","s-1vcpu-2gb","s-2vcpu-2gb","s-2vcpu-4gb","s-4vcpu-8gb","s-6vcpu-16gb","s-8vcpu-32gb","s-12vcpu-36gb","s-16vcpu-64gb","s-20vcpu-96gb","s-24vcpu-128gb"],"features":["private_networking","backups","ipv6","metadata","install_agent","storage"],"available":true},"locked":false}],"links":{},"meta":{"total":2}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_images.json0000664000175000017500000000152013535474530030760 0ustar kamikami00000000000000{ "images": [ { "id": 119192817, "name": "14.04 x64", "distribution": "Ubuntu", "slug": "ubuntu-14-04-x64", "public": true, "regions": [ "nyc1" ], "created_at": "2014-07-29T14:35:40Z", "min_disk_size": 20 }, { "id": 449676376, "name": "14.04 x32", "distribution": "Ubuntu", "slug": "ubuntu-14-04-x32", "public": true, "regions": [ "nyc1" ], "created_at": "2014-07-29T14:35:40Z", "min_disk_size": 20 }, { "id": 449676856, "name": "My Snapshot", "distribution": "Ubuntu", "slug": "", "public": false, "regions": [ "nyc1", "nyc3" ], "created_at": "2014-08-18T16:35:40Z", "min_disk_size": 40 } ], "meta": { "total": 3 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_key_pairs.json0000664000175000017500000000037613535474530031511 0ustar kamikami00000000000000{ "ssh_keys": [ { "id": 7717, "fingerprint": "f5:d1:78:ed:28:72:5f:e1:ac:94:fd:1f:e0:a3:48:6d", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDGk5 example", "name": "test1" } ], "meta": { "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_locations.json0000664000175000017500000000133613570310635031505 0ustar kamikami00000000000000{ "regions": [ { "slug": "nyc1", "name": "New York 1", "sizes": [ "1gb", "512mb" ], "available": true, "features": [ "virtio", "private_networking", "backups", "ipv6" ] }, { "slug": "sfo1", "name": "San Francisco 1", "sizes": [ "1gb", "512mb" ], "available": true, "features": [ "virtio", "backups" ] }, { "slug": "ams1", "name": "Amsterdam 1", "sizes": [ "1gb", "512mb" ], "available": false, "features": [ "virtio", "backups" ] } ], "meta": { "total": 3 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_node.json0000664000175000017500000000556213535474530030452 0ustar kamikami00000000000000{ "droplet": { "status": "active", "kernel": { "version": "3.13.0-57-generic", "id": 5175, "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-57-generic" }, "volume_ids": [], "locked": false, "name": "example.com", "backup_ids": [], "created_at": "2015-11-10T11:01:41Z", "snapshot_ids": [], "size_slug": "8gb", "networks": { "v4": [ { "type": "public", "netmask": "255.255.255.0", "ip_address": "36.123.0.123", "gateway": "36.123.0.1" } ], "v6": [] }, "next_backup_window": null, "vcpus": 4, "size": { "price_monthly": 80.0, "available": true, "transfer": 5.0, "price_hourly": 0.11905, "regions": [ "ams2", "ams3", "blr1", "fra1", "lon1", "nyc1", "nyc2", "nyc3", "sfo1", "sfo2", "sgp1", "tor1" ], "vcpus": 4, "memory": 8192, "disk": 80, "slug": "8gb" }, "image": { "min_disk_size": 20, "slug": null, "name": "14.04 x64", "created_at": "2014-13-13T20:20:20Z", "id": 12089443, "regions": [ "ams2", "nyc3" ], "distribution": "Ubuntu", "type": "snapshot", "public": false, "size_gigabytes": 1.76 }, "memory": 8192, "region": { "available": true, "sizes": [ "32gb", "16gb", "2gb", "1gb", "4gb", "8gb", "512mb", "48gb", "s-1vcpu-3gb", "m-1vcpu-8gb", "m-16gb", "m-32gb", "s-1vcpu-1gb", "s-1vcpu-2gb", "s-2vcpu-2gb", "s-3vcpu-1gb", "s-2vcpu-4gb", "s-4vcpu-8gb", "s-6vcpu-16gb", "s-8vcpu-32gb", "s-12vcpu-48gb" ], "features": [ "private_networking", "backups", "ipv6", "metadata", "install_agent", "image_transfer" ], "name": "Amsterdam 2", "slug": "ams2" }, "disk": 40, "id": 3164444, "tags": ["mytag1", "mytag2"], "features": [ "virtio" ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_nodes.json0000664000175000017500000000356013535474530030631 0ustar kamikami00000000000000{ "droplets": [ { "id": 3164444, "name": "example.com", "memory": 512, "vcpus": 1, "disk": 20, "locked": false, "status": "active", "kernel": { "id": 2233, "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic", "version": "3.13.0-37-generic" }, "created_at": "2014-11-14T16:29:21Z", "features": [ "backups", "ipv6", "virtio" ], "backup_ids": [ 7938002 ], "snapshot_ids": [ ], "image": { "id": 6918990, "name": "14.04 x64", "distribution": "Ubuntu", "slug": "ubuntu-14-04-x64", "public": true, "regions": [ "nyc1", "ams1", "sfo1", "nyc2", "ams2", "sgp1", "lon1", "nyc3", "ams3", "nyc3" ], "created_at": "2014-10-17T20:24:33Z", "min_disk_size": 20 }, "size_slug": "512mb", "networks": { "v4": [ { "ip_address": "104.236.32.182", "netmask": "255.255.192.0", "gateway": "104.236.0.1", "type": "public" } ], "v6": [ { "ip_address": "2604:A880:0800:0010:0000:0000:02DD:4001", "netmask": 64, "gateway": "2604:A880:0800:0010:0000:0000:0000:0001", "type": "public" } ] }, "region": { "name": "New York 3", "slug": "nyc3", "sizes": [ ], "features": [ "virtio", "private_networking", "backups", "ipv6", "metadata" ], "available": null }, "tags": [ "environment:prod", "database" ] } ], "links": {}, "meta": { "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_nodes_empty.json0000664000175000017500000000010413535474530032036 0ustar kamikami00000000000000{ "droplets": [], "links": {}, "meta": { "total": 0 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_nodes_page_1.json0000664000175000017500000000402213535474530032037 0ustar kamikami00000000000000{ "droplets": [ { "id": 3164444, "name": "example.com", "memory": 512, "vcpus": 1, "disk": 20, "locked": false, "status": "active", "kernel": { "id": 2233, "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic", "version": "3.13.0-37-generic" }, "created_at": "2014-11-14T16:29:21Z", "features": [ "backups", "ipv6", "virtio" ], "backup_ids": [ 7938002 ], "snapshot_ids": [ ], "image": { "id": 6918990, "name": "14.04 x64", "distribution": "Ubuntu", "slug": "ubuntu-14-04-x64", "public": true, "regions": [ "nyc1", "ams1", "sfo1", "nyc2", "ams2", "sgp1", "lon1", "nyc3", "ams3", "nyc3" ], "created_at": "2014-10-17T20:24:33Z", "min_disk_size": 20 }, "size_slug": "512mb", "networks": { "v4": [ { "ip_address": "104.236.32.182", "netmask": "255.255.192.0", "gateway": "104.236.0.1", "type": "public" } ], "v6": [ { "ip_address": "2604:A880:0800:0010:0000:0000:02DD:4001", "netmask": 64, "gateway": "2604:A880:0800:0010:0000:0000:0000:0001", "type": "public" } ] }, "region": { "name": "New York 3", "slug": "nyc3", "sizes": [ ], "features": [ "virtio", "private_networking", "backups", "ipv6", "metadata" ], "available": null }, "tags": [ "environment:prod", "database" ] } ], "links": { "pages": { "last":"https://api.digitalocean.com/v2/droplets?page=2", "next":"https://api.digitalocean.com/v2/droplets?page=2" } }, "meta": { "total":2 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_sizes.json0000664000175000017500000000104213535474530030647 0ustar kamikami00000000000000{ "sizes": [ { "slug": "512mb", "memory": 512, "vcpus": 1, "disk": 20, "transfer": 1, "price_monthly": 5.0, "price_hourly": 0.00744, "regions": [ "nyc1", "ams1", "sfo1" ] }, { "slug": "1gb", "memory": 1024, "vcpus": 2, "disk": 30, "transfer": 2, "price_monthly": 10.0, "price_hourly": 0.01488, "regions": [ "nyc1", "ams1", "sfo1" ] } ], "meta": { "total": 2 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_volume_snapshots.json0000664000175000017500000000204613535474530033130 0ustar kamikami00000000000000{ "snapshots": [ { "id": "c0def940-9324-11e6-9a56-000f533176b1", "name": "test-snapshot", "regions": [ "nyc1" ], "created_at": "2016-10-15T22:14:34Z", "resource_id": "8371d4fe-92b0-11e6-9a56-000f533176b1", "resource_type": "volume", "min_disk_size": 1, "size_gigabytes": 0 }, { "id": "c2036724-9343-11e6-aef4-000f53315a41", "name": "test-snapshot-2", "regions": [ "nyc1" ], "created_at": "2016-10-16T01:56:30Z", "resource_id": "8371d4fe-92b0-11e6-9a56-000f533176b1", "resource_type": "volume", "min_disk_size": 1, "size_gigabytes": 0 }, { "id": "d347e033-9343-11e6-9a56-000f533176b1", "name": "test-snapshot-3", "regions": [ "nyc1" ], "created_at": "2016-10-16T01:56:59Z", "resource_id": "8371d4fe-92b0-11e6-9a56-000f533176b1", "resource_type": "volume", "min_disk_size": 1, "size_gigabytes": 0 } ], "links": {}, "meta": { "total": 3 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_volumes.json0000664000175000017500000000132313535474530031206 0ustar kamikami00000000000000{ "volumes": [ { "size_gigabytes": 4, "region": { "slug": "nyc1", "sizes": [ "512mb", "1gb", "2gb", "4gb", "8gb", "16gb", "32gb", "48gb", "64gb" ], "name": "New York 1", "features": [ "private_networking", "backups", "ipv6", "metadata" ], "available": true }, "name": "example", "id": "62766883-2c28-11e6-b8e6-000f53306ae1", "droplet_ids": [], "description": "Block store for examples", "created_at": "2016-06-06T20:51:04Z" } ], "links": {}, "meta": { "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/list_volumes_empty.json0000664000175000017500000000010313535474530032417 0ustar kamikami00000000000000{ "volumes": [], "links": {}, "meta": { "total": 0 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/digitalocean_v2/reboot_node.json0000664000175000017500000000037413535474530030765 0ustar kamikami00000000000000{ "action": { "id":918910, "status":"in-progress", "type":"reboot", "started_at":"2014-12-21T02:19:17Z", "completed_at":null, "resource_id":12345, "resource_type":"droplet", "region":"nyc3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/0000775000175000017500000000000013600223624025341 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/0000775000175000017500000000000013600223624025644 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_response.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_res0000664000175000017500000000052113535474530033641 0ustar kamikami00000000000000 CHANGE_NETWORK_ADAPTER IN_PROGRESS Request to Change Network Adapter for NIC with Id has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/deploy_customised_server.xml0000664000175000017500000000074213535474530033525 0ustar kamikami00000000000000 DEPLOY_UNCUSTOMIZED_SERVER IN_PROGRESS Request to deploy uncustomized Server 'Production Server' has been accepted and is being processed. ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.x0000664000175000017500000000062013535474530033602 0ustar kamikami00000000000000 EXCHANGE_NIC_VLANS OK Request to exchange VLANs for Server with Id '1cec8cfb-69e7-4de9-8404-debf116f5242' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml0000664000175000017500000000614213535474530032352 0ustar kamikami00000000000000 ImportedCustomerImage 2 2015-11-19T14:29:02.000Z NORMAL CustomerImageWithPricedSoftwareLabels 1 MSSQL2008R2S 2015-11-03T15:25:34.000Z NORMAL CopiedCustomerImage 2 2015-11-11T17:17:00.000Z NORMAL ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_0000664000175000017500000000176613535474530033223 0ustar kamikami00000000000000 CustomerImageWithPricedSoftwareLabels 1 MSSQL2008R2S 2015-11-03T15:25:34.000Z NORMAL ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_0000664000175000017500000000222313535474530033047 0ustar kamikami00000000000000 ImportedCustomerImage 2 2015-11-19T14:29:02.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml0000664000175000017500000000431313535474530031130 0ustar kamikami00000000000000 RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 2015-09-17T11:23:48.000Z T-RHEL-6-64-2-4-10 Win2012 DC 2 CPU Windows 2012 Datacenter 4 2015-09-17T11:44:43.000Z T-WIN-2012-DATACTR-64-2-4-50 Win2008 Std 32-bit 2 CPU Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition 4 MSSQL2008R2S 2014-11-20T12:54:22.000Z T-WIN-2008-ENT-32-2-4-50 ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_40000664000175000017500000000127313535474530032671 0ustar kamikami00000000000000 Win2012 DC 2 CPU Windows 2012 Datacenter 4 2015-09-17T11:44:43.000Z T-WIN-2012-DATACTR-64-2-4-50 ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_40000664000175000017500000000130013535474530032431 0ustar kamikami00000000000000 RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 2015-09-17T11:23:48.000Z T-RHEL-6-64-2-4-10 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/import_image_response.xml0000664000175000017500000000057213535474530032777 0ustar kamikami00000000000000 IMPORT_IMAGE IN_PROGRESS Request to import image has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_GetServer.xml0000664000175000017500000000372313535474530031702 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true stopped SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 **OR** apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_cleanServer.xml0000664000175000017500000000064213535474530032242 0ustar kamikami00000000000000 CLEAN_SERVER IN_PROGRESS The request to clean a failed Server deployment for Server e75ead52-692f-4314-8725-c8a4f4d13a87 has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_clone_response.xml0000664000175000017500000000075513535474530033014 0ustar kamikami00000000000000 CLONE_SERVER IN_PROGRESS Request to Clone Server '9ed47330-5561-11e5-8c14-b8ca3a5d9ef8' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server.xml0000664000175000017500000002662513535474530031310 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true PENDING_ADD DEPLOY_SERVER_WITH_DISK_SPEED 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE RECONFIGURE_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true UNKNOWN SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 21 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true false UNKNOWN SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true false NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_NA3.xml0000664000175000017500000000623413535474530031743 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_40000664000175000017500000000336713535474530033001 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE DEPLOY_SERVER 2015-12-02T11:07:40.000Z devuser1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_paginated.xml0000664000175000017500000000631713535474530033320 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 ././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/_oec_0_9_8a8f6abc_2745_4d8a_9cbc_0000664000175000017500000000172013535474530032575 0ustar kamikami00000000000000 Deploy Server SUCCESS Server "Deploy" issued REASON_0 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/audit_log.csv0000664000175000017500000001211713535474530030042 0ustar kamikami00000000000000UUID,Time,Create User,Department,Customer Defined 1,Customer Defined 2,Type,Name,Action,Details,Response Code af779880-0531-45d3-be56-df41c459aa09,2016-09-11 23:59:37,ashaw_plat,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Deploy Server,ATTEMPT: DEPLOY_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]', d127748c-948f-41f0-b6a7-c0b5a2438bd6,2016-09-12 00:06:00,OEC_SYSTEM,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Deploy Server,DEPLOY_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]',OK 85f978b2-0e2a-4ba3-a6ce-7567e329e842,2016-09-12 00:22:48,ashaw_plat,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Start Server,ATTEMPT: START_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]', afc67c82-381a-4ba1-b25e-2285a916d513,2016-09-12 00:23:00,OEC_SYSTEM,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Start Server,START_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]',OK 7378b530-9d37-4339-88d5-19428431fe07,2016-09-12 05:10:47,ashaw_plat,,,,IP_BLOCK,168.128.37.196,Add IP Block,ATTEMPT: ADD_PUBLIC_IP_BLOCK '168.128.37.196', f978f690-13e8-4d7d-8ce3-1ca7e232df69,2016-09-12 05:10:48,ashaw_plat,,,,IP_BLOCK,168.128.37.196,Add IP Block,ADD_PUBLIC_IP_BLOCK '168.128.37.196',OK 822b7483-bb59-4659-9ab1-7a1ad25bacd7,2016-09-12 05:10:58,ashaw_plat,,,,NAT_RULE,10.0.0.5,Create NAT Rule,ATTEMPT: CREATE_NAT_RULE '10.0.0.5'(requestId:au_20160912T151058137+1000_07422779-ec2a-448e-81f4-87a333b79f3c), 2f29ebd2-2ee0-463f-9a46-2e62f09fcc74,2016-09-12 05:10:59,ashaw_plat,,,,NAT_RULE,10.0.0.5,Create NAT Rule,CREATE_NAT_RULE '10.0.0.5'(requestId:au_20160912T151058137+1000_07422779-ec2a-448e-81f4-87a333b79f3c),OK 503aa140-6da9-4fbe-b94e-b118fc5a473a,2016-09-13 04:08:55,mgreenwood_plat,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ATTEMPT: ADD_NAT_RULE '10.208.136.11', bb73bb95-a20c-46f8-9962-3862496793ff,2016-09-13 04:09:00,OEC_SYSTEM,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ADD_NAT_RULE '10.208.136.11',OK 276ab194-ffb3-4516-920d-96cc068dfcfa,2016-09-13 04:11:54,mgreenwood_plat,,,,NAT_RULE,10.208.136.11,Delete NAT Rule,ATTEMPT: DELETE_NAT_RULE '10.208.136.11', 3bb0e6ad-48e1-4268-9423-4cd680edc404,2016-09-13 04:11:57,OEC_SYSTEM,,,,NAT_RULE,10.208.136.11,Delete NAT Rule,DELETE_NAT_RULE '10.208.136.11',OK f9f2684a-796c-4f28-9448-949900f8f4fb,2016-09-13 04:16:22,mgreenwood_plat,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ATTEMPT: ADD_NAT_RULE '10.208.136.11', 0bfbe81f-35fc-445e-a33e-f12a46c25115,2016-09-13 04:16:27,OEC_SYSTEM,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ADD_NAT_RULE '10.208.136.11',OK 629da5f4-7fdc-4bc6-a408-66ab96f539c0,2016-09-13 04:27:19,mgreenwood_plat,,,,ACL_RULE,AD LDAP Port - For Testing,Add Acl Rule,ATTEMPT: Add Acl Rule AD LDAP Port - For Testing to network Aperture, ecee1409-ce7d-496d-a41b-67662d884598,2016-09-13 04:27:22,mgreenwood_plat,,,,ACL_RULE,AD LDAP Port - For Testing,Add Acl Rule,Add Acl Rule AD LDAP Port - For Testing to network Aperture,OK f6e84763-b911-4189-bf69-138e9a23de7a,2016-09-14 03:05:15,aakbar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK ef43056e-1cd0-48bf-80f6-12a4cad8e1c6,2016-09-14 03:05:24,aakbar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK 13f38aa4-a86c-45c2-909f-2a6b96c0c761,2016-09-14 03:13:21,aakbar_plat,,,,SERVER,CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244]',OK 22aa854c-17a2-4f48-82a1-c10a052dd932,2016-09-14 05:42:04,mkumar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK 6c7f3847-e2e8-47c8-8fd0-8c444015ad19,2016-09-14 05:51:58,mkumar_plat,,,,SERVER,CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244]',OK 69ddc5a5-b815-439b-9d32-a1d60345355b,2016-09-14 06:02:50,mkumar_plat,,,,SERVER,CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244]',OK 4ffa5524-926b-4747-9924-581c316b6a60,2016-09-14 06:05:49,mkumar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK 599718fe-f58c-439b-87ae-86fb1347708e,2016-09-14 06:06:21,mkumar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/detailed_usage_report.csv0000664000175000017500000000531513535474530032427 0ustar kamikami00000000000000Name,Type,Location,Private IP Address,Status,"user:ATag","user:BTag","user:CTag",Start Time,End Time,Duration (Hours),CPU Type,CPU Count, RAM (GB), Storage (GB),Economy Storage (GB),CPU Hours,High Performance CPU Hours,RAM Hours,Storage Hours,Economy Storage Hours,Bandwidth-In (GB),Bandwidth-Out (GB),Subadmin Hours,Network Hours,Essentials Network Domain Hours,Advanced Network Domain Hours,VLAN Hours,Public IP Hours,Cloud Files Account Hours,Cloud Storage (GB) Server A,Server,NA1,10.162.12.16,Running,Bob,IT,,19/06/2014 04:16,19/06/2014 11:17,7.03,Standard,1,2,10,0,7.03,0,14.05,70.27,0,0,0,0,0,0,0,0,0,0,0 Server A,Server,NA1,10.162.12.16,Running,Bob,IT,,19/06/2014 11:17,20/06/2014 00:00,12.71,High Performance,1,2,10,0,0,12.71,0,127.06,0,0,0,0,0,0,0,0,0,0,0 Server B,Server,NA1,10.162.12.13,Running,Mary,IT,,19/06/2014 03:42,19/06/2014 11:18,7.61,Essentials,1,2,10,0,0,0,15.22,76.1,0,0,0,0,0,0,0,0,0,0,0 Server B,Server,NA1,10.162.12.13,Stopped,Mary,IT,,19/06/2014 11:18,19/06/2014 23:18,12,Essentials,1,2,10,0,0,0,0,120,0,0,0,0,0,0,0,0,0,0,0 Server B,Server,NA1,10.162.12.13,Stopped,Bob,IT,,19/06/2014 23:18,20/06/2014 00:00,0.689722222,Essentials,1,2,10,0,0,0,0,6.897222223,0,0,0,0,0,0,0,0,0,0,0 Customer Image A,Image,NA1,,Running,Bob,IT,,19/06/2014 03:30,20/06/2014 00:00,20.5,,0,0,10,0,0,0,0,205,0,0,0,0,0,0,0,0,0,0,0 Customer Image B,Image,NA1,,Running,Bob,IT,,19/06/2014 03:10,19/06/2014 03:12,0.04,,0,0,10,0,0,0,0,0.44,0,0,0,0,0,0,0,0,0,0,0 Joseph_F,Sub-Administrator,,,Running,Bob,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0 Lguy,Sub-Administrator,,,Running,Mary,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0 a network,Network,NA1,,Running,,IT,,19/06/2014 01:39,20/06/2014 00:00,22.34,,0,0,0,0,0,0,0,0,0,0,0.9,0,22.34,0,0,0,0,0,0 b network,Network,NA1,,Running,,IT,,19/06/2014 01:49,20/06/2014 00:00,22.18,,0,0,0,0,0,0,0,0,0,0,7.1,0,22.18,0,0,0,0,0,0 Rick's Network Domain,Network Domain,NA9,,Running,Bob,IT,,19/06/2014 04:19,20/06/2014 00:00,19.68,,0,0,0,0,0,0,0,0,0,0,7.1,0,22.18,19.68,0,0,0,0,0 Rick's VLAN,VLAN,NA9,,Running,Bob,IT,,19/06/2014 04:22,20/06/2014 00:00,19.63,,0,0,0,0,0,0,0,0,0,0,0,0,22.18,0,0,19.63,0,0,0 files1_koala,Cloud Files,,,Running,,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,24,52 testbed,Cloud Files,,,Running,,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0.01,0,0,0,0,0,0,24,100 Network: b network IP Block: 168.143.92.136(4),IpBlock,NA1,,Reserved,Mary,IT,,19/06/2014 11:47,20/06/2014 00:00,12.2,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48.82,0,0 TOTAL for 19/06/14,,,,,,,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,8,13,30,606,0,3,23,48,89,20,0,20,49,48,152apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml0000664000175000017500000000554613535474530032056 0ustar kamikami00000000000000 ImportedCustomerImage 2 2015-11-19T14:29:02.000Z NORMAL CustomerImageWithPricedSoftwareLabels 1 MSSQL2008R2S 2015-11-03T15:25:34.000Z NORMAL CopiedCustomerImage 2 2015-11-11T17:17:00.000Z NORMAL ././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_18480000664000175000017500000000167213535474530033241 0ustar kamikami00000000000000 CustomerImageWithPricedSoftwareLabels 1 MSSQL2008R2S 2015-11-03T15:25:34.000Z NORMAL ././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de0000664000175000017500000000212313535474530033215 0ustar kamikami00000000000000 ImportedCustomerImage 2 2015-11-19T14:29:02.000Z NORMAL ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_BAD_REQUEST.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_BAD_REQUEST.x0000664000175000017500000000054713535474530033377 0ustar kamikami00000000000000 GET_CUSTOMER_IMAGE RESOURCE_NOT_FOUND Server Image 2ffa36c8-1848-49eb-b4fa-9d908775f68c not found. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml0000664000175000017500000000402513535474530030625 0ustar kamikami00000000000000 RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 2015-09-17T11:23:48.000Z T-RHEL-6-64-2-4-10 Win2012 DC 2 CPU Windows 2012 Datacenter 4 2015-09-17T11:44:43.000Z T-WIN-2012-DATACTR-64-2-4-50 Win2008 Std 32-bit 2 CPU Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition 4 MSSQL2008R2S 2014-11-20T12:54:22.000Z T-WIN-2008-ENT-32-2-4-50 ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_0000664000175000017500000000120713535474530033045 0ustar kamikami00000000000000 Win2012 DC 2 CPU Windows 2012 Datacenter 4 2015-09-17T11:44:43.000Z T-WIN-2012-DATACTR-64-2-4-50 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_osImage_BAD_REQUEST.xml0000664000175000017500000000054113535474530032502 0ustar kamikami00000000000000 GET_OS_IMAGE RESOURCE_NOT_FOUND Server Image 2ffa36c8-1848-49eb-b4fa-9d908775f68c not found. ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_0000664000175000017500000000121413535474530032601 0ustar kamikami00000000000000 RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 2015-09-17T11:23:48.000Z T-RHEL-6-64-2-4-10 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/infrastructure_datacenter.xml0000664000175000017500000002351713535474530033360 0ustar kamikami00000000000000 US - West Santa Clara California US https://na3.cloud-vpn.net ftps-na.cloud-vpn.net High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Standard STD Standard Disk Speed Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. US - East Ashburn Virginia US https://na1.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed US - East 2 Ashburn Virginia US https://na5.cloud-vpn.net ftps-na.cloud-vpn.net High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Standard STD Standard Disk Speed Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. US - East 3 - MCP 2.0 Ashburn Virginia US https://na9.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. US - West - MCP 2.0 Santa Clara California US https://na12.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/infrastructure_datacenter_NA9.xml0000664000175000017500000000601413535474530034020 0ustar kamikami00000000000000 US - East 3 - MCP 2.0 Ashburn Virginia US https://na9.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. Standard Standard CPU Speed High Performance Faster and more consistent than Standard. Suitable for applications that are more CPU intensive. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/ip_address_list_create.xml0000664000175000017500000000070213535474530032570 0ustar kamikami00000000000000 CREATE_IP_ADDRESS_LIST OK IP Address List 'myAddressList' has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/ip_address_list_delete.xml0000664000175000017500000000061313535474530032570 0ustar kamikami00000000000000 DELETE_IP_ADDRESS_LIST OK IP Address List with Id 84e34850-595d-436e-a885-7cd37edb24a4 has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/ip_address_list_edit.xml0000664000175000017500000000057213535474530032257 0ustar kamikami00000000000000 EDIT_IP_ADDRESS_LIST OK IP Address List 'MyIpAddressList' has been edited successfully. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/ip_address_lists.xml0000664000175000017500000000431113535474530031430 0ustar kamikami00000000000000 TestIPList2 Test web server IP addresses list IPV4 NORMAL 2016-09-01T01:19:53.000Z TestIPList_sub_2 Test web server IP addresses list IPV4 NORMAL 2016-09-01T01:20:56.000Z Test_IP_Address_List_2 Test Description IPV4 NORMAL 2016-09-05T05:37:56.000Z Test_IP_Address_List_3 Test Description IPV4 NORMAL 2016-09-05T05:57:53.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/ip_address_lists_FILTERBYNAME.xml0000664000175000017500000000132013535474530033366 0ustar kamikami00000000000000 Test_IP_Address_List_3 Test Description IPV4 NORMAL 2016-09-05T05:57:53.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_addPublicIpBlock.xml0000664000175000017500000000073013535474530033002 0ustar kamikami00000000000000 ADD_PUBLIC_IP_BLOCK OK Public IPv4 Address Block has been added successfully to Network Domain d3320077-c2ce-4523-8c65-d417e766077b. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_createFirewallRule.xml0000664000175000017500000000064613535474530033436 0ustar kamikami00000000000000 CREATE_FIREWALL_RULE OK Request create Firewall Rule 'My.Rule.2' successful apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_createNatRule.xml0000664000175000017500000000066013535474530032407 0ustar kamikami00000000000000 CREATE_NAT_RULE OK NAT Rule with Id d31c2db0-be6b-4d50-8744-9a7a534b5fba has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_deleteFirewallRule.xml0000664000175000017500000000056013535474530033430 0ustar kamikami00000000000000 DELETE_FIREWALL_RULE OK Firewall Rule (Id:84e34850-595d-436e-a885-7cd37edb24a4) has been deleted apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_deleteNatRule.xml0000664000175000017500000000055213535474530032406 0ustar kamikami00000000000000 DELETE_NAT_RULE OK NAT Rule with Id 2187a636-7ebb-49a1-a2ff-5d617f496dce has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_deleteNetworkDomain.xml0000664000175000017500000000064713535474530033622 0ustar kamikami00000000000000 DELETE_NETWORK_DOMAIN IN_PROGRESS Request to Delete Network Domain (Id: 8cdfd607-f429-4df6-9352- 162cfc0891be) has been accepted and is being processed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_deleteVlan.xml0000664000175000017500000000060713535474530031735 0ustar kamikami00000000000000 DELETE_VLAN IN_PROGRESS Request to Delete VLAN (Id:0e56433f-d808-4669-821d-812769517ff8) has been accepted and is being processed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_deployNetworkDomain.xml0000664000175000017500000000071713535474530033652 0ustar kamikami00000000000000 DEPLOY_NETWORK_DOMAIN IN_PROGRESS Request to Deploy Network Domain 'A Network Domain' has been accepted and is being processed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_deployVlan.xml0000664000175000017500000000067513535474530031774 0ustar kamikami00000000000000 DEPLOY_VLAN IN_PROGRESS Request to deploy VLAN 'Production VLAN' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_editFirewallRule.xml0000664000175000017500000000056013535474530033113 0ustar kamikami00000000000000 EDIT_FIREWALL_RULE OK Firewall Rule with id 1aa3d0ce-d95d-4296-8338-9717e0d37ff9 has been edited apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_editNetworkDomain.xml0000664000175000017500000000055313535474530033301 0ustar kamikami00000000000000 EDIT_NETWORK_DOMAIN OK Network Domain 'Development Network Domain' was edited successfully. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_editVlan.xml0000664000175000017500000000050013535474530031410 0ustar kamikami00000000000000 EDIT_VLAN OK VLAN 'test' was edited successfully apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_expandVlan.xml0000664000175000017500000000057213535474530031753 0ustar kamikami00000000000000 EXPAND_VLAN IN_PROGRESS Request to expand VLAN 'Production VLAN' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_firewallRule.xml0000664000175000017500000000247613535474530032315 0ustar kamikami00000000000000 b30c224c-c95b-4cd9-bb8b-bfdfb5486abf CCDEFAULT.BlockOutboundMailIPv4 DROP IPV4 TCP true NORMAL b30c224c-c95b-4cd9-bb8b-bfdfb5486abf SpecificSourceIP DROP IPV4 TCP true NORMAL ././@LongLink0000000000000000000000000000020100000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_firewallRule_d0a20f59_77b0000664000175000017500000000105313535474530033375 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be CCDEFAULT.BlockOutboundMailIPv4 DROP IPV4 TCP true NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_natRule.xml0000664000175000017500000000141213535474530031257 0ustar kamikami00000000000000 484174a2-ae74-4658-9e56- 50fc90e086cf 10.0.0.15 165.180.12.18 2015-03-06T13:43:45.000Z NORMAL 484174a2-ae74-4658-9e56- 50fc90e086cf 10.0.0.16 165.180.12.19 2015-03-06T13:45:10.000Z NORMAL ././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_natRule_2187a636_7ebb_49a0000664000175000017500000000061213535474530033116 0ustar kamikami00000000000000 484174a2-ae74-4658-9e56-50fc90e086cf 10.0.0.16 165.180.12.19 2015-03-06T13:45:10.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_networkDomain.xml0000664000175000017500000000401513535474530032470 0ustar kamikami00000000000000 Aurora Project Aurora Demo Environments ADVANCED 168.128.2.136 2015-07-13T03:52:16.000Z NORMAL Test net domain description of my network ESSENTIALS 168.128.26.20 2015-07-15T03:36:00.000Z NORMAL another networkj net network netowkrm ESSENTIALS 168.128.26.22 2015-07-15T03:40:09.000Z NORMAL Imports Imported servers ADVANCED 168.128.2.69 2015-08-18T03:53:02.000Z NORMAL Platform R2.0 Lab (MCP 2.0) This is the R2.0 lab for Platform on MCP 2.0 ESSENTIALS 168.128.2.149 2015-08-25T01:39:22.000Z NORMAL ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_networkDomain_8cdfd607_f40000664000175000017500000000061013535474530033564 0ustar kamikami00000000000000 test test2 ESSENTIALS 168.128.26.20 2015-07-15T03:36:00.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock.xml0000664000175000017500000000076613535474530032402 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be 168.128.4.18 2 2015-07-13T04:07:37.000Z NORMAL ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock_4487241a_f00000664000175000017500000000057413535474530033243 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be 168.128.4.18 2 2015-07-13T04:07:37.000Z NORMAL ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_publicIpBlock_9945dc4a_bd0000664000175000017500000000057413535474530033473 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be 168.128.4.18 2 2015-07-13T04:07:37.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_removePublicIpBlock.xml0000664000175000017500000000057413535474530033555 0ustar kamikami00000000000000 REMOVE_PUBLIC_IP_BLOCK OK Public Ip Block bef4334a-844b-11e4-a91c-0030487e0302 has been removed successfully apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_vlan.xml0000664000175000017500000000247513535474530030617 0ustar kamikami00000000000000 Primary 10.0.0.1 2607:f480:111:1336:0:0:0:1 2015-07-13T03:52:45.000Z NORMAL Wi-Fi Wi-Fi 10.230.98.1 2607:f480:111:1199:0:0:0:1 2015-08-18T23:47:04.000Z NORMAL ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_vlan_0e56433f_d808_4669_821d_812769517ff8.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/network_vlan_0e56433f_d808_4669_80000664000175000017500000000117513535474530032635 0ustar kamikami00000000000000 Production VLAN test2 10.0.3.1 2607:f480:1111:1153:0:0:0:1 2015-02-13T10:56:44.000Z NORMAL ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000275013535474530032532 0ustar kamikami00000000000000 Create Anti Affinity Rule SUCCESS Request to create Server Anti-Affinity Rule between 'rhel-ansible-full-test' and 'rhel-ansible-full-test' on 'Deloitte Test' has been accepted and is being processed. REASON_0 5e10b1ab-68f2-4a8b-a49c-d88d623db665 ././@LongLink0000000000000000000000000000022100000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000247513535474530032536 0ustar kamikami00000000000000 Create Anti Affinity Rule ERROR Server 'ansible-test-image-rhel6' (id 22f3544a-c874-4930-a31c-e9e513e51114) is already used in another Anti-Affinity Rule (id 07e3621a-a920-4a9a-943c-d8021f27f418). REASON_692 ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000252013535474530032525 0ustar kamikami00000000000000 Delete Anti Affinity Rule SUCCESS Request to delete Server Anti-Affinity Rule between 'ansible-test-image-rhel6' and 'ansible-custom-image-test-UAT' on 'Deloitte Test' has been accepted and is being processed. REASON_0 ././@LongLink0000000000000000000000000000022100000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000235713535474530032535 0ustar kamikami00000000000000 Delete Anti Affinity Rule ERROR Could not find Anti Affinity Rule with Id 07e3621a-a920-4a9a-943c-d8021f27f418 REASON_693 ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000303013535474530032522 0ustar kamikami00000000000000 NA1 US - East Ashburn Virginia US https://opsource-na1.cloud-vpn.net/ true NA10 US - East3 Ashburn Virginia US https://opsource-na1.cloud-vpn.net/ true ././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000325513535474530032533 0ustar kamikami00000000000000 4bba37be-506f-11e3-b29c-001517c4643e test-net1 Test Network. NA5 10.192.176.0 false 208e3a8e-9d2f-11e2-b29c-001517c4643e Test Network Network description NA9 10.172.74.0 false ././@LongLink0000000000000000000000000000024100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_4bba37be_506f_11e3_b29c_001517c4643e.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000251613535474530032532 0ustar kamikami00000000000000 Add Network SUCCESS Network created successfully (Network ID: 9eb15060-e2f7-11e1-9153-001b21cfdbe0) REASON_0 ././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000201013535474530032517 0ustar kamikami00000000000000 Delete Server SUCCESS Server "Delete" issued REASON_0 ././@LongLink0000000000000000000000000000022000000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000203413535474530032525 0ustar kamikami00000000000000 Delete Server ERROR Operation in progress on Server with Id 11 REASON_392 ././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000201613535474530032525 0ustar kamikami00000000000000 Power Off Server SUCCESS Server "Power Off" issued REASON_0 ././@LongLink0000000000000000000000000000022200000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000203713535474530032530 0ustar kamikami00000000000000 Power Off Server ERROR Operation in progress on Server with Id 11 REASON_392 ././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000172213535474530032530 0ustar kamikami00000000000000 Restart Server SUCCESS Server "Restart" issued REASON_0 ././@LongLink0000000000000000000000000000022100000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000203513535474530032526 0ustar kamikami00000000000000 Restart Server ERROR Operation in progress on Server with Id 11 REASON_392 ././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000174613535474530032536 0ustar kamikami00000000000000 Graceful Shutdown Server SUCCESS Server "Graceful Shutdown" issued REASON_0 ././@LongLink0000000000000000000000000000022200000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000204713535474530032531 0ustar kamikami00000000000000 Graceful Shutdown Server ERROR Operation in progress on Server with Id 11 REASON_392 ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000200613535474530032524 0ustar kamikami00000000000000 Start Server SUCCESS Server "Start" issued REASON_0 ././@LongLink0000000000000000000000000000021700000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000203313535474530032524 0ustar kamikami00000000000000 Start Server ERROR Operation in progress on Server with Id 11 REASON_392 ././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000531013535474530032525 0ustar kamikami00000000000000 abadbc7e-9e10-46ca-9d4a-194bcc6b6c16 testnode01 this is testnode01 description 2 2048 10 20 UNIX REDHAT5/64 44ed8b72-ebea-11df-bdc1-001517c46384 53b4c05b-341e-4ac3-b688-bdd78e43ca9e 10.162.1.1 200.16.132.7 10-162-1-1 true 2011-03-02T17:16:09.882Z dbadbc8e-9e10-56ca-5d4a-155bcc5b5c15 testnode02 this is testnode02 description 4 4096 10 20 UNIX REDHAT5/64 44ed8b72-ebea-11df-bdc1-001517c46384 53b4c05b-341e-4ac3-b688-bdd78e43ca9e 10.162.1.2 10-162-1-2 true 2011-03-02T17:16:10.882Z ././@LongLink0000000000000000000000000000024000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000261513535474530032532 0ustar kamikami00000000000000 Add Local Storage SUCCESS 100 GB of STANDARD local storage is being added to server "abc" on SCSI ID 1 REASON_0 ././@LongLink0000000000000000000000000000024500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_POST.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000047313535474530032532 0ustar kamikami00000000000000 Edit Server SUCCESS Server edited REASON_0 ././@LongLink0000000000000000000000000000024700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000202713535474530032527 0ustar kamikami00000000000000 Delete Local Storage SUCCESS Server "Disk Delete" issued REASON_0 ././@LongLink0000000000000000000000000000026200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSize.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000230613535474530032527 0ustar kamikami00000000000000 Change Server Disk Size SUCCESS Server "Change Server Disk Size" issued REASON_0 ././@LongLink0000000000000000000000000000026300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSpeed.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000231013535474530032522 0ustar kamikami00000000000000 Change Server Disk Speed SUCCESS Server "Change Server Disk Speed" issued REASON_0 ././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_80000664000175000017500000000341413535474530032530 0ustar kamikami00000000000000 e75ead52-692f-4314-8725-c8a4f4d13a87 test2 test2 node 1 2048 10 0 UNIX REDHAT5/64 52ed8b72-ebea-11df-bdc1-001517c46384 52f4c05b-341e-4ac3-b688-bdd78e43ca9e 10.162.151.11 DEPLOY_SERVER 2011-03-20T22:32:23.000Z copia apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_image.xml0000664000175000017500000002377013535474530031460 0ustar kamikami00000000000000 52ed8b72-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed8b72-ebea-11df-bdc1-001517c46384 RedHat 5.5 64-bit 1 CPU RedHat 5.5 Enterprise (Tikanga), 64-bit UNIX REDHAT5/64 NA10 1 2048 10 0 1970-01-01T00:00:02.010Z 52ed8dca-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed8dca-ebea-11df-bdc1-001517c46384 RedHat 5.5 64-bit 2 CPU RedHat 5.5 Enterprise (Tikanga), 64-bit UNIX REDHAT5/64 NA10 2 4096 10 0 1970-01-01T00:00:02.010Z 52ed8ed8-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed8ed8-ebea-11df-bdc1-001517c46384 RedHat 5.5 64-bit 4 CPU RedHat 5.5 Enterprise (Tikanga), 64-bit UNIX REDHAT5/64 NA10 4 6144 10 0 1970-01-01T00:00:02.010Z 6fc040ae-3605-11e0-bfb5-001517c46384 /oec/base/image/6fc040ae-3605-11e0-bfb5-001517c46384 RedHat 5.5 32-bit 1 CPU RedHat 5.5 Enterprise (Tikanga), 32-bit UNIX REDHAT5/32 NA10 1 2048 10 0 2011-02-11T17:36:19.000Z 52ed92d4-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed92d4-ebea-11df-bdc1-001517c46384 Ubuntu 8.04.4 2 CPU Ubuntu 8.04.4 LTS, 64-bit UNIX UBUNTU8/64 NA10 2 4096 10 0 1970-01-01T00:00:02.010Z 52ed876c-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed876c-ebea-11df-bdc1-001517c46384 Win2008 Ent 64-bit R2 2 CPU Windows 2008 Enterprise R2 64-bit WINDOWS WIN2008R2E/64 NA10 2 4096 50 0 1970-01-01T00:00:02.010Z 52ed8a5a-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed8a5a-ebea-11df-bdc1-001517c46384 Win2008 Ent 64-bit R2 4 CPU Windows 2008 Enterprise R2 64-bit WINDOWS WIN2008R2E/64 NA10 4 8192 50 0 1970-01-01T00:00:02.010Z 52ed865e-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed865e-ebea-11df-bdc1-001517c46384 Win2008 Std 64-bit R2 2 CPU Windows 2008 Standard R2 64-bit WINDOWS WIN2008R2S/64 NA10 2 4096 50 0 1970-01-01T00:00:02.010Z 52ed7b96-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed7b96-ebea-11df-bdc1-001517c46384 Win2008 Std 32-bit 1 CPU Windows 2008 Standard SP2 32-bit WINDOWS WIN2008S/32 NA10 1 2048 50 0 1970-01-01T00:00:02.010Z 52ed7cb8-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed7cb8-ebea-11df-bdc1-001517c46384 Win2008 Std 32-bit 2 CPU Windows 2008 Standard SP2 32-bit WINDOWS WIN2008S/32 NA10 2 4096 50 0 1970-01-01T00:00:02.010Z 52ed7da8-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed7da8-ebea-11df-bdc1-001517c46384 Win2008 Std 32-bit 4 CPU Windows 2008 Standard SP2 32-bit WINDOWS WIN2008S/32 NA10 4 4096 50 0 1970-01-01T00:00:02.010Z 52ed7ea2-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed7ea2-ebea-11df-bdc1-001517c46384 Win2008 Ent 32-bit 2 CPU Windows 2008 Enterprise SP2 32-bit WINDOWS WIN2008E/32 NA10 2 4096 50 0 1970-01-01T00:00:02.010Z 52ed8fd2-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed8fd2-ebea-11df-bdc1-001517c46384 Red Hat 4.8 32-bit 1 CPU Red Hat ES 4.8 (Nahant), 32-bit UNIX REDHAT4/32 NA10 1 2048 10 0 1970-01-01T00:00:02.010Z 52ed90cc-ebea-11df-bdc1-001517c46384 /oec/base/image/52ed90cc-ebea-11df-bdc1-001517c46384 CentOS 5.5 32-bit 1 CPU CentOS release 5.5, 32-bit UNIX CENTOS5/32 NA10 1 2048 10 0 1970-01-01T00:00:02.010Z ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_imageWithDiskSpeed.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_imageWithDiskSpeed.x0000664000175000017500000045776413535474530033575 0ustar kamikami00000000000000 RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 2 4096 2015-05-13T07:11:34.000Z NORMAL RedHat 6 64-bit 4 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 8192 2015-05-13T07:11:36.000Z NORMAL RedHat 6 32-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 32-bit 2 4096 2015-05-13T07:11:32.000Z NORMAL RedHat 5 64-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 64-bit 2 4096 2015-05-13T07:11:30.000Z NORMAL RedHat 5 32-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 32-bit 2 4096 2015-05-13T07:11:28.000Z NORMAL CentOS 6 64-bit 2 CPU CentOS Release 6.6 64-bit 2 4096 2015-05-13T07:11:42.000Z NORMAL CentOS 5 64-bit 2 CPU CentOS Release 5.11 64-bit 2 4096 2015-05-13T07:11:40.000Z NORMAL CentOS 5 32-bit 2 CPU CentOS Release 5.11 32-bit 2 4096 2015-05-13T07:11:38.000Z NORMAL Ubuntu 14.04 2 CPU Ubuntu 14.04.2 LTS 64-bit 2 4096 2015-05-13T07:11:50.000Z NORMAL Ubuntu 12.04 2 CPU Ubuntu 12.04.5 LTS 64-bit 2 4096 2015-05-13T07:11:48.000Z NORMAL SuSE Linux Ent 64-bit 2 CPU SuSE Linux Enterprise Server 11 SP3 2 4096 2015-05-13T07:11:44.000Z NORMAL Win2012 R2 Std 2 CPU Windows 2012 R2 Update Standard 2 4096 2015-05-13T07:12:48.000Z NORMAL Win2012 R2 DC 2 CPU Windows 2012 R2 Update Datacenter 2 4096 2015-05-13T07:12:46.000Z NORMAL Win2012 Std 2 CPU Windows 2012 Standard 2 4096 2015-05-13T07:12:44.000Z NORMAL Win2012 DC 2 CPU Windows 2012 Datacenter 2 4096 2015-05-13T07:12:33.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-05-13T07:12:57.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-05-13T07:12:55.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Standard 4 8192 MSSQL2012R2S 2015-05-13T07:12:54.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Enterprise 4 8192 MSSQL2012R2E 2015-05-13T07:12:52.000Z NORMAL Win2012 DC with MS SQL 2014 Std Windows 2012 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-05-13T07:12:41.000Z NORMAL Win2012 DC with MS SQL 2014 Ent Windows 2012 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-05-13T07:12:40.000Z NORMAL Win2012 DC with MS SQL 2012 Std Windows 2012 Datacenter 64-bit installed with SQL 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-05-13T07:12:37.000Z NORMAL Win2012 DC with MS SQL 2012 Ent Windows 2012 Datacenter 64-bit installed with SQL 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-05-13T07:12:35.000Z NORMAL Win2008 R2 Std 2 CPU Windows 2008 R2 Standard SP1 2 4096 2015-05-13T07:12:31.000Z NORMAL Win2008 R2 Ent 2 CPU Windows 2008 R2 Enterprise SP1 2 4096 2015-05-13T07:12:19.000Z NORMAL Win2008 R2 DC 64-bit 2 CPU Windows 2008 R2 Datacenter SP1 2 4096 2015-05-13T07:12:17.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Std Windows 2008 R2 Enterprise SP3 installed with SQL Server 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-05-13T07:12:25.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-05-13T07:12:23.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Std Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Standard SP3 4 8192 MSSQL2008R2S 2015-05-13T07:12:29.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Enterprise SP3 4 8192 MSSQL2008R2E 2015-05-13T07:12:27.000Z NORMAL Win2008 R2 Ent 64-Bit with MS SP Fnd Windows 2008 R2 Enterprise installed with SQL Express & SharePoint Foundation 2010 4 8192 MSSPFND2010 2015-05-13T07:12:21.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml00. SID=DD0 NR=00 2 8192 SAPACCEL 2015-05-13T07:12:07.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml01. SID=DD1 NR=00 2 8192 SAPACCEL 2015-05-13T07:12:05.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed00. SID=TD0 NR=00 4 10240 SAPACCEL 2015-05-13T07:12:01.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed01. SID=TD1 NR=00 4 10240 SAPACCEL 2015-05-13T07:12:03.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg00. SID=PD0 NR=00 8 20480 SAPACCEL 2015-05-13T07:11:58.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg01. SID=PD1 NR=00 8 20480 SAPACCEL 2015-05-13T07:11:59.000Z NORMAL Win2008 Std 64-bit 2 CPU Windows 2008 Standard SP2 64-bit 2 4096 2015-05-13T07:12:15.000Z NORMAL Win2008 Ent 64-bit 2 CPU Windows 2008 Enterprise SP2 64-bit 2 4096 2015-05-13T07:12:11.000Z NORMAL Win2008 Std 32-bit 2 CPU Windows 2008 Standard SP2 32-bit 2 4096 2015-05-13T07:12:13.000Z NORMAL Win2008 Ent 32-bit 2 CPU Windows 2008 Enterprise SP2 32-bit 2 4096 2015-05-13T07:12:09.000Z NORMAL CSfM SharePoint 2013 Trial Windows 2012 R2 Standard 64-bit installed with SharePoint 2013 and Visual Studio 2013 Pro (Trial Version) 4 12288 2015-03-19T18:28:32.000Z NORMAL RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 2 4096 2015-06-19T06:03:01.000Z NORMAL RedHat 6 64-bit 4 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 8192 2015-06-19T06:03:30.000Z NORMAL RedHat 6 32-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 32-bit 2 4096 2015-06-19T06:03:25.000Z NORMAL RedHat 5 64-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 64-bit 2 4096 2015-06-19T06:02:48.000Z NORMAL RedHat 5 32-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 32-bit 2 4096 2015-06-19T06:03:44.000Z NORMAL CentOS 6 64-bit 2 CPU CentOS Release 6.6 64-bit 2 4096 2015-06-19T06:03:28.000Z NORMAL CentOS 5 64-bit 2 CPU CentOS Release 5.11 64-bit 2 4096 2015-06-19T06:02:53.000Z NORMAL CentOS 5 32-bit 2 CPU CentOS Release 5.11 32-bit 2 4096 2015-06-19T06:03:17.000Z NORMAL Ubuntu 14.04 2 CPU Ubuntu 14.04.2 LTS 64-bit 2 4096 2015-06-19T06:02:34.000Z NORMAL Ubuntu 12.04 2 CPU Ubuntu 12.04.5 LTS 64-bit 2 4096 2015-06-19T06:03:32.000Z NORMAL SuSE Linux Ent 64-bit 2 CPU SuSE Linux Enterprise Server 11 SP3 2 4096 2015-06-19T06:03:04.000Z NORMAL Win2012 R2 Std 2 CPU Windows 2012 R2 Update Standard 2 4096 2015-06-19T06:02:40.000Z NORMAL Win2012 R2 Std 4 CPU Windows 2012 R2 Update Standard 4 8192 2015-06-19T06:03:16.000Z NORMAL Win2012 R2 DC 2 CPU Windows 2012 R2 Update Datacenter 2 4096 2015-06-19T06:03:41.000Z NORMAL Win2012 Std 2 CPU Windows 2012 Standard 2 4096 2015-06-19T06:02:33.000Z NORMAL Win2012 DC 2 CPU Windows 2012 Datacenter 2 4096 2015-06-19T06:03:19.000Z NORMAL Win2012 DC with MS SQL 2014 Std Windows 2012 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-06-19T06:02:46.000Z NORMAL Win2012 DC with MS SQL 2014 Ent Windows 2012 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-06-19T06:03:06.000Z NORMAL Win2012 DC with MS SQL 2012 Std Windows 2012 Datacenter 64-bit installed with SQL 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-06-19T06:02:50.000Z NORMAL Win2012 DC with MS SQL 2012 Ent Windows 2012 Datacenter 64-bit installed with SQL 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-06-19T06:03:37.000Z NORMAL Win2008 R2 Std 2 CPU Windows 2008 R2 Standard SP1 2 4096 2015-06-19T06:03:35.000Z NORMAL Win2008 R2 Ent 2 CPU Windows 2008 R2 Enterprise SP1 2 4096 2015-06-19T06:02:59.000Z NORMAL Win2008 R2 DC 64-bit 2 CPU Windows 2008 R2 Datacenter SP1 2 4096 2015-06-19T06:03:23.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Std Windows 2008 R2 Enterprise SP3 installed with SQL Server 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-06-19T06:03:21.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-06-19T06:02:36.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Std Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Standard SP3 4 8192 MSSQL2008R2S 2015-06-19T06:03:46.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Enterprise SP3 4 8192 MSSQL2008R2E 2015-06-19T06:03:39.000Z NORMAL Win2008 R2 Ent 64-Bit with MS SP Fnd Windows 2008 R2 Enterprise installed with SQL Express & SharePoint Foundation 2010 4 8192 MSSPFND2010 2015-06-19T06:03:02.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml00. SID=DD0 NR=00 2 8192 SAPACCEL 2015-06-19T06:02:44.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml01. SID=DD1 NR=00 2 8192 SAPACCEL 2015-06-19T06:03:27.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed00. SID=TD0 NR=00 4 10240 SAPACCEL 2015-06-19T06:02:51.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed01. SID=TD1 NR=00 4 10240 SAPACCEL 2015-06-19T06:03:12.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg00. SID=PD0 NR=00 8 20480 SAPACCEL 2015-06-19T06:03:10.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg01. SID=PD1 NR=00 8 20480 SAPACCEL 2015-06-19T06:03:08.000Z NORMAL Win2008 Std 64-bit 2 CPU Windows 2008 Standard SP2 64-bit 2 4096 2015-06-19T06:03:33.000Z NORMAL Win2008 Ent 64-bit 2 CPU Windows 2008 Enterprise SP2 64-bit 2 4096 2015-06-19T06:02:38.000Z NORMAL Win2008 Std 32-bit 2 CPU Windows 2008 Standard SP2 32-bit 2 4096 2015-06-19T06:03:43.000Z NORMAL Win2008 Ent 32-bit 2 CPU Windows 2008 Enterprise SP2 32-bit 2 4096 2015-06-19T06:02:55.000Z NORMAL RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 2 4096 2015-05-15T08:34:51.000Z NORMAL RedHat 6 64-bit 4 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 8192 2015-05-15T08:34:52.000Z NORMAL RedHat 6 32-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 32-bit 2 4096 2015-05-15T08:34:49.000Z NORMAL RedHat 5 64-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 64-bit 2 4096 2015-05-15T08:34:47.000Z NORMAL RedHat 5 32-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 32-bit 2 4096 2015-05-15T08:34:45.000Z NORMAL CentOS 6 64-bit 2 CPU CentOS Release 6.6 64-bit 2 4096 2015-05-15T08:34:58.000Z NORMAL CentOS 5 64-bit 2 CPU CentOS Release 5.11 64-bit 2 4096 2015-05-15T08:34:56.000Z NORMAL CentOS 5 32-bit 2 CPU CentOS Release 5.11 32-bit 2 4096 2015-05-15T08:34:54.000Z NORMAL Ubuntu 14.04 2 CPU Ubuntu 14.04.2 LTS 64-bit 2 4096 2015-05-15T08:35:06.000Z NORMAL Ubuntu 12.04 2 CPU Ubuntu 12.04.5 LTS 64-bit 2 4096 2015-05-15T08:35:04.000Z NORMAL SuSE Linux Ent 64-bit 2 CPU SuSE Linux Enterprise Server 11 SP3 2 4096 2015-05-15T08:35:00.000Z NORMAL Win2012 R2 Std 2 CPU Windows 2012 R2 Update Standard 2 4096 2015-05-15T08:35:50.000Z NORMAL Win2012 R2 DC 2 CPU Windows 2012 R2 Update Datacenter 2 4096 2015-05-15T08:35:46.000Z NORMAL Win2012 Std 2 CPU Windows 2012 Standard 2 4096 2015-05-15T08:35:52.000Z NORMAL Win2012 DC 2 CPU Windows 2012 Datacenter 2 4096 2015-05-15T08:35:36.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-05-15T08:36:14.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-05-15T08:36:12.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Standard 4 8192 MSSQL2012R2S 2015-05-15T08:36:10.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Enterprise 4 8192 MSSQL2012R2E 2015-05-15T08:36:08.000Z NORMAL Win2012 DC with MS SQL 2014 Std Windows 2012 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-05-15T08:35:48.000Z NORMAL Win2012 DC with MS SQL 2014 Ent Windows 2012 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-05-15T08:35:40.000Z NORMAL Win2012 DC with MS SQL 2012 Std Windows 2012 Datacenter 64-bit installed with SQL 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-05-15T08:35:38.000Z NORMAL Win2012 DC with MS SQL 2012 Ent Windows 2012 Datacenter 64-bit installed with SQL 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-05-15T08:35:42.000Z NORMAL Win2008 R2 Std 2 CPU Windows 2008 R2 Standard SP1 2 4096 2015-05-15T08:35:24.000Z NORMAL Win2008 R2 Ent 2 CPU Windows 2008 R2 Enterprise SP1 2 4096 2015-05-15T08:35:26.000Z NORMAL Win2008 R2 DC 64-bit 2 CPU Windows 2008 R2 Datacenter SP1 2 4096 2015-05-15T08:35:34.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Std Windows 2008 R2 Enterprise SP3 installed with SQL Server 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-05-15T08:35:18.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-05-15T08:35:30.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Std Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Standard SP3 4 8192 MSSQL2008R2S 2015-05-15T08:35:28.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Enterprise SP3 4 8192 MSSQL2008R2E 2015-05-15T08:35:22.000Z NORMAL Win2008 R2 Ent 64-Bit with MS SP Fnd Windows 2008 R2 Enterprise installed with SQL Express & SharePoint Foundation 2010 4 8192 MSSPFND2010 2015-05-15T08:35:32.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml00. SID=DD0 NR=00 2 8192 SAPACCEL 2015-05-15T08:35:58.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml01. SID=DD1 NR=00 2 8192 SAPACCEL 2015-05-15T08:36:06.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed00. SID=TD0 NR=00 4 10240 SAPACCEL 2015-05-15T08:36:04.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed01. SID=TD1 NR=00 4 10240 SAPACCEL 2015-05-15T08:35:56.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg00. SID=PD0 NR=00 8 20480 SAPACCEL 2015-05-15T08:35:54.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg01. SID=PD1 NR=00 8 20480 SAPACCEL 2015-05-15T08:36:02.000Z NORMAL Win2008 Std 64-bit 2 CPU Windows 2008 Standard SP2 64-bit 2 4096 2015-05-15T08:36:00.000Z NORMAL Win2008 Ent 64-bit 2 CPU Windows 2008 Enterprise SP2 64-bit 2 4096 2015-05-15T08:35:16.000Z NORMAL Win2008 Std 32-bit 2 CPU Windows 2008 Standard SP2 32-bit 2 4096 2015-05-15T08:35:20.000Z NORMAL Win2008 Ent 32-bit 2 CPU Windows 2008 Enterprise SP2 32-bit 2 4096 2015-05-15T08:35:14.000Z NORMAL CSfM SharePoint 2013 Trial Windows 2012 R2 Standard 64-bit installed with SharePoint 2013 and Visual Studio 2013 Pro (Trial Version) 4 12288 2015-03-19T18:30:39.000Z NORMAL RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 2 4096 2015-05-15T08:30:51.000Z NORMAL RedHat 6 64-bit 4 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 8192 2015-05-15T08:30:53.000Z NORMAL RedHat 6 32-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 32-bit 2 4096 2015-05-15T08:30:49.000Z NORMAL RedHat 5 64-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 64-bit 2 4096 2015-05-15T08:30:47.000Z NORMAL RedHat 5 32-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 32-bit 2 4096 2015-05-15T08:30:46.000Z NORMAL CentOS 6 64-bit 2 CPU CentOS Release 6.6 64-bit 2 4096 2015-05-15T08:30:58.000Z NORMAL CentOS 5 64-bit 2 CPU CentOS Release 5.11 64-bit 2 4096 2015-05-15T08:30:56.000Z NORMAL CentOS 5 32-bit 2 CPU CentOS Release 5.11 32-bit 2 4096 2015-05-15T08:30:54.000Z NORMAL Ubuntu 14.04 2 CPU Ubuntu 14.04.2 LTS 64-bit 2 4096 2015-05-15T08:31:05.000Z NORMAL Ubuntu 12.04 2 CPU Ubuntu 12.04.5 LTS 64-bit 2 4096 2015-05-15T08:31:03.000Z NORMAL SuSE Linux Ent 64-bit 2 CPU SuSE Linux Enterprise Server 11 SP3 2 4096 2015-05-15T08:31:00.000Z NORMAL Win2012 R2 Std 2 CPU Windows 2012 R2 Update Standard 2 4096 2015-05-15T08:31:54.000Z NORMAL Win2012 R2 DC 2 CPU Windows 2012 R2 Update Datacenter 2 4096 2015-05-15T08:31:53.000Z NORMAL Win2012 Std 2 CPU Windows 2012 Standard 2 4096 2015-05-15T08:31:51.000Z NORMAL Win2012 DC 2 CPU Windows 2012 Datacenter 2 4096 2015-05-15T08:31:42.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-05-15T08:32:03.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-05-15T08:32:01.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Standard 4 8192 MSSQL2012R2S 2015-05-15T08:31:59.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Enterprise 4 8192 MSSQL2012R2E 2015-05-15T08:31:58.000Z NORMAL Win2012 DC with MS SQL 2014 Std Windows 2012 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-05-15T08:31:49.000Z NORMAL Win2012 DC with MS SQL 2014 Ent Windows 2012 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-05-15T08:31:47.000Z NORMAL Win2012 DC with MS SQL 2012 Std Windows 2012 Datacenter 64-bit installed with SQL 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-05-15T08:31:46.000Z NORMAL Win2012 DC with MS SQL 2012 Ent Windows 2012 Datacenter 64-bit installed with SQL 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-05-15T08:31:44.000Z NORMAL Win2008 R2 Std 2 CPU Windows 2008 R2 Standard SP1 2 4096 2015-05-15T08:31:41.000Z NORMAL Win2008 R2 Ent 2 CPU Windows 2008 R2 Enterprise SP1 2 4096 2015-05-15T08:31:29.000Z NORMAL Win2008 R2 DC 64-bit 2 CPU Windows 2008 R2 Datacenter SP1 2 4096 2015-05-15T08:31:27.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Std Windows 2008 R2 Enterprise SP3 installed with SQL Server 2012 Standard SP2 4 8192 MSSQL2012R2S 2015-05-15T08:31:35.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2012 Enterprise SP2 4 8192 MSSQL2012R2E 2015-05-15T08:31:34.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Std Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Standard SP3 4 8192 MSSQL2008R2S 2015-05-15T08:31:39.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Enterprise SP3 4 8192 MSSQL2008R2E 2015-05-15T08:31:37.000Z NORMAL Win2008 R2 Ent 64-Bit with MS SP Fnd Windows 2008 R2 Enterprise installed with SQL Express & SharePoint Foundation 2010 4 8192 MSSPFND2010 2015-05-15T08:31:32.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml00. SID=DD0 NR=00 2 8192 SAPACCEL 2015-05-15T08:31:17.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml01. SID=DD1 NR=00 2 8192 SAPACCEL 2015-05-15T08:31:19.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed00. SID=TD0 NR=00 4 10240 SAPACCEL 2015-05-15T08:31:20.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed01. SID=TD1 NR=00 4 10240 SAPACCEL 2015-05-15T08:31:15.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg00. SID=PD0 NR=00 8 20480 SAPACCEL 2015-05-15T08:31:12.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg01. SID=PD1 NR=00 8 20480 SAPACCEL 2015-05-15T08:31:14.000Z NORMAL Win2008 Std 64-bit 2 CPU Windows 2008 Standard SP2 64-bit 2 4096 2015-05-15T08:31:31.000Z NORMAL Win2008 Ent 64-bit 2 CPU Windows 2008 Enterprise SP2 64-bit 2 4096 2015-05-15T08:31:24.000Z NORMAL Win2008 Std 32-bit 2 CPU Windows 2008 Standard SP2 32-bit 2 4096 2015-05-15T08:31:25.000Z NORMAL Win2008 Ent 32-bit 2 CPU Windows 2008 Enterprise SP2 32-bit 2 4096 2015-05-15T08:31:22.000Z NORMAL CSfM SharePoint 2013 Trial Windows 2012 R2 Standard 64-bit installed with SharePoint 2013 and Visual Studio 2013 Pro (Trial Version) 4 12288 2015-03-19T18:31:00.000Z NORMAL RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 2 4096 2015-03-04T10:10:53.000Z NORMAL RedHat 6 64-bit 4 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 8192 2015-03-03T16:05:54.000Z NORMAL RedHat 6 32-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 32-bit 2 4096 2015-03-03T16:06:04.000Z NORMAL RedHat 5 64-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 64-bit 2 4096 2015-03-03T16:06:15.000Z NORMAL RedHat 5 32-bit 2 CPU RedHat 5.11 Enterprise (Tikanga) 32-bit 2 4096 2015-03-03T16:06:26.000Z NORMAL CentOS 6 64-bit 2 CPU CentOS Release 6.6 64-bit 2 4096 2015-03-03T16:06:37.000Z NORMAL CentOS 5 64-bit 2 CPU CentOS Release 5.11 64-bit 2 4096 2015-06-30T11:27:51.000Z NORMAL CentOS 5 32-bit 2 CPU CentOS Release 5.11 32-bit 2 4096 2015-06-30T11:25:24.000Z NORMAL Ubuntu 14.04 2 CPU Ubuntu 14.04.2 LTS 64-bit 2 4096 2015-03-18T12:22:57.000Z NORMAL Ubuntu 12.04 2 CPU Ubuntu 12.04.5 LTS 64-bit 2 4096 2015-03-03T16:07:07.000Z NORMAL Ubuntu 10.04 2 CPU Ubuntu 10.04.4 LTS 64-bit 2 4096 2015-03-03T16:07:17.000Z NORMAL SuSE Linux Ent 64-bit 2 CPU SuSE Linux Enterprise Server 11 SP3 2 4096 2015-03-03T16:07:27.000Z NORMAL Win2012 R2 Std 2 CPU Windows 2012 R2 Update Standard 2 4096 2015-03-03T17:02:31.000Z NORMAL Win2012 R2 Std 4 CPU Windows 2012 R2 Update Standard 4 8192 2015-03-03T17:02:41.000Z NORMAL Win2012 R2 DC 2 CPU Windows 2012 R2 Update Datacenter 2 4096 2015-03-03T17:03:11.000Z NORMAL Win2008 Std 64-bit 2 CPU Windows 2008 Standard SP2 64-bit 2 4096 2015-03-03T16:19:46.000Z NORMAL Win2012 Std 2 CPU Windows 2012 Standard 2 4096 2015-03-03T16:19:03.000Z NORMAL Win2012 DC 2 CPU Windows 2012 Datacenter 2 4096 2015-03-03T16:19:11.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-05-04T08:29:07.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2014 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-05-04T08:31:44.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Std Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Standard 4 8192 MSSQL2012R2S 2015-05-04T08:34:45.000Z NORMAL Win2012 R2 Datacenter 64-bit MS SQL 2012 Ent Windows 2012 R2 Datacenter 64-bit installed with SQL 2012 Enterprise 4 8192 MSSQL2012R2E 2015-05-04T08:36:36.000Z NORMAL Win2012 DC with MS SQL 2014 Std Windows 2012 Datacenter 64-bit installed with SQL 2014 Standard 4 8192 MSSQL2014S 2015-03-03T16:10:49.000Z NORMAL Win2012 DC with MS SQL 2014 Ent Windows 2012 Datacenter 64-bit installed with SQL 2014 Enterprise 4 8192 MSSQL2014E 2015-03-03T16:10:59.000Z NORMAL Win2012 DC with MS SQL 2012 Std Windows 2012 Datacenter 64-bit installed with SQL 2012 Standard SP2 4 8192 2015-03-03T16:28:40.000Z NORMAL Win2012 DC with MS SQL 2012 Ent Windows 2012 Datacenter 64-bit installed with SQL 2012 Enterprise SP2 4 8192 2015-03-03T16:28:51.000Z NORMAL Win2008 R2 Std 2 CPU Windows 2008 R2 Standard SP1 2 4096 2015-03-03T16:19:20.000Z NORMAL Win2008 R2 Ent 2 CPU Windows 2008 R2 Enterprise SP1 2 4096 2015-03-03T16:19:29.000Z NORMAL Win2008 R2 DC 64-bit 2 CPU Windows 2008 R2 Datacenter SP1 2 4096 2015-03-03T16:19:37.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Std Windows 2008 R2 Enterprise SP3 installed with SQL Server 2012 Standard SP2 4 8192 2015-03-03T16:29:02.000Z NORMAL Win2008 R2 Ent with MS SQL 2012 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2012 Enterprise SP2 4 8192 2015-03-03T16:29:11.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Std Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Standard SP3 4 8192 2015-03-03T16:29:20.000Z NORMAL Win2008 R2 Ent with MS SQL 2008 R2 Ent Windows 2008 R2 Enterprise 64-bit installed with SQL Server 2008 R2 Enterprise SP3 4 8192 2015-03-03T16:29:29.000Z NORMAL Win2008 R2 Ent 64-Bit with MS SP Fnd Windows 2008 R2 Enterprise installed with SQL Express & SharePoint Foundation 2010 4 8192 2015-03-03T16:35:11.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml00. SID=DD0 NR=00 2 8192 SAPACCEL 2015-03-17T11:45:48.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Small DD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapsml01. SID=DD1 NR=00 2 8192 SAPACCEL 2015-03-17T11:56:07.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed00. SID=TD0 NR=00 4 10240 SAPACCEL 2015-03-17T18:05:03.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Medium TD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=sapmed01. SID=TD1 NR=00 4 10240 SAPACCEL 2015-03-17T18:05:13.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD0 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg00. SID=PD0 NR=00 8 20480 SAPACCEL 2015-03-17T12:03:15.000Z NORMAL Win2008 R2 Ent 64-bit with SAP Large PD1 MSSQL 2012 and SAP ECC6_EHP7 (no licensing). Hostname=saplrg01. SID=PD1 NR=00 8 20480 SAPACCEL 2015-03-17T12:05:04.000Z NORMAL Win2008 Ent 64-bit 2 CPU Windows 2008 Enterprise SP2 64-bit 2 4096 2015-03-03T16:20:00.000Z NORMAL Win2008 Std 32-bit 2 CPU Windows 2008 Standard SP2 32-bit 2 4096 2015-03-03T16:20:09.000Z NORMAL Win2008 Ent 32-bit 2 CPU Windows 2008 Enterprise SP2 32-bit 2 4096 2015-03-03T16:20:18.000Z NORMAL CSfM SharePoint 2013 Trial Windows 2012 R2 Standard 64-bit installed with SharePoint 2013 and Visual Studio 2013 Pro (Trial Version) 4 12288 2015-05-21T15:29:21.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_myaccount.xml0000664000175000017500000000303413535474530031375 0ustar kamikami00000000000000 testuser Test User Test User test@example.com 8a8f6abc-2745-4d8a-9cbc-8dabe5a7d0e4 create image reports server primary administrator network apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/port_list_create.xml0000664000175000017500000000063513535474530031444 0ustar kamikami00000000000000 CREATE_PORT_LIST OK Port List 'MyPortList' has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/port_list_delete.xml0000664000175000017500000000057713535474530031450 0ustar kamikami00000000000000 DELETE_PORT_LIST OK Port List with Id 84e34850-595d-436e-a885-7cd37edb24a4 has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/port_list_edit.xml0000664000175000017500000000053413535474530031124 0ustar kamikami00000000000000 EDIT_PORT_LIST OK Port List 'MyPortList' has been edited successfully. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/port_list_get.xml0000664000175000017500000000114313535474530030753 0ustar kamikami00000000000000 MyPortList Production Servers NORMAL 2015-06-21T18:54:42.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/port_list_lists.xml0000664000175000017500000000320513535474530031333 0ustar kamikami00000000000000 MyPortList Production Servers NORMAL 2015-06-21T18:54:42.000Z MyPortList2 Core functions NORMAL 2016-09-01T01:36:49.000Z Test_Port_List_1 Test Description NORMAL 2016-09-06T02:32:29.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/report_usageMonitoring.xml0000664000175000017500000000073713535474530032652 0ustar kamikami00000000000000Date,Location,Server,Server ID,Essentials Monitoring Hours,Advanced Monitoring Hours 2/24/15,NA5,Server A,5a2378ba-11de-11e5-ad2a-ca9798323470,14.25,0 2/24/15,NA5,Server B,6330a644-11de-11e5-ad2a-ca9798323470,0,8.64 2/25/15,NA5,Server A,5a2378ba-11de-11e5-ad2a-ca9798323470,24,0 2/25/15,NA5,Server B,6330a644-11de-11e5-ad2a-ca9798323470,0,24 2/26/15,NA5,Server A,5a2378ba-11de-11e5-ad2a-ca9798323470,17.59,6.41 2/26/15,NA5,Server B,6330a644-11de-11e5-ad2a-ca9798323470,2.11,21.89apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_GetServer.xml0000664000175000017500000000363613535474530031402 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true stopped SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 **OR** apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_addDisk.xml0000664000175000017500000000113313535474530031025 0ustar kamikami00000000000000 ADD_DISK IN_PROGRESS The request to add a 20 GB Standard Speed Disk on Server 'SERVER-1' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_addNic.xml0000664000175000017500000000074413535474530030653 0ustar kamikami00000000000000 ADD_NIC IN_PROGRESS The request to add NIC for VLAN 'Subsystem VLAN' on Server 'Production Mail Server' has been accepted and is being processed.. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_antiAffinityRule_list.xml0000664000175000017500000000525713535474530034005 0ustar kamikami00000000000000 ansible-test-image-rhel6 my new node ansible-custom-image-test-UAT my new node rhel-ansible-full-test RHEL Ansible Test rhel-ansible-full-test RHEL Ansible Test ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_antiAffinityRule_list_PAGINATED.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_antiAffinityRule_list_PAGI0000664000175000017500000000525513535474530034004 0ustar kamikami00000000000000 ansible-test-image-rhel6 my new node ansible-custom-image-test-UAT my new node rhel-ansible-full-test RHEL Ansible Test rhel-ansible-full-test RHEL Ansible Test ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_changeServerMonitoringPlan.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_changeServerMonitoringPlan0000664000175000017500000000056513535474530034170 0ustar kamikami00000000000000 CHANGE_SERVER_MONITORING_PLAN OK Monitoring on Server 'Production Server' has been changed to Service Plan 'ADVANCED'. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_cleanServer.xml0000664000175000017500000000064213535474530031737 0ustar kamikami00000000000000 CLEAN_SERVER IN_PROGRESS The request to clean a failed Server deployment for Server e75ead52-692f-4314-8725-c8a4f4d13a87 has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_deleteServer.xml0000664000175000017500000000062713535474530032122 0ustar kamikami00000000000000 DELETE_SERVER IN_PROGRESS Request to Delete Server (Id:d577a691-e116-4913-a440- 022d2729fc84) has been accepted and is being processed ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_deleteServer_RESOURCEBUSY.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_deleteServer_RESOURCEBUSY.0000664000175000017500000000050313535474530033404 0ustar kamikami00000000000000 DELETE_SERVER RESOURCE_BUSY Server is already busy apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_deployServer.xml0000664000175000017500000000070313535474530032147 0ustar kamikami00000000000000 DEPLOY IN_PROGRESS Request to deploy Server 'Production FTPS Server' has been accepted and is being processed. ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_disableServerMonitoring.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_disableServerMonitoring.xm0000664000175000017500000000055013535474530034150 0ustar kamikami00000000000000 DISABLE_SERVER_MONITORING OK Monitoring on Server 5783e93f-5370-44fc-a772-cd3c29a2ecaa has been disabled. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_enableServerMonitoring.xml0000664000175000017500000000052513535474530034151 0ustar kamikami00000000000000 ENABLE_SERVER_MONITORING OK Monitoring on Server 'Production Server' has been enabled. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_powerOffServer.xml0000664000175000017500000000056613535474530032451 0ustar kamikami00000000000000 POWER_OFF_SERVER IN_PROGRESS Request to power off Server 'Production Server' has been accepted and is being processed. ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_powerOffServer_INPROGRESS.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_powerOffServer_INPROGRESS.0000664000175000017500000000057013535474530033476 0ustar kamikami00000000000000 POWER_OFF_SERVER RESOURCE_BUSY Request to power off Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_rebootServer.xml0000664000175000017500000000056013535474530032146 0ustar kamikami00000000000000 REBOOT_SERVER IN_PROGRESS Request to reboot Server 'Production Server' has been accepted and is being processed. ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_rebootServer_RESOURCEBUSY.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_rebootServer_RESOURCEBUSY.0000664000175000017500000000054613535474530033443 0ustar kamikami00000000000000 REBOOT_SERVER RESOURCE_BUSY Request to reboot Server 'Production Server' did not work, server is busy. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_reconfigureServer.xml0000664000175000017500000000052513535474530033165 0ustar kamikami00000000000000 RECONFIGURE_SERVER OK Request to reconfigure Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_removeDisk.xml0000664000175000017500000000065313535474530031600 0ustar kamikami00000000000000 REMOVE_DISK IN_PROGRESS Request to Remove disk '540c4d86-4d84-11e4-a91c-0030487e0302' from Server 'Server 1' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_removeNic.xml0000664000175000017500000000071213535474530031413 0ustar kamikami00000000000000 REMOVE_NIC IN_PROGRESS Request to Remove NIC 5999db1d-725c-46ba-9d4e-d33991e61ab1 for VLAN 'Subsystem VLAN' from Server 'Production Mail Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_resetServer.xml0000664000175000017500000000055613535474530032003 0ustar kamikami00000000000000 RESET_SERVER IN_PROGRESS Request to reset Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_server.xml0000664000175000017500000002572013535474530031000 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true PENDING_ADD DEPLOY_SERVER_WITH_DISK_SPEED 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE RECONFIGURE_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true UNKNOWN SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 21 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true false UNKNOWN SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true false NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_server_NA3.xml0000664000175000017500000000604213535474530031435 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_server_e75ead52_692f_4314_0000664000175000017500000000327213535474530033060 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE DEPLOY_SERVER 2015-12-02T11:07:40.000Z devuser1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_server_paginated.xml0000664000175000017500000000604013535474530033006 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_server_paginated_empty.xml0000664000175000017500000000022313535474530034221 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_shutdownServer.xml0000664000175000017500000000056413535474530032533 0ustar kamikami00000000000000 SHUTDOWN_SERVER IN_PROGRESS Request to shutdown Server 'Production Server' has been accepted and is being processed. ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_shutdownServer_INPROGRESS.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_shutdownServer_INPROGRESS.0000664000175000017500000000056613535474530033567 0ustar kamikami00000000000000 SHUTDOWN_SERVER RESOURCE_BUSY Request to shutdown Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_startServer.xml0000664000175000017500000000055613535474530032016 0ustar kamikami00000000000000 START_SERVER IN_PROGRESS Request to start Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_startServer_INPROGRESS.xml0000664000175000017500000000056013535474530033564 0ustar kamikami00000000000000 START_SERVER RESOURCE_BUSY Request to start Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/server_updateVmwareTools.xml0000664000175000017500000000056613535474530033160 0ustar kamikami00000000000000 POWER_OFF_SERVER IN_PROGRESS Request to power off Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/summary_usage_report.csv0000664000175000017500000000152513535474530032350 0ustar kamikami00000000000000DAY,Location,CPU Hours,RAM Hours,Storage Hours,Performance Storage Hours,Bandwidth In,Bandwidth Out,Sub-Admin Hours,Network Hours,Public IP Hours,Cloud Files Account Hours,Cloud Files (GB Days),Software Units,Essentials Client Days,Advanced Client Days,Enterprise Client Days,Essentials Backups (GB),Advanced Backups (GB),Enterprise Backups (GB) 01/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 02/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 03/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 04/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 05/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 06/01/2013,NA1,172,344,3958,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 07/01/2013,NA1,205,410,4783,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 08/01/2013,NA1,216,432,5136,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_applyTags.xml0000664000175000017500000000045113535474530030675 0ustar kamikami00000000000000 APPLY_TAGS OK Tag(s) successfully applied. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_applyTags_BADREQUEST.xml0000664000175000017500000000050213535474530032411 0ustar kamikami00000000000000 APPLY_TAGS RESOURCE_NOT_FOUND Tag Key(s) (ChangeNameTes) not found. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_createTagKey.xml0000664000175000017500000000057513535474530031310 0ustar kamikami00000000000000 CREATE_TAG_KEY OK Tag Key 'MyTestKey' has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_createTagKey_BADREQUEST.xml0000664000175000017500000000051713535474530033023 0ustar kamikami00000000000000 CREATE_TAG_KEY NAME_NOT_UNIQUE Another Tag Key named 'MyTestKey' already exists. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_deleteTagKey.xml0000664000175000017500000000052413535474530031301 0ustar kamikami00000000000000 DELETE_TAG_KEY OK Tag Key (Id:4f921962-402d-438d-aa37-6f6a0392a1a9) has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_deleteTagKey_BADREQUEST.xml0000664000175000017500000000047313535474530033023 0ustar kamikami00000000000000 DELETE_TAG_KEY RESOURCE_NOT_FOUND Tag Key fdafdsa not found. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_editTagKey.xml0000664000175000017500000000047013535474530030764 0ustar kamikami00000000000000 EDIT_TAG_KEY OK Tag Key 'ChangeNameTest' has been edited. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_editTagKey_BADREQUEST.xml0000664000175000017500000000060113535474530032477 0ustar kamikami00000000000000 EDIT_TAG_KEY NO_CHANGE At least one of name, description, valueRequired or displayOnReport must be changed from its current value. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_removeTag.xml0000664000175000017500000000045213535474530030663 0ustar kamikami00000000000000 REMOVE_TAGS OK Tag(s) successfully removed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_removeTag_BADREQUEST.xml0000664000175000017500000000057013535474530032403 0ustar kamikami00000000000000 REMOVE_TAGS RESOURCE_NOT_FOUND Tag Key(s) (AaronTestModified) not applied to Server eb222a4a-fffd-4e4a-8346-1279ef621ab0. ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_5ab77f5f_5aa9_426f_8450000664000175000017500000000036713535474530032652 0ustar kamikami00000000000000 LibcloudTest true true ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_5ab77f5f_5aa9_426f_8450000664000175000017500000000052413535474530032645 0ustar kamikami00000000000000 GET_TAG_KEY RESOURCE_NOT_FOUND Tag Key 5ab77f5f-5aa9-426f-8459-4eab34e03d5 not found. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_list.xml0000664000175000017500000000135313535474530031212 0ustar kamikami00000000000000 AaronTestModified Testing for VMWare true true LibcloudTest true true MyTestKey true true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_tagKey_list_SINGLE.xml0000664000175000017500000000052113535474530032247 0ustar kamikami00000000000000 LibcloudTest true true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/dimensiondata/tag_tag_list.xml0000664000175000017500000000254213535474530030542 0ustar kamikami00000000000000 SERVER 09242b55-3bc8-4cb7-b30c-4158267f58e6 App server NA9 5ab77f5f-5aa9-426f-8459-4eab34e03d54 ChangeNameTest No way! true true NETWORK_DOMAIN 1a16bf5e-583b-42c9-af94-a92d9ee1607f An Ho1a Demo NA9 d047c609-93d7-4bc5-8fc9-732c85840075 AaronTestModified Success true true SERVER 77da591d-b58e-43ef-8bc2-ddde3f732893 Test 1 NA9 d047c609-93d7-4bc5-8fc9-732c85840075 AaronTestModified Test VMware true true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/0000775000175000017500000000000013600223624023173 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/allocate_address.xml0000664000175000017500000000034713535474530027225 0ustar kamikami00000000000000 56926e0e-5fa3-41f3-927c-17212def59df 192.0.2.1 standard apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/allocate_vpc_address.xml0000664000175000017500000000042413535474530030071 0ustar kamikami00000000000000 eb920193-37a9-401a-8fff-089783b2c153 192.0.2.2 vpc eipalloc-666d7f04 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/associate_address.xml0000664000175000017500000000030213535474530027403 0ustar kamikami00000000000000 1a470be4-b44d-4423-a80c-44ef2070b8be true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/associate_vpc_address.xml0000664000175000017500000000036613535474530030265 0ustar kamikami00000000000000 s132fsz2-6cdg-4ox3-a148-lpqnvdc98c2a true eipassoc-167a8073 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml0000664000175000017500000000031313535474530030622 0ustar kamikami00000000000000 1eb45fd7-d4f6-4b63-a52f-54fc0c82617e true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/attach_network_interface.xml0000664000175000017500000000035013535474530030763 0ustar kamikami00000000000000 e46c7abc-8b14-4315-99cb-773a0f95d833 eni-attach-2b588b47 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/attach_volume.xml0000664000175000017500000000052513535474530026565 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE vol-4d826724 i-6058a509 /dev/sdh attaching 2008-05-07T11:51:50.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/authorize_security_group_egress.xml0000664000175000017500000000032613535474530032456 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/authorize_security_group_ingress.xml0000664000175000017500000000033013535474530032633 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/copy_image.xml0000664000175000017500000000027513535474530026050 0ustar kamikami00000000000000 7b7d87d5-c045-4c2c-a2c4-b538debe14b2 ami-4db38224 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_encrypted_volume.xml0000664000175000017500000000065013535474530030640 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE vol-4d826724 10 us-east-1a creating 2008-05-07T11:51:50.000Z standard true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_image.xml0000664000175000017500000000030113535474530026327 0ustar kamikami00000000000000 3629ec66-c1f8-4b66-aac5-a8ad1cdf6c15 ami-e9b38280 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml0000664000175000017500000000050513535474530030624 0ustar kamikami00000000000000 437b9824-8143-4583-98f7-0937d53aea83 igw-13ac2b36 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_key_pair.xml0000664000175000017500000000227313535474530027062 0ustar kamikami00000000000000 my-key-pair 1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f ---- BEGIN RSA PRIVATE KEY ---- MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6 b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ 21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4 nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE -----END RSA PRIVATE KEY----- apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_network_interface.xml0000664000175000017500000000230313535474530030762 0ustar kamikami00000000000000 ca764ebe-8abc-4d37-9995-b9e88c086fa8 eni-2b36086d subnet-5ed9d432 vpc-62ded30e us-east-1d My Test 123456789098 false pending 0e:bd:49:3e:11:74 172.16.4.144 ip-172-16-4-144.ec2.internal true sg-495a9926 default 172.16.4.144 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_placement_groups.xml0000664000175000017500000000031013535474530030614 0ustar kamikami00000000000000 d4904fd9-82c2-4ea5-adfe-a9cc3EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_security_group.xml0000664000175000017500000000034513535474530030340 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true sg-52e2f530 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_snapshot.xml0000664000175000017500000000067313535474530027120 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587 snap-a7cb2hd9 vol-4282672b pending 2013-08-15T16:22:30.000Z 60% 1836219348 10 Test description apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_subnet.xml0000664000175000017500000000072113535474530026553 0ustar kamikami00000000000000 e94b315e-6424-4536-b48d-0dfb47732c72 subnet-ce0e7ce6 pending vpc-532135d1 192.168.51.128/26 59 us-east-1b apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_tags.xml0000664000175000017500000000026613535474530026215 0ustar kamikami00000000000000 b001068a-ca0d-4f05-b622-28fe984f44be true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_volume.xml0000664000175000017500000000065213535474530026565 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE vol-4d826724 10 us-east-1a creating 2008-05-07T11:51:50.000Z standard false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/create_vpc.xml0000664000175000017500000000061013535474530026040 0ustar kamikami00000000000000 7a662fe5-1f34-4e17-9ee9-69a28a8ac0be vpc-ad3527cf pending 192.168.55.0/24 dopt-7eded312 default apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml0000664000175000017500000000031313535474530030620 0ustar kamikami00000000000000 b1a5c8c9-91c7-43f3-8234-c162db89a2df true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_key_pair.xml0000664000175000017500000000026413535474530027057 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_network_interface.xml0000664000175000017500000000031513535474530030762 0ustar kamikami00000000000000 c0bc0036-e328-47c6-bd6d-318b007f66ee true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_placement_groups.xml0000664000175000017500000000031013535474530030613 0ustar kamikami00000000000000 d4904fd9-82c2-4ea5-adfe-a9cc3EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_security_group.xml0000664000175000017500000000030413535474530030332 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_snapshot.xml0000664000175000017500000000026313535474530027112 0ustar kamikami00000000000000 5cd6fa89-35bd-4aac-99ed-na8af7 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_subnet.xml0000664000175000017500000000026313535474530026553 0ustar kamikami00000000000000 5cd6fa89-35bd-4aac-99ed-na8af7 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_tags.xml0000664000175000017500000000026613535474530026214 0ustar kamikami00000000000000 7a297da7-3ecb-4156-8bcb-3be73896cc14 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_volume.xml0000664000175000017500000000026713535474530026566 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/delete_vpc.xml0000664000175000017500000000026313535474530026043 0ustar kamikami00000000000000 85793fa6-2ece-480c-855f-0f82c3257e50 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/deregister_image.xml0000664000175000017500000000027313535474530027231 0ustar kamikami00000000000000 d06f248d-444e-475d-a8f8-1ebb4ac39842 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_account_attributes.xml0000664000175000017500000000203413535474530031471 0ustar kamikami00000000000000 a00adaf6-f86c-48eb-85f8-7ac470ae993d max-instances 20 max-elastic-ips 5 vpc-max-elastic-ips 5 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_addresses.xml0000664000175000017500000000120113535474530027537 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE 1.2.3.4 eipalloc-602b5d01 vpc i-4382922a eipassoc-cea049ab eni-83e3c5c5 123456789098 192.168.1.5 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_addresses_all.xml0000664000175000017500000000272513535474530030403 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE 1.2.3.4 eipalloc-602b5d01 vpc i-4382922a eipassoc-cea049ab eni-83e3c5c5 123456789098 192.168.1.5 1.2.3.5 eipalloc-998195fb vpc i-4382922b eipassoc-cea049ac eni-83e3c5c6 123456789098 192.168.1.6 1.2.3.6 eipalloc-922a5cf3 standard 1.2.3.7 eipalloc-992a5cf8 vpc apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_addresses_multi.xml0000664000175000017500000000100713535474530030755 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE 1.2.3.4 i-4382922a 1.2.3.6 i-4382922b 1.2.3.5 i-4382922b apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_addresses_single.xml0000664000175000017500000000046313535474530031111 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE 1.2.3.4 i-4382922a apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_availability_zones.xml0000664000175000017500000000116313535474530031461 0ustar kamikami00000000000000 cc0dfb29-efef-451c-974f-341b3edfb28f eu-west-1a available eu-west-1 eu-west-1b available eu-west-1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_images.xml0000664000175000017500000000572113535474530027042 0ustar kamikami00000000000000 73fac9c5-f6d2-4b45-846f-47adf1e82d6c ami-57ba933a 123456788908/Test Image available 123456788908 false x86_64 machine aki-88aa75e1 Test Image Testing Stuff ebs /dev/sda1 ab-5dh78019 /dev/sda1 snap-88123ed9 10 true standard /dev/sda2 ephemeral0 paravirtual xen ami-85b2a8ae 123456788908/Test Image 2 available 123456788908 false x86_64 machine aki-88aa75e1 Test Image 2 ebs /dev/sda1 as-6dr90319 /dev/sda1 snap-c0bfbbdb 20 false standard paravirtual xen apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml0000664000175000017500000000326313535474530031377 0ustar kamikami00000000000000 73fac9c5-f6d2-4b45-846f-47adf1e82d6c ami-57ba933a 123456788908/Test Image available 123456788908 false x86_64 machine aki-88aa75e1 Test Image Testing Stuff ebs /dev/sda1 ab-5dh78019 /dev/sda1 snap-88123ed9 10 true standard /dev/sda2 ephemeral0 paravirtual xen apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks.xml0000664000175000017500000000140313535474530032224 0ustar kamikami00000000000000 a8c44ac4-8e63-46e9-b8b2-8c72ce3d9b18 import-snap-fh7y6i6w snap-0ea83e8a87e138f39 RAW 1.073741824E10 dummy-bucket dummy-key completed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_import_snapshot_tasks_active.xml0000664000175000017500000000130013535474530033553 0ustar kamikami00000000000000 a8c44ac4-8e63-46e9-b8b2-8c72ce3d9b18 import-snap-fh7y6i6w RAW 1.073741824E10 dummy-bucket dummy-key active apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_instance_types.xml0000664000175000017500000000666013535474530030630 0ustar kamikami00000000000000truem1.small15256t1.micro15256m1.medium110512c1.medium210512m1.large1101024c1.xlarge2101024m1.xlarge1102048m2.xlarge2102048m3.xlarge16152048m2.2xlarge16304096m3.2xlarge16304096cc1.4xlarge16603072m2.4xlarge16604096cc2.8xlarge161206144hi1.4xlarge161206144cg1.4xlarge1620012288cr1.8xlarge1624016384hs1.8xlarge1624000119808apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_instances.xml0000664000175000017500000002120213535474530027554 0ustar kamikami00000000000000 ec0d2a7d-5080-4f4b-9b02-cb0d5d2d4274 r-fd67fb97 123456789098 i-4382922a ami-3215fe5a 80 stopped User initiated (2014-01-11 14:39:31 GMT) fauxkey 0 m1.small 2013-12-02T11:58:11.000Z us-east-1d default aki-88aa75e1 disabled 10.211.11.211 1.2.3.4 sg-42916629 Test Group 1 sg-42916628 Test Group 2 Client.UserInitiatedShutdown Client.UserInitiatedShutdown: User initiated shutdown x86_64 ebs /dev/sda1 /dev/sda1 vol-5e312311 attached 2013-04-09T18:01:01.000Z true paravirtual ifmxj1365530456668 xen false r-88dc1bef 123456789098 i-8474834a ami-29674340 80 stopped ip-172-16-9-139.ec2.internal User initiated (2014-01-11 14:39:31 GMT) cderamus 0 t1.micro 2013-12-02T15:58:29.000Z us-east-1d default aki-88aa75e1 disabled subnet-5fd9d412 vpc-61dcd30e 172.16.9.139 1.2.3.5 true sg-495a9926 default Client.UserInitiatedShutdown Client.UserInitiatedShutdown: User initiated shutdown x86_64 ebs /dev/sda1 /dev/sda1 vol-60124921 attached 2013-12-02T15:58:32.000Z false paravirtual Name Test Server 2 Group VPC Test xen eni-c5dffd83 subnet-5fd9d412 vpc-61dcd30e 123456789098 in-use 0e:27:72:16:52:ab 172.16.9.139 ip-172-16-9-139.ec2.internal true sg-495a9926 default eni-attach-4d924721 0 attached 2013-12-02T15:58:29.000Z true 172.16.4.139 ip-172-16-4-139.ec2.internal true false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml0000664000175000017500000000126613535474530031331 0ustar kamikami00000000000000 843ff26c-f1ac-48f5-93a6-fa28f8abd9dd igw-84dd3ae1 igw-7fdae215 vpc-62cad41e available apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_key_pairs.xml0000664000175000017500000000057713535474530027567 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE gsg-keypair 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_key_pairs_doesnt_exist.xml0000664000175000017500000000037213535474530032350 0ustar kamikami00000000000000 InvalidKeyPair.NotFoundThe key pair 'test-key-pair' does not exist31b97300-eb8e-405e-9567-b0f57b791fed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_network_interfaces.xml0000664000175000017500000000715013535474530031467 0ustar kamikami00000000000000 e8fc6c0b-d6f8-4b85-aa29-e6a097eb4631 eni-18e6c05e subnet-5ed9d432 vpc-62ded30e us-east-1d Test Interface 1 123456789098 false in-use 0e:6e:df:72:78:af 172.16.4.133 ip-172-16-4-133.ec2.internal true sg-495a9926 default eni-attach-c87dd1a4 i-caa71db1 123456789098 1 attached 2013-12-02T17:46:27.000Z false 172.16.4.133 ip-172-16-4-133.ec2.internal true eni-83e3c5c5 subnet-5ed9d432 vpc-62ded30e us-east-1d 123456789098 false in-use 0e:93:0b:e9:e9:c4 172.16.4.145 ip-172-16-4-145.ec2.internal true sg-13e4607c Test Group sg-495a9926 default eni-attach-bae984d6 i-caa71db1 123456789098 0 attached 2013-11-25T13:35:03.000Z true 172.16.4.145 ip-172-16-4-145.ec2.internal true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_placement_groups.xml0000664000175000017500000000104013535474530031132 0ustar kamikami00000000000000 d4904fd9-82c2-4ea5-adfe-a9cc3EXAMPLE XYZ-cluster cluster available XYZ-cluster2 cluster available apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_reserved_instances.xml0000664000175000017500000000201013535474530031447 0ustar kamikami00000000000000 56d0fffa-8819-4658-bdd7-548f143a86d2 93bbbca2-c500-49d0-9ede-9d8737400498 t1.micro us-east-1b 2013-06-18T12:07:53.161Z 2014-06-18T12:07:53.161Z 31536000 23.0 0.012 1 Linux/UNIX active default USD Light Utilization apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_security_groups.xml0000664000175000017500000000316013535474530031036 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE 111122223333 sg-443d0a12 WebServers Web Servers tcp 80 80 0.0.0.0/0 111122223333 sg-5ff8a023 RangedPortsBySource Group A tcp 6000 7000 111122223333 sg-99gh4012 Group B apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_snapshots.xml0000664000175000017500000000377313535474530027624 0ustar kamikami00000000000000 and4xcasi-35bd-4e3c-89ab-cb183 snap-428abd35 vol-e020df80 pending 2013-09-15T15:40:30.000Z 90% 1938218230 30 Daily Backup Keyone DB_Backup snap-18349159 vol-b5a2c1v9 completed 2013-09-15T16:00:30.000Z 30% 1938218230 15 Weekly backup Name DB Backup 1 Key2 db_backup snap-18349160 vol-10ae5e2b pending 2014-09-15T16:00:30.000Z 30% 1938218231 15 Weekly backup Name DB Backup 1 Key2 db_backup apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_subnets.xml0000664000175000017500000000263313535474530027257 0ustar kamikami00000000000000 67bba371-8044-45a7-b4a3-d72fef8b96d8 subnet-ce0e7ce5 available vpc-532135d1 192.168.51.0/25 123 us-east-1a false false Name Test Subnet 1 subnet-ce0e7ce6 available vpc-532135d1 192.168.51.128/64 59 us-east-1b false false Name Test Subnet 2 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_tags.xml0000664000175000017500000000137013535474530026527 0ustar kamikami00000000000000 fa7e0e44-df5e-49a0-98d7-5d4d19a29f95 i-4382922a instance tag test one i-4382922a instance owner libcloud i-4382922a instance stack Production apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_volumes.xml0000664000175000017500000000316613535474530027270 0ustar kamikami00000000000000 766b978a-f574-4c8d-a974-57547a8c304e vol-10ae5e2b 1 us-east-1d available 2013-10-09T05:41:37.000Z vol-v24bfh75 11 us-east-1c in-use 2013-10-08T19:36:49.000Z vol-b6c851ec 8 snap-30d37269 us-east-1d some-unknown-status 2013-06-25T02:04:12.000Z vol-b6c851ec i-d334b4b3 /dev/sda1 attached 2013-06-25T02:04:12.000Z true standard apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_volumes_modifications.xml0000664000175000017500000000250413535474530032173 0ustar kamikami00000000000000 35fdf8d3-6ffa-46dc-8f8e-62fe70bc31a2 10000 100 optimizing 2000 io1 vol-06397e7a0eEXAMPLE 3 2017-02-10T23:40:57.612Z 10 gp2 10000 100 completed 200 io1 vol-bEXAMPLE 100 2017-02-10T22:50:52.207Z 2017-02-10T22:56:04.823Z 8 gp2 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/describe_vpcs.xml0000664000175000017500000000176213535474530026551 0ustar kamikami00000000000000 be8cfa34-0710-4895-941f-961c5738f8f8 vpc-532335e1 available 192.168.51.0/24 dopt-7eded312 default false vpc-62ded30e available 192.168.52.0/24 dopt-7eded312 Name Test VPC default false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml0000664000175000017500000000031313535474530030606 0ustar kamikami00000000000000 7098cc6d-a984-4d34-a5ed-6ae1a645c0b6 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/detach_network_interface.xml0000664000175000017500000000031513535474530030750 0ustar kamikami00000000000000 1a683cd6-58ea-4b93-a6e9-a23b56afddf0 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/detach_volume.xml0000664000175000017500000000052613535474530026552 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE vol-4d826724 i-6058a509 /dev/sdh detaching 2008-05-08T11:51:50.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/disassociate_address.xml0000664000175000017500000000031013535474530030102 0ustar kamikami00000000000000 dfb841f8-cc26-4f45-a3ac-dc08589eec1d true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/get_console_output.xml0000664000175000017500000000045113535474530027651 0ustar kamikami00000000000000 f0ffb5ce-8d62-4ab9-add7-67a0f99c9811 i-40128925 2013-12-02T12:31:38.000Z VGVzdCBTdHJpbmc= apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/import_key_pair.xml0000664000175000017500000000044113535474530027124 0ustar kamikami00000000000000 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE keypair 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/import_snapshot.xml0000664000175000017500000000110613535474530027157 0ustar kamikami00000000000000 0d490bf6-19cf-4456-9c71-31d097faf46d import-snap-fgsddbhv RAW 3 0.0 pending dummy-bucket dummy-key active apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/modify_image_attribute.xml0000664000175000017500000000021113535474530030436 0ustar kamikami00000000000000 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/modify_instance_attribute.xml0000664000175000017500000000031513535474530031165 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/modify_snapshot_attribute.xml0000664000175000017500000000031413535474530031217 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/modify_subnet_attribute.xml0000664000175000017500000000031013570310635030646 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/modify_volume.xml0000664000175000017500000000122213535474530026603 0ustar kamikami00000000000000 5jkdf074-37ed-4004-8671-a78ee82bf1cbEXAMPLE 1000 300 modifying 2 io1 vol-10ae5e2b 0 2017-01-19T23:58:04.922Z 1 gp2 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/reboot_instances.xml0000664000175000017500000000027413535474530027274 0ustar kamikami00000000000000 76dabb7a-fb39-4ed1-b5e0-31a4a0fdf5c0 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/register_image.xml0000664000175000017500000000030513535474530026714 0ustar kamikami00000000000000 6d858ea7-053e-4751-9fae-b891019fc8d2 ami-57c2fb3e apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/release_address.xml0000664000175000017500000000027613535474530027062 0ustar kamikami00000000000000 23ec1390-8c1d-4a3e-8042-b1ad84933f57 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/revoke_security_group_egress.xml0000664000175000017500000000032013535474530031731 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/revoke_security_group_ingress.xml0000664000175000017500000000032213535474530032115 0ustar kamikami00000000000000 59dbff89-35bd-4eac-99ed-be587EXAMPLE true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/run_instances.xml0000664000175000017500000000161513535474530026606 0ustar kamikami00000000000000 r-47a5402e AIDADH4IGTRXXKCD default i-2ba64342 ami-be3adfd7 0 pending example-key-name 0 m1.small 2007-08-07T11:51:50.000Z us-east-1b true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/run_instances_iam_profile.xml0000664000175000017500000000210013535474530031142 0ustar kamikami00000000000000 r-47a5403e AIDADH4IGTRXXKCD default i-2ba64343 ami-be3adfd7 0 pending example-key-name 0 m1.small 2007-08-07T11:51:50.000Z us-east-1b true AIDGPMS9RO4H3FEXAMPLE arn:aws:iam::123456789012:instance-profile/ExampleInstanceProfile apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/run_instances_idem.xml0000664000175000017500000000167613535474530027613 0ustar kamikami00000000000000 r-47a5402e AIDADH4IGTRXXKCD default i-2ba64342 ami-be3adfd7 0 pending example-key-name 0 m1.small 2007-08-07T11:51:50.000Z us-east-1b true testclienttoken apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/run_instances_idem_mismatch.xml0000664000175000017500000000061613535474530031471 0ustar kamikami00000000000000 IdempotentParameterMismatch Arguments on this idempotent request are inconsistent with arguments used in previous request(s). 5dabd361-d2e0-4f79-937d-4b2852a3b719 ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/run_instances_with_subnet_and_security_group.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/run_instances_with_subnet_and_security_grou0000664000175000017500000000713013535474530034225 0ustar kamikami00000000000000 ebfcb9e2-fe5f-4afd-ac91-6a9946305e32 r-11111111 111111111111 i-11111111 ami-11111111 0 pending ip-192-0-2-5.us-east-1.compute.internal 0 m3.medium 2015-09-30T14:37:59.000Z us-east-1a default aki-111111111 disabled subnet-11111111 vpc-11111111 192.0.2.5 true sg-11111111 test-security-group pending pending x86_64 ebs /dev/sda paravirtual xen eni-11111111 subnet-11111111 vpc-11111111 111111111111 in-use 06:ea:24:17:f7:77 192.0.2.5 true sg-11111111 test-security-group eni-attach-11111111 0 attaching 2015-09-30T14:37:59.000Z true 192.0.2.5 true false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/start_instances.xml0000664000175000017500000000102413535474530027131 0ustar kamikami00000000000000 322f78ee-967b-40c9-aecd-8d442022da20 i-ff5de6aa 0 pending 80 stopped apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/stop_instances.xml0000664000175000017500000000102313535474530026760 0ustar kamikami00000000000000 4ace6850-c876-4971-af0b-67a4278c36a1 i-2ba64342 64 stopping 16 running apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ec2/terminate_instances.xml0000664000175000017500000000073013535474530027767 0ustar kamikami00000000000000 fa63083d-e0f7-4933-b31a-f266643bdee8 i-4382922a 32 shutting-down 16 running apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/0000775000175000017500000000000013600223624023271 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/htemplate_list.json0000664000175000017500000000062013535474530027213 0ustar kamikami00000000000000{"templates": [ {"uuid": "1", "hypervisor_name": "kvm-hvm", "cpus": 1, "memory": 512, "arch": "i686", "id": 1, "name": "Small"}, {"uuid": "2", "hypervisor_name": "kvm-hvm", "cpus": 2, "memory": 1024, "arch": "i686", "id": 2, "name": "Medium"}, {"uuid": "3", "hypervisor_name": "kvm-hvm", "cpus": 3, "memory": 2048, "arch": "x86_64", "id": 3, "name": "Large"} ], "errno": 0, "message": "Success"}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/network_list.json0000664000175000017500000000014313535474530026721 0ustar kamikami00000000000000{"errno": 0, "message": "Success", "networks": [{"uuid": "1", "vlan_id": null, "name": "Default"}]}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/ptemplate_list.json0000664000175000017500000000061013535474530027222 0ustar kamikami00000000000000{"errno": 0, "message": "Success", "packages": [ {"os": "unknown", "description": "AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2", "storage": 20480, "uuid": "1", "name": "centos54"}, {"os": "unknown", "description": "AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2", "storage": 20480, "uuid": "2", "name": "centos54 two"} ]}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/vm_1_action_delete.json0000664000175000017500000000004213535474530027714 0ustar kamikami00000000000000{"errno": 0, "message": "Success"}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/vm_1_action_start.json0000664000175000017500000000102313535474530027607 0ustar kamikami00000000000000{"errno": 0, "message": "Success", "vm": {"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "unkown", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.12", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/vm_1_action_stop.json0000664000175000017500000000102413535474530027440 0ustar kamikami00000000000000{"errno": 0, "message": "Success", "vm": {"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "unkown", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/vm_1_get.json0000664000175000017500000000102113535474530025672 0ustar kamikami00000000000000{"errno": 0, "message": "Success", "vm": {"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "off", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/vm_list.json0000664000175000017500000000276413535474530025665 0ustar kamikami00000000000000{"errno": 0, "message": "Success", "vms": [ {"vnc_enabled": true, "uuid": 1, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "running", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"}, {"vnc_enabled": true, "uuid": 2, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:72:b4:71:21", "network_name": "Default", "uuid": "c76edd61-2dfd-11df-84ca-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5902", "name": "dummy-2", "state": "running", "trusted": null, "os": "unknown", "vnc_password": "zoiZW31T", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"}, {"vnc_enabled": true, "uuid": 3, "tags": [], "ip_address": "42.78.124.75", "interfaces": [{"ip": "42.78.124.75", "mac": "00:16:e9:d6:40:c6", "network_name": "Default", "uuid": "479b9823-2ded-11df-94e8-0015174e564c", "network": "fc38963c-a9fa-11de-8c4b-001b63a56c51"}], "vnc_port": "5900", "name": "dummy-1", "state": "stopped", "trusted": null, "os": "unknown", "vnc_password": "jBs5UT00", "vnc_ip_address": "192.168.1.111", "hardware_profile_uuid": "bcaff710-2914-11de-836c-001a929face2"} ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecp/vm_put.json0000664000175000017500000000015013535474530025505 0ustar kamikami00000000000000{"errno": 0, "message": "Success", "txid": "fc38963c-a9fa-11de-8c4b-001baaa56c51", "machine_id": "1234"}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/0000775000175000017500000000000013600223624023274 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/attach_disk.xml0000664000175000017500000000021713535474530026307 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/copy_image.xml0000664000175000017500000000025513535474530026147 0ustar kamikami00000000000000 i-28n7dkvov DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_disk.xml0000664000175000017500000000025513535474530026310 0ustar kamikami00000000000000 i-28n7dkvov DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_image.xml0000664000175000017500000000026113535474530026435 0ustar kamikami00000000000000 i-28n7dkvov DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_instance.xml0000664000175000017500000000027513535474530027164 0ustar kamikami00000000000000 i-28n7dkvov DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_node_describe_instances.xml0000664000175000017500000000353213535474530032213 0ustar kamikami00000000000000 1 1 10 CA75EE06-D5F7-433C-870B-5042EED6C1DC ubuntu1404_64_20G_aliaegis_20150325.vhd 10.163.197.74 ecs.t1 i-28n7dkvov -1 cn-qingdao-b PayByTraffic ca0122d9-374d-4fce-9fc0-71f7c3eaf1c3 false 1024 1 1 true sg-28ou0f3xa iZ28n7dkvovZ classic 114.215.124.73 iZ28n7dkvovZ ecs.t1.small 2015-12-27T07:35Z Running cn-qingdao PostPaid 2999-09-08T16:00Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_public_ip.xml0000664000175000017500000000032513535474530027322 0ustar kamikami00000000000000 F2EF6A3B-E345-46B9-931E-0EA094818567 10.1.149.159 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_security_group.xml0000664000175000017500000000032113535474530030433 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 sg-F876FF7BA apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_snapshot.xml0000664000175000017500000000027513535474530027217 0ustar kamikami00000000000000 i-28n7dkvov DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/create_volume_describe_disks.xml0000664000175000017500000000264513535474530031727 0ustar kamikami00000000000000 PostPaid true true true cloud Description ubuntu1404sys 5 system i-28whl2nj2 2014-07-23T02:44:06Z ubuntu1404_64_20G_aliaegis_20150325.vhd cn-qingdao-b 2016-01-04T15:02:17Z /dev/xvda false cn-qingdao d-28zfrmo13 In_use 2999-09-08T16:00Z 1 10 1 ED5CF6DD-71CA-462C-9C94-A61A78A01479 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/delete_disk.xml0000664000175000017500000000021713535474530026305 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/delete_image.xml0000664000175000017500000000022113535474530026430 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/delete_instance.xml0000664000175000017500000000022713535474530027160 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/delete_security_group_by_id.xml0000664000175000017500000000024113535474530031601 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/delete_snapshot.xml0000664000175000017500000000022713535474530027213 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_disks.xml0000664000175000017500000000471513535474530027015 0ustar kamikami00000000000000 PostPaid true false false cloud 5 data 2014-07-23T02:44:07Z cn-qingdao-b 2014-07-23T07:47:35Z 2014-07-23T08:28:48Z true cn-qingdao d-28m5zbua0 Available PostPaid true true true cloud Description ubuntu1404sys 5 system i-28whl2nj2 2014-07-23T02:44:06Z ubuntu1404_64_20G_aliaegis_20150325.vhd cn-qingdao-b 2016-01-04T15:02:17Z /dev/xvda false cn-qingdao d-28zfrmo13 In_use 2999-09-08T16:00Z 1 10 2 ED5CF6DD-71CA-462C-9C94-A61A78A01479 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_images.xml0000664000175000017500000000244513535474530027143 0ustar kamikami00000000000000 1 1 10 cn-qingdao FAD4D9B9-D75F-4A9E-BC13-991C0F06F50F freebsd1001_64_20G_aliaegis_20150527.vhd freebsd1001_64_20G_aliaegis_20150527.vhd linux x86_64 FreeBSD 10.1 64位 /dev/xvda 20 system 100% instance 2015-06-19T07:25:42Z 1.0.0 Available freebsd1001_64_20G_aliaegis_20150527.vhd false false Freebsd 20 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_instance_types.xml0000664000175000017500000000130413535474530030717 0ustar kamikami00000000000000 1651FBB6-4FBF-49FF-A9F5-DF5D696C7EC6 ecs.t1.xsmall 1 0.5 ecs.t1 ecs.s2.small 2 1.0 ecs.s2 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_instances.xml0000664000175000017500000000353313535474530027664 0ustar kamikami00000000000000 1 1 10 CA75EE06-D5F7-433C-870B-5042EED6C1DC ubuntu1404_64_20G_aliaegis_20150325.vhd 10.163.197.74 ecs.t1 i-28n7dkvov -1 cn-qingdao-b PayByTraffic ca0122d9-374d-4fce-9fc0-71f7c3eaf1c3 false 1024 1 1 true sg-28ou0f3xa iZ28n7dkvovZ classic 114.215.124.73 iZ28n7dkvovZ ecs.t1.small 2015-12-27T07:35Z Starting cn-qingdao PostPaid 2999-09-08T16:00Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_regions.xml0000664000175000017500000000201113535474530027331 0ustar kamikami00000000000000 FD28A957-20B2-447E-8A5A-952F50C4EDF0 ap-southeast-1 亚太(新加坡) cn-shenzhen 深圳 cn-qingdao 青岛 cn-beijing 北京 cn-shanghai 上海 us-east-1 美东弗吉尼亚 cn-hongkong 香港 cn-hangzhou 杭州 us-west-1 美国硅谷 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_security_group_attributes.xml0000664000175000017500000000212513535474530033222 0ustar kamikami00000000000000 sg-m5e5vyj2j0atm2gewww4 Accept sg-m5e5vyj2j0atm2gewww4 System created security group. cn-qingdao 8A3E0262-EEA1-4961-A403-3D6E69F3539C 121.43.18.0/24 internet -1/-1 ingress 1 ALL Accept 2017-07-08T06:20:39Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_security_groups.xml0000664000175000017500000000113613535474530031140 0ustar kamikami00000000000000 1 1 10 cn-qingdao 7F154B0C-2594-416D-B546-75021185A6DA 2015-06-26T08:35:30Z sg-28ou0f3xa sg-28ou0f3xa System created security group. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_snapshots.xml0000664000175000017500000000133113535474530027711 0ustar kamikami00000000000000 1 1 10 09CAE6FF-B864-4104-BBF4-FE1EF08066A6 2016-01-05T11:12:42Z progressing sys-snapshot-20160108 system d-28x069z28 s-28n9lltbf 20 0% none apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/describe_zones.xml0000664000175000017500000000322113535474530027025 0ustar kamikami00000000000000 CE75D5FB-C343-47DB-882D-E0709D95D61E IoOptimized Instance Disk ecs.m2.medium ecs.m1.medium ecs.s2.xlarge ecs.t1.xsmall ecs.s2.large ecs.s2.2xlarge ecs.s3.medium ecs.m1.xlarge ecs.s1.small ecs.s1.large ecs.c2.xlarge ecs.c2.large ecs.s3.large ecs.c1.small ecs.m2.xlarge ecs.c2.medium ecs.t1.small ecs.c1.large ecs.s2.small ecs.s1.medium cn-qingdao-b 青岛可用区B cloud_ssd ephemeral cloud apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/destroy_node_describe_instances.xml0000664000175000017500000000353213535474530032441 0ustar kamikami00000000000000 1 1 10 CA75EE06-D5F7-433C-870B-5042EED6C1DC ubuntu1404_64_20G_aliaegis_20150325.vhd 10.163.197.74 ecs.t1 i-28n7dkvov -1 cn-qingdao-b PayByTraffic ca0122d9-374d-4fce-9fc0-71f7c3eaf1c3 false 1024 1 1 true sg-28ou0f3xa iZ28n7dkvovZ classic 114.215.124.73 iZ28n7dkvovZ ecs.t1.small 2015-12-27T07:35Z Stopped cn-qingdao PostPaid 2999-09-08T16:00Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/destroy_volume_describe_disks.xml0000664000175000017500000000265013535474530032151 0ustar kamikami00000000000000 PostPaid true true true cloud Description ubuntu1404sys 5 system i-28whl2nj2 2014-07-23T02:44:06Z ubuntu1404_64_20G_aliaegis_20150325.vhd cn-qingdao-b 2016-01-04T15:02:17Z /dev/xvda false cn-qingdao d-28zfrmo13 Available 2999-09-08T16:00Z 1 10 1 ED5CF6DD-71CA-462C-9C94-A61A78A01479 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/detach_disk.xml0000664000175000017500000000021713535474530026273 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/detach_volume_describe_disks.xml0000664000175000017500000000264513535474530031714 0ustar kamikami00000000000000 PostPaid true true true cloud Description ubuntu1404sys 5 system i-28whl2nj2 2014-07-23T02:44:06Z ubuntu1404_64_20G_aliaegis_20150325.vhd cn-qingdao-b 2016-01-04T15:02:17Z /dev/xvda false cn-qingdao d-28zfrmo13 In_use 2999-09-08T16:00Z 1 10 1 ED5CF6DD-71CA-462C-9C94-A61A78A01479 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/get_image_describe_images.xml0000664000175000017500000000043613535474530031142 0ustar kamikami00000000000000 0 0 10 cn-qingdao FAD4D9B9-D75F-4A9E-BC13-991C0F06F50F apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/join_security_group_by_id.xml0000664000175000017500000000023513535474530031301 0ustar kamikami00000000000000 473469C7-AA6F-4DC5-B3DB-A3DC0DE3C83E apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/leave_security_group_by_id.xml0000664000175000017500000000023713535474530031440 0ustar kamikami00000000000000 473469C7-AA6F-4DC5-B3DB-A3DC0DE3C83E apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/modify_security_group_by_id.xml0000664000175000017500000000026713535474530031636 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/pages_describe_images.xml0000664000175000017500000000244313535474530030320 0ustar kamikami00000000000000 1 2 1 cn-qingdao FAD4D9B9-D75F-4A9E-BC13-991C0F06F50F freebsd1001_64_20G_aliaegis_20150527.vhd freebsd1001_64_20G_aliaegis_20150527.vhd linux x86_64 FreeBSD 10.1 64位 /dev/xvda 20 system 100% instance 2015-06-19T07:25:42Z 1.0.0 Available freebsd1001_64_20G_aliaegis_20150527.vhd false false Freebsd 20 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/pages_describe_images_page2.xml0000664000175000017500000000244413535474530031377 0ustar kamikami00000000000000 2 2 1 cn-qingdao FAD4D9B9-D75F-4A9E-BC13-991C0F06F50F freebsd1001_64_20G_aliaegis_20150527.vhd freebsd1001_64_20G_aliaegis_20150527.vhd linux x86_64 FreeBSD 10.1 64位 /dev/xvda 20 system 100% instance 2015-06-19T07:25:42Z 1.0.0 Available freebsd1001_64_20G_aliaegis_20150527.vhd false false Freebsd 20 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/reboot_instance.xml0000664000175000017500000000022713535474530027210 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/reboot_node_describe_instances.xml0000664000175000017500000000353213535474530032242 0ustar kamikami00000000000000 1 1 10 CA75EE06-D5F7-433C-870B-5042EED6C1DC ubuntu1404_64_20G_aliaegis_20150325.vhd 10.163.197.74 ecs.t1 i-28n7dkvov -1 cn-qingdao-b PayByTraffic ca0122d9-374d-4fce-9fc0-71f7c3eaf1c3 false 1024 1 1 true sg-28ou0f3xa iZ28n7dkvovZ classic 114.215.124.73 iZ28n7dkvovZ ecs.t1.small 2015-12-27T07:35Z Running cn-qingdao PostPaid 2999-09-08T16:00Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/start_instance.xml0000664000175000017500000000022513535474530027051 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/stop_instance.xml0000664000175000017500000000022313535474530026677 0ustar kamikami00000000000000 DA38B11A-9D6D-420B-942F-95D68606C4FC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ecs/stop_node_describe_instances.xml0000664000175000017500000000353213535474530031735 0ustar kamikami00000000000000 1 1 10 CA75EE06-D5F7-433C-870B-5042EED6C1DC ubuntu1404_64_20G_aliaegis_20150325.vhd 10.163.197.74 ecs.t1 i-28n7dkvov -1 cn-qingdao-b PayByTraffic ca0122d9-374d-4fce-9fc0-71f7c3eaf1c3 false 1024 1 1 true sg-28ou0f3xa iZ28n7dkvovZ classic 114.215.124.73 iZ28n7dkvovZ ecs.t1.small 2015-12-27T07:35Z Stopped cn-qingdao PostPaid 2999-09-08T16:00Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/elastichosts/0000775000175000017500000000000013600223624025227 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/elastichosts/drives_create.json0000664000175000017500000000047713535474530030764 0ustar kamikami00000000000000{ "drive": "0012e24a-6eae-4279-9912-3432f698cec8", "encryption:cipher": "aes-xts-plain", "name": "test drive", "read:bytes": "4096", "read:requests": "1", "size": 10737418240, "status": "active", "user": "2164ce57-591c-43ee-ade5-e2fe0ee13c3e", "write:bytes": "4096", "write:requests": "1" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/elastichosts/drives_info.json0000664000175000017500000000047713535474530030454 0ustar kamikami00000000000000{ "drive": "0012e24a-6eae-4279-9912-3432f698cec8", "encryption:cipher": "aes-xts-plain", "name": "test drive", "read:bytes": "4096", "read:requests": "1", "size": 10737418240, "status": "active", "user": "2164ce57-591c-43ee-ade5-e2fe0ee13c3e", "write:bytes": "4096", "write:requests": "1" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/elastichosts/offline_servers_info.json0000664000175000017500000000064713535474530032352 0ustar kamikami00000000000000[ { "boot": "ide:0:0", "cpu": 2000, "ide:0:0": "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3", "mem": 1024, "name": "test api node", "nic:0:block": "tcp/21 tcp/22 tcp/23 tcp/25", "nic:0:dhcp": "auto", "nic:0:model": "virtio", "server": "b605ca90-c3e6-4cee-85f8-a8ebdf8f9903", "status": "stopped", "user": "2164ce57-591a-43ee-ade5-e2fe0ee13c3f", "vnc:password": "testvncpass" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/elastichosts/servers_create.json0000664000175000017500000000131613535474530031152 0ustar kamikami00000000000000{ "boot": "ide:0:0", "cpu": 2000, "ide:0:0": "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3", "ide:0:0:read:bytes": "299696128", "ide:0:0:read:requests": "73168", "ide:0:0:write:bytes": "321044480", "ide:0:0:write:requests": "78380", "mem": 1024, "name": "test api node", "nic:0:block": "tcp/21 tcp/22 tcp/23 tcp/25", "nic:0:dhcp": ["1.2.3.4", "1.2.3.5"], "nic:0:model": "virtio", "rx": 679560, "rx:packets": 644, "server": "b605ca90-c3e6-4cee-85f8-a8ebdf8f9903", "smp": 1, "started": 1280723696, "status": "active", "tx": 21271, "tx:packets": "251", "user": "2164ce57-591a-43ee-ade5-e2fe0ee13c3f", "vnc:ip": "216.151.208.174", "vnc:password": "testvncpass" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/elastichosts/servers_info.json0000664000175000017500000000141413535474530030641 0ustar kamikami00000000000000[ { "boot": "ide:0:0", "cpu": 2000, "ide:0:0": "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3", "ide:0:0:read:bytes": "299696128", "ide:0:0:read:requests": "73168", "ide:0:0:write:bytes": "321044480", "ide:0:0:write:requests": "78380", "mem": 1024, "name": "test api node", "nic:0:block": "tcp/21 tcp/22 tcp/23 tcp/25", "nic:0:dhcp": "auto", "nic:0:dhcp:ip": ["1.2.3.4", "1.2.3.5"], "nic:0:model": "virtio", "rx": 679560, "rx:packets": 644, "server": "b605ca90-c3e6-4cee-85f8-a8ebdf8f9903", "smp": 1, "started": 1280723696, "status": "active", "tx": 21271, "tx:packets": "251", "user": "2164ce57-591a-43ee-ade5-e2fe0ee13c3f", "vnc:ip": "216.151.208.174", "vnc:password": "testvncpass" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/fcu/0000775000175000017500000000000013600223624023277 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/fcu/ex_describe_instance_types.xml0000664000175000017500000000235713535474530031427 0ustar kamikami00000000000000 0556395e-4fe3-4cc1-80cb-c98b9f44ca4b og4.4xlarge 24 193273528320 412316860416 1 30 true m3.large 2 8050966528 34359738368 1 10 false oc2.8xlarge 15 68718428160 901943132160 4 30 false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/fcu/ex_describe_product_types.xml0000664000175000017500000000114013535474530031270 0ustar kamikami00000000000000 6f5287ac-2833-43d5-8675-b1ffd7b658d3 0001 Linux/UNIX 0002 Windows 0003 MapR apache-libcloud-2.8.0/libcloud/test/compute/fixtures/fcu/ex_describe_quotas.xml0000664000175000017500000000441213535474530027705 0ustar kamikami00000000000000 31ef7689-2521-445f-b634-2a5e3e66f699 true global 366866344682 vm_limit VM Limit Maximum number of VM this user can own Compute 20 1 366866344682 core_limit Core Limit Maximum number of total cores (virtual core) Compute 800 2 366866344682 memory_limit Memory Limit Maximum number of total memory (GiB) Compute 4880 7 vpc-00000000 366866344682 sg_limit Security Groups Limit Maximum number of security groups Security Groups 100 2 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/fcu/ex_get_product_type.xml0000664000175000017500000000037613535474530030116 0ustar kamikami00000000000000 e37f7876-8379-4505-8c3c-73c500e34257 0002 Windows apache-libcloud-2.8.0/libcloud/test/compute/fixtures/fcu/ex_modify_instance_keypair.xml0000664000175000017500000000032713535474530031431 0ustar kamikami00000000000000 9be5a40b-5f0a-4761-89fb-770eada0c865 true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/0000775000175000017500000000000013600223624023604 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/account_info.xml0000664000175000017500000001417113535474530027014 0ustar kamikami00000000000000 handle AB3917-GANDI products errors_for_updating product_name_does_not_match no_action_on_free_product can_release 1 date_end product_name shares_fixed autorenew errors_for_removing errors_for_releasing no_action_on_free_product not_available_resource is_in_redemption errors_for_autorenewing no_action_on_free_product duration 1y date_created 20101028T12:38:17 quantity 12 errors_for_renewing no_action_on_free_product id 11153 redemption 7 errors_for_updating no_action_on_free_product can_release 0 date_end product_name ips autorenew errors_for_removing errors_for_releasing no_action_on_free_product db_can_not_release is_in_redemption errors_for_autorenewing no_action_on_free_product duration 1m date_created 20110124T11:42:35 quantity 4 errors_for_renewing no_action_on_free_product id 11196 redemption 7 share_definition servers 1 bandwidth 5120.0 memory 256 cores 0.25 slots 0.66666666666666663 disk 8192 fullname Aymeric Barantal id 58757 resources available shares 12 servers 8 ips 4 bandwidth 51200.0 memory 2560 cores 3.0 slots 4.0 disk 89088 granted shares 12 servers 12 ips 8 bandwidth 61440 memory 3072 cores 5.0 slots 8.0 disk 98304 used servers 4 ips 4 bandwidth 10240.0 memory 512 cores 2.0 slots 4 disk 9216 expired apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/account_info_rating.xml0000664000175000017500000000213513535474530030355 0ustar kamikami00000000000000 handle AB9090-GANDI rating_enabled 1 date_credits_expiration credits 0 products average_credit_cost share_definition fullname Aymeric BARANTAL id 24 resources available granted used expired apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/datacenter_list.xml0000664000175000017500000000520213535474530027505 0ustar kamikami00000000000000 country France iso FR id 1 dc_code FR-SD2 name Equinix Paris country United States of America iso US dc_code US-BA1 id 2 name Level3 Baltimore apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_attach.xml0000664000175000017500000000202413535474530026615 0ustar kamikami00000000000000 iface_id date_updated 20110921T12:57:05 vm_id 250133 date_start disk_id 34918 source AB3917-GANDI step WAIT ip_id date_created 20110921T12:57:05 type disk_attach id 657982 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_create.xml0000664000175000017500000000172113535474530026617 0ustar kamikami00000000000000 iface_id date_updated 20120629T11:48:20 vm_id date_start disk_id 1263 source AB3917-GANDI step DONE ip_id date_created 20120629T11:48:20 type disk_create id 10895 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_create_from.xml0000664000175000017500000000202413535474530027637 0ustar kamikami00000000000000 iface_id date_updated 20110921T14:20:56 vm_id date_start disk_id 35288 source AB3917-GANDI step WAIT ip_id date_created 20110921T14:20:56 type disk_create id 657985 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_delete.xml0000664000175000017500000000172113535474530026616 0ustar kamikami00000000000000 iface_id date_updated 20120629T11:47:06 vm_id date_start disk_id 1262 source AB3917-GANDI step WAIT ip_id date_created 20120629T11:47:06 type disk_delete id 10894 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_detach.xml0000664000175000017500000000202413535474530026601 0ustar kamikami00000000000000 iface_id date_updated 20110921T12:57:35 vm_id 250133 date_start disk_id 34918 source AB3917-GANDI step WAIT ip_id date_created 20110921T12:57:35 type disk_detach id 657983 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_info.xml0000664000175000017500000000265013535474530026311 0ustar kamikami00000000000000 datacenter_id 1 name libcloud snapshot_profile kernel_version can_snapshot 1 kernel_cmdline visibility private label vms_id source state created is_boot_disk 0 date_updated 20120629T11:49:00 date_created 20120629T11:48:20 type data id 1263 size 1024 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_list.xml0000664000175000017500000000767113535474530026341 0ustar kamikami00000000000000 datacenter_id 1 name disk_libcloud2 kernel_version 2.6.32 can_snapshot 0 visibility private label Debian 5 vms_id source 23351 state created is_boot_disk 0 date_updated 20101116T10:51:59 date_created 20101028T13:52:38 type data id 34918 size 3072 datacenter_id 1 name test1 kernel_version 2.6.32 can_snapshot visibility private label Debian 5 vms_id 250133 source 23351 state created is_boot_disk 1 date_updated 20110120T15:02:01 date_created 20110120T14:57:55 type data id 34951 size 3072 datacenter_id 1 name test_disk kernel_version 2.6.32 can_snapshot 1 visibility private label Debian 5 vms_id 250288 source 23351 state created is_boot_disk 1 date_updated 20110325T16:31:11 date_created 20110324T17:14:06 type data id 35170 size 3072 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/disk_update.xml0000664000175000017500000000202413535474530026633 0ustar kamikami00000000000000 iface_id date_updated 20110921T14:23:10 vm_id date_start disk_id 34951 source AB3917-GANDI step WAIT ip_id date_created 20110921T14:23:10 type disk_update id 657987 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/iface_attach.xml0000664000175000017500000000202413535474530026732 0ustar kamikami00000000000000 iface_id 7857 date_updated 20110921T12:49:35 vm_id 250133 date_start disk_id source AB3917-GANDI step WAIT ip_id date_created 20110921T12:49:35 type iface_attach id 657980 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/iface_detach.xml0000664000175000017500000000202413535474530026716 0ustar kamikami00000000000000 iface_id 7857 date_updated 20110921T12:53:29 vm_id 250133 date_start disk_id source AB3917-GANDI step WAIT ip_id date_created 20110921T12:53:29 type iface_detach id 657981 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/iface_list.xml0000664000175000017500000000370413535474530026447 0ustar kamikami00000000000000 date_updated 20110120T14:58:44 vm_id 250133 bandwidth 5120.0 datacenter_id 1 state used num 0 ips_id 9256 9294 date_created 20110120T14:57:55 type public id 7857 date_updated 20110324T17:14:16 vm_id 250288 bandwidth 5192.0 datacenter_id 1 state used num 0 ips_id 9298 9508 date_created 20110324T17:14:06 type public id 8019 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/image_list_dc0.xml0000664000175000017500000006214713535474530027216 0ustar kamikami00000000000000 date_updated 20100928T10:41:38 disk_id 34198 label GandiOS datacenter_id 1 visibility all os_arch x86-32 date_created 20070101T00:00:00 author_id 248842 id 2 date_updated 20100811T16:30:06 disk_id 11233 label Mandriva 2008.0 datacenter_id 1 visibility all os_arch x86-32 date_created 20070101T00:00:00 author_id 248842 id 3 date_updated 20100811T16:30:06 disk_id 11235 label Centos 5 datacenter_id 1 visibility all os_arch x86-32 date_created 20070101T00:00:00 author_id 248842 id 4 date_updated 20100811T16:30:06 disk_id 11236 label Fedora Core 7 datacenter_id 1 visibility all os_arch x86-32 date_created 20070101T00:00:00 author_id 248842 id 5 date_updated 20100811T16:30:06 disk_id 11237 label Open SUSE 10.3 datacenter_id 1 visibility all os_arch x86-32 date_created 20070101T00:00:00 author_id 248842 id 6 date_updated 20100811T16:30:06 disk_id 11238 label Debian 4 datacenter_id 1 visibility all os_arch x86-32 date_created 20070101T00:00:00 author_id 248842 id 7 date_updated 20100811T16:30:06 disk_id 11239 label Fedora Core 8 datacenter_id 1 visibility all os_arch x86-32 date_created 20080101T00:00:00 author_id 248842 id 8 date_updated 20100811T16:30:06 disk_id 11240 label Open SUSE 11.0 datacenter_id 1 visibility all os_arch x86-32 date_created 20080101T00:00:00 author_id 248842 id 9 date_updated 20100811T16:30:06 disk_id 11241 label Mandriva 2008.1 datacenter_id 1 visibility all os_arch x86-32 date_created 20080101T00:00:00 author_id 248842 id 10 date_updated 20100811T16:30:06 disk_id 11242 label Ubuntu 8.04 datacenter_id 1 visibility all os_arch x86-32 date_created 20080101T00:00:00 author_id 248842 id 11 date_updated 20100922T11:56:05 disk_id 23351 label Debian 5 datacenter_id 1 visibility all os_arch x86-32 date_created 20090101T00:00:00 author_id 248842 id 12 date_updated 20100811T16:30:06 disk_id 23352 label Ubuntu 9.04 datacenter_id 1 visibility all os_arch x86-32 date_created 20090101T00:00:00 author_id 248842 id 13 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/ip_list.xml0000664000175000017500000001232313535474530026005 0ustar kamikami00000000000000 reverse xvm-6-186.ghst.net iface_id 7857 date_updated 20110120T14:57:55 ip 10.5.6.186 datacenter_id 1 state created num 0 version 4 date_created 20101028T12:49:11 id 9256 reverse xvm6-fe37-9f7b.ghst.net iface_id 7857 date_updated 20110120T14:58:44 ip 2001:4b98:dc0:543:216:3eff:fe37:9f7b datacenter_id 1 state created num 1 version 6 date_created 20110120T14:58:44 id 9294 reverse xvm-6-179.ghst.net iface_id 7861 date_updated 20110124T15:53:44 ip 10.5.6.179 datacenter_id 1 state created num 0 version 4 date_created 20110124T11:43:17 id 9298 reverse xvm6-fea8-3724.ghst.net iface_id 7861 date_updated 20110124T15:54:44 ip 2001:4b98:dc0:543:216:3eff:fea8:3724 datacenter_id 1 state created num 1 version 6 date_created 20110124T15:54:44 id 9301 reverse iface_id date_updated 20110217T17:39:39 ip datacenter_id 1 state being_created num version 4 date_created 20110217T17:39:39 id 9323 reverse xvm-6-26.ghst.net iface_id date_updated 20110225T11:59:55 ip 10.5.6.26 datacenter_id 1 state created num 0 version 4 date_created 20110224T16:46:33 id 9332 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/operation_info.xml0000664000175000017500000000157713535474530027366 0ustar kamikami00000000000000 date_updated 20110324T15:49:50 last_error date_start source AB3917-GANDI step DONE eta 39 date_created 20110324T15:49:32 type vm_delete id 637366 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/ssh_delete.xml0000664000175000017500000000022213535474530026454 0ustar kamikami00000000000000 1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/ssh_info.xml0000664000175000017500000000155313535474530026155 0ustar kamikami00000000000000 fingerprint a6:1f:b8:b4:19:91:99:d8:af:ab:d6:17:72:8b:d1:6c name testkey value ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaCXFxl0cPZa+PkXSaux/9Sfn4J81eNJ4f/ZkjdIlmLJVYFUKbpC16eEwXYEfw/QBAZFPODCDQOFAZdgajO572y9scp09F7L7Rhwrw7DYu8STMIBz0XBIO8eOUyu5hVRpxaZGDih9B99e1hITTGFg+BveAmrdB8CPtygKo/fUmaamrocZBrD1betaLTC0i6/DVz7YAbR0CleZLlaBogqVhqmS0TB4J67aG2vvq1MjyOixQY5Ab4aXo4Dz1jd7oqCGCKCO9oKAG0ok94foxkfnCmfRrnfWzOA7SFWjUs65SOrGYZghspDcbJ9vA4ZkUuWJXPPvLVgsI8aHwkezJPD8Th root@testhost id 10 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/ssh_list.xml0000664000175000017500000000070613535474530026174 0ustar kamikami00000000000000 fingerprint a6:1f:b8:b4:19:91:99:d8:af:ab:d6:17:72:8b:d1:6c id 10 name testkey apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/vm_create_from.xml0000664000175000017500000000561413535474530027337 0ustar kamikami00000000000000 iface_id date_updated 20110324T17:14:06 type disk_create date_start disk_id 35170 source AB3917-GANDI step WAIT ip_id date_created 20110324T17:14:06 vm_id id 637370 iface_id 8019 date_updated 20110324T17:14:06 vm_id date_start disk_id source AB3917-GANDI step WAIT ip_id 9298 date_created 20110324T17:14:06 type iface_create id 637371 iface_id date_updated 20110324T17:14:07 type vm_create date_start disk_id source AB3917-GANDI step WAIT ip_id date_created 20110324T17:14:07 vm_id 250288 id 637372 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/vm_delete.xml0000664000175000017500000000202313535474530026302 0ustar kamikami00000000000000 iface_id date_updated 20110324T15:49:32 vm_id 250136 date_start disk_id source AB3917-GANDI step WAIT ip_id date_created 20110324T15:49:32 type vm_delete id 637366 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/vm_info.xml0000664000175000017500000001545513535474530026010 0ustar kamikami00000000000000 memory 256 hostname test2 console 0 description triggers date_updated 20110120T15:25:07 disks datacenter_id 1 name test2 kernel_version 2.6.32 can_snapshot kernel_cmdline root /dev/xvda1 ro 1 console xvc0 nosep 1 visibility private label Debian 5 vms_id 250133 source 23351 state running is_boot_disk 1 date_updated 20110120T15:02:01 date_created 20110120T14:57:55 type data id 34951 size 3072 disks_id 34951 datacenter_id 1 state running flex_shares 0 ai_active 0 vm_max_memory 2048 ifaces date_updated 20110120T14:58:44 vm_id 250133 bandwidth 5120.0 datacenter_id 1 ips reverse xvm-6-186.ghst.net iface_id 7857 date_updated 20110120T14:57:55 ip 10.5.6.186 datacenter_id 1 state created num 0 version 4 date_created 20101028T12:49:11 id 9256 reverse xvm6-fe37-9f7b.ghst.net iface_id 7857 date_updated 20110120T14:58:44 ip 2001:4b98:dc0:543:216:3eff:fe37:9f7b datacenter_id 1 state created num 1 version 6 date_created 20110120T14:58:44 id 9294 state used num 0 ips_id 9256 9294 date_created 20110120T14:57:55 type public id 7857 cores 1 ifaces_id 7857 graph_urls vcpu http://graph.dev.hosting.gandi.net:8080//?key=88a6b2a04f21c3b9c055d73310ee37ea47fe25c7&vm_id=379&dc_id=1&stats_target=vcpu&device_number=0 vdi http://graph.dev.hosting.gandi.net:8080//?key=88a6b2a04f21c3b9c055d73310ee37ea47fe25c7&vm_id=379&dc_id=1&stats_target=vdi&device_number=0 vif http://graph.dev.hosting.gandi.net:8080//?key=88a6b2a04f21c3b9c055d73310ee37ea47fe25c7&vm_id=379&dc_id=1&stats_target=vif&device_number=0 date_created 20110120T14:57:55 id 250133 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/vm_list.xml0000664000175000017500000000527513535474530026027 0ustar kamikami00000000000000 memory 256 console 0 description date_updated 20110120T15:25:07 hostname test1 disks_id 34951 datacenter_id 1 state running flex_shares 0 ai_active 0 vm_max_memory 2048 cores 1 ifaces_id 7857 date_created 20110120T14:57:55 id 250133 memory 256 console 0 description date_updated 20110225T12:09:31 hostname test2 disks_id 34954 datacenter_id 1 state halted flex_shares 0 ai_active 0 vm_max_memory 2048 cores 1 ifaces_id 7861 date_created 20110124T15:53:44 id 250136 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/vm_reboot.xml0000664000175000017500000000202313535474530026332 0ustar kamikami00000000000000 iface_id date_updated 20110325T13:18:27 vm_id 250133 date_start disk_id source AB3917-GANDI step WAIT ip_id date_created 20110325T13:18:27 type vm_reboot id 637398 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gandi/vm_stop.xml0000664000175000017500000000202113535474530026023 0ustar kamikami00000000000000 iface_id date_updated 20110325T13:19:52 vm_id 250133 date_start disk_id source AB3917-GANDI step WAIT ip_id date_created 20110325T13:19:52 type vm_stop id 637399 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/0000775000175000017500000000000013600223624023260 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/_zones_us_central1_a_instanceGroupManagers_myinstancegroup_listManagedInstances.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/_zones_us_central1_a_instanceGroupManagers_0000664000175000017500000000163313535474530034034 0ustar kamikami00000000000000{ "managedInstances": [ { "currentAction": "NONE", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/base-foo-2vld", "instanceStatus": "RUNNING" }, { "currentAction": "NONE", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/base-foo-il30", "instanceStatus": "RUNNING" }, { "currentAction": "NONE", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/base-foo-lnnr", "instanceStatus": "RUNNING" }, { "currentAction": "NONE", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/base-foo-s41w", "instanceStatus": "RUNNING" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_addresses.json0000664000175000017500000000630413535474530030320 0ustar kamikami00000000000000{ "id": "projects/project_name/aggregated/addresses", "items": { "regions/europe-west1": { "addresses": [ { "address": "192.158.29.247", "creationTimestamp": "2013-06-26T09:51:47.506-07:00", "description": "", "id": "10955781597205896134", "kind": "compute#address", "name": "libcloud-demo-europe-address", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1/addresses/libcloud-demo-europe-address", "status": "RESERVED" } ] }, "regions/us-central1": { "addresses": [ { "address": "173.255.113.20", "creationTimestamp": "2013-06-26T12:21:40.625-07:00", "description": "", "id": "01531551729918243104", "kind": "compute#address", "name": "lcaddress", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", "status": "RESERVED" }, { "address": "108.59.82.4", "creationTimestamp": "2013-06-26T09:48:31.184-07:00", "description": "", "id": "17634862894218443422", "kind": "compute#address", "name": "libcloud-demo-address", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/libcloud-demo-address", "status": "RESERVED" }, { "address": "173.255.114.104", "creationTimestamp": "2013-06-04T16:28:43.764-07:00", "description": "", "id": "11879548153827627972", "kind": "compute#address", "name": "testaddress", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/testaddress", "status": "RESERVED" } ] }, "regions/us-central2": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/us-central2" } ], "message": "There are no results for scope 'regions/us-central2' on this page." } }, "global": { "addresses": [ { "address": "173.99.99.99", "creationTimestamp": "2013-06-26T12:21:40.625-07:00", "description": "", "id": "01531551729918243104", "kind": "compute#address", "name": "lcaddressglobal", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses/lcaddressglobal", "status": "RESERVED" } ] } }, "kind": "compute#addressAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/addresses" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_autoscalers.json0000664000175000017500000002140213535474530030664 0ustar kamikami00000000000000{ "items": { "regions/asia-east1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/asia-east1" } ], "message": "There are no results for scope 'regions/asia-east1' on this page." } }, "regions/europe-west1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/europe-west1" } ], "message": "There are no results for scope 'regions/europe-west1' on this page." } }, "regions/us-central1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/us-central1" } ], "message": "There are no results for scope 'regions/us-central1' on this page." } }, "regions/us-east1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/us-east1" } ], "message": "There are no results for scope 'regions/us-east1' on this page." } }, "regions/us-west1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/us-west1" } ], "message": "There are no results for scope 'regions/us-west1' on this page." } }, "zones/asia-east1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/asia-east1-a" } ], "message": "There are no results for scope 'zones/asia-east1-a' on this page." } }, "zones/asia-east1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/asia-east1-b" } ], "message": "There are no results for scope 'zones/asia-east1-b' on this page." } }, "zones/asia-east1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/asia-east1-c" } ], "message": "There are no results for scope 'zones/asia-east1-c' on this page." } }, "zones/europe-west1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/europe-west1-b" } ], "message": "There are no results for scope 'zones/europe-west1-b' on this page." } }, "zones/europe-west1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/europe-west1-c" } ], "message": "There are no results for scope 'zones/europe-west1-c' on this page." } }, "zones/europe-west1-d": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/europe-west1-d" } ], "message": "There are no results for scope 'zones/europe-west1-d' on this page." } }, "zones/us-central1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-central1-a" } ], "message": "There are no results for scope 'zones/us-central1-a' on this page." } }, "zones/us-central1-b": { "autoscalers": [ { "autoscalingPolicy": { "coolDownPeriodSec": 60, "cpuUtilization": { "utilizationTarget": 0.6 }, "maxNumReplicas": 10, "minNumReplicas": 2 }, "creationTimestamp": "2016-07-20T10:29:22.850-07:00", "id": "7161434716533557789", "kind": "compute#autoscaler", "name": "my-autoscaler", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/autoscalers/my-autoscaler", "target": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instanceGroupManagers/myinstancegroup", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" } ] }, "zones/us-central1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-central1-c" } ], "message": "There are no results for scope 'zones/us-central1-c' on this page." } }, "zones/us-central1-f": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-central1-f" } ], "message": "There are no results for scope 'zones/us-central1-f' on this page." } }, "zones/us-east1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-east1-b" } ], "message": "There are no results for scope 'zones/us-east1-b' on this page." } }, "zones/us-east1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-east1-c" } ], "message": "There are no results for scope 'zones/us-east1-c' on this page." } }, "zones/us-east1-d": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-east1-d" } ], "message": "There are no results for scope 'zones/us-east1-d' on this page." } }, "zones/us-west1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-west1-a" } ], "message": "There are no results for scope 'zones/us-west1-a' on this page." } }, "zones/us-west1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-west1-b" } ], "message": "There are no results for scope 'zones/us-west1-b' on this page." } } }, "kind": "compute#autoscalerAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/autoscalers" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_disks.json0000664000175000017500000003421413577507766027477 0ustar kamikami00000000000000{ "id": "projects/project_name/aggregated/disks", "items": { "zones/europe-west1-a": { "disks": [ { "creationTimestamp": "2013-12-13T10:43:33.753-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "0819226106922408217", "kind": "compute#disk", "name": "libcloud-demo-europe-boot-disk", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-boot-disk", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }, { "creationTimestamp": "2013-12-13T10:43:20.420-08:00", "id": "30789070506648158", "kind": "compute#disk", "name": "libcloud-demo-europe-attach-disk", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-attach-disk", "sizeGb": "1", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }, { "creationTimestamp": "2013-12-13T10:43:07.390-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "01221310665639400697", "kind": "compute#disk", "name": "libcloud-demo-europe-np-node", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-np-node", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }, { "creationTimestamp": "2013-12-13T10:43:53.598-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "17495188440080825940", "kind": "compute#disk", "name": "libcloud-demo-europe-multiple-nodes-000", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-multiple-nodes-000", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" } ] }, "zones/europe-west1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/europe-west1-b" } ], "message": "There are no results for scope 'zones/europe-west1-b' on this page." } }, "zones/us-central1-a": { "disks": [ { "creationTimestamp": "2013-12-13T10:45:20.308-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "0265567475385851075", "kind": "compute#disk", "name": "node-name", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-standard", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", "sizeGb": "25", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }, { "creationTimestamp": "2013-12-13T10:45:42.139-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "08045379695757218000", "kind": "compute#disk", "name": "lcdisk", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-ssd", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "labelFingerprint": "42WmSpB8rSM=", "labels": { "one": "1", "two": "2", "three": "3" }, "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567789", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }, { "creationTimestamp": "2013-12-13T10:54:07.687-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "08045379695757218002", "kind": "compute#disk", "name": "lcnode-000", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-standard", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcnode-000", "sizeGb": "25", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567789", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }, { "creationTimestamp": "2013-12-13T10:54:07.687-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "08045379695757218000", "kind": "compute#disk", "name": "lcnode-001", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-standard", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcnode-001", "sizeGb": "25", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567791", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ] }, "zones/us-central1-b": { "disks": [ { "creationTimestamp": "2013-09-04T11:03:54.122-07:00", "description": "Persistent boot disk created from https://www.googleapis.com/compute/v1beta15/projects/debian-cloud/global/images/debian-7-wheezy-v20130723.", "id": "8658241308250794904", "kind": "compute#disk", "name": "test1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/test1", "sizeGb": "10", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" }, { "creationTimestamp": "2013-12-13T10:54:07.687-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "08045379695757218001", "kind": "compute#disk", "name": "libcloud-lb-demo-www-000", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/diskTypes/pd-standard", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/libcloud-lb-demo-www-000", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567791", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" }, { "creationTimestamp": "2013-12-13T10:54:07.687-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "08045379695757218001", "kind": "compute#disk", "name": "libcloud-lb-demo-www-001", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/diskTypes/pd-standard", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/libcloud-lb-demo-www-001", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567791", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" } ] }, "zones/us-central2-a": { "disks": [ { "creationTimestamp": "2013-12-13T10:41:59.430-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "3371304879167251249", "kind": "compute#disk", "name": "libcloud-demo-boot-disk", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-boot-disk", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "creationTimestamp": "2013-12-13T10:42:15.355-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "12650345960824309663", "kind": "compute#disk", "name": "libcloud-demo-multiple-nodes-000", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-000", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "creationTimestamp": "2013-12-13T10:41:52.533-08:00", "id": "01867312924613359214", "kind": "compute#disk", "name": "libcloud-demo-attach-disk", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-attach-disk", "sizeGb": "1", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "creationTimestamp": "2013-12-13T10:42:15.949-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "12498700959701905851", "kind": "compute#disk", "name": "libcloud-demo-multiple-nodes-001", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-001", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "creationTimestamp": "2013-12-13T10:41:44.063-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "345757781195247006", "kind": "compute#disk", "name": "libcloud-demo-np-node", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-np-node", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "creationTimestamp": "2013-12-13T10:45:42.139-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "08045379695757218000", "kind": "compute#disk", "name": "lcdisk", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/diskTypes/pd-ssd", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/lcdisk", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567789", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" } ] } }, "kind": "compute#diskAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/disks" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_disktypes.json0000664000175000017500000001076313535474530030366 0ustar kamikami00000000000000{ "kind": "compute#diskTypeAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/diskTypes", "items": { "zones/us-central1-a": { "diskTypes": [ { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-ssd", "description": "SSD Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-ssd", "defaultDiskSizeGb": "100" }, { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "local-ssd", "description": "Local SSD", "validDiskSize": "375GB-375", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/local-ssd", "defaultDiskSizeGb": "375" }, { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.530-07:00", "name": "pd-standard", "description": "Standard Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-standard", "defaultDiskSizeGb": "500" } ] }, "zones/us-central1-b": { "diskTypes": [ { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-ssd", "description": "SSD Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/diskTypes/pd-ssd", "defaultDiskSizeGb": "100" }, { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.530-07:00", "name": "pd-standard", "description": "Standard Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/diskTypes/pd-standard", "defaultDiskSizeGb": "500" } ] }, "zones/europe-west1-a": { "diskTypes": [ { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-ssd", "description": "SSD Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/diskTypes/pd-ssd", "defaultDiskSizeGb": "100" }, { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.530-07:00", "name": "pd-standard", "description": "Standard Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/diskTypes/pd-standard", "defaultDiskSizeGb": "500" } ] }, "zones/europe-west1-b": { "diskTypes": [ { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-ssd", "description": "SSD Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/diskTypes/pd-ssd", "defaultDiskSizeGb": "100" }, { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.530-07:00", "name": "pd-standard", "description": "Standard Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/diskTypes/pd-standard", "defaultDiskSizeGb": "500" } ] } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_forwardingRules.json0000664000175000017500000000447613535474530031530 0ustar kamikami00000000000000{ "id": "projects/project_name/aggregated/forwardingRules", "items": { "regions/europe-west1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/europe-west1" } ], "message": "There are no results for scope 'regions/europe-west1' on this page." } }, "regions/us-central1": { "forwardingRules": [ { "IPAddress": "108.59.86.60", "IPProtocol": "TCP", "creationTimestamp": "2013-12-13T10:51:47.602-08:00", "id": "0401221837226610637", "kind": "compute#forwardingRule", "name": "libcloud-lb-demo-lb", "portRange": "80-80", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/libcloud-lb-demo-lb", "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" }, { "IPAddress": "173.255.114.35", "IPProtocol": "TCP", "creationTimestamp": "2013-12-13T10:52:57.170-08:00", "id": "06342111469679701315", "kind": "compute#forwardingRule", "name": "lcforwardingrule", "description": "test forwarding rule", "portRange": "8000-8500", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" } ] }, "regions/us-central2": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/us-central2" } ], "message": "There are no results for scope 'regions/us-central2' on this page." } } }, "kind": "compute#forwardingRuleAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/forwardingRules" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_instanceGroupManagers.json0000664000175000017500000001556713535474530032655 0ustar kamikami00000000000000{ "kind": "compute#instanceGroupManagerAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/instanceGroupManagers", "items": { "regions/us-central1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'regions/us-central1' on this page.", "data": [ { "key": "scope", "value": "regions/us-central1" } ] } }, "regions/europe-west1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'regions/europe-west1' on this page.", "data": [ { "key": "scope", "value": "regions/europe-west1" } ] } }, "regions/us-west1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'regions/us-west1' on this page.", "data": [ { "key": "scope", "value": "regions/us-west1" } ] } }, "regions/asia-east1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'regions/asia-east1' on this page.", "data": [ { "key": "scope", "value": "regions/asia-east1" } ] } }, "regions/us-east1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'regions/us-east1' on this page.", "data": [ { "key": "scope", "value": "regions/us-east1" } ] } }, "zones/us-central1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-central1-a' on this page.", "data": [ { "key": "scope", "value": "zones/us-central1-a" } ] } }, "zones/us-central1-b": { "instanceGroupManagers": [ { "kind": "compute#instanceGroupManager", "id": "8604381270851510464", "creationTimestamp": "2016-07-18T15:54:39.153-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", "name": "myinstancegroup", "description": "my description for myinstancegroup", "instanceTemplate": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1", "instanceGroup": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instanceGroups/myinstancegroup", "baseInstanceName": "base-foo", "fingerprint": "Q21hYveq9do=", "currentActions": { "none": 4, "creating": 0, "recreating": 0, "deleting": 0, "abandoning": 0, "restarting": 0, "refreshing": 0 }, "targetSize": 4, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instanceGroupManagers/myinstancegroup" } ] }, "zones/us-central1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-central1-c' on this page.", "data": [ { "key": "scope", "value": "zones/us-central1-c" } ] } }, "zones/us-central1-f": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-central1-f' on this page.", "data": [ { "key": "scope", "value": "zones/us-central1-f" } ] } }, "zones/europe-west1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/europe-west1-b' on this page.", "data": [ { "key": "scope", "value": "zones/europe-west1-b" } ] } }, "zones/europe-west1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/europe-west1-c' on this page.", "data": [ { "key": "scope", "value": "zones/europe-west1-c" } ] } }, "zones/europe-west1-d": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/europe-west1-d' on this page.", "data": [ { "key": "scope", "value": "zones/europe-west1-d" } ] } }, "zones/us-west1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-west1-a' on this page.", "data": [ { "key": "scope", "value": "zones/us-west1-a" } ] } }, "zones/us-west1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-west1-b' on this page.", "data": [ { "key": "scope", "value": "zones/us-west1-b" } ] } }, "zones/asia-east1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/asia-east1-a' on this page.", "data": [ { "key": "scope", "value": "zones/asia-east1-a" } ] } }, "zones/asia-east1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/asia-east1-b' on this page.", "data": [ { "key": "scope", "value": "zones/asia-east1-b" } ] } }, "zones/asia-east1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/asia-east1-c' on this page.", "data": [ { "key": "scope", "value": "zones/asia-east1-c" } ] } }, "zones/us-east1-b": { "instanceGroupManagers": [ { "kind": "compute#instanceGroupManager", "id": "8588434319274454491", "creationTimestamp": "2016-07-18T10:34:44.679-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b", "name": "myinstancegroup", "instanceTemplate": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1", "instanceGroup": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b/instanceGroups/myinstancegroup", "baseInstanceName": "myinstancegroup", "fingerprint": "5bKcxzAnGOg=", "currentActions": { "none": 2, "creating": 0, "recreating": 0, "deleting": 0, "abandoning": 0, "restarting": 0, "refreshing": 0 }, "targetSize": 2, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b/instanceGroupManagers/myinstancegroup" } ] }, "zones/us-east1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-east1-c' on this page.", "data": [ { "key": "scope", "value": "zones/us-east1-c" } ] } }, "zones/us-east1-d": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-east1-d' on this page.", "data": [ { "key": "scope", "value": "zones/us-east1-d" } ] } } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_instances.json0000664000175000017500000004245113570310635030327 0ustar kamikami00000000000000{ "id": "projects/project_name/aggregated/instances", "items": { "zones/europe-west1-a": { "instances": [ { "canIpForward": false, "creationTimestamp": "2013-12-13T10:43:58.782-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-europe-multiple-nodes-000", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-multiple-nodes-000", "type": "PERSISTENT" } ], "id": "10947706194464948790", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-europe-multiple-nodes-000", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "192.158.28.252", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.122.85" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-multiple-nodes-000", "status": "RUNNING", "tags": { "fingerprint": "W7t6ZyTyIrc=", "items": [ "libcloud" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }, { "canIpForward": false, "creationTimestamp": "2013-12-13T10:43:37.267-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-europe-boot-disk", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-boot-disk", "type": "PERSISTENT" } ], "id": "517678477070693411", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-europe-persist-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.251.128.32", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.240.204" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-persist-node", "status": "RUNNING", "tags": { "fingerprint": "EbZdwVRtKyg=", "items": [ "libcloud", "newtag" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }, { "canIpForward": false, "creationTimestamp": "2013-12-13T10:43:12.706-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-europe-np-node", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-np-node", "type": "PERSISTENT" }, { "deviceName": "libcloud-demo-europe-attach-disk", "index": 1, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-attach-disk", "type": "PERSISTENT" } ], "id": "3421745795082776097", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-europe-np-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.251.128.10", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.221.125" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", "status": "RUNNING", "tags": { "fingerprint": "W7t6ZyTyIrc=", "items": [ "libcloud" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" } ] }, "zones/europe-west1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/europe-west1-b" } ], "message": "There are no results for scope 'zones/europe-west1-b' on this page." } }, "zones/us-central1-a": { "instances": [ { "canIpForward": false, "creationTimestamp": "2013-12-13T10:45:23.351-08:00", "disks": [ { "boot": true, "deviceName": "persistent-disk-0", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", "type": "PERSISTENT" } ], "id": "4006034190819017667", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "node-name", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.15", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.72.75" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "status": "RUNNING", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ] }, "zones/us-central1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "zones/us-central1-b" } ], "message": "There are no results for scope 'zones/us-central1-b' on this page." } }, "zones/us-central2-a": { "instances": [ { "canIpForward": false, "creationTimestamp": "2013-12-13T10:42:03.180-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-boot-disk", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-boot-disk", "type": "PERSISTENT" } ], "id": "2184470466384636715", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-persist-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "173.255.120.70", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.235.148" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-persist-node", "status": "RUNNING", "tags": { "fingerprint": "EbZdwVRtKyg=", "items": [ "libcloud", "newtag" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "canIpForward": false, "creationTimestamp": "2013-12-13T10:41:47.059-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-np-node", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-np-node", "type": "PERSISTENT" }, { "deviceName": "libcloud-demo-attach-disk", "index": 1, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-attach-disk", "type": "PERSISTENT" } ], "id": "18059053700460342373", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-np-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "173.255.120.58", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.45.206" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-np-node", "status": "RUNNING", "tags": { "fingerprint": "W7t6ZyTyIrc=", "items": [ "libcloud" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "canIpForward": false, "creationTimestamp": "2013-12-13T10:42:24.841-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-multiple-nodes-000", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-000", "type": "PERSISTENT" } ], "id": "4196532528539285480", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-multiple-nodes-000", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "173.255.120.211", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.218.251" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-multiple-nodes-000", "status": "RUNNING", "tags": { "fingerprint": "W7t6ZyTyIrc=", "items": [ "libcloud" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" }, { "canIpForward": false, "creationTimestamp": "2013-12-13T10:42:19.041-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-multiple-nodes-001", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-multiple-nodes-001", "type": "PERSISTENT" } ], "id": "1066146046261788296", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-multiple-nodes-001", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "173.255.120.207", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.24.29" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/instances/libcloud-demo-multiple-nodes-001", "status": "SUSPENDED", "tags": { "fingerprint": "W7t6ZyTyIrc=", "items": [ "libcloud" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" } ] } }, "kind": "compute#instanceAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/instances" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_machineTypes.json0000664000175000017500000023032213535474530030773 0ustar kamikami00000000000000{ "id": "projects/project_name/aggregated/machineTypes", "items": { "zones/europe-west1-a": { "machineTypes": [ { "creationTimestamp": "2012-11-16T11:43:17.400-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "05095504563332567951", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-4-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:48:06.087-08:00", "description": "4 vCPUs, 3.6 GB RAM", "guestCpus": 4, "id": "04759000181765218034", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-4", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:51:04.549-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-8", "state": "DEPRECATED" }, "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "02507333096579477005", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-8-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:44:25.985-08:00", "description": "8 vCPUs, 52 GB RAM", "guestCpus": 8, "id": "01717932668777642040", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-8", "zone": "europe-west1-a" }, { "creationTimestamp": "2013-04-25T13:32:49.088-07:00", "description": "1 vCPU (shared physical core) and 0.6 GB RAM", "guestCpus": 1, "id": "1133568312750571513", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 614, "name": "f1-micro", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/f1-micro", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-06-07T13:48:34.258-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "state": "DEPRECATED" }, "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", "guestCpus": 1, "id": "10583029372018866711", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1-d", "scratchDisks": [ { "diskGb": 420 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:46:10.572-08:00", "description": "2 vCPUs, 1.8 GB RAM", "guestCpus": 2, "id": "16898271314080235997", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-2", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:45:08.195-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-8", "state": "DEPRECATED" }, "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "07181827135536388552", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-8-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-06-07T13:49:19.448-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "06313284160910191442", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-2-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:49:07.563-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-4", "state": "DEPRECATED" }, "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "01151097524490134507", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-4-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:40:06.129-08:00", "description": "2 vCPUs, 13 GB RAM", "guestCpus": 2, "id": "05438694236916301519", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-2", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-06-07T13:48:56.867-07:00", "description": "2 vCPUs, 7.5 GB RAM", "guestCpus": 2, "id": "17936898073622676356", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-2", "zone": "europe-west1-a" }, { "creationTimestamp": "2013-04-25T13:32:45.550-07:00", "description": "1 vCPU (shared physical core) and 1.7 GB RAM", "guestCpus": 1, "id": "1500265464823777597", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 1740, "name": "g1-small", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/g1-small", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:40:59.630-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "00770157291441082211", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-2-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-06-07T13:49:40.050-07:00", "description": "4 vCPUs, 15 GB RAM", "guestCpus": 4, "id": "09494636486174545828", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-4", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:50:15.128-08:00", "description": "8 vCPUs, 7.2 GB RAM", "guestCpus": 8, "id": "01206886442411821831", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-8", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:42:08.983-08:00", "description": "4 vCPUs, 26 GB RAM", "guestCpus": 4, "id": "11556032176405786676", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highmem-4", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-11-16T11:47:07.825-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "15178384466070744001", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-highcpu-2-d", "zone": "europe-west1-a" }, { "creationTimestamp": "2012-06-07T13:50:05.677-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "00523085164784013586", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-4-d", "zone": "europe-west1-a" } ] }, "zones/europe-west1-b": { "machineTypes": [ { "creationTimestamp": "2012-11-16T11:43:17.400-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "05095504563332567951", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-4-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:45:08.195-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-8", "state": "DEPRECATED" }, "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "07181827135536388552", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-8-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2013-04-25T13:32:49.088-07:00", "description": "1 vCPU (shared physical core) and 0.6 GB RAM", "guestCpus": 1, "id": "1133568312750571513", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 614, "name": "f1-micro", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/f1-micro", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:40:59.630-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "00770157291441082211", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-2-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:40:06.129-08:00", "description": "2 vCPUs, 13 GB RAM", "guestCpus": 2, "id": "05438694236916301519", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-2", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:47:07.825-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "15178384466070744001", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-2-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-06-07T13:48:56.867-07:00", "description": "2 vCPUs, 7.5 GB RAM", "guestCpus": 2, "id": "17936898073622676356", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-2", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:50:15.128-08:00", "description": "8 vCPUs, 7.2 GB RAM", "guestCpus": 8, "id": "01206886442411821831", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-8", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:44:25.985-08:00", "description": "8 vCPUs, 52 GB RAM", "guestCpus": 8, "id": "01717932668777642040", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-8", "zone": "europe-west1-b" }, { "creationTimestamp": "2013-04-25T13:32:45.550-07:00", "description": "1 vCPU (shared physical core) and 1.7 GB RAM", "guestCpus": 1, "id": "1500265464823777597", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 1740, "name": "g1-small", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/g1-small", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-06-07T13:49:19.448-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "06313284160910191442", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-2-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-06-07T13:50:05.677-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "00523085164784013586", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-4-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:49:07.563-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-4", "state": "DEPRECATED" }, "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "01151097524490134507", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-4-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-06-07T13:48:34.258-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-1", "state": "DEPRECATED" }, "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", "guestCpus": 1, "id": "10583029372018866711", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1-d", "scratchDisks": [ { "diskGb": 420 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-1-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-1", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:48:06.087-08:00", "description": "4 vCPUs, 3.6 GB RAM", "guestCpus": 4, "id": "04759000181765218034", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-4", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:46:10.572-08:00", "description": "2 vCPUs, 1.8 GB RAM", "guestCpus": 2, "id": "16898271314080235997", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-2", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-06-07T13:49:40.050-07:00", "description": "4 vCPUs, 15 GB RAM", "guestCpus": 4, "id": "09494636486174545828", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-standard-4", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:51:04.549-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-8", "state": "DEPRECATED" }, "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "02507333096579477005", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highcpu-8-d", "zone": "europe-west1-b" }, { "creationTimestamp": "2012-11-16T11:42:08.983-08:00", "description": "4 vCPUs, 26 GB RAM", "guestCpus": 4, "id": "11556032176405786676", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b/machineTypes/n1-highmem-4", "zone": "europe-west1-b" } ] }, "zones/us-central1-a": { "machineTypes": [ { "creationTimestamp": "2012-06-07T13:49:40.050-07:00", "description": "4 vCPUs, 15 GB RAM", "guestCpus": 4, "id": "09494636486174545828", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:47:07.825-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "15178384466070744001", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2-d", "zone": "us-central1-a" }, { "creationTimestamp": "2013-04-25T13:32:45.550-07:00", "description": "1 vCPU (shared physical core) and 1.7 GB RAM", "guestCpus": 1, "id": "1500265464823777597", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 1740, "name": "g1-small", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/g1-small", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:49:19.448-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "06313284160910191442", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2-d", "zone": "us-central1-a" }, { "creationTimestamp": "2013-04-25T13:32:49.088-07:00", "description": "1 vCPU (shared physical core) and 0.6 GB RAM", "guestCpus": 1, "id": "1133568312750571513", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 614, "name": "f1-micro", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/f1-micro", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:49:07.563-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", "state": "DEPRECATED" }, "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "01151097524490134507", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:48:06.087-08:00", "description": "4 vCPUs, 3.6 GB RAM", "guestCpus": 4, "id": "04759000181765218034", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:40:59.630-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "00770157291441082211", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:43:17.400-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "05095504563332567951", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:45:08.195-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", "state": "DEPRECATED" }, "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "07181827135536388552", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:48:56.867-07:00", "description": "2 vCPUs, 7.5 GB RAM", "guestCpus": 2, "id": "17936898073622676356", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:48:34.258-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "state": "DEPRECATED" }, "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", "guestCpus": 1, "id": "10583029372018866711", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1-d", "scratchDisks": [ { "diskGb": 420 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:46:10.572-08:00", "description": "2 vCPUs, 1.8 GB RAM", "guestCpus": 2, "id": "16898271314080235997", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:50:15.128-08:00", "description": "8 vCPUs, 7.2 GB RAM", "guestCpus": 8, "id": "01206886442411821831", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:42:08.983-08:00", "description": "4 vCPUs, 26 GB RAM", "guestCpus": 4, "id": "11556032176405786676", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:44:25.985-08:00", "description": "8 vCPUs, 52 GB RAM", "guestCpus": 8, "id": "01717932668777642040", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:40:06.129-08:00", "description": "2 vCPUs, 13 GB RAM", "guestCpus": 2, "id": "05438694236916301519", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:50:05.677-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "00523085164784013586", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:51:04.549-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", "state": "DEPRECATED" }, "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "02507333096579477005", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8-d", "zone": "us-central1-a" } ] }, "zones/us-central1-b": { "machineTypes": [ { "creationTimestamp": "2013-04-25T13:32:45.550-07:00", "description": "1 vCPU (shared physical core) and 1.7 GB RAM", "guestCpus": 1, "id": "1500265464823777597", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 1740, "name": "g1-small", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/g1-small", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:40:59.630-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "00770157291441082211", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-2-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:51:04.549-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-8", "state": "DEPRECATED" }, "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "02507333096579477005", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-8-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:46:10.572-08:00", "description": "2 vCPUs, 1.8 GB RAM", "guestCpus": 2, "id": "16898271314080235997", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-2", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:44:25.985-08:00", "description": "8 vCPUs, 52 GB RAM", "guestCpus": 8, "id": "01717932668777642040", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-8", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:42:08.983-08:00", "description": "4 vCPUs, 26 GB RAM", "guestCpus": 4, "id": "11556032176405786676", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-4", "zone": "us-central1-b" }, { "creationTimestamp": "2013-04-25T13:32:49.088-07:00", "description": "1 vCPU (shared physical core) and 0.6 GB RAM", "guestCpus": 1, "id": "1133568312750571513", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 614, "name": "f1-micro", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/f1-micro", "zone": "us-central1-b" }, { "creationTimestamp": "2012-06-07T13:50:05.677-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "00523085164784013586", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-4-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:47:07.825-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "15178384466070744001", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-2-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:43:17.400-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "05095504563332567951", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-4-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-06-07T13:48:56.867-07:00", "description": "2 vCPUs, 7.5 GB RAM", "guestCpus": 2, "id": "17936898073622676356", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-2", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:48:06.087-08:00", "description": "4 vCPUs, 3.6 GB RAM", "guestCpus": 4, "id": "04759000181765218034", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-4", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:50:15.128-08:00", "description": "8 vCPUs, 7.2 GB RAM", "guestCpus": 8, "id": "01206886442411821831", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-8", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:49:07.563-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-4", "state": "DEPRECATED" }, "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "01151097524490134507", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highcpu-4-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:45:08.195-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-8", "state": "DEPRECATED" }, "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "07181827135536388552", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-8-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-06-07T13:49:40.050-07:00", "description": "4 vCPUs, 15 GB RAM", "guestCpus": 4, "id": "09494636486174545828", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-4", "zone": "us-central1-b" }, { "creationTimestamp": "2012-06-07T13:49:19.448-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "06313284160910191442", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-2-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-11-16T11:40:06.129-08:00", "description": "2 vCPUs, 13 GB RAM", "guestCpus": 2, "id": "05438694236916301519", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-highmem-2", "zone": "us-central1-b" }, { "creationTimestamp": "2012-06-07T13:48:34.258-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", "state": "DEPRECATED" }, "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", "guestCpus": 1, "id": "10583029372018866711", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1-d", "scratchDisks": [ { "diskGb": 420 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1-d", "zone": "us-central1-b" }, { "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", "zone": "us-central1-b" } ] }, "zones/us-central2-a": { "machineTypes": [ { "creationTimestamp": "2012-06-07T13:49:40.050-07:00", "description": "4 vCPUs, 15 GB RAM", "guestCpus": 4, "id": "09494636486174545828", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-4", "zone": "us-central2-a" }, { "creationTimestamp": "2012-06-07T13:48:56.867-07:00", "description": "2 vCPUs, 7.5 GB RAM", "guestCpus": 2, "id": "17936898073622676356", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-2", "zone": "us-central2-a" }, { "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:48:06.087-08:00", "description": "4 vCPUs, 3.6 GB RAM", "guestCpus": 4, "id": "04759000181765218034", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-4", "zone": "us-central2-a" }, { "creationTimestamp": "2013-04-25T13:32:45.550-07:00", "description": "1 vCPU (shared physical core) and 1.7 GB RAM", "guestCpus": 1, "id": "1500265464823777597", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 1740, "name": "g1-small", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/g1-small", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:47:07.825-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "15178384466070744001", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-2-d", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:40:59.630-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "00770157291441082211", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-2-d", "zone": "us-central2-a" }, { "creationTimestamp": "2013-04-25T13:32:49.088-07:00", "description": "1 vCPU (shared physical core) and 0.6 GB RAM", "guestCpus": 1, "id": "1133568312750571513", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 614, "name": "f1-micro", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/f1-micro", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:42:08.983-08:00", "description": "4 vCPUs, 26 GB RAM", "guestCpus": 4, "id": "11556032176405786676", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-4", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:51:04.549-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-8", "state": "DEPRECATED" }, "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "02507333096579477005", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-8-d", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:44:25.985-08:00", "description": "8 vCPUs, 52 GB RAM", "guestCpus": 8, "id": "01717932668777642040", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-8", "zone": "us-central2-a" }, { "creationTimestamp": "2012-06-07T13:50:05.677-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "00523085164784013586", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-4-d", "zone": "us-central2-a" }, { "creationTimestamp": "2012-06-07T13:49:19.448-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "06313284160910191442", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-2-d", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:50:15.128-08:00", "description": "8 vCPUs, 7.2 GB RAM", "guestCpus": 8, "id": "01206886442411821831", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-8", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:45:08.195-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-8", "state": "DEPRECATED" }, "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "07181827135536388552", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-8-d", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:43:17.400-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "05095504563332567951", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-4-d", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:46:10.572-08:00", "description": "2 vCPUs, 1.8 GB RAM", "guestCpus": 2, "id": "16898271314080235997", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-2", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:40:06.129-08:00", "description": "2 vCPUs, 13 GB RAM", "guestCpus": 2, "id": "05438694236916301519", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highmem-2", "zone": "us-central2-a" }, { "creationTimestamp": "2012-11-16T11:49:07.563-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-4", "state": "DEPRECATED" }, "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "01151097524490134507", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-highcpu-4-d", "zone": "us-central2-a" }, { "creationTimestamp": "2012-06-07T13:48:34.258-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1", "state": "DEPRECATED" }, "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", "guestCpus": 1, "id": "10583029372018866711", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1-d", "scratchDisks": [ { "diskGb": 420 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/machineTypes/n1-standard-1-d", "zone": "us-central2-a" } ] } }, "kind": "compute#machineTypeAggregatedList", "nextPageToken": "ChhQRVJfUFJPSkVDVF9NQUNISU5FX1RZUEUSGjYwMDUzMTk1NTY3NS5uMS1zdGFuZGFyZC04", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/machineTypes" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_subnetworks.json0000664000175000017500000000517713535474530030740 0ustar kamikami00000000000000{ "kind": "compute#subnetworkAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/subnetworks", "items": { "regions/us-central1": { "subnetworks": [ { "kind": "compute#subnetwork", "id": "4297043163355844284", "creationTimestamp": "2016-03-25T05:34:27.209-07:00", "gatewayAddress": "10.128.0.1", "name": "cf-972cf02e6ad49112", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.128.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112" } ] }, "regions/europe-west1": { "subnetworks": [ { "kind": "compute#subnetwork", "id": "447043451408125628", "creationTimestamp": "2016-03-25T05:34:27.272-07:00", "gatewayAddress": "10.132.0.1", "name": "cf-df1837b06a6f927b", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.132.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1/subnetworks/cf-df1837b06a6f927b" } ] }, "regions/asia-east1": { "subnetworks": [ { "kind": "compute#subnetwork", "id": "1240429769038270140", "creationTimestamp": "2016-03-25T05:34:27.413-07:00", "gatewayAddress": "10.140.0.1", "name": "cf-4c2da366a0381eb9", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.140.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1/subnetworks/cf-4c2da366a0381eb9" } ] }, "regions/us-east1": { "subnetworks": [ { "kind": "compute#subnetwork", "id": "648244394139881148", "creationTimestamp": "2016-03-25T05:34:27.475-07:00", "gatewayAddress": "10.142.0.1", "name": "cf-daf1e2124a902a47", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.142.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1/subnetworks/cf-daf1e2124a902a47" } ] } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_targetInstances.json0000664000175000017500000000664713535474530031513 0ustar kamikami00000000000000{ "kind": "compute#targetInstanceAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/targetInstances", "id": "projects/project_name/aggregated/targetInstances", "items": { "zones/asia-east1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/asia-east1-a' on this page.", "data": [ { "key": "scope", "value": "zones/asia-east1-a" } ] } }, "zones/asia-east1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/asia-east1-b' on this page.", "data": [ { "key": "scope", "value": "zones/asia-east1-b" } ] } }, "zones/asia-east1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/asia-east1-c' on this page.", "data": [ { "key": "scope", "value": "zones/asia-east1-c" } ] } }, "zones/europe-west1-a": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/europe-west1-a' on this page.", "data": [ { "key": "scope", "value": "zones/europe-west1-a" } ] } }, "zones/europe-west1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/europe-west1-b' on this page.", "data": [ { "key": "scope", "value": "zones/europe-west1-b" } ] } }, "zones/europe-west1-c": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/europe-west1-c' on this page.", "data": [ { "key": "scope", "value": "zones/europe-west1-c" } ] } }, "zones/us-central1-a": { "targetInstances": [ { "kind": "compute#targetInstance", "id": "8092539649535704539", "creationTimestamp": "2014-08-07T12:46:10.372-07:00", "name": "hello", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "natPolicy": "NO_NAT", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/hello" }, { "kind": "compute#targetInstance", "id": "9539205115599811578", "creationTimestamp": "2014-08-07T13:09:19.634-07:00", "name": "lctargetinstance", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "natPolicy": "NO_NAT", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/lctargetinstance" } ] }, "zones/us-central1-b": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-central1-b' on this page.", "data": [ { "key": "scope", "value": "zones/us-central1-b" } ] } }, "zones/us-central1-f": { "warning": { "code": "NO_RESULTS_ON_PAGE", "message": "There are no results for scope 'zones/us-central1-f' on this page.", "data": [ { "key": "scope", "value": "zones/us-central1-f" } ] } } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/aggregated_targetPools.json0000664000175000017500000001177513535474530030656 0ustar kamikami00000000000000{ "id": "projects/project_name/aggregated/targetPools", "items": { "regions/europe-west1": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/europe-west1" } ], "message": "There are no results for scope 'regions/europe-west1' on this page." } }, "regions/us-central1": { "targetPools": [ { "creationTimestamp": "2013-11-01T14:50:04.620-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "id": "6918395933376220338", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" ], "kind": "compute#targetPool", "name": "libcloud-lb-demo-lb-tp", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" }, { "creationTimestamp": "2013-11-01T14:51:45.822-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "id": "2277093827336176997", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" ], "kind": "compute#targetPool", "name": "lctargetpool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" }, { "creationTimestamp": "2013-11-01T12:09:45.831-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check" ], "id": "03531496913089065061", "kind": "compute#targetPool", "name": "www-pool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/www-pool", "sessionAffinity": "NONE" }, { "kind": "compute#targetPool", "id": "17914960036329768493", "creationTimestamp": "2014-11-26T08:37:28.831-08:00", "name": "backup-pool", "description": "", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/default-health-check" ], "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-002" ], "sessionAffinity": "CLIENT_IP", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/backup-pool" }, { "kind": "compute#targetPool", "id": "11474672125700394323", "creationTimestamp": "2014-11-24T12:52:13.366-08:00", "name": "lb-pool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000" ], "sessionAffinity": "NONE", "failoverRatio": 0.1, "backupPool": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/backup-pool", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lb-pool" } ] }, "regions/us-central2": { "warning": { "code": "NO_RESULTS_ON_PAGE", "data": [ { "key": "scope", "value": "regions/us-central2" } ], "message": "There are no results for scope 'regions/us-central2' on this page." } } }, "kind": "compute#targetPoolAggregatedList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/aggregated/targetPools" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/generic_disk.json0000664000175000017500000000124613535474530026617 0ustar kamikami00000000000000{ "creationTimestamp": "2013-12-13T10:54:04.074-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "3535838963674672928", "kind": "compute#disk", "name": "genericdisk", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/genericdisk", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_addresses.json0000664000175000017500000000107313535474530027464 0ustar kamikami00000000000000{ "id": "projects/project_name/global/addresses", "items": [ { "address": "173.99.99.99", "creationTimestamp": "2013-06-26T09:48:31.184-07:00", "description": "", "id": "17634862894218443422", "kind": "compute#address", "name": "lcaddressglobal", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses/lcaddressglobal", "status": "RESERVED" } ], "kind": "compute#addressList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_addresses_lcaddressglobal.json0000664000175000017500000000051513535474530032671 0ustar kamikami00000000000000{ "address": "173.99.99.99", "creationTimestamp": "2013-06-26T12:21:40.625-07:00", "description": "", "id": "01531551729918243104", "kind": "compute#address", "name": "lcaddressglobal", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses/lcaddressglobal", "status": "RESERVED" } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_addresses_lcaddressglobal_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_addresses_lcaddressglobal_delete.jso0000664000175000017500000000117413535474530034037 0ustar kamikami00000000000000{ "id": "7128783508312083402", "insertTime": "2013-06-26T12:21:44.075-07:00", "kind": "compute#operation", "name": "operation-global_addresses_lcaddressglobal_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_addresses_lcaddressglobal_delete", "startTime": "2013-06-26T12:21:44.110-07:00", "status": "PENDING", "targetId": "01531551729918243104", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses/lcaddressglobal", "user": "foo@developer.gserviceaccount.com" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_addresses_post.json0000664000175000017500000000106313535474530030530 0ustar kamikami00000000000000{ "id": "16064059851942653139", "insertTime": "2013-06-26T12:21:40.299-07:00", "kind": "compute#operation", "name": "operation-global_addresses_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_addresses_post", "startTime": "2013-06-26T12:21:40.358-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses/lcaddressglobal", "user": "foo@developer.gserviceaccount.com" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_backendServices-empty.json0000664000175000017500000000030413535474530031732 0ustar kamikami00000000000000{ "kind": "compute#backendServiceList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices", "id": "projects/project_name/global/backendServices" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_backendServices-web-service.json0000664000175000017500000000234113535474530033012 0ustar kamikami00000000000000{ "kind": "compute#backendServiceList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices", "id": "projects/project_name/global/backendServices", "items": [ { "kind": "compute#backendService", "id": "12158223670162062306", "creationTimestamp": "2014-08-14T14:37:36.728-07:00", "name": "web-service", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "backends": [ { "description": "", "group": "https://www.googleapis.com/resourceviews/v1beta1/projects/project_name/zones/us-central1-b/resourceViews/us-resources", "balancingMode": "RATE", "maxRate": 100, "capacityScaler": 1.0 }, { "description": "", "group": "https://www.googleapis.com/resourceviews/v1beta1/projects/project_name/zones/europe-west1-b/resourceViews/eu-resources", "balancingMode": "RATE", "maxRate": 100, "capacityScaler": 1.0 } ], "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check" ], "timeoutSec": 30, "port": 80, "protocol": "HTTP", "fingerprint": "Do4_wUywpJU=", "portName": "" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_backendServices_no_backends.json0000664000175000017500000000074413535474530033134 0ustar kamikami00000000000000{ "kind": "compute#backendService", "id": "12158223690162062306", "creationTimestamp": "2014-08-14T14:37:36.728-07:00", "name": "web-service", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check" ], "timeoutSec": 30, "port": 80, "protocol": "HTTP", "fingerprint": "5qm-QyYGyzw=", "portName": "" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_backendServices_post.json0000664000175000017500000000106613535474530031651 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "8150500075597870926", "name": "operation-global_backendServices_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-10T16:39:17.206-07:00", "startTime": "2014-10-10T16:39:17.613-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_backendServices_post" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_backendServices_web_service.json0000664000175000017500000000167713535474530033171 0ustar kamikami00000000000000{ "kind": "compute#backendService", "id": "1814698108461677231", "creationTimestamp": "2014-08-15T16:14:43.729-07:00", "name": "web-service", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "backends": [ { "description": "", "group": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup", "balancingMode": "RATE", "maxRate": 100, "capacityScaler": 1.0 }, { "description": "", "group": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup", "balancingMode": "RATE", "maxRate": 150, "capacityScaler": 1.0 } ], "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check" ], "timeoutSec": 30, "port": 80, "protocol": "HTTP", "fingerprint": "ha9VAg-MJ5M=", "portName": "" } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_backendServices_web_service_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_backendServices_web_service_delete.j0000664000175000017500000000116713535474530033765 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "3333333333333333333", "name": "operation_global_backendServices_web_service_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "targetId": "15555555555223232737", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-28T12:51:20.402-07:00", "startTime": "2014-10-28T12:51:20.623-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_backendServices_web_service_delete" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_custom_image_setLabels_post.json0000664000175000017500000000120513535474530033223 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setImageLabelspost", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-setImageLabels_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "PENDING", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/custom-image/setLabels", "user": "foo@developer.gserviceaccount.com" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_firewalls.json0000664000175000017500000000654613535474530027511 0ustar kamikami00000000000000{ "id": "projects/project_name/global/firewalls", "items": [ { "allowed": [ { "IPProtocol": "udp" }, { "IPProtocol": "tcp" }, { "IPProtocol": "icmp" } ], "creationTimestamp": "2013-06-25T19:50:41.630-07:00", "description": "", "id": "5399576268464751692", "kind": "compute#firewall", "name": "default-allow-internal", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/default-allow-internal", "sourceRanges": [ "10.240.0.0/16" ] }, { "allowed": [ { "IPProtocol": "tcp", "ports": [ "22" ] } ], "creationTimestamp": "2013-06-25T19:48:25.111-07:00", "description": "", "id": "8063006729705804986", "kind": "compute#firewall", "name": "default-ssh", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/default-ssh", "sourceRanges": [ "0.0.0.0/0" ] }, { "allowed": [ { "IPProtocol": "tcp", "ports": [ "3141" ] } ], "creationTimestamp": "2013-11-01T14:46:25.155-07:00", "id": "13827675544891616808", "kind": "compute#firewall", "name": "libcloud-demo-europe-firewall", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-europe-network", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/libcloud-demo-europe-firewall", "sourceRanges": [ "0.0.0.0/0" ], "sourceTags": [ "libcloud" ] }, { "allowed": [ { "IPProtocol": "tcp", "ports": [ "3141" ] } ], "creationTimestamp": "2013-11-01T14:44:31.284-07:00", "id": "1648761630208029546", "kind": "compute#firewall", "name": "libcloud-demo-firewall", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-network", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/libcloud-demo-firewall", "sourceRanges": [ "0.0.0.0/0" ], "sourceTags": [ "libcloud" ] }, { "allowed": [ { "IPProtocol": "tcp", "ports": [ "80" ] } ], "creationTimestamp": "2013-08-19T14:40:22.562-07:00", "description": "", "id": "01326795494450101956", "kind": "compute#firewall", "name": "www-firewall", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/www-firewall", "sourceRanges": [ "0.0.0.0/0" ], "targetTags": [ "www-tag" ] } ], "kind": "compute#firewallList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall-deny.json0000664000175000017500000000116513535474530032642 0ustar kamikami00000000000000{ "denied": [ { "IPProtocol": "tcp", "ports": [ "4567" ] } ], "creationTimestamp": "2013-06-26T10:04:43.773-09:00", "description": "Libcloud Deny Firewall", "direction": "INGRESS", "id": "0565629596395414123", "kind": "compute#firewall", "name": "lcfirewall-deny", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "priority": 900, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall-deny", "sourceRanges": [ "10.240.100.0/24" ], "sourceTags": [ "libcloud" ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall-egress.json0000664000175000017500000000123213535474530033166 0ustar kamikami00000000000000{ "allowed": [ { "IPProtocol": "tcp", "ports": [ "4567" ] } ], "creationTimestamp": "2013-06-26T10:05:43.773-07:00", "description": "Libcloud Egress Firewall", "direction": "EGRESS", "id": "0565629596395414122", "kind": "compute#firewall", "name": "lcfirewall-egress", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "priority": 900, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall-egress", "targetServiceAccounts": [ "lctarget@gserviceaccount.com" ], "destinationRanges": [ "8.8.8.8/32" ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall.json0000664000175000017500000000120213535474530031675 0ustar kamikami00000000000000{ "allowed": [ { "IPProtocol": "tcp", "ports": [ "4567" ] } ], "creationTimestamp": "2013-06-26T10:04:43.773-07:00", "description": "Libcloud Test Firewall", "direction": "INGRESS", "id": "0565629596395414121", "kind": "compute#firewall", "name": "lcfirewall", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "priority": 900, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", "sourceServiceAccounts": [ "lcsource@gserviceaccount.com" ], "targetTags": [ "libcloud" ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_delete.json0000664000175000017500000000116413535474530033226 0ustar kamikami00000000000000{ "id": "8983098895755095934", "insertTime": "2013-06-26T10:04:53.453-07:00", "kind": "compute#operation", "name": "operation-global_firewalls_lcfirewall_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_delete", "startTime": "2013-06-26T10:04:53.508-07:00", "status": "PENDING", "targetId": "0565629596395414121", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", "user": "897001307951@developer.gserviceaccount.com" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_firewalls_lcfirewall_put.json0000664000175000017500000000115713535474530032576 0ustar kamikami00000000000000{ "id": "6526551968265354277", "insertTime": "2013-06-26T20:52:00.355-07:00", "kind": "compute#operation", "name": "operation-global_firewalls_lcfirewall_put", "operationType": "update", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_put", "startTime": "2013-06-26T20:52:00.410-07:00", "status": "PENDING", "targetId": "10942695305090163011", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", "user": "897001307951@developer.gserviceaccount.com" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_firewalls_post.json0000664000175000017500000000106613535474530030546 0ustar kamikami00000000000000{ "id": "16789512465352307784", "insertTime": "2013-06-26T20:51:06.068-07:00", "kind": "compute#operation", "name": "operation-global_firewalls_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_post", "startTime": "2013-06-26T20:51:06.128-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", "user": "897001307951@developer.gserviceaccount.com" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_forwardingRules.json0000664000175000017500000000215313535474530030664 0ustar kamikami00000000000000{ "kind": "compute#forwardingRuleList", "id": "projects/project_name/global/forwardingRules", "items": [ { "kind": "compute#forwardingRule", "id": "16224943838916174114", "creationTimestamp": "2014-08-22T11:15:26.174-07:00", "name": "http-rule", "IPAddress": "192.0.2.1", "IPProtocol": "TCP", "portRange": "80-80", "target": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules/http-rule" }, { "kind": "compute#forwardingRule", "id": "16224943838916174115", "creationTimestamp": "2014-08-22T11:15:26.174-07:00", "name": "http-rule2", "IPAddress": "192.0.2.2", "IPProtocol": "TCP", "portRange": "80-80", "target": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules/http-rule2" } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_forwardingRules_http_rule.json0000664000175000017500000000073613535474530032757 0ustar kamikami00000000000000{ "kind": "compute#forwardingRule", "id": "16224243838919174114", "creationTimestamp": "2014-08-22T11:15:26.174-07:00", "name": "http-rule", "IPAddress": "192.0.2.1", "IPProtocol": "TCP", "portRange": "80-80", "target": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "description": "global forwarding rule", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules/http-rule" } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_forwardingRules_http_rule_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_forwardingRules_http_rule_delete.jso0000664000175000017500000000116613535474530034121 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "3333333333333333333", "name": "operation_global_forwardingRules_http_rule_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules/http-rule-test", "targetId": "16224243838919174114", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-28T10:53:13.433-07:00", "startTime": "2014-10-28T10:53:13.723-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_forwardingRules_http_rule_delete" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_forwardingRules_post.json0000664000175000017500000000106513535474530031732 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "33333333333333333333", "name": "operation_global_forwardingRules_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules/http-rule", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-27T17:10:54.102-07:00", "startTime": "2014-10-27T17:10:54.531-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_forwardingRules_post" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks.json0000664000175000017500000000327013535474530030736 0ustar kamikami00000000000000{ "id": "projects/project_name/global/httpHealthChecks", "items": [ { "checkIntervalSec": 5, "creationTimestamp": "2013-08-19T14:42:28.947-07:00", "description": "", "healthyThreshold": 2, "host": "", "id": "7660832580304455442", "kind": "compute#httpHealthCheck", "name": "basic-check", "port": 80, "requestPath": "/", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check", "timeoutSec": 5, "unhealthyThreshold": 2 }, { "checkIntervalSec": 10, "creationTimestamp": "2013-12-13T10:52:46.800-08:00", "healthyThreshold": 3, "host": "lchost", "id": "022194976205566532", "kind": "compute#httpHealthCheck", "name": "lchealthcheck", "description": "test healthcheck", "port": 9000, "requestPath": "/lc", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/lchealthcheck", "timeoutSec": 10, "unhealthyThreshold": 4 }, { "checkIntervalSec": 5, "creationTimestamp": "2013-12-13T10:51:42.762-08:00", "healthyThreshold": 2, "id": "08359377740909791076", "kind": "compute#httpHealthCheck", "name": "libcloud-lb-demo-healthcheck", "port": 80, "requestPath": "/", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck", "timeoutSec": 5, "unhealthyThreshold": 2 } ], "kind": "compute#httpHealthCheckList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_basic-check.json0000664000175000017500000000065713535474530033160 0ustar kamikami00000000000000{ "checkIntervalSec": 5, "creationTimestamp": "2013-08-19T14:42:28.947-07:00", "description": "", "healthyThreshold": 2, "host": "", "id": "7660832580304455442", "kind": "compute#httpHealthCheck", "name": "basic-check", "port": 80, "requestPath": "/", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check", "timeoutSec": 5, "unhealthyThreshold": 2 }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck.json0000664000175000017500000000072013535474530033575 0ustar kamikami00000000000000{ "checkIntervalSec": 10, "creationTimestamp": "2013-09-02T22:18:01.180-07:00", "description": "test healthcheck", "healthyThreshold": 3, "host": "lchost", "id": "06860603312991823381", "kind": "compute#httpHealthCheck", "name": "lchealthcheck", "port": 8000, "requestPath": "/lc", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/lchealthcheck", "timeoutSec": 10, "unhealthyThreshold": 4 }././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_delet0000664000175000017500000000117513535474530034007 0ustar kamikami00000000000000{ "id": "1159296103027566387", "insertTime": "2013-09-02T22:18:02.509-07:00", "kind": "compute#operation", "name": "operation-global_httpHealthChecks_lchealthcheck_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_delete", "startTime": "2013-09-02T22:18:02.558-07:00", "status": "PENDING", "targetId": "06860603312991823381", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_put.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_lchealthcheck_put.j0000664000175000017500000000116613535474530033752 0ustar kamikami00000000000000{ "id": "6717642434182216609", "insertTime": "2013-09-03T02:19:55.574-07:00", "kind": "compute#operation", "name": "operation-global_httpHealthChecks_lchealthcheck_put", "operationType": "update", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_put", "startTime": "2013-09-03T02:19:55.628-07:00", "status": "PENDING", "targetId": "0742691415598204878", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_libcloud-lb-demo-healthcheck.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_libcloud-lb-demo-he0000664000175000017500000000065713535474530033560 0ustar kamikami00000000000000{ "checkIntervalSec": 5, "creationTimestamp": "2013-09-02T22:25:44.759-07:00", "healthyThreshold": 2, "id": "16372093408499501663", "kind": "compute#httpHealthCheck", "name": "libcloud-lb-demo-healthcheck", "port": 80, "requestPath": "/", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck", "timeoutSec": 5, "unhealthyThreshold": 2 }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_httpHealthChecks_post.json0000664000175000017500000000106713535474530032005 0ustar kamikami00000000000000{ "id": "3903393118268087410", "insertTime": "2013-09-03T02:19:54.629-07:00", "kind": "compute#operation", "name": "operation-global_httpHealthChecks_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_post", "startTime": "2013-09-03T02:19:54.718-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", "user": "user@gserviceaccount.com" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_images.json0000664000175000017500000000252613535474530026760 0ustar kamikami00000000000000{ "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images", "id": "projects/project_name/global/images", "items": [ { "kind": "compute#image", "id": "7094983038334682865", "creationTimestamp": "2017-10-26T07:58:38.442-07:00", "name": "custom-image", "description": "a custom image", "sourceType": "RAW", "status": "READY", "archiveSizeBytes": "1314375168", "diskSizeGb": "10", "sourceDisk": "projects/project_name/zones/us-central1-b/disks/custom-instance", "sourceDiskId": "3436116182804197834", "family": "custom", "selfLink": "projects/project_name/global/images/custom-image", "labelFingerprint": "42WmSpB8rSM=", "labels": { "foo": "bar", "one": "1", "two": "two" }, "getResourceId": {}, "getDisplayName": {}, "getResourceType": {}, "getFullResourcePath": {} }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/custom-image", "id": "15632509721401584263", "creationTimestamp": "2014-12-09T09:26:27.234-08:00", "name": "custom-image", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "243720274", "diskSizeGb": "10" } ] } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20131014_deprecate.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20131014_dep0000664000175000017500000000123713535474530033122 0ustar kamikami00000000000000{ "status": "PENDING", "kind": "compute#operation", "name": "operation-1394594316110-4f4604ad0e708-2e4622ab", "startTime": "2014-03-11T20:18:36.194-07:00", "insertTime": "2014-03-11T20:18:36.110-07:00", "targetId": "10034929421075729520", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/debian_7_wheezy_v20131014", "operationType": "setDeprecation", "progress": 0, "id": "11223768474922166090", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-1394594316110-4f4604ad0e708-2e4622ab", "user": "user@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20131120_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_images_debian_7_wheezy_v20131120_del0000664000175000017500000000122013535474530033104 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "10762099380229198553", "name": "operation-global_images_debian7_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/debian-7-wheezy-v20131120", "targetId": "14881612020726561163", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-03-11T14:37:48.075-07:00", "startTime": "2014-03-11T14:37:48.158-07:00", "endTime": "2014-03-11T14:37:48.634-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_images_debian7_delete" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_images_family_notfound.json0000664000175000017500000000053113535474530032227 0ustar kamikami00000000000000{ "error": { "code": 404, "errors": [ { "domain": "global", "message": "The resource 'projects/project-name/global/images/family/coreos-stable' was not found", "reason": "notFound" } ], "message": "The resource 'projects/project-name/global/images/family/coreos-stable' was not found" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_images_post.json0000664000175000017500000000102313535474530030014 0ustar kamikami00000000000000{ "id": "15196339658718959621", "insertTime": "2014-03-09T21:04:31.228-07:00", "kind": "compute#operation", "name": "coreos", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_image_post", "startTime": "2014-03-09T21:04:31.291-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/coreos", "user": "897001307951@developer.gserviceaccount.com" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_instanceTemplates.json0000664000175000017500000000550013535474530031171 0ustar kamikami00000000000000{ "id": "projects/project_name/global/instanceTemplates", "items": [ { "creationTimestamp": "2016-07-18T09:53:22.323-07:00", "description": "", "id": "8161922600535111533", "kind": "compute#instanceTemplate", "name": "my-instance-template1", "properties": { "canIpForward": false, "disks": [ { "autoDelete": true, "boot": true, "deviceName": "my-instance-template1", "initializeParams": { "diskSizeGb": "10", "diskType": "pd-standard", "sourceImage": "projects/project_name/global/images/my-new-image1" }, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "type": "PERSISTENT" } ], "machineType": "n1-standard-1", "metadata": { "fingerprint": "Jt9ALJ07B8Q=", "kind": "compute#metadata" }, "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "type": "ONE_TO_ONE_NAT" } ], "network": "https://content.googleapis.com/compute/v1/projects/project_name/global/networks/default" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE", "preemptible": false }, "serviceAccounts": [ { "email": "default", "scopes": [ "https://www.googleapis.com/auth/devstorage.read_only", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring.write", "https://www.googleapis.com/auth/servicecontrol", "https://www.googleapis.com/auth/service.management" ] } ] }, "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1" } ], "kind": "compute#instanceTemplateList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_instanceTemplates_insert.json0000664000175000017500000000114113535474530032552 0ustar kamikami00000000000000{ "status": "PENDING", "kind": "compute#operation", "name": "my_instance_template1", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my_instance_template1", "operationType": "compute.instanceTemplates.insert", "progress": 50, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_instanceTemplates_my_instance_template1_insert", "user": "1264195755357-compute@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_instanceTemplates_my_instance_template1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_instanceTemplates_my_instance_templa0000664000175000017500000000416713535474530034164 0ustar kamikami00000000000000{ "creationTimestamp": "2016-07-18T09:53:22.323-07:00", "description": "", "id": "8161922600535111533", "kind": "compute#instanceTemplate", "name": "my-instance-template1", "properties": { "canIpForward": false, "disks": [ { "autoDelete": true, "boot": true, "deviceName": "my-instance-template1", "initializeParams": { "diskSizeGb": "10", "diskType": "pd-standard", "sourceImage": "projects/project_name/global/images/my-new-image1" }, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "type": "PERSISTENT" } ], "machineType": "n1-standard-1", "metadata": { "fingerprint": "Jt9ALJ07B8Q=", "kind": "compute#metadata" }, "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "type": "ONE_TO_ONE_NAT" } ], "network": "https://content.googleapis.com/compute/v1/projects/project_name/global/networks/default" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE", "preemptible": false }, "serviceAccounts": [ { "email": "default", "scopes": [ "https://www.googleapis.com/auth/devstorage.read_only", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring.write", "https://www.googleapis.com/auth/servicecontrol", "https://www.googleapis.com/auth/service.management" ] } ] }, "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1" } ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_instanceTemplates_my_instance_template_shared_network.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_instanceTemplates_my_instance_templa0000664000175000017500000000447713535474530034170 0ustar kamikami00000000000000{ "creationTimestamp": "2016-07-18T09:53:22.323-07:00", "description": "", "id": "8161922600535111533", "kind": "compute#instanceTemplate", "name": "my-instance-template_shared_network", "properties": { "canIpForward": false, "disks": [ { "autoDelete": true, "boot": true, "deviceName": "my-instance-template_shared_network", "initializeParams": { "diskSizeGb": "10", "diskType": "pd-standard", "sourceImage": "projects/project_name/global/images/my-new-image1" }, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "type": "PERSISTENT" } ], "machineType": "n1-standard-1", "metadata": { "fingerprint": "Jt9ALJ07B8Q=", "kind": "compute#metadata" }, "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "type": "ONE_TO_ONE_NAT" } ], "network": "https://www.googleapis.com/compute/v1/projects/other_name/global/networks/shared_network_for_mig", "subnetwork": "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1/subnetworks/shared_subnetwork_for_mig" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE", "preemptible": false }, "serviceAccounts": [ { "email": "default", "scopes": [ "https://www.googleapis.com/auth/devstorage.read_only", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring.write", "https://www.googleapis.com/auth/servicecontrol", "https://www.googleapis.com/auth/service.management" ] } ] }, "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template_shared_network" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks.json0000664000175000017500000000337013535474530027365 0ustar kamikami00000000000000{ "kind": "compute#networkList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks", "id": "projects/project_name/global/networks", "items": [ { "kind": "compute#network", "id": "5125152985904090792", "creationTimestamp": "2016-03-25T05:34:15.077-07:00", "name": "cf", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "autoCreateSubnetworks": true, "subnetworks": [ "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112", "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1/subnetworks/cf-daf1e2124a902a47", "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1/subnetworks/cf-4c2da366a0381eb9", "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1/subnetworks/cf-df1837b06a6f927b" ] }, { "kind": "compute#network", "id": "7887441312352916157", "creationTimestamp": "2016-04-30T10:33:06.252-07:00", "name": "custom", "description": "Custom network", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/custom", "autoCreateSubnetworks": false, "subnetworks": [ "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/subnet1" ] }, { "kind": "compute#network", "id": "2672023774255449680", "creationTimestamp": "2014-01-21T10:30:55.392-08:00", "name": "default", "description": "Default network for the project", "IPv4Range": "10.240.0.0/16", "gatewayIPv4": "10.240.0.1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_cf.json0000664000175000017500000000135013535474530030031 0ustar kamikami00000000000000{ "kind": "compute#network", "id": "5125152985904090792", "creationTimestamp": "2016-03-25T05:34:15.077-07:00", "name": "cf", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "autoCreateSubnetworks": true, "subnetworks": [ "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112", "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1/subnetworks/cf-daf1e2124a902a47", "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1/subnetworks/cf-4c2da366a0381eb9", "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1/subnetworks/cf-df1837b06a6f927b" ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_custom_network.json0000664000175000017500000000140113535474530032521 0ustar kamikami00000000000000{ "kind": "compute#network", "id": "5125152985904090792", "creationTimestamp": "2016-03-25T05:34:15.077-07:00", "name": "custom-network", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/custom-network", "autoCreateSubnetworks": false, "subnetworks": [ "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112", "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1/subnetworks/cf-daf1e2124a902a47", "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1/subnetworks/cf-4c2da366a0381eb9", "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1/subnetworks/cf-df1837b06a6f927b" ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_default.json0000664000175000017500000000046013535474530031066 0ustar kamikami00000000000000{ "IPv4Range": "10.240.0.0/16", "creationTimestamp": "2013-06-19T12:37:13.233-07:00", "gatewayIPv4": "10.240.0.1", "id": "08257021638942464470", "kind": "compute#network", "name": "default", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork.json0000664000175000017500000000062013535474530031450 0ustar kamikami00000000000000{ "IPv4Range": "10.11.0.0/16", "creationTimestamp": "2013-06-26T10:05:03.500-07:00", "gatewayIPv4": "10.11.0.1", "description": "A custom network", "id": "16211908079305042870", "kind": "compute#network", "name": "lcnetwork", "routingConfig": { "routingMode": "REGIONAL" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_lcnetwork_delete.json0000664000175000017500000000115713535474530033000 0ustar kamikami00000000000000{ "id": "4914541423567262393", "insertTime": "2013-06-26T10:05:11.102-07:00", "kind": "compute#operation", "name": "operation-global_networks_lcnetwork_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_lcnetwork_delete", "startTime": "2013-06-26T10:05:11.273-07:00", "status": "PENDING", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-europe-network.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-europe-networ0000664000175000017500000000053013535474530034020 0ustar kamikami00000000000000{ "IPv4Range": "10.10.0.0/16", "creationTimestamp": "2013-06-26T09:51:34.018-07:00", "gatewayIPv4": "10.10.0.1", "id": "13254259054875092094", "kind": "compute#network", "name": "libcloud-demo-europe-network", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-europe-network" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_libcloud-demo-network.json0000664000175000017500000000051213535474530033646 0ustar kamikami00000000000000{ "IPv4Range": "10.10.0.0/16", "creationTimestamp": "2013-06-26T09:48:15.703-07:00", "gatewayIPv4": "10.10.0.1", "id": "17172579178188075621", "kind": "compute#network", "name": "libcloud-demo-network", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/libcloud-demo-network" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_networks_post.json0000664000175000017500000000106113535474530030425 0ustar kamikami00000000000000{ "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-global_networks_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_operations_operation_setImageLabels_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_operations_operation_setImageLabels_0000664000175000017500000000120413535474530034076 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setImageLabelspost", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-setImageLabels_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "DONE", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/custom-image/setLabels", "user": "foo@developer.gserviceaccount.com" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_routes.json0000664000175000017500000000466613535474530027043 0ustar kamikami00000000000000{ "kind": "compute#routeList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes", "id": "projects/project_name/global/routes", "items": [ { "kind": "compute#route", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/default-route-17d11bbbba01ce80", "id": "15220239546867835355", "creationTimestamp": "2014-01-21T10:30:55.592-08:00", "name": "default-route-17d11bbbba01ce80", "description": "Default route to the virtual network.", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "destRange": "10.240.0.0/16", "priority": 1000, "nextHopNetwork": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default" }, { "kind": "compute#route", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/default-route-e1808a2caeaf17fb", "id": "4898173129042082424", "creationTimestamp": "2014-01-21T10:30:55.584-08:00", "name": "default-route-e1808a2caeaf17fb", "description": "Default route to the Internet.", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "destRange": "0.0.0.0/0", "priority": 1000, "nextHopGateway": "https://www.googleapis.com/compute/v1/projects/project_name/global/gateways/default-internet-gateway" }, { "kind": "compute#route", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute", "id": "14575183394193523469", "creationTimestamp": "2014-11-25T11:00:45.062-08:00", "name": "lcdemoroute", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "tags": [ "tag1", "tag2" ], "destRange": "192.168.25.0/24", "priority": 1000, "nextHopInstance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100", "warnings": [ { "code": "NEXT_HOP_CANNOT_IP_FORWARD", "message": "Next hop instance 'https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100' cannot forward ip traffic. The next hop instance must have canIpForward set.", "data": [ { "key": "instance", "value": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100" } ] } ] } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute.json0000664000175000017500000000176213535474530031437 0ustar kamikami00000000000000{ "kind": "compute#route", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute", "id": "14575183394193523469", "creationTimestamp": "2014-11-25T11:00:45.062-08:00", "name": "lcdemoroute", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "tags": [ "tag1", "tag2" ], "destRange": "192.168.25.0/24", "priority": 1000, "nextHopInstance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100", "warnings": [ { "code": "NEXT_HOP_CANNOT_IP_FORWARD", "message": "Next hop instance 'https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100' cannot forward ip traffic. The next hop instance must have canIpForward set.", "data": [ { "key": "instance", "value": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-f/instances/libcloud-100" } ] } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_routes_lcdemoroute_delete.json0000664000175000017500000000105213535474530032751 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "17322940416642455149", "name": "operation-global_routes_lcdemoroute_delete", "operationType": "destroy", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2014-11-25T11:00:44.049-08:00", "startTime": "2014-11-25T11:00:44.385-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_routes_lcdemoroute_delete" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_routes_post.json0000664000175000017500000000101513535474530030071 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "17322940416642455149", "name": "operation-global_routes_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2014-11-25T11:00:44.049-08:00", "startTime": "2014-11-25T11:00:44.385-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_routes_post" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_snapshots.json0000664000175000017500000000237213535474530027534 0ustar kamikami00000000000000{ "id": "projects/project_name/global/snapshots", "items": [ { "creationTimestamp": "2013-12-16T13:03:51.345-08:00", "description": "", "diskSizeGb": "1", "id": "17482266715940883688", "kind": "compute#snapshot", "name": "lcsnapshot", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", "sourceDisk": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "sourceDiskId": "-2511816066479461182", "status": "READY" }, { "creationTimestamp": "2013-12-16T12:48:12.557-08:00", "description": "", "diskSizeGb": "10", "id": "3341332334980930052", "kind": "compute#snapshot", "name": "libcloud-demo-snapshot", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/libcloud-demo-snapshot", "sourceDisk": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a/disks/libcloud-demo-snap-template", "sourceDiskId": "-6245698478147030397", "status": "READY" } ], "kind": "compute#snapshotList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot.json0000664000175000017500000000072413535474530031771 0ustar kamikami00000000000000{ "creationTimestamp": "2013-12-16T13:03:51.345-08:00", "description": "", "diskSizeGb": "10", "id": "17482266715940883688", "kind": "compute#snapshot", "name": "lcsnapshot", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", "sourceDisk": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "sourceDiskId": "-2511816066479461182", "status": "READY" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_snapshots_lcsnapshot_delete.json0000664000175000017500000000122613535474530033311 0ustar kamikami00000000000000{ "id": "5994251357251874363", "insertTime": "2013-12-16T13:04:03.831-08:00", "kind": "compute#operation", "name": "operation-global_snapshots_lcsnapshot_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_snapshots_lcsnapshot_delete", "startTime": "2013-12-16T13:04:03.924-08:00", "status": "PENDING", "targetId": "17482266715940883688", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_sslcertificates.json0000664000175000017500000000114313535474530030674 0ustar kamikami00000000000000{ "kind": "compute#sslCertificateList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/sslCertificates", "id": "projects/project_name/global/sslCertificates", "items": [ { "kind": "compute#sslCertificate", "id": "2064539516762881220", "creationTimestamp": "2016-08-30T10:28:11.926-07:00", "name": "example", "description": "my example ssl cert.", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/sslCertificates/example-cert", "certificate": "-----BEGIN CERTIFICATE-----\nfoobar==\n-----END CERTIFICATE-----\n" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_sslcertificates_example.json0000664000175000017500000000057113535474530032413 0ustar kamikami00000000000000{ "kind": "compute#sslCertificate", "id": "2064539516762881220", "creationTimestamp": "2016-08-30T10:28:11.926-07:00", "name": "example", "description": "my example ssl cert.", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/sslCertificates/example", "certificate": "-----BEGIN CERTIFICATE-----\nfoobar==\n-----END CERTIFICATE-----\n" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_sslcertificates_post.json0000664000175000017500000000111213535474530031735 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "5564862567931215044", "name": "operation-1472578091714-53b4d4e0f85d1-cf587a68-9d7a9200", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/sslCertificates/example", "targetId": "2064539516762881220", "status": "PENDING", "user": "1294195755358-compute@developer.gserviceaccount.com", "progress": 0, "insertTime": "2016-08-30T10:28:11.948-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_sslcertificates_post" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_targetHttpProxies.json0000664000175000017500000000170013535474530031204 0ustar kamikami00000000000000{ "kind": "compute#targetHttpProxyList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies", "id": "projects/project_name/global/targetHttpProxies", "items": [ { "kind": "compute#targetHttpProxy", "id": "2276970411930672658", "creationTimestamp": "2014-08-22T09:47:35.425-07:00", "name": "web-proxy", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "urlMap": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map" }, { "kind": "compute#targetHttpProxy", "id": "2276970411930672659", "creationTimestamp": "2014-08-22T09:47:35.425-07:00", "name": "web-proxy2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy2", "urlMap": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_targetHttpProxies_post.json0000664000175000017500000000107213535474530032253 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "3333333333333333333", "name": "operation_global_targetHttpProxies_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-27T16:22:40.726-07:00", "startTime": "2014-10-27T16:22:41.027-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_targetHttpProxies_post" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_targetHttpProxies_web_proxy.json0000664000175000017500000000054213535474530033305 0ustar kamikami00000000000000{ "kind": "compute#targetHttpProxy", "id": "2276970411950672658", "creationTimestamp": "2014-08-22T09:47:35.425-07:00", "name": "web-proxy", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "urlMap": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map" } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_targetHttpProxies_web_proxy_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_targetHttpProxies_web_proxy_delete.j0000664000175000017500000000116713535474530034113 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "33333333333333333333", "name": "operation_global_targetHttpProxies_web_proxy_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "targetId": "5243939392541625113", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-28T12:21:47.406-07:00", "startTime": "2014-10-28T12:21:47.666-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_targetHttpProxies_web_proxy_delete" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_urlMaps.json0000664000175000017500000000111513535474530027127 0ustar kamikami00000000000000{ "kind": "compute#urlMapList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps", "id": "projects/project_name/global/urlMaps", "items": [ { "kind": "compute#urlMap", "id": "4266107551250249032", "creationTimestamp": "2014-08-15T16:16:54.084-07:00", "name": "web-map", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map", "defaultService": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "fingerprint": "JiV2ACVOAlg=" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_urlMaps_post.json0000664000175000017500000000103513535474530030175 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "14014132704089638847", "name": "operation-global_urlMaps_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/test-map2", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-27T15:21:17.438-07:00", "startTime": "2014-10-27T15:21:17.631-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_urlMaps_post" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_urlMaps_web_map.json0000664000175000017500000000057713535474530030634 0ustar kamikami00000000000000{ "kind": "compute#urlMap", "id": "4266107551250249032", "creationTimestamp": "2014-08-15T16:16:54.084-07:00", "name": "web-map", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map", "defaultService": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "fingerprint": "JiV2ACVOAlg=" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/global_urlMaps_web_map_delete.json0000664000175000017500000000112213535474530032141 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "3333333333333333333", "name": "operation_global_urlMaps_web_map_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map", "targetId": "1955555555986139870", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-10-28T12:36:28.927-07:00", "startTime": "2014-10-28T12:36:29.146-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_urlMaps_web_map_delete" } ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_addresses_lcaddressglobal_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_addresses_lcadd0000664000175000017500000000117313535474530034167 0ustar kamikami00000000000000{ "id": "7128783508312083402", "insertTime": "2013-06-26T12:21:44.075-07:00", "kind": "compute#operation", "name": "operation-global_addresses_lcaddressglobal_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_addresses_lcaddressglobal_delete", "startTime": "2013-06-26T12:21:44.110-07:00", "status": "DONE", "targetId": "01531551729918243104", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses/lcaddressglobal", "user": "foo@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_addresses_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_addresses_post.0000664000175000017500000000113013535474530034154 0ustar kamikami00000000000000{ "id": "16064059851942653139", "insertTime": "2013-06-26T12:21:40.299-07:00", "kind": "compute#operation", "name": "operation-global_addresses_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_addresses_post", "startTime": "2013-06-26T12:21:40.358-07:00", "status": "DONE", "targetId": "01531551729918243104", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/addresses/lcaddressglobal", "user": "foo@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_backendServices_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_backendServices0000664000175000017500000000120613535474530034153 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "8150500072597970926", "name": "operation_global_backendServices_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "targetId": "4582947879210482708", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-10T16:39:17.206-07:00", "startTime": "2014-10-10T16:39:17.613-07:00", "endTime": "2014-10-10T16:39:18.330-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_backendServices_post" } ././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_backendServices_web_service_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_backendServices0000664000175000017500000000124313535474530034154 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "3333333333333333333", "name": "operation_global_backendServices_web_service_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/web-service", "targetId": "15555555555223232737", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-28T12:51:20.402-07:00", "startTime": "2014-10-28T12:51:20.623-07:00", "endTime": "2014-10-28T12:51:21.218-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_backendServices_web_service_delete" } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfir0000664000175000017500000000124113535474530034226 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:00.978-07:00", "id": "8983098895755095934", "insertTime": "2013-06-26T10:04:53.453-07:00", "kind": "compute#operation", "name": "operation-global_firewalls_lcfirewall_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_delete", "startTime": "2013-06-26T10:04:53.508-07:00", "status": "DONE", "targetId": "0565629596395414121", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfirewall_put.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_lcfir0000664000175000017500000000123413535474530034230 0ustar kamikami00000000000000{ "endTime": "2013-06-26T20:52:10.075-07:00", "id": "6526551968265354277", "insertTime": "2013-06-26T20:52:00.355-07:00", "kind": "compute#operation", "name": "operation-global_firewalls_lcfirewall_put", "operationType": "update", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_lcfirewall_put", "startTime": "2013-06-26T20:52:00.410-07:00", "status": "DONE", "targetId": "10942695305090163011", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_firewalls_post.0000664000175000017500000000121113535474530034167 0ustar kamikami00000000000000{ "endTime": "2013-06-26T20:51:12.108-07:00", "id": "16789512465352307784", "insertTime": "2013-06-26T20:51:06.068-07:00", "kind": "compute#operation", "name": "operation-global_firewalls_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_firewalls_post", "startTime": "2013-06-26T20:51:06.128-07:00", "status": "DONE", "targetId": "10942695305090163011", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/firewalls/lcfirewall", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_forwardingRules_http_rule_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_forwardingRules0000664000175000017500000000124213535474530034235 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "4444444444444444444", "name": "operation_global_forwardingRules_http_rule_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules/http-rule-test", "targetId": "16224243838919174114", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-28T10:53:13.433-07:00", "startTime": "2014-10-28T10:53:13.723-07:00", "endTime": "2014-10-28T10:53:16.304-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_forwardingRules_http_rule_delete" } ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_forwardingRules_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_forwardingRules0000664000175000017500000000120613535474530034235 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "44444444444444444444", "name": "operation_global_forwardingRules_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/forwardingRules/http-rule", "targetId": "16224243838919174114", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-27T17:10:54.102-07:00", "startTime": "2014-10-27T17:10:54.531-07:00", "endTime": "2014-10-27T17:10:59.466-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_forwardingRules_post" } ././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthCheck0000664000175000017500000000117413535474530034127 0ustar kamikami00000000000000{ "id": "1159296103027566387", "insertTime": "2013-09-02T22:18:02.509-07:00", "kind": "compute#operation", "name": "operation-global_httpHealthChecks_lchealthcheck_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_delete", "startTime": "2013-09-02T22:18:02.558-07:00", "status": "DONE", "targetId": "06860603312991823381", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_lchealthcheck_put.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthCheck0000664000175000017500000000124313535474530034124 0ustar kamikami00000000000000{ "endTime": "2013-09-03T02:20:02.194-07:00", "id": "6717642434182216609", "insertTime": "2013-09-03T02:19:55.574-07:00", "kind": "compute#operation", "name": "operation-global_httpHealthChecks_lchealthcheck_put", "operationType": "update", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_lchealthcheck_put", "startTime": "2013-09-03T02:19:55.628-07:00", "status": "DONE", "targetId": "0742691415598204878", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthChecks_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_httpHealthCheck0000664000175000017500000000113313535474530034122 0ustar kamikami00000000000000{ "id": "3903393118268087410", "insertTime": "2013-09-03T02:19:54.629-07:00", "kind": "compute#operation", "name": "operation-global_httpHealthChecks_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_httpHealthChecks_post", "startTime": "2013-09-03T02:19:54.718-07:00", "status": "DONE", "targetId": "0742691415598204878", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/healthChecks/lchealthcheck", "user": "user@gserviceaccount.com" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_image_post.json0000664000175000017500000000114613535474530034162 0ustar kamikami00000000000000{ "endTime": "2014-03-09T21:04:33.291-07:00", "id": "15196339658718959621", "insertTime": "2014-03-09T21:04:31.228-07:00", "kind": "compute#operation", "name": "coreos", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_image_post", "startTime": "2014-03-09T21:04:31.291-07:00", "status": "DONE", "targetId": "12551176716147327315", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/coreos", "user": "897001307951@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_images_debian7_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_images_debian7_0000664000175000017500000000121713535474530034057 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "10762099380229198553", "name": "operation-global_images_debian7_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/images/debian-7-wheezy-v20131120", "targetId": "14881612020726561163", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-03-11T14:37:48.075-07:00", "startTime": "2014-03-11T14:37:48.158-07:00", "endTime": "2014-03-11T14:37:48.634-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_images_debian7_delete" } ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_instanceTemplates_insert.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_instanceTemplat0000664000175000017500000000113713535474530034216 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "my_instance_template1", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my_instance_template1", "operationType": "compute.instanceTemplates.insert", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_instanceTemplates_my_instance_template1_insert", "user": "1264195755357-compute@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_lcnetwork_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_lcnetw0000664000175000017500000000123413535474530034311 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:12.607-07:00", "id": "4914541423567262393", "insertTime": "2013-06-26T10:05:11.102-07:00", "kind": "compute#operation", "name": "operation-global_networks_lcnetwork_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_lcnetwork_delete", "startTime": "2013-06-26T10:05:11.273-07:00", "status": "DONE", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_networks_post.j0000664000175000017500000000120413535474530034227 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-global_networks_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_networks_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "DONE", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_lcdemoroute_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_lcdemoro0000664000175000017500000000103113535474530034261 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "17322940416642455149", "name": "operation-global_route_lcdemoroute", "operationType": "destroy", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2014-11-25T11:00:44.049-08:00", "startTime": "2014-11-25T11:00:44.385-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_route_lcdemoroute" } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_routes_post.jso0000664000175000017500000000104413535474530034240 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "17322940416642455149", "name": "operation-global_routes_lcdemoroute_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/routes/lcdemoroute", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2014-11-25T11:00:44.049-08:00", "startTime": "2014-11-25T11:00:44.385-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_routes_lcdemoroute_post" } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_snapshots_lcsnapshot_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_snapshots_lcsna0000664000175000017500000000130313535474530034260 0ustar kamikami00000000000000{ "endTime": "2013-12-16T13:04:11.565-08:00", "id": "5994251357251874363", "insertTime": "2013-12-16T13:04:03.831-08:00", "kind": "compute#operation", "name": "operation-global_snapshots_lcsnapshot_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_snapshots_lcsnapshot_delete", "startTime": "2013-12-16T13:04:03.924-08:00", "status": "DONE", "targetId": "17482266715940883688", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/snapshots/lcsnapshot", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_sslcertificates_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_sslcertificates0000664000175000017500000000111113535474530034242 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "5564862567931215044", "name": "operation-1472578091714-53b4d4e0f85d1-cf587a68-9d7a9200", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/sslCertificates/example", "targetId": "2064539516762881220", "status": "DONE", "user": "1294195755358-compute@developer.gserviceaccount.com", "progress": 100, "insertTime": "2016-08-30T10:28:11.948-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_sslcertificates_post" } ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_targetHttpProxies_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_targetHttpProxi0000664000175000017500000000121213535474530034225 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "7514147734702416613", "name": "operation_global_targetHttpProxies_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "targetId": "5242670162541625113", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-27T16:22:40.726-07:00", "startTime": "2014-10-27T16:22:41.027-07:00", "endTime": "2014-10-27T16:22:41.657-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_targetHttpProxies_post" } ././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_targetHttpProxies_web_proxy_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_targetHttpProxi0000664000175000017500000000124313535474530034231 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "12025659947133083605", "name": "operation_global_targetHttpProxies_web_proxy_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/targetHttpProxies/web-proxy", "targetId": "5243939392541625113", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-28T12:21:47.406-07:00", "startTime": "2014-10-28T12:21:47.666-07:00", "endTime": "2014-10-28T12:21:48.419-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_targetHttpProxies_web_proxy_delete" } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_urlMaps_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_urlMaps_post.js0000664000175000017500000000115313535474530034164 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "14014131794489638887", "name": "operation-global_urlMaps_post", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map", "targetId": "4266107551250249032", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-27T15:21:17.438-07:00", "startTime": "2014-10-27T15:21:17.631-07:00", "endTime": "2014-10-27T15:21:18.422-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-global_urlMaps_post" } ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_urlMaps_web_map_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_global_urlMaps_web_map0000664000175000017500000000117613535474530034203 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "3333333333333333333", "name": "operation_global_urlMaps_web_map_delete", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/urlMaps/web-map", "targetId": "1955555555986139870", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-10-28T12:36:28.927-07:00", "startTime": "2014-10-28T12:36:29.146-07:00", "endTime": "2014-10-28T12:36:29.693-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation_global_urlMaps_web_map_delete" } ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_lcaddress_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ad0000664000175000017500000000140413535474530034070 0ustar kamikami00000000000000{ "id": "7128783508312083402", "insertTime": "2013-06-26T12:21:44.075-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_addresses_lcaddress_delete", "operationType": "delete", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_lcaddress_delete", "startTime": "2013-06-26T12:21:44.110-07:00", "status": "DONE", "targetId": "01531551729918243104", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_addresses_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ad0000664000175000017500000000135513535474530034075 0ustar kamikami00000000000000{ "id": "16064059851942653139", "insertTime": "2013-06-26T12:21:40.299-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_addresses_post", "operationType": "insert", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_post", "startTime": "2013-06-26T12:21:40.358-07:00", "status": "DONE", "targetId": "01531551729918243104", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000021700000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_lcforwardingrule_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_fo0000664000175000017500000000151013535474530034106 0ustar kamikami00000000000000{ "endTime": "2013-09-03T00:17:43.917-07:00", "id": "09064254309855814339", "insertTime": "2013-09-03T00:17:36.062-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", "operationType": "delete", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", "startTime": "2013-09-03T00:17:36.168-07:00", "status": "DONE", "targetId": "10901665092293158938", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_forwardingRules_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_fo0000664000175000017500000000144113535474530034111 0ustar kamikami00000000000000{ "endTime": "2013-09-03T00:17:33.965-07:00", "id": "0651769405845333112", "insertTime": "2013-09-03T00:17:25.381-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_forwardingRules_post", "operationType": "insert", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_post", "startTime": "2013-09-03T00:17:25.434-07:00", "status": "DONE", "targetId": "10901665092293158938", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_subnetworks_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_su0000664000175000017500000000137613535474530034143 0ustar kamikami00000000000000{ "id": "16064059851942653139", "insertTime": "2013-06-26T12:21:40.299-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_subnetworks_post", "operationType": "insert", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_subnetworks_post", "startTime": "2013-06-26T12:21:40.358-07:00", "status": "DONE", "targetId": "01531551729918243104", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112", "user": "897001307951@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lb_pool_setBackup_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ta0000664000175000017500000000146513535474530034117 0ustar kamikami00000000000000{ "endTime": "2013-09-03T01:29:07.021-07:00", "id": "04072826501537092633", "insertTime": "2013-09-03T01:29:03.082-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lb_pool_setBackup_post", "operationType": "setBackup", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lb_pool_setBackup_post", "startTime": "2013-09-03T01:29:03.145-07:00", "status": "DONE", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lb-pool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000022400000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ta0000664000175000017500000000152313535474530034112 0ustar kamikami00000000000000{ "endTime": "2013-09-03T01:28:49.271-07:00", "id": "17341029456963557514", "insertTime": "2013-09-03T01:28:40.774-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", "operationType": "addHealthCheck", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", "startTime": "2013-09-03T01:28:40.838-07:00", "status": "DONE", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000022100000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_addInstance_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ta0000664000175000017500000000151213535474530034110 0ustar kamikami00000000000000{ "endTime": "2013-09-03T01:29:07.021-07:00", "id": "04072826501537092633", "insertTime": "2013-09-03T01:29:03.082-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", "operationType": "addInstance", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", "startTime": "2013-09-03T01:29:03.145-07:00", "status": "DONE", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ta0000664000175000017500000000140213535474530034106 0ustar kamikami00000000000000{ "id": "13500662190763995965", "insertTime": "2013-09-03T00:51:06.799-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_delete", "operationType": "delete", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_delete", "startTime": "2013-09-03T00:51:06.840-07:00", "status": "DONE", "targetId": "13598380121688918358", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000022700000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ta0000664000175000017500000000153413535474530034114 0ustar kamikami00000000000000{ "endTime": "2013-09-03T01:28:37.095-07:00", "id": "14738174613993796821", "insertTime": "2013-09-03T01:28:32.889-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", "operationType": "removeHealthCheck", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", "startTime": "2013-09-03T01:28:32.942-07:00", "status": "DONE", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000022400000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_lctargetpool_removeInstance_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ta0000664000175000017500000000152213535474530034111 0ustar kamikami00000000000000{ "endTime": "2013-09-03T01:28:59.247-07:00", "id": "1815686149437875016", "insertTime": "2013-09-03T01:28:53.049-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", "operationType": "removeInstance", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", "startTime": "2013-09-03T01:28:53.109-07:00", "status": "DONE", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_targetPools_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_regions_us-central1_ta0000664000175000017500000000134313535474530034112 0ustar kamikami00000000000000{ "id": "7487852523793007955", "insertTime": "2013-09-03T00:51:05.064-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_post", "operationType": "insert", "progress": 100, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_post", "startTime": "2013-09-03T00:51:05.115-07:00", "status": "DONE", "targetId": "13598380121688918358", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_setCommonInstanceMetadata.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_setCommonInstanceMetad0000664000175000017500000000120513535474530034143 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setCommonInstanceMetadat", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-setCommonInstanceMetadata", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "DONE", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/setCommonInstanceMetadata", "user": "foo@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_setUsageExportBucket.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_setUsageExportBucket.j0000664000175000017500000000105013535474530034105 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "17203609782824174066", "name": "operation-setUsageExportBucket", "operationType": "setUsageExportBucket", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name", "targetId": "8116069320260064853", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2014-11-21T06:58:03.602-08:00", "startTime": "2014-11-21T06:58:04.018-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-setUsageExportBucket" } ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_europe-west1-a_instances_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_europe-west1-a_i0000664000175000017500000000205213535474530034044 0ustar kamikami00000000000000{ "error": { "errors": [ { "code": "RESOURCE_ALREADY_EXISTS", "message": "The resource 'projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node' already exists" } ] }, "httpErrorMessage": "CONFLICT", "httpErrorStatusCode": 409, "id": "1510575454210533141", "insertTime": "2013-06-26T20:57:34.366-07:00", "kind": "compute#operation", "name": "operation-zones_europe-west1-a_instances_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/operations/operation-zones_europe-west1-a_instances_post", "startTime": "2013-06-26T20:57:34.453-07:00", "status": "DONE", "targetId": "14308265828754333159", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_createSnapshot_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_di0000664000175000017500000000153613535474530034014 0ustar kamikami00000000000000{ "endTime": "2013-12-16T13:04:01.580-08:00", "id": "0158330665043557584", "insertTime": "2013-12-16T13:03:51.000-08:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", "operationType": "createSnapshot", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", "startTime": "2013-12-16T13:03:51.042-08:00", "status": "DONE", "targetId": "07494414044179227172", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_di0000664000175000017500000000135613535474530034014 0ustar kamikami00000000000000{ "id": "06887337364510109333", "insertTime": "2013-06-26T10:06:11.835-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_disks_lcdisk_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_delete", "startTime": "2013-06-26T10:06:12.006-07:00", "status": "DONE", "targetId": "16109451798967042451", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_resize_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_di0000664000175000017500000000152613570310635034005 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "4992266504414588438", "name": "operation-1562104056794-58cb9b1684c7e-8109138e-848683f7", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "resizeDisk", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/904434546113910404", "targetId": "904434546113910404", "status": "DONE", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", "progress": 100, "insertTime": "2019-07-02T14:47:37.095-07:00", "startTime": "2019-07-02T14:47:37.111-07:00", "endTime": "2019-07-02T14:47:41.991-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-1562104056794-58cb9b1684c7e-8109138e-848683f7" }././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_lcdisk_setLabels_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_di0000664000175000017500000000153113577507766034025 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "4992266504414588438", "name": "operation-zones_us-central1-a_disks_lcdisk_setLabels_post", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setLabels", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/904434546113910404", "targetId": "904434546113910404", "status": "DONE", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", "progress": 100, "insertTime": "2019-07-02T14:47:37.095-07:00", "startTime": "2019-07-02T14:47:37.111-07:00", "endTime": "2019-07-02T14:47:41.991-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_setLabels_post" }././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_disks_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_di0000664000175000017500000000141113535474530034004 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:48:25.375-07:00", "id": "0211151278250678078", "insertTime": "2013-06-26T16:48:17.403-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_disks_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_post", "startTime": "2013-06-26T16:48:17.479-07:00", "status": "DONE", "targetId": "03196637868764498730", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-000_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000146213535474530034024 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:13:36.800-07:00", "id": "3319596145594427549", "insertTime": "2013-06-26T16:13:12.903-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_lcnode-000_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-000_delete", "startTime": "2013-06-26T16:13:12.948-07:00", "status": "DONE", "targetId": "5390075309006132922", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-000", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_lcnode-001_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000146413535474530034026 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:13:56.931-07:00", "id": "17469711273432628502", "insertTime": "2013-06-26T16:13:40.579-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_lcnode-001_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-001_delete", "startTime": "2013-06-26T16:13:40.620-07:00", "status": "DONE", "targetId": "16630486471904253898", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000021300000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_attachDisk_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000150513535474530034022 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:48:31.831-07:00", "id": "7455886659787654716", "insertTime": "2013-06-26T16:48:27.691-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_attachDisk_post", "operationType": "attachDisk", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_attachDisk_post", "startTime": "2013-06-26T16:48:27.762-07:00", "status": "DONE", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000146013535474530034022 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:06:00.917-07:00", "id": "6999931397447918763", "insertTime": "2013-06-26T10:05:40.350-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_delete", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_delete", "startTime": "2013-06-26T10:05:40.405-07:00", "status": "DONE", "targetId": "07410051435384876224", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000021300000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_detachDisk_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000150513535474530034022 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:48:41.278-07:00", "id": "3921383727105838816", "insertTime": "2013-06-26T16:48:35.357-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_detachDisk_post", "operationType": "detachDisk", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_detachDisk_post", "startTime": "2013-06-26T16:48:35.398-07:00", "status": "DONE", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_reset_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000141113535474530034016 0ustar kamikami00000000000000{ "id": "10507122129283663728", "insertTime": "2013-06-26T15:03:02.766-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_reset_post", "operationType": "reset", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_reset_post", "startTime": "2013-06-26T15:03:02.813-07:00", "status": "DONE", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node-name_setTags_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000147413535474530034027 0ustar kamikami00000000000000{ "endTime": "2013-06-26T21:20:10.487-07:00", "id": "8115150846190320932", "insertTime": "2013-06-26T21:20:03.962-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_setTags_post", "operationType": "setTags", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_setTags_post", "startTime": "2013-06-26T21:20:04.103-07:00", "status": "DONE", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000022000000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_addAccessConfig_done.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000131513535474530034021 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:13:08.382-07:00", "id": "1858155812259649243", "insertTime": "2013-06-26T16:12:51.492-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node_name_addAccessConfig_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node_name_addAccessConfig_post", "startTime": "2013-06-26T16:12:51.537-07:00", "status": "DONE", "targetId": "16630486471904253898", "user": "foo@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000022000000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_addAccessConfig_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000131613535474530034022 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:13:08.382-07:00", "id": "1858155812259649243", "insertTime": "2013-06-26T16:12:51.492-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node_name_addAccessConfig_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node_name_addAccessConfig_post", "startTime": "2013-06-26T16:12:51.537-07:00", "status": "PENDING", "targetId": "16630486471904253898", "user": "foo@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_deleteAccessConfig_done.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000132313535474530034020 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:13:08.382-07:00", "id": "1858155812259649243", "insertTime": "2013-06-26T16:12:51.492-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node_name_deleteAccessConfig_post", "operationType": "delete", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node_name_deleteAccessConfig_post", "startTime": "2013-06-26T16:12:51.537-07:00", "status": "DONE", "targetId": "16630486471904253898", "user": "foo@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_node_name_deleteAccessConfig_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000132413535474530034021 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:13:08.382-07:00", "id": "1858155812259649243", "insertTime": "2013-06-26T16:12:51.492-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node_name_deleteAccessConfig_post", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node_name_deleteAccessConfig_post", "startTime": "2013-06-26T16:12:51.537-07:00", "status": "PENDING", "targetId": "16630486471904253898", "user": "foo@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_instances_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_in0000664000175000017500000000143113535474530034020 0ustar kamikami00000000000000{ "endTime": "2013-06-26T16:13:08.382-07:00", "id": "1858155812259649243", "insertTime": "2013-06-26T16:12:51.492-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_post", "startTime": "2013-06-26T16:12:51.537-07:00", "status": "DONE", "targetId": "16630486471904253898", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000021700000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_targetInstances_lctargetinstance_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_ta0000664000175000017500000000140613535474530034020 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "16305469717066123402", "name": "operation-zones_us-central1-a_targetInstances_lctargetinstance_delete", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/lctargetinstance", "targetId": "8092539649535704539", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2014-11-14T13:05:18.564-08:00", "startTime": "2014-11-14T13:05:18.868-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_targetInstances_lctargetinstance_delete" } ././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_targetInstances_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us-central1-a_ta0000664000175000017500000000127413535474530034023 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "17976948162128740230", "name": "operation-zones_us-central1-a_targetInstances_post", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/lctargetinstance", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2014-11-14T13:21:20.789-08:00", "startTime": "2014-11-14T13:21:21.118-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_targetInstances_post" } ././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_insert.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_in0000664000175000017500000000115513535474530034167 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones_us_central1_a/instanceGroups/myname", "operationType": "compute.instanceGroups.insert", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_insert", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_addInstances.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_in0000664000175000017500000000117113535474530034165 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.addInstances", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_addInstances", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000020400000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_in0000664000175000017500000000115513535474530034167 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.delete", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_delete", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_removeInstances.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_in0000664000175000017500000000117713535474530034173 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.removeInstances", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_removeInstances", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000021300000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_instanceGroups_myname_setNamedPorts.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_in0000664000175000017500000000117313535474530034167 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.setNamedPorts", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_setNamedPorts", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setLabels_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_no0000664000175000017500000000122513535474530034173 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setLabels_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setLabels_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "DONE", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name/setLabels", "user": "foo@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setMetadata_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_no0000664000175000017500000000123313535474530034172 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setMetadata_post", "operationType": "insert", "progress": 100, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setMetadata_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "DONE", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name/setMetadata", "user": "foo@developer.gserviceaccount.com" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/project.json0000664000175000017500000000357413535474530025645 0ustar kamikami00000000000000{ "kind": "compute#project", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name", "id": "8116069320260064853", "creationTimestamp": "2014-01-21T10:30:53.390-08:00", "name": "project_name", "description": "", "commonInstanceMetadata": { "kind": "compute#metadata", "fingerprint": "3zEcGBxH6Vs=", "items": [ { "key": "sshKeys", "value": "ABCDEF" }, { "key": "startup-script", "value": "#!/bin/bash\n\nAUTO_SCRIPT=$(curl -s http://metadata/computeMetadata/v1/instance/attributes/my-auto-script -H \"Metadata-Flavor: Google\")\nCHECK=${AUTO_SCRIPT:-disabled}\n\nif [ \"${CHECK}\" = \"enabled\" -a -f /etc/debian_version ]; then\n export DEBIAN_FRONTEND=noninteractive\n apt-get -q -y update\n apt-get -q -y install git vim tmux\n fi\nexit 0\n" } ] }, "quotas": [ { "metric": "SNAPSHOTS", "limit": 1000, "usage": 1 }, { "metric": "NETWORKS", "limit": 5, "usage": 3 }, { "metric": "FIREWALLS", "limit": 100, "usage": 6 }, { "metric": "IMAGES", "limit": 100, "usage": 1 }, { "metric": "STATIC_ADDRESSES", "limit": 7, "usage": 1 }, { "metric": "ROUTES", "limit": 100, "usage": 2 }, { "metric": "FORWARDING_RULES", "limit": 50, "usage": 0 }, { "metric": "TARGET_POOLS", "limit": 50, "usage": 0 }, { "metric": "HEALTH_CHECKS", "limit": 50, "usage": 1 }, { "metric": "IN_USE_ADDRESSES", "limit": 23, "usage": 0 }, { "metric": "TARGET_INSTANCES", "limit": 50, "usage": 3 }, { "metric": "TARGET_HTTP_PROXIES", "limit": 50, "usage": 0 }, { "metric": "URL_MAPS", "limit": 50, "usage": 1 }, { "metric": "BACKEND_SERVICES", "limit": 50, "usage": 1 } ], "usageExportLocation": { "bucketName": "gs://graphite-usage-reports", "reportNamePrefix": "graphite-report" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_centos-cloud_global_images.json0000664000175000017500000003711613535474530033353 0ustar kamikami00000000000000{ "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images", "id": "projects/centos-cloud/global/images", "items": [ { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20131120", "id": "11748647391859510935", "creationTimestamp": "2013-11-25T15:13:50.611-08:00", "name": "centos-6-v20131120", "description": "SCSI-enabled CentOS 6 built on 2013-11-20", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140318" }, "status": "READY", "archiveSizeBytes": "269993565", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140318", "id": "11743140967858608122", "creationTimestamp": "2014-03-19T15:01:13.388-07:00", "name": "centos-6-v20140318", "description": "CentOS 6.5 x86_64 built on 2014-03-18", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140408" }, "status": "READY", "archiveSizeBytes": "341230444", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140408", "id": "18033188469723077298", "creationTimestamp": "2014-04-09T10:31:57.518-07:00", "name": "centos-6-v20140408", "description": "CentOS 6.5 x86_64 built on 2014-04-08", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140415" }, "status": "READY", "archiveSizeBytes": "342252847", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140415", "id": "10463166969914166288", "creationTimestamp": "2014-04-22T12:05:16.927-07:00", "name": "centos-6-v20140415", "description": "CentOS 6.5 x86_64 built on 2014-04-15", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140522" }, "status": "READY", "archiveSizeBytes": "1026663807", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140522", "id": "14390164727436022001", "creationTimestamp": "2014-06-03T10:21:42.109-07:00", "name": "centos-6-v20140522", "description": "CentOS 6.5 x86_64 built on 2014-05-22", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140606" }, "status": "READY", "archiveSizeBytes": "1028292810", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140605", "id": "16310166269920012092", "creationTimestamp": "2014-06-05T11:04:45.767-07:00", "name": "centos-6-v20140605", "description": "CentOS 6.5 x86_64 built on 2014-06-05", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140606" }, "status": "READY", "archiveSizeBytes": "1028745777", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140606", "id": "6290630306542078308", "creationTimestamp": "2014-06-06T13:16:42.265-07:00", "name": "centos-6-v20140606", "description": "CentOS 6.5 x86_64 built on 2014-06-06", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140619" }, "status": "READY", "archiveSizeBytes": "1028757792", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140619", "id": "3614861379648377676", "creationTimestamp": "2014-06-24T13:28:11.552-07:00", "name": "centos-6-v20140619", "description": "CentOS 6.5 x86_64 built on 2014-06-19", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140718" }, "status": "READY", "archiveSizeBytes": "1029860991", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140718", "id": "16259951858818091437", "creationTimestamp": "2014-07-24T09:02:18.298-07:00", "name": "centos-6-v20140718", "description": "CentOS 6.5 x86_64 built on 2014-07-18", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140924" }, "status": "READY", "archiveSizeBytes": "1031630715", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140924", "id": "13087714199807465700", "creationTimestamp": "2014-09-24T19:21:53.421-07:00", "name": "centos-6-v20140924", "description": "CentOS 6.5 x86_64 built on 2014-09-24", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140926" }, "status": "READY", "archiveSizeBytes": "1040237724", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20140926", "id": "2580521871229876339", "creationTimestamp": "2014-09-29T09:26:44.364-07:00", "name": "centos-6-v20140926", "description": "CentOS 6.5 x86_64 built on 2014-09-26", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141007" }, "status": "READY", "archiveSizeBytes": "1040082792", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141007", "id": "3381938258505751441", "creationTimestamp": "2014-10-16T14:52:10.720-07:00", "name": "centos-6-v20141007", "description": "CentOS 6.5 x86_64 built on 2014-10-07", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141016" }, "status": "READY", "archiveSizeBytes": "1040311077", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141016", "id": "2365868823508405185", "creationTimestamp": "2014-10-17T16:46:57.144-07:00", "name": "centos-6-v20141016", "description": "CentOS 6.5 x86_64 built on 2014-10-16", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141021" }, "status": "READY", "archiveSizeBytes": "1040361036", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141021", "id": "10836725743769588052", "creationTimestamp": "2014-10-22T18:24:03.632-07:00", "name": "centos-6-v20141021", "description": "CentOS 6.5 x86_64 built on 2014-10-21", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141108" }, "status": "READY", "archiveSizeBytes": "1040416587", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141108", "id": "4053040619898291132", "creationTimestamp": "2014-11-10T14:25:17.670-08:00", "name": "centos-6-v20141108", "description": "CentOS 6.6 x86_64 built on 2014-11-08", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141205" }, "status": "READY", "archiveSizeBytes": "1049466963", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-6-v20141205", "id": "17207937043950962086", "creationTimestamp": "2014-12-08T16:14:54.943-08:00", "name": "centos-6-v20141205", "description": "CentOS 6.6 x86_64 built on 2014-12-05", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1056393081", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20140903", "id": "4568702763004249623", "creationTimestamp": "2014-09-04T09:50:19.966-07:00", "name": "centos-7-v20140903", "description": "CentOS 7.0 x86_64 built on 2014-09-03", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20140924" }, "status": "READY", "archiveSizeBytes": "1168167201", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20140924", "id": "4822681162745636585", "creationTimestamp": "2014-09-24T19:57:13.650-07:00", "name": "centos-7-v20140924", "description": "CentOS 7 x86_64 built on 2014-09-24", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20140926" }, "status": "READY", "archiveSizeBytes": "1181699781", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20140926", "id": "11630347837395986864", "creationTimestamp": "2014-09-29T09:29:54.626-07:00", "name": "centos-7-v20140926", "description": "CentOS 7 x86_64 built on 2014-09-26", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141007" }, "status": "READY", "archiveSizeBytes": "1182441174", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141007", "id": "13420104487111729570", "creationTimestamp": "2014-10-16T14:18:33.905-07:00", "name": "centos-7-v20141007", "description": "CentOS 7.0 x86_64 built on 2014-10-07", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141016" }, "status": "READY", "archiveSizeBytes": "1182982164", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141016", "id": "4506010319257803087", "creationTimestamp": "2014-10-17T16:43:06.539-07:00", "name": "centos-7-v20141016", "description": "CentOS 7.0 x86_64 built on 2014-10-16", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141021" }, "status": "READY", "archiveSizeBytes": "1184558412", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141021", "id": "4536638025069785573", "creationTimestamp": "2014-10-22T18:27:40.851-07:00", "name": "centos-7-v20141021", "description": "CentOS 7 x86_64 built on 2014-10-21", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141108" }, "status": "READY", "archiveSizeBytes": "1183591245", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141108", "id": "853041310537923411", "creationTimestamp": "2014-11-10T14:22:16.416-08:00", "name": "centos-7-v20141108", "description": "CentOS 7 x86_64 built on 2014-11-08", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141205" }, "status": "READY", "archiveSizeBytes": "1192600188", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/centos-cloud/global/images/centos-7-v20141205", "id": "9955643093605856709", "creationTimestamp": "2014-12-08T16:35:02.271-08:00", "name": "centos-7-v20141205", "description": "CentOS 7 x86_64 built on 2014-12-05", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1196735889", "diskSizeGb": "10" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images.json0000664000175000017500000022273713535474530033357 0ustar kamikami00000000000000{ "kind": "compute#imageList", "id": "projects/coreos-cloud/global/images", "items": [ { "kind": "compute#image", "id": "4695747588770162260", "creationTimestamp": "2017-05-25T15:20:43.546-07:00", "name": "coreos-alpha-1122-0-0-v20160727", "description": "CoreOS, CoreOS alpha, 1122.0.0, amd64-usr published on 2016-07-27", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED" }, "status": "READY", "archiveSizeBytes": "317622899", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1122-0-0-v20160727", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3107955306779855492", "creationTimestamp": "2017-03-16T13:24:11.491-07:00", "name": "coreos-alpha-1353-0-0-v20170316", "description": "CoreOS, CoreOS alpha, 1353.0.0, amd64-usr published on 2017-03-16", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1353-1-0-v20170317" }, "status": "READY", "archiveSizeBytes": "375484650", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1353-0-0-v20170316", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "8793447092679971460", "creationTimestamp": "2017-03-17T11:35:23.424-07:00", "name": "coreos-alpha-1353-1-0-v20170317", "description": "CoreOS, CoreOS alpha, 1353.1.0, amd64-usr published on 2017-03-17", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1367-5-0-v20170401" }, "status": "READY", "archiveSizeBytes": "376139501", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1353-1-0-v20170317", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "7867764550994707028", "creationTimestamp": "2017-03-31T18:04:59.295-07:00", "name": "coreos-alpha-1367-5-0-v20170401", "description": "CoreOS, CoreOS alpha, 1367.5.0, amd64-usr published on 2017-04-01", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1381-0-0-v20170413" }, "status": "READY", "archiveSizeBytes": "376276205", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1367-5-0-v20170401", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3951901945058146963", "creationTimestamp": "2017-04-13T16:06:36.674-07:00", "name": "coreos-alpha-1381-0-0-v20170413", "description": "CoreOS, CoreOS alpha, 1381.0.0, amd64-usr published on 2017-04-13", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1395-0-0-v20170427" }, "status": "READY", "archiveSizeBytes": "375076474", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1381-0-0-v20170413", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "6955051234309932588", "creationTimestamp": "2017-04-27T11:30:27.356-07:00", "name": "coreos-alpha-1395-0-0-v20170427", "description": "CoreOS, CoreOS alpha, 1395.0.0, amd64-usr published on 2017-04-27", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1409-0-0-v20170511" }, "status": "READY", "archiveSizeBytes": "374705530", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1395-0-0-v20170427", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3877520232569995102", "creationTimestamp": "2017-05-11T12:55:29.282-07:00", "name": "coreos-alpha-1409-0-0-v20170511", "description": "CoreOS, CoreOS alpha, 1409.0.0, amd64-usr published on 2017-05-11", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1423-0-0-v20170525" }, "status": "READY", "archiveSizeBytes": "383589509", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1409-0-0-v20170511", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "7859070867191014126", "creationTimestamp": "2017-05-25T11:01:37.468-07:00", "name": "coreos-alpha-1423-0-0-v20170525", "description": "CoreOS, CoreOS alpha, 1423.0.0, amd64-usr published on 2017-05-25", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1430-0-0-v20170531" }, "status": "READY", "archiveSizeBytes": "387676297", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1423-0-0-v20170525", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "3849476475535420699", "creationTimestamp": "2017-05-31T16:38:28.911-07:00", "name": "coreos-alpha-1430-0-0-v20170531", "description": "CoreOS, CoreOS alpha, 1430.0.0, amd64-usr published on 2017-05-31", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1437-0-0-v20170608" }, "status": "READY", "archiveSizeBytes": "387963522", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1430-0-0-v20170531", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "3834637015636521853", "creationTimestamp": "2017-06-08T10:46:58.678-07:00", "name": "coreos-alpha-1437-0-0-v20170608", "description": "CoreOS, CoreOS alpha, 1437.0.0, amd64-usr published on 2017-06-08", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1451-2-0-v20170623" }, "status": "READY", "archiveSizeBytes": "388495781", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1437-0-0-v20170608", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "6565444485921229965", "creationTimestamp": "2017-06-22T18:44:02.977-07:00", "name": "coreos-alpha-1451-2-0-v20170623", "description": "CoreOS, CoreOS alpha, 1451.2.0, amd64-usr published on 2017-06-23", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1465-0-0-v20170706" }, "status": "READY", "archiveSizeBytes": "390296986", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1451-2-0-v20170623", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "4165632660333607425", "creationTimestamp": "2017-07-06T11:43:58.814-07:00", "name": "coreos-alpha-1465-0-0-v20170706", "description": "CoreOS, CoreOS alpha, 1465.0.0, amd64-usr published on 2017-07-06", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1478-0-0-v20170719" }, "status": "READY", "archiveSizeBytes": "395186083", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1465-0-0-v20170706", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "2094793880548547038", "creationTimestamp": "2017-07-19T11:38:41.271-07:00", "name": "coreos-alpha-1478-0-0-v20170719", "description": "CoreOS, CoreOS alpha, 1478.0.0, amd64-usr published on 2017-07-19", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-0-0-v20170802" }, "status": "READY", "archiveSizeBytes": "394661543", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1478-0-0-v20170719", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "8005091676415346513", "creationTimestamp": "2017-08-02T09:11:42.466-07:00", "name": "coreos-alpha-1492-0-0-v20170802", "description": "CoreOS, CoreOS alpha, 1492.0.0, amd64-usr published on 2017-08-02", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-1-0-v20170803" }, "status": "READY", "archiveSizeBytes": "416683693", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-0-0-v20170802", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "951618730468562683", "creationTimestamp": "2017-08-02T17:02:28.640-07:00", "name": "coreos-alpha-1492-1-0-v20170803", "description": "CoreOS, CoreOS alpha, 1492.1.0, amd64-usr published on 2017-08-03", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-3-0-v20170810" }, "status": "READY", "archiveSizeBytes": "422836642", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-1-0-v20170803", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "6999557570912412720", "creationTimestamp": "2017-08-10T15:14:55.316-07:00", "name": "coreos-alpha-1492-3-0-v20170810", "description": "CoreOS, CoreOS alpha, 1492.3.0, amd64-usr published on 2017-08-10", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-4-0-v20170814" }, "status": "READY", "archiveSizeBytes": "422501298", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-3-0-v20170810", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "1605407439769812676", "creationTimestamp": "2017-08-14T12:55:23.836-07:00", "name": "coreos-alpha-1492-4-0-v20170814", "description": "CoreOS, CoreOS alpha, 1492.4.0, amd64-usr published on 2017-08-14", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1506-0-0-v20170817" }, "status": "READY", "archiveSizeBytes": "421956009", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1492-4-0-v20170814", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "2770527991526613100", "creationTimestamp": "2017-08-17T11:20:51.127-07:00", "name": "coreos-alpha-1506-0-0-v20170817", "description": "CoreOS, CoreOS alpha, 1506.0.0, amd64-usr published on 2017-08-17", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1520-0-0-v20170830" }, "status": "READY", "archiveSizeBytes": "423172275", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1506-0-0-v20170817", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "100760484785641629", "creationTimestamp": "2017-08-30T09:23:14.513-07:00", "name": "coreos-alpha-1520-0-0-v20170830", "description": "CoreOS, CoreOS alpha, 1520.0.0, amd64-usr published on 2017-08-30", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1520-1-0-v20170906" }, "status": "READY", "archiveSizeBytes": "427216805", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1520-0-0-v20170830", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "8321248140378079276", "creationTimestamp": "2017-09-06T11:30:27.324-07:00", "name": "coreos-alpha-1520-1-0-v20170906", "description": "CoreOS, CoreOS alpha, 1520.1.0, amd64-usr published on 2017-09-06", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1535-0-0-v20170914" }, "status": "READY", "archiveSizeBytes": "427229568", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1520-1-0-v20170906", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "4476739239175215301", "creationTimestamp": "2017-09-14T13:27:22.146-07:00", "name": "coreos-alpha-1535-0-0-v20170914", "description": "CoreOS, CoreOS alpha, 1535.0.0, amd64-usr published on 2017-09-14", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1535-1-0-v20170916" }, "status": "READY", "archiveSizeBytes": "428319104", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1535-0-0-v20170914", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "1635790407785894373", "creationTimestamp": "2017-09-15T17:23:38.970-07:00", "name": "coreos-alpha-1535-1-0-v20170916", "description": "CoreOS, CoreOS alpha, 1535.1.0, amd64-usr published on 2017-09-16", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1535-2-0-v20170921" }, "status": "READY", "archiveSizeBytes": "427828352", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1535-1-0-v20170916", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "1972836437337207295", "creationTimestamp": "2017-09-21T07:39:12.787-07:00", "name": "coreos-alpha-1535-2-0-v20170921", "description": "CoreOS, CoreOS alpha, 1535.2.0, amd64-usr published on 2017-09-21", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1548-0-0-v20170927" }, "status": "READY", "archiveSizeBytes": "422514304", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1535-2-0-v20170921", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "6105978479544006724", "creationTimestamp": "2017-09-27T08:41:31.739-07:00", "name": "coreos-alpha-1548-0-0-v20170927", "description": "CoreOS, CoreOS alpha, 1548.0.0, amd64-usr published on 2017-09-27", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1562-0-0-v20171011" }, "status": "READY", "archiveSizeBytes": "451743360", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1548-0-0-v20170927", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "3179613202588892810", "creationTimestamp": "2017-10-11T09:01:42.129-07:00", "name": "coreos-alpha-1562-0-0-v20171011", "description": "CoreOS, CoreOS alpha, 1562.0.0, amd64-usr published on 2017-10-11", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1562-1-0-v20171012" }, "status": "READY", "archiveSizeBytes": "453697920", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1562-0-0-v20171011", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "3232831081496605863", "creationTimestamp": "2017-10-12T13:02:16.316-07:00", "name": "coreos-alpha-1562-1-0-v20171012", "description": "CoreOS, CoreOS alpha, 1562.1.0, amd64-usr published on 2017-10-12", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "453563008", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-alpha" ], "family": "coreos-alpha", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-alpha-1562-1-0-v20171012", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "109679624318003812", "creationTimestamp": "2016-11-30T10:03:55.344-08:00", "name": "coreos-beta-1235-1-0-v20161130", "description": "CoreOS, CoreOS beta, 1235.1.0, amd64-usr published on 2016-11-30", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1235-2-0-v20161207" }, "status": "READY", "archiveSizeBytes": "370231261", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1235-1-0-v20161130", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "444908478975541914", "creationTimestamp": "2016-12-07T08:44:37.130-08:00", "name": "coreos-beta-1235-2-0-v20161207", "description": "CoreOS, CoreOS beta, 1235.2.0, amd64-usr published on 2016-12-07", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1248-2-0-v20170104" }, "status": "READY", "archiveSizeBytes": "370990814", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1235-2-0-v20161207", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "6785527900163599752", "creationTimestamp": "2017-01-04T11:56:23.879-08:00", "name": "coreos-beta-1248-2-0-v20170104", "description": "CoreOS, CoreOS beta, 1248.2.0, amd64-usr published on 2017-01-04", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1248-3-0-v20170109" }, "status": "READY", "archiveSizeBytes": "374908131", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1248-2-0-v20170104", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "2413509264537512823", "creationTimestamp": "2017-01-08T16:13:12.107-08:00", "name": "coreos-beta-1248-3-0-v20170109", "description": "CoreOS, CoreOS beta, 1248.3.0, amd64-usr published on 2017-01-09", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1248-4-0-v20170111" }, "status": "READY", "archiveSizeBytes": "374932193", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1248-3-0-v20170109", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3028522721326148042", "creationTimestamp": "2017-01-10T18:23:33.739-08:00", "name": "coreos-beta-1248-4-0-v20170111", "description": "CoreOS, CoreOS beta, 1248.4.0, amd64-usr published on 2017-01-11", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1298-3-0-v20170202" }, "status": "READY", "archiveSizeBytes": "374389985", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1248-4-0-v20170111", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "74870675315017693", "creationTimestamp": "2017-02-02T10:23:47.021-08:00", "name": "coreos-beta-1298-3-0-v20170202", "description": "CoreOS, CoreOS beta, 1298.3.0, amd64-usr published on 2017-02-02", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1298-4-0-v20170223" }, "status": "READY", "archiveSizeBytes": "364330700", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1298-3-0-v20170202", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "5517176404980217691", "creationTimestamp": "2017-02-22T23:05:24.839-08:00", "name": "coreos-beta-1298-4-0-v20170223", "description": "CoreOS, CoreOS beta, 1298.4.0, amd64-usr published on 2017-02-23", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1325-2-0-v20170301" }, "status": "READY", "archiveSizeBytes": "370154475", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1298-4-0-v20170223", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "1295998296394470025", "creationTimestamp": "2017-03-01T12:17:42.964-08:00", "name": "coreos-beta-1325-2-0-v20170301", "description": "CoreOS, CoreOS beta, 1325.2.0, amd64-usr published on 2017-03-01", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1353-2-0-v20170329" }, "status": "READY", "archiveSizeBytes": "370906342", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1325-2-0-v20170301", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "6427063981104544818", "creationTimestamp": "2017-03-29T11:54:22.005-07:00", "name": "coreos-beta-1353-2-0-v20170329", "description": "CoreOS, CoreOS beta, 1353.2.0, amd64-usr published on 2017-03-29", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1353-4-0-v20170401" }, "status": "READY", "archiveSizeBytes": "377249029", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1353-2-0-v20170329", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "4791136252595487547", "creationTimestamp": "2017-03-31T18:09:40.095-07:00", "name": "coreos-beta-1353-4-0-v20170401", "description": "CoreOS, CoreOS beta, 1353.4.0, amd64-usr published on 2017-04-01", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1381-1-0-v20170426" }, "status": "READY", "archiveSizeBytes": "376690157", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1353-4-0-v20170401", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3603530705250638540", "creationTimestamp": "2017-04-26T11:17:07.941-07:00", "name": "coreos-beta-1381-1-0-v20170426", "description": "CoreOS, CoreOS beta, 1381.1.0, amd64-usr published on 2017-04-26", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1409-1-0-v20170524" }, "status": "READY", "archiveSizeBytes": "377222784", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1381-1-0-v20170426", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "2548796104397845319", "creationTimestamp": "2017-05-24T11:15:04.201-07:00", "name": "coreos-beta-1409-1-0-v20170524", "description": "CoreOS, CoreOS beta, 1409.1.0, amd64-usr published on 2017-05-24", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1437-1-0-v20170621" }, "status": "READY", "archiveSizeBytes": "381190276", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1409-1-0-v20170524", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5762706482594776145", "creationTimestamp": "2017-06-21T11:28:14.781-07:00", "name": "coreos-beta-1437-1-0-v20170621", "description": "CoreOS, CoreOS beta, 1437.1.0, amd64-usr published on 2017-06-21", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1437-2-0-v20170622" }, "status": "READY", "archiveSizeBytes": "385733790", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1437-1-0-v20170621", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "4809130752545492791", "creationTimestamp": "2017-06-22T14:08:40.251-07:00", "name": "coreos-beta-1437-2-0-v20170622", "description": "CoreOS, CoreOS beta, 1437.2.0, amd64-usr published on 2017-06-22", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1437-3-0-v20170630" }, "status": "READY", "archiveSizeBytes": "386975895", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1437-2-0-v20170622", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "3180906060768308478", "creationTimestamp": "2017-06-30T15:34:57.701-07:00", "name": "coreos-beta-1437-3-0-v20170630", "description": "CoreOS, CoreOS beta, 1437.3.0, amd64-usr published on 2017-06-30", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-2-0-v20170719" }, "status": "READY", "archiveSizeBytes": "385996189", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1437-3-0-v20170630", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "2740598821171107469", "creationTimestamp": "2017-07-19T11:43:46.931-07:00", "name": "coreos-beta-1465-2-0-v20170719", "description": "CoreOS, CoreOS beta, 1465.2.0, amd64-usr published on 2017-07-19", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-3-0-v20170802" }, "status": "READY", "archiveSizeBytes": "393477793", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-2-0-v20170719", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "7766808750554105481", "creationTimestamp": "2017-08-02T09:05:58.670-07:00", "name": "coreos-beta-1465-3-0-v20170802", "description": "CoreOS, CoreOS beta, 1465.3.0, amd64-usr published on 2017-08-02", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-4-0-v20170810" }, "status": "READY", "archiveSizeBytes": "392527258", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-3-0-v20170802", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "3908238070589253137", "creationTimestamp": "2017-08-10T15:06:54.850-07:00", "name": "coreos-beta-1465-4-0-v20170810", "description": "CoreOS, CoreOS beta, 1465.4.0, amd64-usr published on 2017-08-10", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-5-0-v20170814" }, "status": "READY", "archiveSizeBytes": "392992922", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-4-0-v20170810", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "8936475241727410374", "creationTimestamp": "2017-08-14T12:46:49.798-07:00", "name": "coreos-beta-1465-5-0-v20170814", "description": "CoreOS, CoreOS beta, 1465.5.0, amd64-usr published on 2017-08-14", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1492-5-0-v20170817" }, "status": "READY", "archiveSizeBytes": "393997471", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1465-5-0-v20170814", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5759478647156658938", "creationTimestamp": "2017-08-17T12:18:45.273-07:00", "name": "coreos-beta-1492-5-0-v20170817", "description": "CoreOS, CoreOS beta, 1492.5.0, amd64-usr published on 2017-08-17", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1492-6-0-v20170906" }, "status": "READY", "archiveSizeBytes": "420365736", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1492-5-0-v20170817", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5148360541019700052", "creationTimestamp": "2017-09-06T12:00:12.009-07:00", "name": "coreos-beta-1492-6-0-v20170906", "description": "CoreOS, CoreOS beta, 1492.6.0, amd64-usr published on 2017-09-06", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1520-2-0-v20170914" }, "status": "READY", "archiveSizeBytes": "419903872", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1492-6-0-v20170906", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "2985095052869986620", "creationTimestamp": "2017-09-14T12:26:11.266-07:00", "name": "coreos-beta-1520-2-0-v20170914", "description": "CoreOS, CoreOS beta, 1520.2.0, amd64-usr published on 2017-09-14", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1520-3-0-v20170916" }, "status": "READY", "archiveSizeBytes": "417439360", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1520-2-0-v20170914", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "4047503918464357695", "creationTimestamp": "2017-09-15T17:09:52.641-07:00", "name": "coreos-beta-1520-3-0-v20170916", "description": "CoreOS, CoreOS beta, 1520.3.0, amd64-usr published on 2017-09-16", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1520-4-0-v20170921" }, "status": "READY", "archiveSizeBytes": "423404160", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1520-3-0-v20170916", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "2671230722763550742", "creationTimestamp": "2017-09-21T07:38:49.339-07:00", "name": "coreos-beta-1520-4-0-v20170921", "description": "CoreOS, CoreOS beta, 1520.4.0, amd64-usr published on 2017-09-21", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1548-1-0-v20171011" }, "status": "READY", "archiveSizeBytes": "422685824", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1520-4-0-v20170921", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "2918441957920603826", "creationTimestamp": "2017-10-11T09:01:33.540-07:00", "name": "coreos-beta-1548-1-0-v20171011", "description": "CoreOS, CoreOS beta, 1548.1.0, amd64-usr published on 2017-10-11", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1548-2-0-v20171012" }, "status": "READY", "archiveSizeBytes": "451512448", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1548-1-0-v20171011", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "3594322033371149421", "creationTimestamp": "2017-10-12T13:03:14.220-07:00", "name": "coreos-beta-1548-2-0-v20171012", "description": "CoreOS, CoreOS beta, 1548.2.0, amd64-usr published on 2017-10-12", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "451914112", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-beta" ], "family": "coreos-beta", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-beta-1548-2-0-v20171012", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5382223799496530918", "creationTimestamp": "2016-10-20T17:44:57.346-07:00", "name": "coreos-stable-1122-3-0-v20161021", "description": "CoreOS, CoreOS stable, 1122.3.0, amd64-usr published on 2016-10-21", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1185-3-0-v20161101" }, "status": "READY", "archiveSizeBytes": "303330504", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1122-3-0-v20161021", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "1527572715277741875", "creationTimestamp": "2016-11-01T10:33:16.258-07:00", "name": "coreos-stable-1185-3-0-v20161101", "description": "CoreOS, CoreOS stable, 1185.3.0, amd64-usr published on 2016-11-01", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1185-5-0-v20161207" }, "status": "READY", "archiveSizeBytes": "302681552", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1185-3-0-v20161101", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "379200328364819444", "creationTimestamp": "2016-12-07T08:47:23.487-08:00", "name": "coreos-stable-1185-5-0-v20161207", "description": "CoreOS, CoreOS stable, 1185.5.0, amd64-usr published on 2016-12-07", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-4-0-v20170104" }, "status": "READY", "archiveSizeBytes": "302934727", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1185-5-0-v20161207", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "649072115903051317", "creationTimestamp": "2017-02-22T23:01:47.036-08:00", "name": "coreos-stable-1235-12-0-v20170223", "description": "CoreOS, CoreOS stable, 1235.12.0, amd64-usr published on 2017-02-23", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1298-5-0-v20170228" }, "status": "READY", "archiveSizeBytes": "369691368", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-12-0-v20170223", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "5692980712181919496", "creationTimestamp": "2017-01-04T11:49:59.326-08:00", "name": "coreos-stable-1235-4-0-v20170104", "description": "CoreOS, CoreOS stable, 1235.4.0, amd64-usr published on 2017-01-04", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-5-0-v20170109" }, "status": "READY", "archiveSizeBytes": "369674730", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-4-0-v20170104", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "509682010342517217", "creationTimestamp": "2017-01-08T16:19:27.053-08:00", "name": "coreos-stable-1235-5-0-v20170109", "description": "CoreOS, CoreOS stable, 1235.5.0, amd64-usr published on 2017-01-09", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-6-0-v20170111" }, "status": "READY", "archiveSizeBytes": "369898205", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-5-0-v20170109", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "4429072154521774226", "creationTimestamp": "2017-01-10T18:20:45.476-08:00", "name": "coreos-stable-1235-6-0-v20170111", "description": "CoreOS, CoreOS stable, 1235.6.0, amd64-usr published on 2017-01-11", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-8-0-v20170131" }, "status": "READY", "archiveSizeBytes": "369501149", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-6-0-v20170111", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "6463382104296962964", "creationTimestamp": "2017-01-31T13:45:31.492-08:00", "name": "coreos-stable-1235-8-0-v20170131", "description": "CoreOS, CoreOS stable, 1235.8.0, amd64-usr published on 2017-01-31", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-9-0-v20170202" }, "status": "READY", "archiveSizeBytes": "368565480", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-8-0-v20170131", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "7185758735485033030", "creationTimestamp": "2017-02-02T08:56:09.452-08:00", "name": "coreos-stable-1235-9-0-v20170202", "description": "CoreOS, CoreOS stable, 1235.9.0, amd64-usr published on 2017-02-02", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-12-0-v20170223" }, "status": "READY", "archiveSizeBytes": "370081515", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1235-9-0-v20170202", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "6607481358041768333", "creationTimestamp": "2017-02-28T12:36:50.692-08:00", "name": "coreos-stable-1298-5-0-v20170228", "description": "CoreOS, CoreOS stable, 1298.5.0, amd64-usr published on 2017-02-28", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1298-6-0-v20170315" }, "status": "READY", "archiveSizeBytes": "370570987", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1298-5-0-v20170228", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "6464305049821786041", "creationTimestamp": "2017-03-15T12:09:10.664-07:00", "name": "coreos-stable-1298-6-0-v20170315", "description": "CoreOS, CoreOS stable, 1298.6.0, amd64-usr published on 2017-03-15", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1298-7-0-v20170401" }, "status": "READY", "archiveSizeBytes": "370942193", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1298-6-0-v20170315", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "6014865507167191078", "creationTimestamp": "2017-03-31T18:13:45.043-07:00", "name": "coreos-stable-1298-7-0-v20170401", "description": "CoreOS, CoreOS stable, 1298.7.0, amd64-usr published on 2017-04-01", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1353-6-0-v20170425" }, "status": "READY", "archiveSizeBytes": "365081311", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1298-7-0-v20170401", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3827656126096345475", "creationTimestamp": "2017-04-25T13:54:05.060-07:00", "name": "coreos-stable-1353-6-0-v20170425", "description": "CoreOS, CoreOS stable, 1353.6.0, amd64-usr published on 2017-04-25", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1353-7-0-v20170427" }, "status": "READY", "archiveSizeBytes": "374909574", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1353-6-0-v20170425", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "8122013459453638362", "creationTimestamp": "2017-04-26T18:24:05.794-07:00", "name": "coreos-stable-1353-7-0-v20170427", "description": "CoreOS, CoreOS stable, 1353.7.0, amd64-usr published on 2017-04-27", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1353-8-0-v20170531" }, "status": "READY", "archiveSizeBytes": "374887805", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1353-7-0-v20170427", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3555354078563511800", "creationTimestamp": "2017-05-30T17:49:27.320-07:00", "name": "coreos-stable-1353-8-0-v20170531", "description": "CoreOS, CoreOS stable, 1353.8.0, amd64-usr published on 2017-05-31", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-2-0-v20170620" }, "status": "READY", "archiveSizeBytes": "374924926", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1353-8-0-v20170531", "labelFingerprint": "42WmSpB8rSM=" }, { "kind": "compute#image", "id": "3615899944778780014", "creationTimestamp": "2017-06-20T12:12:02.025-07:00", "name": "coreos-stable-1409-2-0-v20170620", "description": "CoreOS, CoreOS stable, 1409.2.0, amd64-usr published on 2017-06-20", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-5-0-v20170623" }, "status": "READY", "archiveSizeBytes": "381081255", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-2-0-v20170620", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5675333718078771517", "creationTimestamp": "2017-06-22T18:33:06.951-07:00", "name": "coreos-stable-1409-5-0-v20170623", "description": "CoreOS, CoreOS stable, 1409.5.0, amd64-usr published on 2017-06-23", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-6-0-v20170706" }, "status": "READY", "archiveSizeBytes": "382278050", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-5-0-v20170623", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "2558058712479776125", "creationTimestamp": "2017-07-06T11:38:10.081-07:00", "name": "coreos-stable-1409-6-0-v20170706", "description": "CoreOS, CoreOS stable, 1409.6.0, amd64-usr published on 2017-07-06", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-7-0-v20170719" }, "status": "READY", "archiveSizeBytes": "381072802", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-6-0-v20170706", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "1650233566770107587", "creationTimestamp": "2017-07-19T11:51:24.316-07:00", "name": "coreos-stable-1409-7-0-v20170719", "description": "CoreOS, CoreOS stable, 1409.7.0, amd64-usr published on 2017-07-19", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-8-0-v20170810" }, "status": "READY", "archiveSizeBytes": "381212066", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-7-0-v20170719", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5125114056300125467", "creationTimestamp": "2017-08-10T15:53:40.530-07:00", "name": "coreos-stable-1409-8-0-v20170810", "description": "CoreOS, CoreOS stable, 1409.8.0, amd64-usr published on 2017-08-10", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-9-0-v20170814" }, "status": "READY", "archiveSizeBytes": "381134504", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-8-0-v20170810", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "4439862469585552288", "creationTimestamp": "2017-08-14T12:43:11.593-07:00", "name": "coreos-stable-1409-9-0-v20170814", "description": "CoreOS, CoreOS stable, 1409.9.0, amd64-usr published on 2017-08-14", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1465-6-0-v20170817" }, "status": "READY", "archiveSizeBytes": "377216673", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1409-9-0-v20170814", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5563715618352948145", "creationTimestamp": "2017-08-17T11:15:58.673-07:00", "name": "coreos-stable-1465-6-0-v20170817", "description": "CoreOS, CoreOS stable, 1465.6.0, amd64-usr published on 2017-08-17", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1465-7-0-v20170906" }, "status": "READY", "archiveSizeBytes": "392304041", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1465-6-0-v20170817", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "1127922138626259762", "creationTimestamp": "2017-09-06T12:00:46.001-07:00", "name": "coreos-stable-1465-7-0-v20170906", "description": "CoreOS, CoreOS stable, 1465.7.0, amd64-usr published on 2017-09-06", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1465-8-0-v20170921" }, "status": "READY", "archiveSizeBytes": "393191296", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1465-7-0-v20170906", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "6610501905484247127", "creationTimestamp": "2017-09-21T07:37:44.728-07:00", "name": "coreos-stable-1465-8-0-v20170921", "description": "CoreOS, CoreOS stable, 1465.8.0, amd64-usr published on 2017-09-21", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1520-5-0-v20171011" }, "status": "READY", "archiveSizeBytes": "393742208", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1465-8-0-v20170921", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "9017650089265725093", "creationTimestamp": "2017-10-11T09:01:14.919-07:00", "name": "coreos-stable-1520-5-0-v20171011", "description": "CoreOS, CoreOS stable, 1520.5.0, amd64-usr published on 2017-10-11", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1520-6-0-v20171012" }, "status": "READY", "archiveSizeBytes": "450138752", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1520-5-0-v20171011", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] }, { "kind": "compute#image", "id": "5454100008489088098", "creationTimestamp": "2017-10-12T13:03:25.293-07:00", "name": "coreos-stable-1520-6-0-v20171012", "description": "CoreOS, CoreOS stable, 1520.6.0, amd64-usr published on 2017-10-12", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "445453184", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1520-6-0-v20171012", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] } ], "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images" } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images_family_coreos_beta.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images_family_0000664000175000017500000000076113535474530034076 0ustar kamikami00000000000000{ "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-beta-522-3-0-v20141226", "id": "14171939663085407486", "creationTimestamp": "2014-12-26T15:04:01.237-08:00", "name": "coreos-beta-522-3-0-v20141226", "description": "CoreOS beta 522.3.0", "family": "coreos-beta", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "220932284", "diskSizeGb": "9" } ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images_family_coreos_stable.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_images_family_0000664000175000017500000000147013535474530034074 0ustar kamikami00000000000000{ "kind": "compute#image", "id": "5454100008489088098", "creationTimestamp": "2017-10-12T13:03:25.293-07:00", "name": "coreos-stable-1520-6-0-v20171012", "description": "CoreOS, CoreOS stable, 1520.6.0, amd64-usr published on 2017-10-12", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "445453184", "diskSizeGb": "9", "licenses": [ "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/licenses/coreos-stable" ], "family": "coreos-stable", "selfLink": "https://www.googleapis.com/compute/beta/projects/coreos-cloud/global/images/coreos-stable-1520-6-0-v20171012", "labelFingerprint": "42WmSpB8rSM=", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" } ] } ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_licenses_coreos_stable.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_coreos-cloud_global_licenses_coreo0000664000175000017500000000027313535474530034123 0ustar kamikami00000000000000{ "kind": "compute#license", "selfLink": "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/licenses/coreos-stable", "name": "coreos-stable", "chargesUseFee": true } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_cos-cloud_global_images.json0000664000175000017500000000617113535474530032641 0ustar kamikami00000000000000{ "kind": "compute#imageList", "id": "projects/cos-cloud/global/images", "items": [ { "archiveSizeBytes": "2781566400", "creationTimestamp": "2018-03-16T11:58:21.963-07:00", "description": "Google, Container-Optimized OS, 65-10323.55.0 beta, Kernel: ChromiumOS-4.4.111 Kubernetes: 1.8.7 Docker: 17.03.2", "diskSizeGb": "10", "family": "cos-beta", "id": "7977998760666049826", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/licenses/cos" ], "name": "cos-beta-65-10323-55-0", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-beta-65-10323-55-0", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "2904964800", "creationTimestamp": "2018-03-16T11:46:19.959-07:00", "description": "Google, Container-Optimized OS, 66-10452.13.0 dev, Kernel: ChromiumOS-4.14.22 Kubernetes: 1.9.3 Docker: 17.03.2", "diskSizeGb": "10", "family": "cos-dev", "id": "5462067189945314836", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/licenses/cos" ], "name": "cos-dev-66-10452-13-0", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-dev-66-10452-13-0", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "2862244800", "creationTimestamp": "2018-01-19T10:59:30.098-08:00", "description": "Google, Container-Optimized OS, 63-10032.88.0 stable, Kernel: ChromiumOS-4.4.86 Kubernetes: 1.7.8 Docker: 17.03.2", "diskSizeGb": "10", "family": "cos-stable", "id": "9037695461801066238", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/licenses/cos" ], "name": "cos-stable-63-10032-88-0", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-63-10032-88-0", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "2776416960", "creationTimestamp": "2018-02-02T15:15:12.894-08:00", "description": "Google, Container-Optimized OS, 64-10176.62.0 stable, Kernel: ChromiumOS-4.4.96 Kubernetes: 1.8.7 Docker: 17.03.2", "diskSizeGb": "10", "family": "cos-stable", "id": "5241841702474960879", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/licenses/cos" ], "name": "cos-stable-64-10176-62-0", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-64-10176-62-0", "sourceType": "RAW", "status": "READY" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json0000664000175000017500000003531013535474530033274 0ustar kamikami00000000000000{ "id": "projects/debian-cloud/global/images", "items": [ { "archiveSizeBytes": "365056004", "creationTimestamp": "2013-12-02T17:49:01.206-08:00", "description": "Debian GNU/Linux 7.2 (wheezy) with backports kernel built on 2013-11-27", "id": "11823693270029497919", "kind": "compute#image", "name": "backports-debian-7-wheezy-v20131127", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/backports-debian-7-wheezy-v20131127", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "214107225", "creationTimestamp": "2013-05-07T17:09:22.111-07:00", "deprecated": { "deleted": "1970-01-03", "deprecated": "1970-01-01", "obsolete": "1970-01-02", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130507", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-07", "id": "647943287916432906", "kind": "compute#image", "name": "debian-6-squeeze-v20130507", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130507", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "255972840", "creationTimestamp": "2013-05-09T12:56:21.720-07:00", "deprecated": { "deprecated": "2064-03-11T20:18:36.194-07:00", "obsolete": "2074-03-11T20:18:36.194-07:00", "deleted": "2084-03-11T20:18:36.194-07:00", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-09", "id": "15745758816845911589", "kind": "compute#image", "name": "debian-6-squeeze-v20130509", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130509", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "219458106", "creationTimestamp": "2013-05-14T21:01:12.124-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-15", "id": "006866479348046290", "kind": "compute#image", "name": "debian-6-squeeze-v20130515", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130515", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "265118282", "creationTimestamp": "2013-05-30T09:48:37.837-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-05-22", "id": "1266148899538866390", "kind": "compute#image", "name": "debian-6-squeeze-v20130522", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130522", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "233984980", "creationTimestamp": "2013-06-19T13:45:44.111-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-06-17", "id": "04009358257173422091", "kind": "compute#image", "name": "debian-6-squeeze-v20130617", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130617", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "258168500", "creationTimestamp": "2013-07-24T12:31:06.054-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-07-23", "id": "3115342424904648000", "kind": "compute#image", "name": "debian-6-squeeze-v20130723", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130723", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "300710522", "creationTimestamp": "2013-09-04T13:21:53.292-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-08-16", "id": "06130699342353523133", "kind": "compute#image", "name": "debian-6-squeeze-v20130816", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130816", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "300710522", "creationTimestamp": "2013-10-11T09:26:47.736-07:00", "deprecated": { "deprecated": "2064-03-11T20:18:36.194-07:00", "obsolete": "2074-03-11T20:18:36.194-07:00", "deleted": "2084-03-11T20:18:36.194-07:00", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 6.0.7 (squeeze) built on 2013-09-26", "id": "0225119674082940764", "kind": "compute#image", "name": "debian-6-squeeze-v20130926", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-6-squeeze-v20130926", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "237290472", "creationTimestamp": "2013-05-07T17:01:30.071-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-07", "id": "15638477823580670459", "kind": "compute#image", "name": "debian-7-wheezy-v20130507", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130507", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "270107366", "creationTimestamp": "2013-05-09T12:56:47.910-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-09", "id": "020034532765408091", "kind": "compute#image", "name": "debian-7-wheezy-v20130509", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130509", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "265604335", "creationTimestamp": "2013-05-14T21:02:55.044-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-15", "id": "0587071888358410836", "kind": "compute#image", "name": "debian-7-wheezy-v20130515", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130515", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "284301993", "creationTimestamp": "2013-05-30T09:47:30.980-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.0 (wheezy) built on 2013-05-22", "id": "622079684385221180", "kind": "compute#image", "name": "debian-7-wheezy-v20130522", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130522", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "310882322", "creationTimestamp": "2013-06-19T13:47:20.563-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-06-17", "id": "1549141992333368759", "kind": "compute#image", "name": "debian-7-wheezy-v20130617", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130617", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "258869806", "creationTimestamp": "2013-07-24T12:31:36.790-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-07-23", "id": "3119304810142650253", "kind": "compute#image", "name": "debian-7-wheezy-v20130723", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130723", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "279162251", "creationTimestamp": "2013-09-04T13:24:30.479-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-08-16", "id": "2595370902107306327", "kind": "compute#image", "name": "debian-7-wheezy-v20130816", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130816", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "279162251", "creationTimestamp": "2013-10-11T09:26:56.993-07:00", "deprecated": { "deprecated": "2013-11-14T00:00:00Z", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.1 (wheezy) built on 2013-09-26", "id": "06737951524754934395", "kind": "compute#image", "name": "debian-7-wheezy-v20130926", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20130926", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "405683884", "creationTimestamp": "2013-10-28T13:52:08.233-07:00", "deprecated": { "deprecated": "2064-03-11T20:18:36.194-07:00", "obsolete": "2074-03-11T20:18:36.194-07:00", "deleted": "2084-03-11T20:18:36.194-07:00", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "state": "DEPRECATED" }, "description": "Debian GNU/Linux 7.2 (wheezy) built on 2013-10-14", "id": "1405559880052641502", "kind": "compute#image", "name": "debian-7-wheezy-v20131014", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "341857472", "creationTimestamp": "2013-11-25T15:17:00.436-08:00", "description": "Debian GNU/Linux 7.2 (wheezy) built on 2013-11-20", "id": "05708985343919147751", "kind": "compute#image", "name": "debian-7-wheezy-v20131120", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceType": "RAW", "status": "READY" } ], "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_opensuse-cloud_global_images.json0000664000175000017500000000632413535474530033716 0ustar kamikami00000000000000{ "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/opensuse-cloud/global/images", "id": "projects/opensuse-cloud/global/images", "items": [ { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-1-v20140609", "id": "5330388859130445578", "creationTimestamp": "2014-06-09T11:45:56.997-07:00", "name": "opensuse-13-1-v20140609", "description": "", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-1-v20140627", "deprecated": "2014-06-27T00:00:00Z" }, "status": "READY", "archiveSizeBytes": "872777232", "diskSizeGb": "8" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-1-v20140627", "id": "635369188275126205", "creationTimestamp": "2014-06-27T08:44:37.896-07:00", "name": "opensuse-13-1-v20140627", "description": "", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-1-v20140711", "deprecated": "2014-07-11T00:00:00Z" }, "status": "READY", "archiveSizeBytes": "878545758", "diskSizeGb": "8" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-1-v20140711", "id": "414150705420767734", "creationTimestamp": "2014-07-11T14:04:35.210-07:00", "name": "opensuse-13-1-v20140711", "description": "", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-1-v20141102", "deprecated": "2014-11-02T00:00:00Z" }, "status": "READY", "archiveSizeBytes": "878437869", "diskSizeGb": "8" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-1-v20141102", "id": "4629398803823711760", "creationTimestamp": "2014-11-02T04:34:26.263-08:00", "name": "opensuse-13-1-v20141102", "description": "openSUSE 13.1 (built on 2014-11-02)", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "881210631", "diskSizeGb": "8" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/opensuse-cloud/global/images/opensuse-13-2-v20141205", "id": "7015477126275748573", "creationTimestamp": "2014-12-09T05:36:16.085-08:00", "name": "opensuse-13-2-v20141205", "description": "openSUSE 13.2 (built on 2014-12-05)", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1091494581", "diskSizeGb": "8" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_cf.json0000664000175000017500000000061013535474530034141 0ustar kamikami00000000000000{ "kind": "compute#network", "id": "5125152985904090792", "creationTimestamp": "2016-03-25T05:34:15.077-07:00", "name": "cf", "selfLink": "https://www.googleapis.com/compute/v1/projects/other_name/global/networks/cf", "autoCreateSubnetworks": true, "subnetworks": [ "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1/subnetworks/cf-972cf02e6ad49114" ] } ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_lcnetwork.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_lcnetwo0000664000175000017500000000052613535474530034262 0ustar kamikami00000000000000{ "IPv4Range": "10.11.0.0/16", "creationTimestamp": "2013-06-26T10:05:03.500-07:00", "gatewayIPv4": "10.11.0.1", "description": "A custom network", "id": "16211908079305042870", "kind": "compute#network", "name": "lcnetwork", "selfLink": "https://www.googleapis.com/compute/v1/projects/other_name/global/networks/lcnetwork" } ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_shared_network_for_mig.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_global_networks_shared_0000664000175000017500000000066613535474530034221 0ustar kamikami00000000000000{ "kind": "compute#network", "id": "5125152985904090796", "creationTimestamp": "2016-03-25T05:34:15.077-07:00", "name": "shared_network_for_mig", "selfLink": "https://www.googleapis.com/compute/v1/projects/other_name/global/networks/shared_network_for_mig", "autoCreateSubnetworks": true, "subnetworks": [ "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1/subnetworks/shared_subnetwork_for_mig" ] } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1.jso0000664000175000017500000000231213535474530034004 0ustar kamikami00000000000000{ "kind": "compute#region", "id": "1000", "creationTimestamp": "2014-05-30T18:35:16.413-07:00", "name": "us-central1", "description": "us-central1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/other_name/zones/us-central1-a", "https://www.googleapis.com/compute/v1/projects/other_name/zones/us-central1-b" ], "quotas": [ { "metric": "CPUS", "limit": 1050.0, "usage": 30.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 20000.0, "usage": 344.0 }, { "metric": "STATIC_ADDRESSES", "limit": 10.0, "usage": 2.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 1050.0, "usage": 11.0 }, { "metric": "SSD_TOTAL_GB", "limit": 2048.0, "usage": 500.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUPS", "limit": 100.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUP_MANAGERS", "limit": 50.0, "usage": 0.0 }, { "metric": "INSTANCES", "limit": 10500.0, "usage": 11.0 }, { "metric": "AUTOSCALERS", "limit": 50.0, "usage": 0.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1" } ././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1_subnetworks_cf_972cf02e6ad49114.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1_sub0000664000175000017500000000104213535474530034062 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#subnetwork", "id": "4297043163355844285", "creationTimestamp": "2016-03-25T05:34:27.209-07:00", "gatewayAddress": "10.128.0.1", "name": "cf-972cf02e6ad49114", "network": "https://www.googleapis.com/compute/v1/projects/other_name/global/networks/cf", "ipCidrRange": "10.128.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112" } ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1_subnetworks_shared_subnetwork_for_mig.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_other_name_regions_us-central1_sub0000664000175000017500000000110213535474530034057 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#subnetwork", "id": "4297043163355844289", "creationTimestamp": "2016-03-25T05:34:27.209-07:00", "gatewayAddress": "10.128.0.1", "name": "shared_subnetwork_for_mig", "network": "https://www.googleapis.com/compute/v1/projects/other_name/global/networks/shared_network_for_mig", "ipCidrRange": "10.128.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1/subnetworks/shared_subnetwork_for_mig" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_rhel-cloud_global_images.json0000664000175000017500000000311613535474530033003 0ustar kamikami00000000000000{ "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/rhel-cloud/global/images", "id": "projects/rhel-cloud/global/images", "items": [ { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/rhel-cloud/global/images/rhel-7-v20141108", "id": "9656001643961289198", "creationTimestamp": "2014-11-10T14:15:28.054-08:00", "name": "rhel-7-v20141108", "description": "Red Hat Enterprise Linux 7.0 x86_64 built on 2014-11-08", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/rhel-cloud/global/images/rhel-7-v20141205" }, "status": "READY", "archiveSizeBytes": "1201321944", "diskSizeGb": "10", "licenses": [ "https://content.googleapis.com/compute/v1/projects/rhel-cloud/global/licenses/rhel-7-server" ] }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/rhel-cloud/global/images/rhel-7-v20141205", "id": "9718957591079040023", "creationTimestamp": "2014-12-08T17:07:02.804-08:00", "name": "rhel-7-v20141205", "description": "Red Hat Enterprise Linux 7.0 x86_64 built on 2014-12-05", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1204146084", "diskSizeGb": "10", "licenses": [ "https://content.googleapis.com/compute/v1/projects/rhel-cloud/global/licenses/rhel-7-server" ] } ] } ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_rhel-cloud_global_licenses_rhel_server.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_rhel-cloud_global_licenses_rhel_se0000664000175000017500000000027413535474530034076 0ustar kamikami00000000000000{ "kind": "compute#license", "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/rhel-7-server", "name": "rhel-7-server", "chargesUseFee": true } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_suse-byos-cloud_global_images.json0000664000175000017500000001264313535474530034007 0ustar kamikami00000000000000{ "kind": "compute#imageList", "id": "projects/suse-byos-cloud/global/images", "items": [ { "archiveSizeBytes": "4903362048", "creationTimestamp": "2018-01-04T15:38:28.707-08:00", "description": "SUSE, SUSE Linux Enterprise Server 11 SP4 BYOS configuration, x86_64, built on 2018-01-04", "diskSizeGb": "10", "family": "sles-11-byos", "id": "2387143735879336987", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "name": "sles-11-sp4-byos-v20180104", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/images/sles-11-sp4-byos-v20180104", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "3656075520", "creationTimestamp": "2017-05-15T13:07:01.943-07:00", "description": "SUSE, SUSE Linux Enterprise Server 12 SP2, x86_64, built on 2017-05-15", "diskSizeGb": "10", "family": "sles-12-byos", "id": "3705265501102388362", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/licenses/sles-12-byos" ], "name": "sles-12-sp2-byos-v20170515", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/images/sles-12-sp2-byos-v20170515", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "10602881280", "creationTimestamp": "2018-02-14T12:21:27.529-08:00", "description": "SUSE, SUSE Linux Enterprise Server 12 SP2 For SAP BYOS configuration, x86_64, built on 2018-02-14", "diskSizeGb": "10", "family": "sles-12-sp2-sap-byos", "id": "6191777507858523304", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/licenses/sles-sap-12-byos" ], "name": "sles-12-sp2-sap-byos-v20180214", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/images/sles-12-sp2-sap-byos-v20180214", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "6914937600", "creationTimestamp": "2018-02-14T09:40:30.237-08:00", "description": "SUSE, SUSE Linux Enterprise Server 12 SP3, x86_64, built on 2018-02-14", "diskSizeGb": "10", "family": "sles-12-byos", "id": "1750160000940624482", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/licenses/sles-12-byos" ], "name": "sles-12-sp3-byos-v20180214", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/images/sles-12-sp3-byos-v20180214", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "10740059520", "creationTimestamp": "2018-02-14T10:20:54.913-08:00", "description": "SUSE, SUSE Linux Enterprise Server 12 SP3 For SAP BYOS configuration, x86_64, built on 2018-02-14", "diskSizeGb": "10", "family": "sles-12-sp3-sap-byos", "id": "2521622434670035177", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/licenses/sles-sap-12-byos" ], "name": "sles-12-sp3-sap-byos-v20180214", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/images/sles-12-sp3-sap-byos-v20180214", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "8562081600", "creationTimestamp": "2018-02-14T13:03:08.443-08:00", "description": "SUSE, SUSE Manager 3.1 Proxy BYOS, x86_64 built on 2018-02-14, Based on SLES 12 SP2", "diskSizeGb": "10", "family": "suse-manager-proxy-byos", "id": "3455542315608251107", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/licenses/suma-proxy-byos" ], "name": "suse-manager-3-1-proxy-byos-v20180214", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/images/suse-manager-3-1-proxy-byos-v20180214", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "15142568640", "creationTimestamp": "2018-02-14T12:42:11.295-08:00", "description": "SUSE, SUSE Manager 3.1 Server BYOS, x86_64 built on 2018-02-14, Based on SLES 12 SP2", "diskSizeGb": "10", "family": "suse-manager-server-byos", "id": "5720192942026072525", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/licenses/suma-server-byos" ], "name": "suse-manager-3-1-server-byos-v20180214", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-byos-cloud/global/images/suse-manager-3-1-server-byos-v20180214", "sourceType": "RAW", "status": "READY" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_images.json0000664000175000017500000001236013535474530033031 0ustar kamikami00000000000000{ "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images", "id": "projects/suse-cloud/global/images", "items": [ { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140306", "id": "3727805086509383287", "creationTimestamp": "2014-03-06T13:13:29.791-08:00", "name": "sles-11-sp3-v20140306", "description": "", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140609", "deprecated": "2014-06-09T00:00:00Z" }, "status": "READY", "archiveSizeBytes": "354497936", "diskSizeGb": "8", "licenses": [ "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" ] }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140609", "id": "10656986931280984622", "creationTimestamp": "2014-06-09T10:29:06.385-07:00", "name": "sles-11-sp3-v20140609", "description": "", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140712", "deprecated": "2014-07-12T00:00:00Z" }, "status": "READY", "archiveSizeBytes": "1191603546", "diskSizeGb": "8", "licenses": [ "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" ] }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140712", "id": "3415847542100990147", "creationTimestamp": "2014-07-12T03:39:17.695-07:00", "name": "sles-11-sp3-v20140712", "description": "SUSE Linux Enterprise 11 SP3 built on 2014-07-12", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140826", "deprecated": "2014-06-26T00:00:00Z" }, "status": "READY", "archiveSizeBytes": "1071997074", "diskSizeGb": "8", "licenses": [ "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" ] }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140826", "id": "588070221570840387", "creationTimestamp": "2014-08-26T14:46:38.449-07:00", "name": "sles-11-sp3-v20140826", "description": "SUSE Linux Enterprise 11 SP3 released on 2014-06-26, built on 2014-08-20", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140930", "deprecated": "2014-10-30T00:00:00Z" }, "status": "READY", "archiveSizeBytes": "1072617138", "diskSizeGb": "8", "licenses": [ "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" ] }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140930", "id": "3132872945991231828", "creationTimestamp": "2014-09-30T08:27:46.201-07:00", "name": "sles-11-sp3-v20140930", "description": "SUSE Linux Enterprise Server 11 SP3", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1102825953", "diskSizeGb": "8", "licenses": [ "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" ] }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20141105", "id": "14793554030256860036", "creationTimestamp": "2014-11-05T16:11:49.996-08:00", "name": "sles-11-sp3-v20141105", "description": "SUSE Linux Enterprise Server 11 SP3 built on 2014-11-05", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1075782309", "diskSizeGb": "8", "licenses": [ "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" ] }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-12-v20141023", "id": "15301906009182317384", "creationTimestamp": "2014-10-26T08:14:59.932-07:00", "name": "sles-12-v20141023", "description": "SUSE Linux Enterprise Server 12 built on 2014-10-23", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1525260684", "diskSizeGb": "8", "licenses": [ "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-12" ] } ] } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_11.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_110000664000175000017500000000025513535474530033750 0ustar kamikami00000000000000{ "kind": "compute#license", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11", "name": "sles-11", "chargesUseFee": true } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_12.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_120000664000175000017500000000025513535474530033751 0ustar kamikami00000000000000{ "kind": "compute#license", "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-12", "name": "sles-12", "chargesUseFee": true } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_suse-sap-cloud_global_images.json0000664000175000017500000000314613535474530033614 0ustar kamikami00000000000000{ "kind": "compute#imageList", "id": "projects/suse-sap-cloud/global/images", "items": [ { "archiveSizeBytes": "10610274240", "creationTimestamp": "2018-02-14T11:36:42.181-08:00", "description": "SUSE, SUSE Linux Enterprise Server 12 SP2 For SAP, x86_64, built on 2018-02-14", "diskSizeGb": "10", "family": "sles-12-sp2-sap", "id": "1678965261537456422", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-sap-cloud/global/licenses/sles-sap-12" ], "name": "sles-12-sp2-sap-v20180214", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-sap-cloud/global/images/sles-12-sp2-sap-v20180214", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "10651082880", "creationTimestamp": "2018-02-14T09:25:13.871-08:00", "description": "SUSE, SUSE Linux Enterprise Server 12 SP3 For SAP, x86_64, built on 2018-02-14", "diskSizeGb": "10", "family": "sles-12-sp3-sap", "id": "1354274246585077270", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/suse-sap-cloud/global/licenses/sles-sap-12" ], "name": "sles-12-sp3-sap-v20180214", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-sap-cloud/global/images/sles-12-sp3-sap-v20180214", "sourceType": "RAW", "status": "READY" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_ubuntu-os-cloud_global_images.json0000664000175000017500000001317113535474530034014 0ustar kamikami00000000000000{ "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images", "id": "projects/ubuntu-os-cloud/global/images", "items": [ { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1204-precise-v20141028", "id": "15508054221909398824", "creationTimestamp": "2014-10-29T09:51:42.018-07:00", "name": "ubuntu-1204-precise-v20141028", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1204-precise-v20141212" }, "status": "READY", "archiveSizeBytes": "378614228", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1204-precise-v20141031", "id": "3216640293232429175", "creationTimestamp": "2014-11-07T00:48:18.673-08:00", "name": "ubuntu-1204-precise-v20141031", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1204-precise-v20141212" }, "status": "READY", "archiveSizeBytes": "1137275331", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1204-precise-v20141212", "id": "12756823774499736482", "creationTimestamp": "2014-12-17T11:31:59.126-08:00", "name": "ubuntu-1204-precise-v20141212", "description": "Canonical, Ubuntu, 12.04 LTS, amd64 precise image built on 2014-12-12", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1140352383", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1404-trusty-v20141028", "id": "17781692821175088041", "creationTimestamp": "2014-10-29T09:51:42.072-07:00", "name": "ubuntu-1404-trusty-v20141028", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1404-trusty-v20141212" }, "status": "READY", "archiveSizeBytes": "375105326", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1404-trusty-v20141031a", "id": "6500942514398264968", "creationTimestamp": "2014-11-07T00:48:04.471-08:00", "name": "ubuntu-1404-trusty-v20141031a", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1404-trusty-v20141212" }, "status": "READY", "archiveSizeBytes": "1015791618", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1404-trusty-v20141212", "id": "14921913565797044708", "creationTimestamp": "2014-12-17T11:31:37.868-08:00", "name": "ubuntu-1404-trusty-v20141212", "description": "Canonical, Ubuntu, 14.04 LTS, amd64 trusty image built on 2014-12-12", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "981936603", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1410-utopic-v20141029", "id": "13898107879086076373", "creationTimestamp": "2014-10-29T09:51:39.609-07:00", "name": "ubuntu-1410-utopic-v20141029", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1410-utopic-v20141217" }, "status": "READY", "archiveSizeBytes": "348037877", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1410-utopic-v20141030a", "id": "2412636152371793564", "creationTimestamp": "2014-11-07T00:47:53.082-08:00", "name": "ubuntu-1410-utopic-v20141030a", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "deprecated": { "state": "DEPRECATED", "replacement": "https://content.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1410-utopic-v20141217" }, "status": "READY", "archiveSizeBytes": "1044175299", "diskSizeGb": "10" }, { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/ubuntu-os-cloud/global/images/ubuntu-1410-utopic-v20141217", "id": "6363233028234584116", "creationTimestamp": "2014-12-17T11:31:26.695-08:00", "name": "ubuntu-1410-utopic-v20141217", "description": "Canonical, Ubuntu, 14.10, amd64 utopic image built on 2014-12-17", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "1048366941", "diskSizeGb": "10" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_windows-cloud_global_images.json0000664000175000017500000000157613535474530033553 0ustar kamikami00000000000000{ "kind": "compute#imageList", "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/images", "id": "projects/windows-cloud/global/images", "items": [ { "kind": "compute#image", "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/images/windows-server-2008-r2-dc-v20141120", "id": "10752443450426453317", "creationTimestamp": "2014-12-02T10:31:56.162-08:00", "name": "windows-server-2008-r2-dc-v20141120", "description": "Microsoft Windows Server 2008 R2 Datacenter Edition built on 2014-11-20", "sourceType": "RAW", "rawDisk": { "source": "", "containerType": "TAR" }, "status": "READY", "archiveSizeBytes": "6974709077", "diskSizeGb": "100", "licenses": [ "https://content.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2008-r2-dc" ] } ] } ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_windows-cloud_global_licenses_windows_server_2008_r2_dc.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_windows-cloud_global_licenses_wind0000664000175000017500000000030613535474530034152 0ustar kamikami00000000000000{ "kind": "compute#license", "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-2008-r2-dc", "name": "windows-2008-r2-dc", "chargesUseFee": true } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_windows-sql-cloud_global_images.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/projects_windows-sql-cloud_global_images.js0000664000175000017500000005034413535474530034010 0ustar kamikami00000000000000{ "kind": "compute#imageList", "id": "projects/windows-sql-cloud/global/images", "items": [ { "archiveSizeBytes": "292570851840", "creationTimestamp": "2018-03-16T12:56:34.051-07:00", "description": "Microsoft, SQL Server 2012 Enterprise, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-ent-2012-win-2012-r2", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "691184437710397342", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2012-enterprise", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2012-enterprise-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2012-enterprise-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "289458120960", "creationTimestamp": "2018-03-16T12:56:34.100-07:00", "description": "Microsoft, SQL Server 2012 Standard, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-std-2012-win-2012-r2", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "7039869042978561950", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2012-standard", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2012-standard-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2012-standard-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "281538677760", "creationTimestamp": "2018-03-16T12:56:33.984-07:00", "description": "Microsoft, SQL Server 2012 Web, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-web-2012-win-2012-r2", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "8315170259090907038", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2012-web", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2012-web-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2012-web-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "241746543360", "creationTimestamp": "2018-03-16T12:56:31.079-07:00", "description": "Microsoft, SQL Server 2012 Enterprise, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-ent-2014-win-2012-r2", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "6850934007153139585", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2014-enterprise", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2014-enterprise-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2014-enterprise-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "215371714560", "creationTimestamp": "2018-03-16T12:56:34.317-07:00", "description": "Microsoft, SQL Server 2012 Enterprise, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-ent-2014-win-2016", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "8779506358941753246", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2014-enterprise", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2014-enterprise-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2014-enterprise-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "241815690240", "creationTimestamp": "2018-03-16T12:56:34.015-07:00", "description": "Microsoft, SQL Server 2014 Standard, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-std-2014-win-2012-r2", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "2727026445279928222", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2014-standard", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2014-standard-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2014-standard-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "235978583040", "creationTimestamp": "2018-03-16T12:56:34.136-07:00", "description": "Microsoft, SQL Server 2014 Web, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-web-2014-win-2012-r2", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "8854164671641526174", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2014-web", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2014-web-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2014-web-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "275054722560", "creationTimestamp": "2018-03-16T12:56:34.145-07:00", "description": "Microsoft, SQL Server 2016 Enterprise, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-ent-2016-win-2012-r2", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "7568452089731456926", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2016-enterprise", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2016-enterprise-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2016-enterprise-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "217748267520", "creationTimestamp": "2018-03-16T12:56:34.162-07:00", "description": "Microsoft, SQL Server 2016 Enterprise, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-ent-2016-win-2016", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "8158037467522506654", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2016-enterprise", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2016-enterprise-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2016-enterprise-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "275475156480", "creationTimestamp": "2018-03-16T12:56:34.135-07:00", "description": "Microsoft, SQL Server 2016 Standard, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-std-2016-win-2012-r2", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "7321671631204622238", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2016-standard", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2016-standard-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2016-standard-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "216044855040", "creationTimestamp": "2018-03-16T12:56:34.139-07:00", "description": "Microsoft, SQL Server 2016 Standard, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-std-2016-win-2016", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "7345241359458082718", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2016-standard", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2016-standard-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2016-standard-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "257308473600", "creationTimestamp": "2018-03-16T12:56:34.090-07:00", "description": "Microsoft, SQL Server 2016 Web, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-web-2016-win-2012-r2", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "5306288240788086686", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2016-web", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2016-web-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2016-web-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "206679609600", "creationTimestamp": "2018-03-16T12:56:34.116-07:00", "description": "Microsoft, SQL Server 2016 Web, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-web-2016-win-2016", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "3442119052452011934", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2016-web", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2016-web-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2016-web-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "180692828160", "creationTimestamp": "2018-03-16T12:56:33.957-07:00", "description": "Microsoft, SQL Server 2017 Enterprise, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-ent-2017-win-2016", "guestOsFeatures": [ { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "WINDOWS" }, { "type": "MULTI_IP_SUBNET" } ], "id": "5009147572728733598", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2017-enterprise", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2017-enterprise-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2017-enterprise-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "186363325440", "creationTimestamp": "2018-03-16T12:56:33.978-07:00", "description": "Microsoft, SQL Server 2017 Express, on Windows Server 2012 R2 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-exp-2017-win-2012-r2", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "5306872833081712542", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2017-express", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2012-r2-dc" ], "name": "sql-2017-express-windows-2012-r2-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2017-express-windows-2012-r2-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "161739521280", "creationTimestamp": "2018-03-16T12:56:33.964-07:00", "description": "Microsoft, SQL Server 2017 Express, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-exp-2017-win-2016", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "2606423252507139998", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2017-express", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2017-express-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2017-express-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "180530031360", "creationTimestamp": "2018-03-16T12:56:33.960-07:00", "description": "Microsoft, SQL Server 2017 Standard, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-std-2017-win-2016", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "7610921752851488670", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2017-standard", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2017-standard-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2017-standard-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" }, { "archiveSizeBytes": "176303884800", "creationTimestamp": "2018-03-16T12:56:34.055-07:00", "description": "Microsoft, SQL Server 2017 Web, on Windows Server 2016 Datacenter, x64 built on 20180313", "diskSizeGb": "50", "family": "sql-web-2017-win-2016", "guestOsFeatures": [ { "type": "WINDOWS" }, { "type": "VIRTIO_SCSI_MULTIQUEUE" }, { "type": "MULTI_IP_SUBNET" } ], "id": "8377634188974727070", "kind": "compute#image", "labelFingerprint": "42WmSpB8rSM=", "licenses": [ "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/licenses/sql-server-2017-web", "https://www.googleapis.com/compute/v1/projects/windows-cloud/global/licenses/windows-server-2016-dc" ], "name": "sql-2017-web-windows-2016-dc-v20180313", "rawDisk": { "containerType": "TAR", "source": "" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/windows-sql-cloud/global/images/sql-2017-web-windows-2016-dc-v20180313", "sourceType": "RAW", "status": "READY" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions-paged-1.json0000664000175000017500000000421713535474530027054 0ustar kamikami00000000000000{ "kind": "compute#regionList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions", "id": "projects/project_name/regions", "items": [ { "kind": "compute#region", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1", "id": "1220", "creationTimestamp": "2014-04-11T13:47:12.495-07:00", "name": "asia-east1", "description": "asia-east1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/asia-east1-a" ], "quotas": [ { "metric": "CPUS", "limit": 24.0, "usage": 0.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 5120.0, "usage": 0.0 }, { "metric": "STATIC_ADDRESSES", "limit": 7.0, "usage": 0.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 23.0, "usage": 0.0 }, { "metric": "SSD_TOTAL_GB", "limit": 1024.0, "usage": 0.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 1500.0, "usage": 0.0 } ] }, { "kind": "compute#region", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", "id": "1100", "creationTimestamp": "2014-04-11T13:47:12.495-07:00", "name": "europe-west1", "description": "europe-west1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a", "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b" ], "quotas": [ { "metric": "CPUS", "limit": 24.0, "usage": 0.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 5120.0, "usage": 0.0 }, { "metric": "STATIC_ADDRESSES", "limit": 7.0, "usage": 0.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 23.0, "usage": 0.0 }, { "metric": "SSD_TOTAL_GB", "limit": 1024.0, "usage": 0.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 1500.0, "usage": 0.0 } ] } ], "nextPageToken": "CjQIz5W-w6HRxAI6KQoCGAEKAiAACgIYAQoCIAAKAhgTCg4qDGV1cm9wZS13ZXN0MQoDIMwI" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions-paged-2.json0000664000175000017500000000223313535474530027051 0ustar kamikami00000000000000{ "kind": "compute#regionList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions", "id": "projects/project_name/regions", "items": [ { "kind": "compute#region", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "id": "1000", "creationTimestamp": "2014-04-11T13:47:12.495-07:00", "name": "us-central1", "description": "us-central1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" ], "quotas": [ { "metric": "CPUS", "limit": 24.0, "usage": 1.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 5120.0, "usage": 60.0 }, { "metric": "STATIC_ADDRESSES", "limit": 7.0, "usage": 1.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 23.0, "usage": 1.0 }, { "metric": "SSD_TOTAL_GB", "limit": 1024.0, "usage": 0.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 1500.0, "usage": 0.0 } ] } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions.json0000664000175000017500000000574313535474530025645 0ustar kamikami00000000000000{ "id": "projects/project_name/regions", "items": [ { "creationTimestamp": "2013-04-19T17:58:16.641-07:00", "description": "europe-west1", "id": "0827308347805275727", "kind": "compute#region", "name": "europe-west1", "quotas": [ { "limit": 24.0, "metric": "CPUS", "usage": 0.0 }, { "limit": 5120.0, "metric": "DISKS_TOTAL_GB", "usage": 0.0 }, { "limit": 7.0, "metric": "STATIC_ADDRESSES", "usage": 0.0 }, { "limit": 23.0, "metric": "IN_USE_ADDRESSES", "usage": 0.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a", "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b" ] }, { "creationTimestamp": "2013-04-19T18:17:05.050-07:00", "description": "us-central1", "id": "06713580496607310378", "kind": "compute#region", "name": "us-central1", "quotas": [ { "limit": 24.0, "metric": "CPUS", "usage": 3.0 }, { "limit": 5120.0, "metric": "DISKS_TOTAL_GB", "usage": 10.0 }, { "limit": 7.0, "metric": "STATIC_ADDRESSES", "usage": 0.0 }, { "limit": 23.0, "metric": "IN_USE_ADDRESSES", "usage": 4.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" ] }, { "creationTimestamp": "2013-04-19T18:19:05.482-07:00", "description": "us-central2", "id": "04157375529195793136", "kind": "compute#region", "name": "us-central2", "quotas": [ { "limit": 24.0, "metric": "CPUS", "usage": 0.0 }, { "limit": 5120.0, "metric": "DISKS_TOTAL_GB", "usage": 0.0 }, { "limit": 7.0, "metric": "STATIC_ADDRESSES", "usage": 0.0 }, { "limit": 23.0, "metric": "IN_USE_ADDRESSES", "usage": 0.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central2", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a" ] } ], "kind": "compute#regionList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_asia-east1.json0000664000175000017500000000227313535474530027650 0ustar kamikami00000000000000{ "kind": "compute#region", "id": "1220", "creationTimestamp": "2014-05-30T18:35:16.514-07:00", "name": "asia-east1", "description": "asia-east1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/asia-east1-a", "https://www.googleapis.com/compute/v1/projects/project_name/zones/asia-east1-b" ], "quotas": [ { "metric": "CPUS", "limit": 24.0, "usage": 0.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "STATIC_ADDRESSES", "limit": 7.0, "usage": 0.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 23.0, "usage": 0.0 }, { "metric": "SSD_TOTAL_GB", "limit": 2048.0, "usage": 0.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUPS", "limit": 100.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUP_MANAGERS", "limit": 50.0, "usage": 0.0 }, { "metric": "INSTANCES", "limit": 240.0, "usage": 0.0 }, { "metric": "AUTOSCALERS", "limit": 50.0, "usage": 0.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_europe-west1.json0000664000175000017500000000215713535474530030261 0ustar kamikami00000000000000{ "kind": "compute#region", "id": "1100", "creationTimestamp": "2014-05-30T18:35:16.413-07:00", "name": "europe-west1", "description": "europe-west1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b" ], "quotas": [ { "metric": "CPUS", "limit": 24.0, "usage": 0.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "STATIC_ADDRESSES", "limit": 7.0, "usage": 0.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 23.0, "usage": 0.0 }, { "metric": "SSD_TOTAL_GB", "limit": 2048.0, "usage": 0.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUPS", "limit": 100.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUP_MANAGERS", "limit": 50.0, "usage": 0.0 }, { "metric": "INSTANCES", "limit": 240.0, "usage": 0.0 }, { "metric": "AUTOSCALERS", "limit": 50.0, "usage": 0.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1.json0000664000175000017500000000231613535474530030054 0ustar kamikami00000000000000{ "kind": "compute#region", "id": "1000", "creationTimestamp": "2014-05-30T18:35:16.413-07:00", "name": "us-central1", "description": "us-central1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" ], "quotas": [ { "metric": "CPUS", "limit": 1050.0, "usage": 30.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 20000.0, "usage": 344.0 }, { "metric": "STATIC_ADDRESSES", "limit": 10.0, "usage": 2.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 1050.0, "usage": 11.0 }, { "metric": "SSD_TOTAL_GB", "limit": 2048.0, "usage": 500.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUPS", "limit": 100.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUP_MANAGERS", "limit": 50.0, "usage": 0.0 }, { "metric": "INSTANCES", "limit": 10500.0, "usage": 11.0 }, { "metric": "AUTOSCALERS", "limit": 50.0, "usage": 0.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses.json0000664000175000017500000000226013535474530032107 0ustar kamikami00000000000000{ "id": "projects/project_name/regions/us-central1/addresses", "items": [ { "address": "108.59.82.4", "creationTimestamp": "2013-06-26T09:48:31.184-07:00", "description": "", "id": "17634862894218443422", "kind": "compute#address", "name": "libcloud-demo-address", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/libcloud-demo-address", "status": "RESERVED" }, { "address": "173.255.114.104", "creationTimestamp": "2013-06-04T16:28:43.764-07:00", "description": "", "id": "11879548153827627972", "kind": "compute#address", "name": "testaddress", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/testaddress", "status": "RESERVED" } ], "kind": "compute#addressList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses" }././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress.jso0000664000175000017500000000065613535474530033764 0ustar kamikami00000000000000{ "address": "173.255.113.20", "creationTimestamp": "2013-06-26T12:21:40.625-07:00", "description": "", "id": "01531551729918243104", "kind": "compute#address", "name": "lcaddress", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", "status": "RESERVED" }././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddress_del0000664000175000017500000000140513535474530034007 0ustar kamikami00000000000000{ "id": "7128783508312083402", "insertTime": "2013-06-26T12:21:44.075-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_addresses_lcaddress_delete", "operationType": "delete", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_lcaddress_delete", "startTime": "2013-06-26T12:21:44.110-07:00", "status": "PENDING", "targetId": "01531551729918243104", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddressinternal.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_lcaddressinte0000664000175000017500000000073013535474530034043 0ustar kamikami00000000000000{ "address": "10.128.0.12", "creationTimestamp": "2013-06-26T12:21:40.625-07:00", "description": "", "id": "01531551729918243104", "kind": "compute#address", "name": "lcaddressinternal", "addressType": "INTERNAL", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddressinternal", "status": "RESERVED" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_post.json0000664000175000017500000000131013535474530033147 0ustar kamikami00000000000000{ "id": "16064059851942653139", "insertTime": "2013-06-26T12:21:40.299-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_addresses_post", "operationType": "insert", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_addresses_post", "startTime": "2013-06-26T12:21:40.358-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/lcaddress", "user": "897001307951@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_testaddress.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_addresses_testaddress.j0000664000175000017500000000066413535474530034002 0ustar kamikami00000000000000{ "address": "173.255.114.104", "creationTimestamp": "2013-06-04T16:28:43.764-07:00", "description": "", "id": "11879548153827627972", "kind": "compute#address", "name": "testaddress", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/addresses/testaddress", "status": "RESERVED" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules.json0000664000175000017500000000277713535474530033324 0ustar kamikami00000000000000{ "id": "projects/project_name/regions/us-central1/forwardingRules", "items": [ { "IPAddress": "173.255.119.224", "IPProtocol": "TCP", "creationTimestamp": "2013-09-03T00:17:25.544-07:00", "id": "10901665092293158938", "kind": "compute#forwardingRule", "name": "lcforwardingrule", "portRange": "8000-8500", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" }, { "IPAddress": "173.255.119.185", "IPProtocol": "TCP", "creationTimestamp": "2013-09-02T22:25:50.575-07:00", "id": "15826316229163619337", "kind": "compute#forwardingRule", "name": "libcloud-lb-demo-lb", "portRange": "80-80", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/libcloud-lb-demo-lb", "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" } ], "kind": "compute#forwardingRuleList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules" }././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwa0000664000175000017500000000116413535474530034056 0ustar kamikami00000000000000{ "IPAddress": "173.255.119.224", "IPProtocol": "TCP", "creationTimestamp": "2013-09-03T00:17:25.544-07:00", "id": "10901665092293158938", "kind": "compute#forwardingRule", "name": "lcforwardingrule", "description": "test forwarding rule", "portRange": "8000-8500", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" } ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwardingrule_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_lcforwa0000664000175000017500000000143313535474530034055 0ustar kamikami00000000000000{ "id": "09064254309855814339", "insertTime": "2013-09-03T00:17:36.062-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", "operationType": "delete", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_lcforwardingrule_delete", "startTime": "2013-09-03T00:17:36.168-07:00", "status": "PENDING", "targetId": "10901665092293158938", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_libcloud-lb-demo-lb.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_libclou0000664000175000017500000000112313535474530034045 0ustar kamikami00000000000000{ "IPAddress": "108.59.83.110", "IPProtocol": "TCP", "creationTimestamp": "2013-09-29T13:30:00.702-07:00", "id": "1077550228014866104", "kind": "compute#forwardingRule", "name": "libcloud-lb-demo-lb", "portRange": "80-80", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/libcloud-lb-demo-lb", "target": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" }././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_forwardingRules_post.js0000664000175000017500000000131613535474530034020 0ustar kamikami00000000000000{ "id": "0651769405845333112", "insertTime": "2013-09-03T00:17:25.381-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_forwardingRules_post", "operationType": "insert", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_forwardingRules_post", "startTime": "2013-09-03T00:17:25.434-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/forwardingRules/lcforwardingrule", "user": "user@gserviceaccount.com" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks.json0000664000175000017500000000141513535474530032521 0ustar kamikami00000000000000{ "kind": "compute#subnetworkList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks", "id": "projects/project_name/regions/us-central1/subnetworks", "items": [ { "kind": "compute#subnetwork", "id": "4297043163355844284", "creationTimestamp": "2016-03-25T05:34:27.209-07:00", "gatewayAddress": "10.128.0.1", "name": "cf-972cf02e6ad49112", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.128.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112" } ] } ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_cf_972cf02e6ad49112.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_cf_972cf02e0000664000175000017500000000134613535474530033445 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#subnetwork", "id": "4297043163355844284", "creationTimestamp": "2016-03-25T05:34:27.209-07:00", "description": "LCTestSubnet", "gatewayAddress": "10.128.0.1", "name": "cf-972cf02e6ad49112", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.128.0.0/20", "privateIpGoogleAccess": true, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "secondaryIpRanges": [ { "ipCidrRange": "192.168.168.0/24", "rangeName": "secondary" } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_post.json0000664000175000017500000000133113535474530033563 0ustar kamikami00000000000000{ "id": "16064059851942653139", "insertTime": "2013-06-26T12:21:40.299-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_subnetworks_post", "operationType": "insert", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_subnetworks_post", "startTime": "2013-06-26T12:21:40.358-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112", "user": "897001307951@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_subnet_1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_subnetworks_subnet_1.js0000664000175000017500000000077613535474530033775 0ustar kamikami00000000000000{ "kind": "compute#subnetwork", "id": "4297043163355844286", "creationTimestamp": "2016-10-01T05:34:27.209-07:00", "gatewayAddress": "10.128.0.1", "name": "subnet_1", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.128.0.0/16", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/subnet_1" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools.json0000664000175000017500000000715713535474530032447 0ustar kamikami00000000000000{ "id": "projects/project_name/regions/us-central1/targetPools", "items": [ { "creationTimestamp": "2013-09-03T00:51:05.300-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "id": "13598380121688918358", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" ], "kind": "compute#targetPool", "name": "lctargetpool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" }, { "creationTimestamp": "2013-09-02T22:25:45.817-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "id": "16862638289615591831", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-002", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000" ], "kind": "compute#targetPool", "name": "libcloud-lb-demo-lb-tp", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" }, { "kind": "compute#targetPool", "id": "17914960036329768493", "creationTimestamp": "2014-11-26T08:37:28.831-08:00", "name": "backup-pool", "description": "", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/default-health-check" ], "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-002" ], "sessionAffinity": "CLIENT_IP", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/backup-pool" }, { "kind": "compute#targetPool", "id": "11474672125700394323", "creationTimestamp": "2014-11-24T12:52:13.366-08:00", "name": "lb-pool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000" ], "sessionAffinity": "NONE", "failoverRatio": 0.1, "backupPool": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/backup-pool", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lb-pool" } ], "kind": "compute#targetPoolList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools" } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_backup_pool.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_backup_pool0000664000175000017500000000140513535474530034043 0ustar kamikami00000000000000{ "creationTimestamp": "2013-09-03T00:51:05.300-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "id": "13598380121688918358", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" ], "kind": "compute#targetPool", "name": "backup-pool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/backup-pool" } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool.jso0000664000175000017500000000146313535474530033771 0ustar kamikami00000000000000{ "kind": "compute#targetPool", "id": "11474672125700394323", "creationTimestamp": "2014-11-24T12:52:13.366-08:00", "name": "lb-pool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000" ], "sessionAffinity": "NONE", "failoverRatio": 0.1, "backupPool": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/backup-pool", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lb-pool" } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool_getHealth.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool_get0000664000175000017500000000042213535474530034030 0ustar kamikami00000000000000{ "kind": "compute#targetPoolInstanceHealth", "healthStatus": [ { "ipAddress": "130.99.99.99", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/libcloud-lb-demo-www-000", "healthState": "UNHEALTHY" } ] } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool_setBackup_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lb_pool_set0000664000175000017500000000146613535474530034055 0ustar kamikami00000000000000{ "endTime": "2013-09-03T01:29:07.021-07:00", "id": "04072826501537092633", "insertTime": "2013-09-03T01:29:03.082-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lb_pool_setBackup_post", "operationType": "setBackup", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lb_pool_setBackup_post", "startTime": "2013-09-03T01:29:03.145-07:00", "status": "PENDING", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lb-pool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpoo0000664000175000017500000000140613535474530034071 0ustar kamikami00000000000000{ "creationTimestamp": "2013-09-03T00:51:05.300-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "id": "13598380121688918358", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001" ], "kind": "compute#targetPool", "name": "lctargetpool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool" }././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpoo0000664000175000017500000000144613535474530034075 0ustar kamikami00000000000000{ "id": "17341029456963557514", "insertTime": "2013-09-03T01:28:40.774-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", "operationType": "addHealthCheck", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addHealthCheck_post", "startTime": "2013-09-03T01:28:40.838-07:00", "status": "PENDING", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_addInstance_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpoo0000664000175000017500000000143513535474530034073 0ustar kamikami00000000000000{ "id": "04072826501537092633", "insertTime": "2013-09-03T01:29:03.082-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", "operationType": "addInstance", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_addInstance_post", "startTime": "2013-09-03T01:29:03.145-07:00", "status": "PENDING", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpoo0000664000175000017500000000140313535474530034066 0ustar kamikami00000000000000{ "id": "13500662190763995965", "insertTime": "2013-09-03T00:51:06.799-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_delete", "operationType": "delete", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_delete", "startTime": "2013-09-03T00:51:06.840-07:00", "status": "PENDING", "targetId": "13598380121688918358", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpoo0000664000175000017500000000145713535474530034077 0ustar kamikami00000000000000{ "id": "14738174613993796821", "insertTime": "2013-09-03T01:28:32.889-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", "operationType": "removeHealthCheck", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post", "startTime": "2013-09-03T01:28:32.942-07:00", "status": "PENDING", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_removeInstance_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpoo0000664000175000017500000000144513535474530034074 0ustar kamikami00000000000000{ "id": "1815686149437875016", "insertTime": "2013-09-03T01:28:53.049-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", "operationType": "removeInstance", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_lctargetpool_removeInstance_post", "startTime": "2013-09-03T01:28:53.109-07:00", "status": "PENDING", "targetId": "16862638289615591831", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_sticky.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpoo0000664000175000017500000000064313535474530034073 0ustar kamikami00000000000000{ "creationTimestamp": "2014-07-11T15:52:43.720-07:00", "id": "13598380121688918358", "kind": "compute#targetPool", "name": "lctargetpool-sticky", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool-sticky", "sessionAffinity": "CLIENT_IP_PROTO" }././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_libcloud-lb-demo-lb-tp.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_libcloud-lb0000664000175000017500000000162413535474530033740 0ustar kamikami00000000000000{ "creationTimestamp": "2013-09-02T22:25:45.817-07:00", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/libcloud-lb-demo-healthcheck" ], "id": "16862638289615591831", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-002", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000" ], "kind": "compute#targetPool", "name": "libcloud-lb-demo-lb-tp", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/libcloud-lb-demo-lb-tp" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_post.json0000664000175000017500000000127613535474530033510 0ustar kamikami00000000000000{ "id": "7487852523793007955", "insertTime": "2013-09-03T00:51:05.064-07:00", "kind": "compute#operation", "name": "operation-regions_us-central1_targetPools_post", "operationType": "insert", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/operations/operation-regions_us-central1_targetPools_post", "startTime": "2013-09-03T00:51:05.115-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool", "user": "user@gserviceaccount.com" }././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_www-pool.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_www-pool.js0000664000175000017500000000150013535474530033747 0ustar kamikami00000000000000{ "creationTimestamp": "2013-08-19T14:43:25.289-07:00", "description": "", "healthChecks": [ "https://www.googleapis.com/compute/v1/projects/project_name/global/httpHealthChecks/basic-check" ], "id": "09965129111508633746", "instances": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/www1", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/www2", "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/www3" ], "kind": "compute#targetPool", "name": "www-pool", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/www-pool" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-east1.json0000664000175000017500000000213713535474530027361 0ustar kamikami00000000000000{ "kind": "compute#region", "id": "1230", "creationTimestamp": "2014-09-03T16:13:49.013-07:00", "name": "us-east1", "description": "us-east1", "status": "UP", "zones": [ "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b" ], "quotas": [ { "metric": "CPUS", "limit": 24.0, "usage": 0.0 }, { "metric": "DISKS_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "STATIC_ADDRESSES", "limit": 7.0, "usage": 0.0 }, { "metric": "IN_USE_ADDRESSES", "limit": 23.0, "usage": 0.0 }, { "metric": "SSD_TOTAL_GB", "limit": 2048.0, "usage": 0.0 }, { "metric": "LOCAL_SSD_TOTAL_GB", "limit": 10240.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUPS", "limit": 100.0, "usage": 0.0 }, { "metric": "INSTANCE_GROUP_MANAGERS", "limit": 50.0, "usage": 0.0 }, { "metric": "INSTANCES", "limit": 240.0, "usage": 0.0 }, { "metric": "AUTOSCALERS", "limit": 50.0, "usage": 0.0 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1" } ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-east1_subnetworks_cf_972cf02e6ad49113.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/regions_us-east1_subnetworks_cf_972cf02e6ad0000664000175000017500000000102213535474530033333 0ustar kamikami00000000000000{ "kind": "compute#subnetwork", "id": "4297043163355844284", "creationTimestamp": "2016-10-01T05:34:27.209-07:00", "gatewayAddress": "10.128.0.1", "name": "cf-972cf02e6ad49113", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/cf", "ipCidrRange": "10.128.0.0/20", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49113" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/setCommonInstanceMetadata_post.json0000664000175000017500000000120713535474530032325 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setCommonInstanceMetadata", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-setCommonInstanceMetadata", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "PENDING", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/setCommonInstanceMetadata", "user": "foo@developer.gserviceaccount.com" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/setUsageExportBucket_post.json0000664000175000017500000000105113535474530031350 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "17203609782824174066", "name": "operation-setUsageExportBucket", "operationType": "setUsageExportBucket", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name", "targetId": "8116069320260064853", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2014-11-21T06:58:03.602-08:00", "startTime": "2014-11-21T06:58:04.018-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/global/operations/operation-setUsageExportBucket" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones.json0000664000175000017500000000711613535474530025331 0ustar kamikami00000000000000{ "id": "projects/project_name/zones", "items": [ { "kind": "compute#zone", "selfLink": "https://www.googleapis.com/compute/v1/projects/verb-test/zones/asia-east1-a", "id": "2220", "creationTimestamp": "2014-05-30T18:35:16.575-07:00", "name": "asia-east1-a", "description": "asia-east1-a", "status": "UP", "region": "https://www.googleapis.com/compute/v1/projects/verb-test/regions/asia-east1" }, { "creationTimestamp": "2013-02-05T16:19:23.254-08:00", "description": "europe-west1-a", "id": "13416642339679437530", "kind": "compute#zone", "maintenanceWindows": [ { "beginTime": "2014-01-18T12:00:00.000-08:00", "description": "maintenance zone", "endTime": "2014-02-02T12:00:00.000-08:00", "name": "2014-01-18-planned-outage" } ], "name": "europe-west1-a", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a", "status": "UP" }, { "creationTimestamp": "2013-02-05T16:19:23.254-08:00", "description": "europe-west1-b", "id": "20623650177407096", "kind": "compute#zone", "maintenanceWindows": [ { "beginTime": "2014-03-15T12:00:00.000-07:00", "description": "maintenance zone", "endTime": "2014-03-30T12:00:00.000-07:00", "name": "2014-03-15-planned-outage" } ], "name": "europe-west1-b", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/europe-west1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-b", "status": "UP" }, { "creationTimestamp": "2013-02-05T16:19:23.269-08:00", "description": "us-central1-a", "id": "13462829244527433283", "kind": "compute#zone", "name": "us-central1-a", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "status": "UP" }, { "creationTimestamp": "2013-02-05T16:19:23.269-08:00", "description": "us-central1-b", "id": "1045862591201432620", "kind": "compute#zone", "name": "us-central1-b", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", "status": "UP" }, { "creationTimestamp": "2013-02-05T16:19:23.257-08:00", "deprecated": { "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", "state": "DEPRECATED" }, "description": "us-central2-a", "id": "1001467574647549152", "kind": "compute#zone", "maintenanceWindows": [ { "beginTime": "2013-12-31T12:00:00.000-08:00", "description": "maintenance zone", "endTime": "2014-07-01T12:00:00.000-07:00", "name": "2013-12-31-planned-outage" } ], "name": "us-central2-a", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central2-a", "status": "UP" } ], "kind": "compute#zoneList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_asia-east1-b.json0000664000175000017500000000055013535474530027553 0ustar kamikami00000000000000{ "kind": "compute#zone", "id": "2220", "creationTimestamp": "2014-05-30T18:35:16.575-07:00", "name": "asia-east1-a", "description": "asia-east1-a", "status": "UP", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/asia-east1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/asia-east1-a" } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_diskTypes_pd_standard.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_diskTypes_pd_standard.0000664000175000017500000000067313535474530033700 0ustar kamikami00000000000000{ "creationTimestamp": "2014-06-02T11:07:28.530-07:00", "defaultDiskSizeGb": "500", "description": "Standard Persistent Disk", "kind": "compute#diskType", "name": "pd-standard", "selfLink": "https://www.googleapis.com/compute/v1/projects/gifted-electron-225/zones/europe-west1-a/diskTypes/pd-standard", "validDiskSize": "10GB-10240GB", "zone": "https://www.googleapis.com/compute/v1/projects/gifted-electron-225/zones/europe-west1-a" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances.json0000664000175000017500000001361713535474530032241 0ustar kamikami00000000000000{ "id": "projects/project_name/zones/europe-west1-a/instances", "items": [ { "canIpForward": false, "creationTimestamp": "2013-12-13T10:43:58.782-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-europe-multiple-nodes-000", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-multiple-nodes-000", "type": "PERSISTENT" } ], "id": "10947706194464948790", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-europe-multiple-nodes-000", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "192.158.28.252", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.122.85" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-multiple-nodes-000", "status": "RUNNING", "tags": { "fingerprint": "W7t6ZyTyIrc=", "items": [ "libcloud" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }, { "canIpForward": false, "creationTimestamp": "2013-12-13T10:43:12.706-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-europe-np-node", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-np-node", "type": "PERSISTENT" }, { "deviceName": "libcloud-demo-europe-attach-disk", "index": 1, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-attach-disk", "type": "PERSISTENT" } ], "id": "3421745795082776097", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-europe-np-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.251.128.10", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.221.125" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", "status": "RUNNING", "tags": { "fingerprint": "W7t6ZyTyIrc=", "items": [ "libcloud" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }, { "canIpForward": false, "creationTimestamp": "2013-12-13T10:43:37.267-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-demo-europe-boot-disk", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/disks/libcloud-demo-europe-boot-disk", "type": "PERSISTENT" } ], "id": "517678477070693411", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "libcloud-demo-europe-persist-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.251.128.32", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.240.204" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-persist-node", "status": "RUNNING", "tags": { "fingerprint": "EbZdwVRtKyg=", "items": [ "libcloud", "newtag" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" } ], "kind": "compute#instanceList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_instances_post.json0000664000175000017500000000140313535474530033274 0ustar kamikami00000000000000{ "id": "1510575454210533141", "insertTime": "2013-06-26T20:57:34.366-07:00", "kind": "compute#operation", "name": "operation-zones_europe-west1-a_instances_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/operations/operation-zones_europe-west1-a_instances_post", "startTime": "2013-06-26T20:57:34.453-07:00", "status": "PENDING", "targetId": "14308265828754333159", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/instances/libcloud-demo-europe-np-node", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a" }././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_machineTypes_n1-standard-1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_europe-west1-a_machineTypes_n1-standa0000664000175000017500000000073613535474530033577 0ustar kamikami00000000000000{ "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/europe-west1-a/machineTypes/n1-standard-1", "zone": "europe-west1-a" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a.json0000664000175000017500000000060313535474530027757 0ustar kamikami00000000000000{ "creationTimestamp": "2013-02-05T16:19:23.269-08:00", "description": "us-central1-a", "id": "13462829244527433283", "kind": "compute#zone", "name": "us-central1-a", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "status": "UP" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_diskTypes.json0000664000175000017500000000213613535474530032021 0ustar kamikami00000000000000{ "kind": "compute#diskTypeList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes", "id": "projects/project_name/zones/us-central1-a/diskTypes", "items": [ { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-ssd", "description": "SSD Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-ssd", "defaultDiskSizeGb": "100" }, { "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.530-07:00", "name": "pd-standard", "description": "Standard Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-standard", "defaultDiskSizeGb": "500" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_diskTypes_pd_ssd.json0000664000175000017500000000064513535474530033360 0ustar kamikami00000000000000{ "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-ssd", "description": "SSD Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-ssd", "defaultDiskSizeGb": "100" } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_diskTypes_pd_standard.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_diskTypes_pd_standard.j0000664000175000017500000000066413535474530033650 0ustar kamikami00000000000000{ "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-standard", "description": "Standard Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-standard", "defaultDiskSizeGb": "500" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks.json0000664000175000017500000000314713535474530031162 0ustar kamikami00000000000000{ "id": "projects/project_name/zones/us-central1-a/disks", "items": [ { "creationTimestamp": "2013-12-13T10:45:42.139-08:00", "id": "08045379695757218000", "kind": "compute#disk", "name": "lcdisk", "description": "I'm a happy little SSD", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-ssd", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "sizeGb": "10", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }, { "creationTimestamp": "2013-12-13T10:45:20.308-08:00", "description": "Image: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "id": "0265567475385851075", "kind": "compute#disk", "name": "node-name", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-standard", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", "sizeGb": "10", "sourceImage": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131120", "sourceImageId": "17312518942796567788", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ], "kind": "compute#diskList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk.json0000664000175000017500000000102413535474530032503 0ustar kamikami00000000000000{ "creationTimestamp": "2013-06-26T10:06:04.007-07:00", "id": "16109451798967042451", "kind": "compute#disk", "name": "lcdisk", "description": "I'm a happy little SSD", "type": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-ssd", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "sizeGb": "10", "status": "READY", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_createSnapshot_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_createSnap0000664000175000017500000000146113535474530033705 0ustar kamikami00000000000000{ "id": "0158330665043557584", "insertTime": "2013-12-16T13:03:51.000-08:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", "operationType": "createSnapshot", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_createSnapshot_post", "startTime": "2013-12-16T13:03:51.042-08:00", "status": "PENDING", "targetId": "07494414044179227172", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_delete.jso0000664000175000017500000000135713535474530033660 0ustar kamikami00000000000000{ "id": "06887337364510109333", "insertTime": "2013-06-26T10:06:11.835-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_disks_lcdisk_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_delete", "startTime": "2013-06-26T10:06:12.006-07:00", "status": "PENDING", "targetId": "16109451798967042451", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_resize_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_resize_pos0000664000175000017500000000143313570310635033773 0ustar kamikami00000000000000{ "id": "4992266504414588438", "insertTime": "2019-07-02T14:47:37.095-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_disks_lcdisk_resize_post", "operationType": "resizeDisk", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_resize_post", "startTime": "2019-07-02T14:47:37.111-07:00", "status": "PENDING", "targetId": "904434546113910404", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_setLabel_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_lcdisk_setLabel_p0000664000175000017500000000151613577507766033711 0ustar kamikami00000000000000{ "id": "0158330665043557584", "name": "operation-zones_us-central1-a_disks_lcdisk_setLabels_post", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setLabels", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "targetId": "6142245483972904501", "status": "DONE", "user": "487551519631-t6qvu2na6p4u9ptm46bsdujf0ohbdro7@developer.gserviceaccount.com", "progress": 100, "insertTime": "2019-11-27T05:23:41.870-08:00", "startTime": "2019-11-27T05:23:41.873-08:00", "endTime": "2019-11-27T05:23:41.873-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_lcdisk_setLabels_post", "kind": "compute#operation" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disks_post.json0000664000175000017500000000126613535474530032227 0ustar kamikami00000000000000{ "id": "0211151278250678078", "insertTime": "2013-06-26T16:48:17.403-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_disks_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_disks_post", "startTime": "2013-06-26T16:48:17.479-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_disktypes_pd-ssd.json0000664000175000017500000000064513535474530033336 0ustar kamikami00000000000000{ "kind": "compute#diskType", "creationTimestamp": "2014-06-02T11:07:28.529-07:00", "name": "pd-ssd", "description": "SSD Persistent Disk", "validDiskSize": "10GB-10240GB", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/diskTypes/pd-ssd", "defaultDiskSizeGb": "100" } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers.j0000664000175000017500000000225013535474530033616 0ustar kamikami00000000000000{ "kind": "compute#instanceGroupManagerList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroupManagers", "id": "projects/project_name/zones/us-central1-a/instanceGroupManagers", "items": [ { "kind": "compute#instanceGroupManager", "id": "8588434319274454491", "creationTimestamp": "2016-07-18T10:34:44.679-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "name": "myinstancegroup", "instanceTemplate": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1", "instanceGroup": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup", "baseInstanceName": "myinstancegroup", "fingerprint": "5bKcxzAnGOg=", "currentActions": { "none": 2, "creating": 0, "recreating": 0, "deleting": 0, "abandoning": 0, "restarting": 0, "refreshing": 0 }, "targetSize": 2, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroupManagers/myinstancegroup" } ] } ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_insert.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_i0000664000175000017500000000163013535474530033677 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "5029726187056811377", "name": "operation-zones_us-central1-a_instanceGroupManagers_insert_post", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "compute.instanceGroupManagers.insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroupManagers/managed-instance-group-1", "targetId": "1549031063416753526", "status": "PENDING", "user": "999999-compute@developer.gserviceaccount.com", "progress": 90, "insertTime": "2016-08-12T09:04:46.114-07:00", "startTime": "2016-08-12T09:04:46.117-07:00", "endTime": "2016-08-12T09:04:46.117-07:00", "selfLink" : "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instanceGroupManagers_insert_post" } ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_myinstancegroup.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_m0000664000175000017500000000171613535474530033710 0ustar kamikami00000000000000{ "kind": "compute#instanceGroupManager", "id": "8604381270851510464", "creationTimestamp": "2016-07-18T15:54:39.153-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "name": "myinstancegroup", "description": "my description for myinstancegroup", "instanceTemplate": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1", "instanceGroup": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup", "baseInstanceName": "base-foo", "fingerprint": "Q21hYveq9do=", "currentActions": { "none": 4, "creating": 0, "recreating": 0, "deleting": 0, "abandoning": 0, "restarting": 0, "refreshing": 0 }, "targetSize": 4, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroupManagers/myinstancegroup" } ././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_myinstancegroup_shared_network.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroupManagers_m0000664000175000017500000000201113535474530033675 0ustar kamikami00000000000000{ "kind": "compute#instanceGroupManager", "id": "8604381270851510465", "creationTimestamp": "2016-07-18T15:54:39.153-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "name": "myinstancegroup-shared-network", "description": "my description for myinstancegroup", "instanceTemplate": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template-shared-network", "instanceGroup": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup-shared-network", "baseInstanceName": "base-foo", "fingerprint": "Q21hYveq9do=", "currentActions": { "none": 4, "creating": 0, "recreating": 0, "deleting": 0, "abandoning": 0, "restarting": 0, "refreshing": 0 }, "targetSize": 4, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroupManagers/myinstancegroup-shared-network" } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstancegroup.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstanc0000664000175000017500000000164613535474530034005 0ustar kamikami00000000000000{ "kind": "compute#instanceGroup", "id": "1968709502073089769", "creationTimestamp": "2016-08-11T16:53:42.413-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "name": "myinstancegroup", "description": "This instance group is controlled by Instance Group Manager 'myinstancegroup'. To modify instances in this group, use the Instance Group Manager API: https://cloud.google.com/compute/docs/reference/latest/instanceGroupManagers", "network": "https://content.googleapis.com/compute/v1/projects/project_name/global/networks/default", "fingerprint": "42WmSpB8rSM=", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup", "size": 4, "subnetwork": "https://content.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112" } ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstancegroup2.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstanc0000664000175000017500000000132613535474530034000 0ustar kamikami00000000000000{ "kind": "compute#instanceGroup", "id": "1968709502073089768", "creationTimestamp": "2016-08-26T16:53:42.413-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "name": "myinstancegroup2", "description": "myinstancegroup2", "network": "https://content.googleapis.com/compute/v1/projects/project_name/global/networks/default", "fingerprint": "42WmSpB8rSN=", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup2", "size": 4, "subnetwork": "https://content.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112" } ././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstancegroup_shared_network.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instanceGroup_myinstanc0000664000175000017500000000171513535474530034002 0ustar kamikami00000000000000{ "kind": "compute#instanceGroup", "id": "1968709502073089770", "creationTimestamp": "2016-08-11T16:53:42.413-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "name": "myinstancegroup_shared_network", "description": "This instance group is controlled by Instance Group Manager 'myinstancegroup'. To modify instances in this group, use the Instance Group Manager API: https://cloud.google.com/compute/docs/reference/latest/instanceGroupManagers", "network": "https://www.googleapis.com/compute/v1/projects/other_name/global/networks/shared_network_for_mig", "subnetwork": "https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1/subnetworks/shared_subnetwork_for_mig", "fingerprint": "42WmSpB8rSM=", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myinstancegroup_shared_network", "size": 4 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances.json0000664000175000017500000000366113570310635032027 0ustar kamikami00000000000000{ "id": "projects/project_name/zones/us-central1-a/instances", "items": [ { "canIpForward": false, "creationTimestamp": "2013-12-13T10:45:23.351-08:00", "disks": [ { "boot": true, "deviceName": "persistent-disk-0", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", "type": "PERSISTENT" } ], "id": "4006034190819017667", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "node-name", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.15", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.72.75" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "status": "RUNNING", "cpuPlatform": "Intel Skylake", "minCpuPlatform": "Intel Skylake", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ], "kind": "compute#instanceList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances" } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000.js0000664000175000017500000000270113535474530033313 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:54:07.687-08:00", "disks": [ { "boot": true, "deviceName": "lcnode-000", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcnode-000", "type": "PERSISTENT" } ], "id": "17170905942674172532", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "lcnode-000", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "173.255.114.35", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.160.66" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-000", "status": "RUNNING", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-000_de0000664000175000017500000000140513535474530033350 0ustar kamikami00000000000000{ "id": "3319596145594427549", "insertTime": "2013-06-26T16:13:12.903-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_lcnode-000_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-000_delete", "startTime": "2013-06-26T16:13:12.948-07:00", "status": "PENDING", "targetId": "5390075309006132922", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-000", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001.js0000664000175000017500000000270113535474530033314 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:54:08.639-08:00", "disks": [ { "boot": true, "deviceName": "lcnode-001", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcnode-001", "type": "PERSISTENT" } ], "id": "09356229693786319079", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "lcnode-001", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "173.255.117.19", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.168.208" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", "status": "RUNNING", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_lcnode-001_de0000664000175000017500000000140713535474530033353 0ustar kamikami00000000000000{ "id": "17469711273432628502", "insertTime": "2013-06-26T16:13:40.579-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_lcnode-001_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_lcnode-001_delete", "startTime": "2013-06-26T16:13:40.620-07:00", "status": "PENDING", "targetId": "16630486471904253898", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name.jso0000664000175000017500000000270013535474530033573 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:45:23.351-08:00", "disks": [ { "boot": true, "deviceName": "persistent-disk-0", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", "type": "PERSISTENT" } ], "id": "4006034190819017667", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "node-name", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.15", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.72.75" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "status": "RUNNING", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_attachDisk_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_att0000664000175000017500000000143013535474530033650 0ustar kamikami00000000000000{ "id": "7455886659787654716", "insertTime": "2013-06-26T16:48:27.691-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_attachDisk_post", "operationType": "attachDisk", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_attachDisk_post", "startTime": "2013-06-26T16:48:27.762-07:00", "status": "PENDING", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_del0000664000175000017500000000140413535474530033625 0ustar kamikami00000000000000{ "id": "6999931397447918763", "insertTime": "2013-06-26T10:05:40.350-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_delete", "operationType": "delete", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_delete", "startTime": "2013-06-26T10:05:40.405-07:00", "status": "PENDING", "targetId": "07410051435384876224", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_detachDisk_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_det0000664000175000017500000000143013535474530033634 0ustar kamikami00000000000000{ "id": "3921383727105838816", "insertTime": "2013-06-26T16:48:35.357-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_detachDisk_post", "operationType": "detachDisk", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_detachDisk_post", "startTime": "2013-06-26T16:48:35.398-07:00", "status": "PENDING", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_reset_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_res0000664000175000017500000000141213535474530033651 0ustar kamikami00000000000000{ "id": "10507122129283663728", "insertTime": "2013-06-26T15:03:02.766-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_reset_post", "operationType": "reset", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_reset_post", "startTime": "2013-06-26T15:03:02.813-07:00", "status": "PENDING", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_setTags_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node-name_set0000664000175000017500000000141713535474530033660 0ustar kamikami00000000000000{ "id": "8115150846190320932", "insertTime": "2013-06-26T21:20:03.962-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_node-name_setTags_post", "operationType": "setTags", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_node-name_setTags_post", "startTime": "2013-06-26T21:20:04.103-07:00", "status": "PENDING", "targetId": "1845312225624811608", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node_name_getSerialOutput.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_node_name_get0000664000175000017500000000033613535474530033725 0ustar kamikami00000000000000{ "kind": "compute#serialPortOutput", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name/serialPort", "contents": "This is some serial\r\noutput for you." } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_post.json0000664000175000017500000000130613535474530033074 0ustar kamikami00000000000000{ "id": "1858155812259649243", "insertTime": "2013-06-26T16:12:51.492-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_instances_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instances_post", "startTime": "2013-06-26T16:12:51.537-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", "user": "897001307951@developer.gserviceaccount.com", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_sn-node-name.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_instances_sn-node-name.0000664000175000017500000000311613535474530033477 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:45:23.351-08:00", "disks": [ { "boot": true, "deviceName": "persistent-disk-0", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/node-name", "type": "PERSISTENT" } ], "id": "4006034190819017667", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "sn-node-name", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.15", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "subnetwork": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112", "networkIP": "10.240.72.75" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/sn-node-name", "status": "RUNNING", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes.json0000664000175000017500000003645513535474530032506 0ustar kamikami00000000000000{ "id": "projects/project_name/zones/us-central1-a/machineTypes", "items": [ { "creationTimestamp": "2013-04-25T13:32:49.088-07:00", "description": "1 vCPU (shared physical core) and 0.6 GB RAM", "guestCpus": 1, "id": "1133568312750571513", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 614, "name": "f1-micro", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/f1-micro", "zone": "us-central1-a" }, { "creationTimestamp": "2013-04-25T13:32:45.550-07:00", "description": "1 vCPU (shared physical core) and 1.7 GB RAM", "guestCpus": 1, "id": "1500265464823777597", "imageSpaceGb": 0, "kind": "compute#machineType", "maximumPersistentDisks": 4, "maximumPersistentDisksSizeGb": "3072", "memoryMb": 1740, "name": "g1-small", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/g1-small", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:46:10.572-08:00", "description": "2 vCPUs, 1.8 GB RAM", "guestCpus": 2, "id": "16898271314080235997", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:47:07.825-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 1.8 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "15178384466070744001", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 1843, "name": "n1-highcpu-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-2-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:48:06.087-08:00", "description": "4 vCPUs, 3.6 GB RAM", "guestCpus": 4, "id": "04759000181765218034", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:49:07.563-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4", "state": "DEPRECATED" }, "description": "4 vCPUS, 3.6 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "01151097524490134507", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3686, "name": "n1-highcpu-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-4-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:50:15.128-08:00", "description": "8 vCPUs, 7.2 GB RAM", "guestCpus": 8, "id": "01206886442411821831", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:51:04.549-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8", "state": "DEPRECATED" }, "description": "8 vCPUS, 7.2 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "02507333096579477005", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7373, "name": "n1-highcpu-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highcpu-8-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:40:06.129-08:00", "description": "2 vCPUs, 13 GB RAM", "guestCpus": 2, "id": "05438694236916301519", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:40:59.630-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 13 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "00770157291441082211", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 13312, "name": "n1-highmem-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-2-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:42:08.983-08:00", "description": "4 vCPUs, 26 GB RAM", "guestCpus": 4, "id": "11556032176405786676", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:43:17.400-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 26 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "05095504563332567951", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 26624, "name": "n1-highmem-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-4-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:44:25.985-08:00", "description": "8 vCPUs, 52 GB RAM", "guestCpus": 8, "id": "01717932668777642040", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", "zone": "us-central1-a" }, { "creationTimestamp": "2012-11-16T11:45:08.195-08:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8", "state": "DEPRECATED" }, "description": "8 vCPUs, 52 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "07181827135536388552", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 53248, "name": "n1-highmem-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-highmem-8-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:48:34.258-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "state": "DEPRECATED" }, "description": "1 vCPU, 3.75 GB RAM, 1 scratch disk (420 GB)", "guestCpus": 1, "id": "10583029372018866711", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1-d", "scratchDisks": [ { "diskGb": 420 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:48:56.867-07:00", "description": "2 vCPUs, 7.5 GB RAM", "guestCpus": 2, "id": "17936898073622676356", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:49:19.448-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2", "state": "DEPRECATED" }, "description": "2 vCPUs, 7.5 GB RAM, 1 scratch disk (870 GB)", "guestCpus": 2, "id": "06313284160910191442", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 7680, "name": "n1-standard-2-d", "scratchDisks": [ { "diskGb": 870 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-2-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:49:40.050-07:00", "description": "4 vCPUs, 15 GB RAM", "guestCpus": 4, "id": "09494636486174545828", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:50:05.677-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4", "state": "DEPRECATED" }, "description": "4 vCPUs, 15 GB RAM, 1 scratch disk (1770 GB)", "guestCpus": 4, "id": "00523085164784013586", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 15360, "name": "n1-standard-4-d", "scratchDisks": [ { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-4-d", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:50:42.334-07:00", "description": "8 vCPUs, 30 GB RAM", "guestCpus": 8, "id": "04084282969223214132", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 30720, "name": "n1-standard-8", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-8", "zone": "us-central1-a" }, { "creationTimestamp": "2012-06-07T13:51:19.936-07:00", "deprecated": { "deprecated": "2013-12-02T20:00:00-08:00", "replacement": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-8", "state": "DEPRECATED" }, "description": "8 vCPUs, 30 GB RAM, 2 scratch disks (1770 GB, 1770 GB)", "guestCpus": 8, "id": "00035824420671580077", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 30720, "name": "n1-standard-8-d", "scratchDisks": [ { "diskGb": 1770 }, { "diskGb": 1770 } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-8-d", "zone": "us-central1-a" } ], "kind": "compute#machineTypeList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes" }././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standar0000664000175000017500000000073413535474530033555 0ustar kamikami00000000000000{ "creationTimestamp": "2012-06-07T13:48:14.670-07:00", "description": "1 vCPU, 3.75 GB RAM", "guestCpus": 1, "id": "11077240422128681563", "imageSpaceGb": 10, "kind": "compute#machineType", "maximumPersistentDisks": 16, "maximumPersistentDisksSizeGb": "10240", "memoryMb": 3840, "name": "n1-standard-1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "zone": "us-central1-a" }././@LongLink0000000000000000000000000000023500000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_operations_operation_zones_us-central1-a_instanceGroupManagers_insert_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_operations_operation_zo0000664000175000017500000000162613535474530034050 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "5029726187056811377", "name": "operation-zones_us-central1-a_instanceGroupManagers_insert_post", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "compute.instanceGroupManagers.insert", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroupManagers/managed-instance-group-1", "targetId": "1549031063416753526", "status": "DONE", "user": "999999-compute@developer.gserviceaccount.com", "progress": 100, "insertTime": "2016-08-12T09:04:46.114-07:00", "startTime": "2016-08-12T09:04:46.117-07:00", "endTime": "2016-08-12T09:04:46.117-07:00", "selfLink" : "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_instanceGroupManagers_insert_post" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances.json0000664000175000017500000000240313535474530033175 0ustar kamikami00000000000000{ "kind": "compute#targetInstanceList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances", "id": "projects/project_name/zones/us-central1-a/targetInstances", "items": [ { "kind": "compute#targetInstance", "id": "8092539649535704539", "creationTimestamp": "2014-08-07T12:46:10.372-07:00", "name": "hello", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "natPolicy": "NO_NAT", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/hello" }, { "kind": "compute#targetInstance", "id": "9539205115599811578", "creationTimestamp": "2014-08-07T13:09:19.634-07:00", "name": "lctargetinstance", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "natPolicy": "NO_NAT", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/lctargetinstance" } ] } ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_lctargetinstance.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_lctarge0000664000175000017500000000100113535474530033717 0ustar kamikami00000000000000{ "kind": "compute#targetInstance", "id": "9539205115599811578", "creationTimestamp": "2014-08-07T13:09:19.634-07:00", "name": "lctargetinstance", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "natPolicy": "NO_NAT", "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/lctargetinstance" } ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_lctargetinstance_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_lctarge0000664000175000017500000000140713535474530033731 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "16305469717066123402", "name": "operation-zones_us-central1-a_targetInstances_lctargetinstance_delete", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "delete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/lctargetinstance", "targetId": "8092539649535704539", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2014-11-14T13:05:18.564-08:00", "startTime": "2014-11-14T13:05:18.868-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_targetInstances_lctargetinstance_delete" } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-a_targetInstances_post.js0000664000175000017500000000131713535474530033710 0ustar kamikami00000000000000{ "id": "7487852523793007955", "insertTime": "2013-09-03T00:51:05.064-07:00", "kind": "compute#operation", "name": "operation-zones_us-central1-a_targetInstances_post", "operationType": "insert", "progress": 0, "region": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us-central1-a_targetInstances_post", "startTime": "2013-09-03T00:51:05.115-07:00", "status": "PENDING", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/targetInstances/lctargetinstance", "user": "user@gserviceaccount.com" } ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instanceGroupManagers_myinstancegroup.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instanceGroupManagers_m0000664000175000017500000000171613535474530033711 0ustar kamikami00000000000000{ "kind": "compute#instanceGroupManager", "id": "8604381270851510464", "creationTimestamp": "2016-07-18T15:54:39.153-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", "name": "myinstancegroup", "description": "my description for myinstancegroup", "instanceTemplate": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1", "instanceGroup": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instanceGroups/myinstancegroup", "baseInstanceName": "base-foo", "fingerprint": "Q21hYveq9do=", "currentActions": { "none": 4, "creating": 0, "recreating": 0, "deleting": 0, "abandoning": 0, "restarting": 0, "refreshing": 0 }, "targetSize": 4, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instanceGroupManagers/myinstancegroup" } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instanceGroup_myinstancegroup.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instanceGroup_myinstanc0000664000175000017500000000165713535474530034010 0ustar kamikami00000000000000{ "kind": "compute#instanceGroup", "id": "1968709502073089769", "creationTimestamp": "2016-08-11T16:53:42.413-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b", "name": "managed-instance-group-1", "description": "This instance group is controlled by Instance Group Manager 'myinstancegroup'. To modify instances in this group, use the Instance Group Manager API: https://cloud.google.com/compute/docs/reference/latest/instanceGroupManagers", "network": "https://content.googleapis.com/compute/v1/projects/project_name/global/networks/default", "fingerprint": "42WmSpB8rSM=", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instanceGroups/myinstancegroup", "size": 4, "subnetwork": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112" } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-000.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-d0000664000175000017500000000332513535474530033554 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:51:24.339-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-lb-demo-www-000", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/libcloud-lb-demo-www-000", "type": "PERSISTENT" } ], "id": "08447900841145802741", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", "metadata": { "fingerprint": "IZjMMp0A_8k=", "items": [ { "key": "startup-script", "value": "apt-get -y update && apt-get -y install apache2 && hostname > /var/www/index.html" } ], "kind": "compute#metadata" }, "name": "libcloud-lb-demo-www-000", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.15", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.104.11" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-000", "status": "RUNNING", "tags": { "fingerprint": "XI0he92M8l8=", "items": [ "libcloud-lb-demo-www" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" }././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-001.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-d0000664000175000017500000000332613535474530033555 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:51:25.165-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-lb-demo-www-001", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/libcloud-lb-demo-www-001", "type": "PERSISTENT" } ], "id": "11523404878553997348", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", "metadata": { "fingerprint": "09vSzO6KXcw=", "items": [ { "key": "startup-script", "value": "apt-get -y update && apt-get -y install apache2 && hostname > /var/www/index.html" } ], "kind": "compute#metadata" }, "name": "libcloud-lb-demo-www-001", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.59", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.94.107" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-demo-www-001", "status": "RUNNING", "tags": { "fingerprint": "XI0he92M8l8=", "items": [ "libcloud-lb-demo-www" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-demo-www-002.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-d0000664000175000017500000000060113535474530033546 0ustar kamikami00000000000000{ "error": { "code": 404, "errors": [ { "domain": "global", "message": "The resource 'projects/project-name/zones/us-central1-b/instances/libcloud-lb-demo-www-002' was not found", "reason": "notFound" } ], "message": "The resource 'projects/project-name/zones/us-central1-b/instances/libcloud-lb-demo-www-002' was not found" } } ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-nopubip-001.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-central1-b_instances_libcloud-lb-n0000664000175000017500000000301313535474530033560 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:51:25.165-08:00", "disks": [ { "boot": true, "deviceName": "libcloud-lb-demo-www-001", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/disks/libcloud-lb-demo-www-001", "type": "PERSISTENT" } ], "id": "11523404878663997348", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/machineTypes/n1-standard-1", "metadata": { "fingerprint": "09vSzO6KXcw=", "items": [ { "key": "startup-script", "value": "apt-get -y update && apt-get -y install apache2 && hostname > /var/www/index.html" } ], "kind": "compute#metadata" }, "name": "libcloud-lb-nopubip-001", "networkInterfaces": [ { "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.94.66" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b/instances/libcloud-lb-nopubip-001", "status": "RUNNING", "tags": { "fingerprint": "XI0he92M8l8=", "items": [ "libcloud-lb-demo-www" ] }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-b" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-east1-b.json0000664000175000017500000000054013535474530027264 0ustar kamikami00000000000000{ "kind": "compute#zone", "id": "2231", "creationTimestamp": "2015-09-08T16:57:06.746-07:00", "name": "us-east1-b", "description": "us-east1-b", "status": "UP", "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-east1", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-east1-b_instanceGroupManagers.json0000664000175000017500000000223113535474530033642 0ustar kamikami00000000000000{ "kind": "compute#instanceGroupManagerList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b/instanceGroupManagers", "id": "projects/project_name/zones/us-east1-b/instanceGroupManagers", "items": [ { "kind": "compute#instanceGroupManager", "id": "8588434319274454491", "creationTimestamp": "2016-07-18T10:34:44.679-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b", "name": "myinstancegroup", "instanceTemplate": "https://content.googleapis.com/compute/v1/projects/project_name/global/instanceTemplates/my-instance-template1", "instanceGroup": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b/instanceGroups/myinstancegroup", "baseInstanceName": "myinstancegroup", "fingerprint": "5bKcxzAnGOg=", "currentActions": { "none": 2, "creating": 0, "recreating": 0, "deleting": 0, "abandoning": 0, "restarting": 0, "refreshing": 0 }, "targetSize": 2, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b/instanceGroupManagers/myinstancegroup" } ] } ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-east1-b_instanceGroup_myinstancegroup.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us-east1-b_instanceGroup_myinstancegr0000664000175000017500000000164613535474530034010 0ustar kamikami00000000000000{ "kind": "compute#instanceGroup", "id": "1968709502073089769", "creationTimestamp": "2016-08-11T16:53:42.413-07:00", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b", "name": "managed-instance-group-1", "description": "This instance group is controlled by Instance Group Manager 'myinstancegroup'. To modify instances in this group, use the Instance Group Manager API: https://cloud.google.com/compute/docs/reference/latest/instanceGroupManagers", "network": "https://content.googleapis.com/compute/v1/projects/project_name/global/networks/default", "fingerprint": "42WmSpB8rSM=", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-east1-b/instanceGroups/myinstancegroup", "size": 4, "subnetwork": "https://content.googleapis.com/compute/v1/projects/project_name/regions/us-east1/subnetworks/cf-972cf02e6ad49113" } ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_acceleratorTypes_nvidia_tesla_k80.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_acceleratorTypes_nvidia0000664000175000017500000000066413535474530034105 0ustar kamikami00000000000000{ "kind": "compute#acceleratorType", "description": "NVIDIA Tesla K80", "creationTimestamp": "1969-12-31T16:00:00.000-08:00", "maximumCardsPerInstance": 8, "name": "nvidia-tesla-k80", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/acceleratorTypes/nvidia-tesla-k80", "id": "10002" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups.json0000664000175000017500000000244113535474530033211 0ustar kamikami00000000000000{ "id": "projects/project_name/zones/us-central1-a/instanceGroups", "items": [ { "creationTimestamp": "2016-09-09T13:48:39.700-07:00", "description": "", "fingerprint": "42WmSpB8rSM=", "id": "5837905299775594184", "kind": "compute#instanceGroup", "name": "myname", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "size": 0, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" }, { "creationTimestamp": "2016-09-09T13:54:30.857-07:00", "description": "", "fingerprint": "42WmSpB8rSM=", "id": "6825641674983513961", "kind": "compute#instanceGroup", "name": "myname2", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname2", "size": 0, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ], "kind": "compute#instanceGroupList", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups" } ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_insert.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_insert.j0000664000175000017500000000115513535474530034056 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones_us_central1_a/instanceGroups/myname", "operationType": "compute.instanceGroups.insert", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_insert", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname.j0000664000175000017500000000067313535474530034044 0ustar kamikami00000000000000{ "kind": "compute#instanceGroup", "id": "5837905299775594184", "creationTimestamp": "2016-09-09T13:48:39.700-07:00", "name": "myname", "description": "", "fingerprint": "42WmSpB8rSM=", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "size": 0 } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_addInstances.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_a0000664000175000017500000000117113535474530034106 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.addInstances", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_addInstances", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_d0000664000175000017500000000115513535474530034113 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.delete", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_delete", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_listInstances.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_l0000664000175000017500000000122313535474530034117 0ustar kamikami00000000000000{ "id": "projects/project_name/zones/us-central1-a/instanceGroups/myname/listInstances", "items": [ { "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "status": "RUNNING" }, { "instance": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/lcnode-001", "status": "RUNNING" } ], "kind": "compute#instanceGroupsListInstances", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname/listInstances" } ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_removeInstances.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_r0000664000175000017500000000117713535474530034135 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.removeInstances", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_removeInstances", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_setNamedPorts.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instanceGroups_myname_s0000664000175000017500000000117313535474530034132 0ustar kamikami00000000000000{ "status": "DONE", "kind": "compute#operation", "name": "myname", "zone": "us-central1-a", "insertTime": "2016-09-02T09:31:52.285-07:00", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instanceGroups/myname", "operationType": "compute.instanceGroups.setNamedPorts", "progress": 100, "id": 123456, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-zones_us_central1_a_instanceGroups_myname_setNamedPorts", "user": "1264195755357-compute@developer.gserviceaccount.com" }././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_custom_node.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_custom_node.j0000664000175000017500000000270513535474530034056 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:45:23.351-08:00", "disks": [ { "boot": true, "deviceName": "persistent-disk-0", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "type": "PERSISTENT" } ], "id": "4006034190819017667", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "custom-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.15", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.72.75" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/custom-node", "status": "TERMINATED", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setDiskAutoDelete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_set0000664000175000017500000000135613535474530034110 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "14265294323024381703", "name": "operation-volume-auto-delete", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setDiskAutoDelete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/dev-test", "targetId": "4313186599918690450", "status": "PENDING", "user": "user@developer.gserviceaccount.com", "progress": 0, "insertTime": "2014-03-13T21:50:57.612-07:00", "startTime": "2014-03-13T21:50:57.717-07:00", "endTime": "2014-03-13T21:50:58.047-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-volume-auto-delete" } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setLabels_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_set0000664000175000017500000000122513535474530034103 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setLabelspost", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setLabels_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "PENDING", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name/setLabels", "user": "foo@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setMachineType.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_set0000664000175000017500000000127713535474530034112 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-setMachineType-notstopped", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setMachineType", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "targetId": "12335588484913203363", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setMachineType-notstopped" } ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setMetadata_post.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_set0000664000175000017500000000123413535474530034103 0ustar kamikami00000000000000{ "endTime": "2013-06-26T10:05:07.630-07:00", "id": "3681664092089171723", "insertTime": "2013-06-26T10:05:03.271-07:00", "kind": "compute#operation", "name": "operation-setMetadata_post", "operationType": "insert", "progress": 0, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setMetadata_post", "startTime": "2013-06-26T10:05:03.315-07:00", "status": "PENDING", "targetId": "16211908079305042870", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name/setMetadata", "user": "foo@developer.gserviceaccount.com" } ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_stop.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_sto0000664000175000017500000000122313535474530034113 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-stopnode", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "stop", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "targetId": "12335588484913203363", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-stopnode" } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node.0000664000175000017500000000270713535474530034052 0ustar kamikami00000000000000{ "canIpForward": false, "creationTimestamp": "2013-12-13T10:45:23.351-08:00", "disks": [ { "boot": true, "deviceName": "persistent-disk-0", "index": 0, "kind": "compute#attachedDisk", "mode": "READ_WRITE", "source": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/disks/lcdisk", "type": "PERSISTENT" } ], "id": "4006034190819017667", "kind": "compute#instance", "machineType": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", "metadata": { "fingerprint": "42WmSpB8rSM=", "kind": "compute#metadata" }, "name": "stopped-node", "networkInterfaces": [ { "accessConfigs": [ { "kind": "compute#accessConfig", "name": "External NAT", "natIP": "23.236.58.15", "type": "ONE_TO_ONE_NAT" } ], "name": "nic0", "network": "https://www.googleapis.com/compute/v1/projects/project_name/global/networks/default", "networkIP": "10.240.72.75" } ], "scheduling": { "automaticRestart": true, "onHostMaintenance": "MIGRATE" }, "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", "status": "TERMINATED", "tags": { "fingerprint": "42WmSpB8rSM=" }, "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a" } ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_setMachineType.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_0000664000175000017500000000125413535474530034127 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-setMachineType", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setMachineType", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", "targetId": "12335588484913203363", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setMachineType" } ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_start.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_0000664000175000017500000000123113535474530034122 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-startnode", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "start", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", "targetId": "12335588484913203363", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-startnode" } ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_stop.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_stopped_node_0000664000175000017500000000122613535474530034126 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-stopnode", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "stop", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", "targetId": "12335588484913203363", "status": "PENDING", "user": "erjohnso@google.com", "progress": 0, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-stopnode" } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_setMachineType.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_se0000664000175000017500000000125313535474530034167 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-setMachineType", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setMachineType", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", "targetId": "12335588484913203363", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setMachineType" } ././@LongLink0000000000000000000000000000020100000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_setMachineType_notstopped.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_se0000664000175000017500000000176013535474530034172 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "1122640775725896976", "name": "operation-setMachineType-notstopped", "zone": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setMachineType", "targetLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "targetId": "10940055899777330894", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2016-03-07T08:09:34.445-08:00", "startTime": "2016-03-07T08:09:34.679-08:00", "endTime": "2016-03-07T08:09:35.161-08:00", "error": { "errors": [ { "code": "RESOURCE_NOT_READY", "message": "The resource 'projects/project_name/zones/us-central1-a/instances/node-name' is not ready" } ] }, "httpErrorStatusCode": 400, "httpErrorMessage": "BAD REQUEST", "selfLink": "https://content.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setMachineType-notstopped" } ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_startnode.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_st0000664000175000017500000000123013535474530034201 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-startnode", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "start", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/stopped-node", "targetId": "12335588484913203363", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-startnode" } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_stopnode.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_st0000664000175000017500000000122213535474530034202 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "18431811683007150988", "name": "operation-stopnode", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "stop", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name", "targetId": "12335588484913203363", "status": "DONE", "user": "erjohnso@google.com", "progress": 100, "insertTime": "2015-01-30T06:55:11.503-08:00", "startTime": "2015-01-30T06:55:11.847-08:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-stopnode" } ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_volume_auto_delete.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/gce/zones_us_central1_a_operations_operation_vo0000664000175000017500000000135513535474530034207 0ustar kamikami00000000000000{ "kind": "compute#operation", "id": "14265294323024381703", "name": "operation-volume-auto-delete", "zone": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a", "operationType": "setDiskAutoDelete", "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/dev-test", "targetId": "4313186599918690450", "status": "DONE", "user": "user@developer.gserviceaccount.com", "progress": 100, "insertTime": "2014-03-13T21:50:57.612-07:00", "startTime": "2014-03-13T21:50:57.717-07:00", "endTime": "2014-03-13T21:50:58.047-07:00", "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-volume-auto-delete" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/0000775000175000017500000000000013600223624023775 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/image_list.json0000664000175000017500000001274513535474530027031 0ustar kamikami00000000000000{ "list": [ { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, { "billingtokens": [ { "id": 47, "name": "CentOS 5.3 64bit", "price": 0 } ], "description": "CentOS 5.3 (64-bit) w/ None", "friendlyName": "CentOS 5.3 (64-bit) w/ None", "id": 1532, "isActive": true, "isPublic": true, "location": "gogrid/GSI-939ef909-84b8-4a2f-ad56-02ccd7da05ff.img", "name": "centos5.3_64_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (64-bit)", "id": 17, "name": "CentOS 5.3 (64-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789076417 }, { "billingtokens": [ { "id": 48, "name": "RHEL 5.4 32bit", "price": 0 } ], "description": "RHEL 5.4 (32-bit) w/ None", "friendlyName": "RHEL 5.4 (32-bit) w/ None", "id": 1533, "isActive": true, "isPublic": true, "location": "gogrid/GSI-4c88cb92-dd7b-4bb1-95b6-7cc93eb1d2aa.img", "name": "rhel5.4_32_base", "object": "serverimage", "os": { "description": "RHEL 5.4 (32-bit)", "id": 18, "name": "RHEL 5.4 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789076417 }, { "billingtokens": [ { "id": 49, "name": "RHEL 5.4 64bit", "price": 0 } ], "description": "RHEL 5.4 (64-bit) w/ None", "friendlyName": "RHEL 5.4 (64-bit) w/ None", "id": 1534, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2bd8ddb3-cc53-4a76-8188-0dce7537a422.img", "name": "rhel5.4_64_base", "object": "serverimage", "os": { "description": "RHEL 5.4 (64-bit)", "id": 19, "name": "RHEL 5.4 (64-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789076417 } ], "method": "/grid/image/list", "status": "success", "summary": { "numpages": 0, "returned": 59, "start": 0, "total": 59 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/image_save.json0000664000175000017500000000344113535474530027005 0ustar kamikami00000000000000{ "list": [ { "architecture": { "description": "32 bit OS", "id": 1, "name": "32-bit", "object": "option" }, "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "object": "billingtoken", "price": 0 } ], "createdTime": 1289119839685, "description": "", "friendlyName": "testimage", "id": 5050, "isActive": true, "isPublic": false, "location": "123/GSI-3ee65927-f80d-43df-92df-6c7e352f009c.img", "name": "GSI-3ee65927-f80d-43df-92df-6c7e352f009c", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": 123, "name": "name", "object": "customer" }, "price": 0, "state": { "description": "Image is being saved", "id": 1, "name": "Saving", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1289119839685 } ], "method": "/grid/image/save", "status": "success", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/ip_list.json0000664000175000017500000000367013535474530026354 0ustar kamikami00000000000000{ "list": [ { "datacenter": { "description": "US West 1 Datacenter", "id": 1, "name": "US-West-1", "object": "option" }, "id": 5348099, "ip": "192.168.75.66", "object": "ip", "public": true, "state": { "description": "IP is available to use", "id": 1, "name": "Unassigned", "object": "option" }, "subnet": "192.168.75.64/255.255.255.240" }, { "datacenter": { "description": "US West 1 Datacenter", "id": 1, "name": "US-West-1", "object": "option" }, "id": 5348100, "ip": "192.168.75.67", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.75.64/255.255.255.240" }, { "datacenter": { "description": "US West 1 Datacenter", "id": 1, "name": "US-West-1", "object": "option" }, "id": 5348101, "ip": "192.168.75.68", "object": "ip", "public": false, "state": { "description": "IP is available to use", "id": 1, "name": "Unassigned", "object": "option" }, "subnet": "192.168.75.64/255.255.255.240" } ], "method": "/grid/ip/list", "status": "success", "summary": { "numpages": 0, "returned": 3, "start": 0, "total": 3 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/ip_list_empty.json0000664000175000017500000000027513535474530027570 0ustar kamikami00000000000000{ "list": [ ], "method": "/grid/ip/list", "status": "success", "summary": { "numpages": 0, "returned": 0, "start": 0, "total": 0 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/lookup_list_ip_datacenter.json0000664000175000017500000000101113535474530032122 0ustar kamikami00000000000000{ "list": [ { "description": "US West 1 Datacenter", "id": 1, "name": "US-West-1", "object": "option" }, { "description": "US East 1 Datacenter", "id": 2, "name": "US-East-1", "object": "option" } ], "method": "/common/lookup/list", "status": "success", "summary": { "numpages": 0, "returned": 2, "start": 0, "total": 2 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/password_list.json0000664000175000017500000000425413535474530027605 0ustar kamikami00000000000000{ "list": [ { "password": "bebebe", "object": "password", "username": "root", "server": { "id": 90967, "image": { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, "ip": { "id": 1659927, "ip": "192.168.0.202", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.0.192/255.255.255.240" }, "isSandbox": false, "name": "test1", "object": "server", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "ram": { "description": "Server with 512MB RAM", "id": 1, "name": "512MB", "object": "option" }, "state": { "description": "Server is in active state.", "id": 1, "name": "On", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" } } } ], "method": "/grid/server/list", "status": "success", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/server_add.json0000664000175000017500000000575213535474530027032 0ustar kamikami00000000000000{ "list": [ { "image": { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, "ip": { "id": 1659927, "ip": "192.168.0.202", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.0.192/255.255.255.240" }, "isSandbox": false, "name": "test1", "object": "server", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "ram": { "description": "Server with 512MB RAM", "id": 1, "name": "512MB", "object": "option" }, "state": { "description": "Server is in active state.", "id": 1, "name": "On", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" } } ], "method": "/grid/server/add", "status": "success", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/server_delete.json0000664000175000017500000000600613535474530027535 0ustar kamikami00000000000000{ "list": [ { "id": 90967, "image": { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, "ip": { "id": 1659927, "ip": "192.168.0.202", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.0.192/255.255.255.240" }, "isSandbox": false, "name": "test1", "object": "server", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "ram": { "description": "Server with 512MB RAM", "id": 1, "name": "512MB", "object": "option" }, "state": { "description": "Server is in active state.", "id": 1, "name": "On", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" } } ], "method": "/grid/server/delete", "status": "success", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/server_edit.json0000664000175000017500000000600413535474530027216 0ustar kamikami00000000000000{ "list": [ { "id": 90967, "image": { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, "ip": { "id": 1659927, "ip": "192.168.0.202", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.0.192/255.255.255.240" }, "isSandbox": false, "name": "test1", "object": "server", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "ram": { "description": "Server with 512MB RAM", "id": 1, "name": "512MB", "object": "option" }, "state": { "description": "Server is in active state.", "id": 1, "name": "On", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" } } ], "method": "/grid/server/edit", "status": "success", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/server_list.json0000664000175000017500000000605613535474530027253 0ustar kamikami00000000000000{ "list": [ { "id": 90967, "image": { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, "ip": { "id": 1659927, "ip": "192.168.0.202", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.0.192/255.255.255.240" }, "isSandbox": false, "name": "test1", "description": "test server", "object": "server", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "ram": { "description": "Server with 512MB RAM", "id": 1, "name": "512MB", "object": "option" }, "state": { "description": "Server is in active state.", "id": 1, "name": "On", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" } } ], "method": "/grid/server/list", "status": "success", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/server_power.json0000664000175000017500000000600513535474530027426 0ustar kamikami00000000000000{ "list": [ { "id": 90967, "image": { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, "ip": { "id": 1659927, "ip": "192.168.0.202", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.0.192/255.255.255.240" }, "isSandbox": false, "name": "test1", "object": "server", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "ram": { "description": "Server with 512MB RAM", "id": 1, "name": "512MB", "object": "option" }, "state": { "description": "Server is in active state.", "id": 1, "name": "On", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" } } ], "method": "/grid/server/power", "status": "success", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gogrid/server_power_fail.json0000664000175000017500000000600513535474530030421 0ustar kamikami00000000000000{ "list": [ { "id": 90967, "image": { "billingtokens": [ { "id": 46, "name": "CentOS 5.3 32bit", "price": 0 } ], "description": "CentOS 5.3 (32-bit) w/ None", "friendlyName": "CentOS 5.3 (32-bit) w/ None", "id": 1531, "isActive": true, "isPublic": true, "location": "gogrid/GSI-2c4c6672-69e1-4928-ac9d-a564521d55fe.img", "name": "centos5.3_32_base", "object": "serverimage", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "owner": { "id": -1, "name": "GoGrid", "object": "customer" }, "price": 0, "state": { "description": "Image is available for adds", "id": 2, "name": "Available", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" }, "updatedTime": 1257789046453 }, "ip": { "id": 1659927, "ip": "192.168.0.202", "object": "ip", "public": true, "state": { "description": "IP is reserved or in use", "id": 2, "name": "Assigned", "object": "option" }, "subnet": "192.168.0.192/255.255.255.240" }, "isSandbox": false, "name": "test1", "object": "server", "os": { "description": "CentOS 5.3 (32-bit)", "id": 16, "name": "CentOS 5.3 (32-bit)", "object": "option" }, "ram": { "description": "Server with 512MB RAM", "id": 1, "name": "512MB", "object": "option" }, "state": { "description": "Server is in active state.", "id": 1, "name": "On", "object": "option" }, "type": { "description": "Web or Application Server", "id": 1, "name": "Web Server", "object": "option" } } ], "method": "/grid/server/power", "status": "failure", "summary": { "numpages": 0, "returned": 1, "start": 0, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/0000775000175000017500000000000013600223624024457 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_image.json0000664000175000017500000000016213570310635027763 0ustar kamikami00000000000000{ "request_uuid": "x123xx1x-123x-1x12-123x-123xxx123x1x", "object_uuid": "690de890-13c0-4e76-8a01-e10ba8786e53" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_image_dict.json0000664000175000017500000000137113570310635030771 0ustar kamikami00000000000000{ "adf09edd-9411-43b1-b99e-b92070e65f22": { "description": null, "ostype": null, "version": null, "location_country": "de", "location_name": "de/fra", "capacity": 50, "create_time": "2019-06-21T09:28:58Z", "location_iata": "fra", "name": "test.test", "status": "active", "labels": [], "parent_uuid": "e66bb753_4a03_4ee2_a069_a601f393c9ee", "usage_in_minutes": 225600, "license_product_no": null, "current_price": 0.99264, "object_uuid": "690de890_13c0_4e76_8a01_e10ba8786e53", "change_time": "2019-06-21T09:28:58Z", "private": true, "metadata": {}, "distro": null, "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_ip.json0000664000175000017500000000016313570310635027312 0ustar kamikami00000000000000 { "request_uuid": "x123xx1x-123x-1x12-123x-123xxx123x1x", "object_uuid": "690de890-13c0-4e76-8a01-e10ba8786e53" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_ip_response_dict.json0000664000175000017500000001341113570310635032233 0ustar kamikami00000000000000{ "eaa06a81-39f5-48e4-ba5b-fe1be151118b": { "create_time": "2019-06-07T15:00:03Z", "name": "Default IP", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "reverse_dns": "static-2a06-2380-0-1-229.ipv6.gridserver.io", "current_price": 0, "family": 6, "location_iata": "fra", "location_name": "de/fra", "status": "active", "relations": { "loadbalancers": [], "servers": [] }, "object_uuid": "eaa06a81-39f5-48e4-ba5b-fe1be151118b", "change_time": "2019-06-07T15:00:03Z", "failover": false, "usage_in_minutes": 0, "ip": "2a06:2380:0:1::229", "delete_block": false, "prefix": "2a06:2380:0:1::229/128", "labels": [] }, "56b8d161-325b-4fd4-a453-6101cf563713": { "create_time": "2019-06-07T12:57:26Z", "name": "test.test_ip", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "reverse_dns": "static-185-102-95-236.ipv4.gridserver.io", "current_price": 1.47738, "family": 4, "location_iata": "fra", "location_name": "de/fra", "status": "active", "relations": { "loadbalancers": [], "servers": [ { "create_time": "2019-06-07T12:57:30Z", "server_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f", "server_name": "test.test" } ] }, "object_uuid": "56b8d161-325b-4fd4-a453-6101cf563713", "change_time": "2019-06-07T12:57:26Z", "failover": false, "usage_in_minutes": 24623, "ip": "185.102.95.236", "delete_block": false, "prefix": "185.102.95.236/32", "labels": [] }, "0235e7c4-18c9-4b2f-a3c3-2d9624a67498": { "create_time": "2019-06-07T14:59:17Z", "name": "Default IP", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "reverse_dns": "static-2a06-2380-0-1-211.ipv6.gridserver.io", "current_price": 0, "family": 6, "location_iata": "fra", "location_name": "de/fra", "status": "active", "relations": { "loadbalancers": [], "servers": [ { "create_time": "2019-06-07T14:59:47Z", "server_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f", "server_name": "test.test" } ] }, "object_uuid": "0235e7c4-18c9-4b2f-a3c3-2d9624a67498", "change_time": "2019-06-07T14:59:17Z", "failover": false, "usage_in_minutes": 0, "ip": "2a06:2380:0:1::211", "delete_block": false, "prefix": "2a06:2380:0:1::211/128", "labels": [] }, "ace17032-3127-4c9e-943b-a2a4679984a3": { "create_time": "2019-06-14T09:47:37Z", "name": "test.test_ip", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "reverse_dns": "static-185-201-146-56.ipv4.gridserver.io", "current_price": 0.88392, "family": 4, "location_iata": "fra", "location_name": "de/fra", "status": "active", "relations": { "loadbalancers": [], "servers": [] }, "object_uuid": "ace17032-3127-4c9e-943b-a2a4679984a3", "change_time": "2019-06-14T09:47:37Z", "failover": false, "usage_in_minutes": 14732, "ip": "185.201.146.56", "delete_block": false, "prefix": "185.201.146.56/32", "labels": [] }, "63b57604-40a2-454c-a143-69300ea6941c": { "create_time": "2019-06-14T17:31:18Z", "name": "test.test_ip", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "reverse_dns": "static-185-102-95-79.ipv4.gridserver.io", "current_price": 0.85614, "family": 4, "location_iata": "fra", "location_name": "de/fra", "status": "active", "relations": { "loadbalancers": [], "servers": [] }, "object_uuid": "63b57604-40a2-454c-a143-69300ea6941c", "change_time": "2019-06-14T17:31:18Z", "failover": false, "usage_in_minutes": 14269, "ip": "185.102.95.79", "delete_block": false, "prefix": "185.102.95.79/32", "labels": [] }, "fa81b132-6dd9-4fc6-b7f9-844f89e50b15": { "create_time": "2019-06-07T13:42:55Z", "name": "test.test_ip", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "reverse_dns": "static-185-102-95-217.ipv4.gridserver.io", "current_price": 1.47462, "family": 4, "location_iata": "fra", "location_name": "de/fra", "status": "active", "relations": { "loadbalancers": [], "servers": [] }, "object_uuid": "fa81b132-6dd9-4fc6-b7f9-844f89e50b15", "change_time": "2019-06-07T13:42:55Z", "failover": false, "usage_in_minutes": 24577, "ip": "185.102.95.217", "delete_block": false, "prefix": "185.102.95.217/32", "labels": [] }, "4f1bef38-b970-4ff3-b891-5ac03af5bdeb": { "create_time": "2019-06-14T14:10:11Z", "name": "test.test_ip", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "reverse_dns": "static-185-201-147-66.ipv4.gridserver.io", "current_price": 0.8682, "family": 4, "location_iata": "fra", "location_name": "de/fra", "status": "active", "relations": { "loadbalancers": [], "servers": [] }, "object_uuid": "4f1bef38-b970-4ff3-b891-5ac03af5bdeb", "change_time": "2019-06-14T14:10:11Z", "failover": false, "usage_in_minutes": 14470, "ip": "185.201.147.66", "delete_block": false, "prefix": "185.201.147.66/32", "labels": [] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_network.json0000664000175000017500000000206513570310635030376 0ustar kamikami00000000000000{ "networks": { "1196529b-a8de-417f-ac95-0e13ef4fdfd7": { "delete_block": false, "relations": { "servers": [ { "bootdevice": false, "create_time": "2019-06-07T14:59:47Z", "ordering": 0, "l3security": [ "185.102.95.236/32" ], "mac": "16:63:95:5d:1f:01", "object_name": "test.test", "network_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7", "object_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f" } ], "vlans": [] }, "labels": [], "network_type": "network", "change_time": "2019-04-08T09:10:08Z", "status": "active", "create_time": "2018-12-06T13:09:08Z", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "location_name": "de/fra", "name": "network", "location_iata": "fra", "l2security": true, "public_net": true, "location_country": "de", "object_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_node.json0000664000175000017500000000016313570310635027627 0ustar kamikami00000000000000 { "request_uuid": "x123xx1x-123x-1x12-123x-123xxx123x1x", "object_uuid": "690de890-13c0-4e76-8a01-e10ba8786e53" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_node_dict.json0000664000175000017500000000527513570310635030643 0ustar kamikami00000000000000{ "1479405e-d46c-47a2-91e8-eb43951c899f": { "hardware_profile": "default", "relations": { "storages": [ { "storage_type": "storage", "last_used_template": "a5112c72-c9fa-4a23-8115-5f6303eb047b", "create_time": "2019-06-24T10:10:51Z", "capacity": 50, "lun": 0, "controller": 0, "target": 0, "object_uuid": "e66bb753-4a03-4ee2-a069-a601f393c9ee", "bootdevice": true, "object_name": "linux", "license_product_no": null, "bus": 0 } ], "networks": [ { "mac": "16:63:95:5d:1f:01", "network_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7", "network_type": "network", "mcast": null, "create_time": "2019-06-07T14:59:47Z", "public_net": true, "partner_uuid": "95a2980b-7012-43dd-81f2-07577cfcb9f0", "ordering": 0, "vlan": null, "firewall": null, "l2security": true, "firewall_template_uuid": null, "vxlan": null, "object_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7", "bootdevice": false, "object_name": "network", "l3security": [ "185.102.95.236/32" ] } ], "isoimages": [], "public_ips": [ { "object_uuid": "56b8d161-325b-4fd4-a453-6101cf563713", "ip": "185.102.95.236", "family": 4, "create_time": "2019-06-07T12:57:30Z", "prefix": "185.102.95.236/32" }, { "object_uuid": "0235e7c4-18c9-4b2f-a3c3-2d9624a67498", "ip": "2a06:2380:0:1::211", "family": 6, "create_time": "2019-06-07T14:59:47Z", "prefix": "2a06:2380:0:1::211/128" } ] }, "memory": 10, "location_iata": "fra", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "change_time": "2019-06-17T14:13:31Z", "object_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f", "labels": [], "usage_in_minutes_cores": 25030, "cores": 2, "console_token": "088f625818dc5b9114f8bee8e7f67d7b5510fc5159968a02752875f4b55ca911d59fd6cbe3eeb60358c0f353b1d7cbb9", "availability_zone": null, "location_name": "de/fra", "create_time": "2019-06-07T12:56:44Z", "location_country": "de", "legacy": false, "current_price": 17.89645, "power": false, "status": "active", "auto_recovery": true, "name": "test.test", "usage_in_minutes_memory": 125150 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_node_response_dict.json0000664000175000017500000000017713570310635032555 0ustar kamikami00000000000000{ "x123xx1x-123x-1x12-123x-123xxx123x1x": { "create_time": "2018-06-05T11:31:12Z", "status": "done", "message": "Success." } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_volume.json0000664000175000017500000000016213570310635030210 0ustar kamikami00000000000000{ "request_uuid": "x123xx1x-123x-1x12-123x-123xxx123x1x", "object_uuid": "690de890-13c0-4e76-8a01-e10ba8786e53" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/create_volume_response_dict.json0000664000175000017500000000213213570310635033130 0ustar kamikami00000000000000{ "e66bb753-4a03-4ee2-a069-a601f393c9ee": { "snapshots": [], "capacity": 50, "relations": { "snapshot_schedules": [], "servers": [ { "create_time": "2019-06-24T10:10:51Z", "bootdevice": true, "lun": 0, "bus": 0, "object_name": "test.test", "target": 0, "object_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f", "controller": 0 } ] }, "storage_type": "storage", "last_used_template": "a5112c72-c9fa-4a23-8115-5f6303eb047b", "object_uuid": "e66bb753-4a03-4ee2-a069-a601f393c9ee", "license_product_no": null, "location_country": "de", "current_price": 3.09298, "create_time": "2019-06-14T17:31:10Z", "change_time": "2019-06-14T17:31:10Z", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "labels": [], "name": "linux", "usage_in_minutes": 702950, "location_name": "de/fra", "location_iata": "fra", "status": "active", "parent_uuid": null } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/ex_list_ips.json0000664000175000017500000000170013570310635027677 0ustar kamikami00000000000000{ "ips": { "56b8d161-325b-4fd4-a453-6101cf563713": { "family": 4, "location_uuid": "45ed677b-3702-4b36", "object_uuid": "56b8d161-325b-4fd4", "change_time": "2019-06-07T12:57:26Z", "relations": { "loadbalancers": [], "servers": [ { "server_name": "test.test", "server_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f", "create_time": "2019-06-07T12:57:30Z" } ] }, "create_time": "2019-06-07T12:57:26Z", "location_name": "de/fra", "location_country": "de", "location_iata": "fra", "ip": "185.102.95.236", "labels": [], "reverse_dns": "static-185-102-95-236.ipv4.gridserver.io", "delete_block": false, "failover": false, "usage_in_minutes": 27893, "current_price": 1.67358, "status": "active", "name": "test.test_ip", "prefix": "185.102.95.236/32" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/ex_list_networks.json0000664000175000017500000000177713570310635030776 0ustar kamikami00000000000000{ "networks": { "1196529b-a8de-417f-ac95-0e13ef4fdfd7": { "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "network_type": "network", "delete_block": false, "relations": { "vlans": [], "servers": [ { "ordering": 0, "create_time": "2019-06-07T14:59:47Z", "l3security": [ "185.102.95.236/32" ], "mac": "16:63:95:5d:1f:01", "object_name": "test.test", "bootdevice": false, "network_uuid": "1196529b-a8de-417f", "object_uuid": "1479405e-d46c-47a2" } ] }, "location_iata": "fra", "create_time": "2018-12-06T13:09:08Z", "location_name": "de/fra", "location_country": "de", "name": "network", "change_time": "2019-04-08T09:10:08Z", "l2security": true, "public_net": true, "object_uuid": "1196529b-a8de-417f", "status": "active", "labels": [] } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/ex_start_node.json0000664000175000017500000000000013570310635030203 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/get_image.json0000664000175000017500000000106113570310635027276 0ustar kamikami00000000000000{ "templates":{ "capacity": 20, "name": "Plesk", "license_product_no": null, "ostype": "1click", "object_uuid": "12345", "distro": "Plesk", "change_time": "2019-01-03T17:06:49Z", "location_country": "de", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "usage_in_minutes": 23795240, "create_time": "2017-03-26T17:51:54Z", "status": "active", "labels": ["karl"], "current_price": 104.699056, "location_iata": "fra", "location_name": "de/fra", "version": "Ubuntu 16.04 LTS & Plesk Onyx", "description": "Plesk", "private": false } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/ips_to_node.json0000664000175000017500000000000013570310635027647 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/list_images.json0000664000175000017500000010267113570310635027666 0ustar kamikami00000000000000{ "templates": { "adf09edd-9411-43b1-b99e-b92070e65f22": { "description": null, "ostype": null, "version": null, "location_country": "de", "location_name": "de/fra", "capacity": 50, "create_time": "2019-06-21T09:28:58Z", "location_iata": "fra", "name": "test.test", "status": "active", "labels": [], "usage_in_minutes": 225600, "license_product_no": null, "current_price": 0.99264, "object_uuid": "adf09edd-9411-43b1-b99e-b92070e65f22", "change_time": "2019-06-21T09:28:58Z", "private": true, "metadata": {}, "distro": null, "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "ec4ef18f-84df-42bb-b7c4-c2957635ee53": { "description": "no swap", "ostype": "linux", "version": "16.04 LTS", "location_country": "de", "location_name": "de/fra", "capacity": 5, "create_time": "2016-05-13T18:51:41Z", "location_iata": "fra", "name": "Ubuntu 16.04 LTS (Xenial Xerus)", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "ec4ef18f-84df-42bb-b7c4-c2957635ee53", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "Ubuntu", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "4db64bfc-9fb2-4976-80b5-94ff43b1233a": { "description": "(Bionic Beaver)", "ostype": "linux", "version": "18.04 LTS", "location_country": "de", "location_name": "de/fra", "capacity": 10, "create_time": "2018-05-03T08:49:33Z", "location_iata": "fra", "name": "Ubuntu 18.04 LTS", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "4db64bfc-9fb2-4976-80b5-94ff43b1233a", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "Ubuntu", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "ae05b3d7-f9ca-4099-8f5a-ff75bc4bc5a4": { "description": "Wordpress", "ostype": "1click", "version": "Ubuntu 16.04 LTS & Wordpress", "location_country": "de", "location_name": "de/fra", "capacity": 3, "create_time": "2017-04-10T15:38:20Z", "location_iata": "fra", "name": "WordPress", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "ae05b3d7-f9ca-4099-8f5a-ff75bc4bc5a4", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": { "icon": "/img/assets/logos_marketplace/wordpress.png", "description": { "de": "# Übersicht\n\nWordPress ist eine freie Webanwendung zur Verwaltung der Inhalte einer Website (wie z. B. Texte und Bilder, aber auch Audio- und Video-Dateien). Sie bietet sich besonders zum Aufbau und zur Pflege eines Weblogs (\"Blog\") an, da sie jeden Beitrag einer oder mehreren frei erstellbaren Kategorien zuweisen kann und dazu automatisch die entsprechenden Navigationselemente erzeugt. Parallel kann WordPress auch hierarchische Seiten verwalten und gestattet den Einsatz als Content-Management-System (CMS).\n\n# Dokumentation\n\nNachdem der WordPress-Server fertiggestellt und eingeschaltet ist, verbinde dich mit Hilfe unserer VNC Konsole (>\\_) auf den Bildschirm des Servers. Dort findest du Informationen bezüglich Zugangsdaten und Zugriff auf WordPress.\n\nFür weitere Dokumentation kannst du die **[WordPress Dokumentation](https://codex.wordpress.org/Main_Page)** lesen.\n\n# Nutzungsbedingungen\n\nSiehe [GNU General Public License v2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) (GPL).", "en": "# Overview\n\nWordPress is a free web application for managing the contents of a website (such as texts and images, but also audio and video files). It is particularly useful for building and maintaining a weblog (\"blog\"), as it can assign each post to one or more freely definable categories and automatically generates the corresponding navigation elements for this purpose. At the same time, WordPress can also manage hierarchical pages and allows its use as a content management system (CMS).\n\n# Documentation\n\nAfter the WordPress server is ready and turned on, connect to the server's screen using our VNC console (>\\_). There you will find information regarding login credentials and access to WordPress.\n\nFor more documentation you can read the **[WordPress documentation](https://codex.wordpress.org/Main_Page)**.\n\n# Terms of Use\n\nSee [GNU General Public License v2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) (GPL)." }, "setup": { "storage_type": "storage_insane", "memory": 2, "capacity": 50, "cores": 1 }, "os": "Ubuntu 16.04 LTS", "other_software": { "PHP": "7.0", "MariaDB": "10.0", "Apache": "2.4" }, "publisher": "WordPress Foundation", "version": "4.7", "category": "CMS", "top": false, "licence": "GNU General Public License v2 (GPLv2)", "short_description": { "de": "Das meistgenutzte CMS", "en": "The most used CMS" } }, "distro": "WordPress", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "c1f05dde-ed3c-4ab5-ab77-d3a9c6966852": { "description": "Plesk", "ostype": "1click", "version": "Ubuntu 16.04 LTS & Plesk Onyx", "location_country": "de", "location_name": "de/fra", "capacity": 20, "create_time": "2017-03-26T17:51:54Z", "location_iata": "fra", "name": "Plesk", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "c1f05dde-ed3c-4ab5-ab77-d3a9c6966852", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": { "icon": "/img/assets/logos_marketplace/plesk.png", "description": { "de": "# Übersicht\n\nPlesk ist eine Webserver-Distribution mit Konfigurationstool für Webhosting, entwickelt von Parallels Inc. (jetzt Odin).\nBenutzer können Server ohne detaillierte Kenntnisse des Betriebssystems verwalten. Es vereinfacht komplexe Operationen wie die Einrichtung eines Mail- und Webservers für eine Domain.\n\n# Dokumentation\n\nNachdem du den Plesk Server erstellt und gestartet hast, melde dich am besten als \"root\" per SSH am Server an. Nach erfolgreicher Anmeldung werden in der Konsole weitere Informationen zum Zugriff auf das plesk-Panel angezeigt.\n\nFür weitere Dokumentation kannst du die **[Plesk-Dokumentation](https://docs.plesk.com/en-US/onyx/)** lesen.\n\n# Nutzungsbedingungen\n\nSiehe [Plesk Nutzungsbedingungen](https://www.plesk.com/legal/#terms-of-use)", "en": "# Overview\n\nPlesk is a web server distribution with configuration tool for web hosting, developed by Parallels Inc. (now Odin).\nUsers can manage servers without in-depth knowledge of the operating system. It simplifies complex operations such as setting up a mail and web server for a domain.\n\n# Documentation\n\nAfter you have created and started the Plesk server, log in to the server as \"root\" via SSH. After successful login, the console displays additional information about access to the plesk panel.\n\nFor more documentation you can read the **[Plesk documentation](https://docs.plesk.com/en-US/onyx/)**.\n\n# Terms of Use\n\nSee [Plesk Terms of use](https://www.plesk.com/legal/#terms-of-use)" }, "setup": { "storage_type": "storage_insane", "memory": 2, "capacity": 50, "cores": 1 }, "os": "Ubuntu 16.04 LTS", "other_software": { "PHP": "5.6 / 7.0 / 7.1", "Apache": "2.4", "MySQL": "5.7" }, "publisher": "Parallels Inc.", "version": "17", "category": "Adminpanel", "top": false, "licence": "Free trial", "short_description": { "de": "Innovatives Hosting Control Panel", "en": "Innovative Hosting Control Panel" } }, "distro": "Plesk", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "a3aa8787-7e6e-49fa-adae-6c694b612a65": { "description": "no swap", "ostype": "linux", "version": "Debian 9", "location_country": "de", "location_name": "de/fra", "capacity": 3, "create_time": "2017-06-14T10:07:39Z", "location_iata": "fra", "name": "Debian 9", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "a3aa8787-7e6e-49fa-adae-6c694b612a65", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "Debian", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "a5112c72-c9fa-4a23-8115-5f6303eb047b": { "description": "no swap", "ostype": "linux", "version": "Debian 8", "location_country": "de", "location_name": "de/fra", "capacity": 3, "create_time": "2015-10-03T12:57:21Z", "location_iata": "fra", "name": "Debian 8 (64bit)", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "a5112c72-c9fa-4a23-8115-5f6303eb047b", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "Debian", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "49b40a10-4ef0-4dd7-b113-d1266168fa1b": { "description": "Marketplace Template - Ubuntu 16.04 LTS with LiveConfig", "ostype": "marketplace", "version": "Ubuntu 16.04 LTS", "location_country": "de", "location_name": "de/fra", "capacity": 50, "create_time": "2018-07-25T15:49:18Z", "location_iata": "fra", "name": "LiveConfig", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "49b40a10-4ef0-4dd7-b113-d1266168fa1b", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": { "icon": "/img/assets/logos_marketplace/liveconfig.png", "description": { "de": "# Übersicht\n\nLiveConfig ist ein einzigartiges und besonders ressourcenschonendes Hosting Control Panel. Es ermöglicht dir die sichere Administration deiner Server über eine moderne, SSL-geschützte Weboberfläche. Dabei erkennt es automatisch die vorhandenen Softwarepakete und konfiguriert diese mittel quelloffener und anpassbarer Skripte. Die Multi-Server-Fähigkeit, Unabhängigkeit von PHP und Benutzer- und Rechteverwaltung sind nur einige der vielen Vorteile im Vergleich mit anderen Control Panels die LiveConfig bietet. \n\n## Features\n\n- Reseller, Kunden und User Management\n- Webspace-Einstellungen\n- PHP-Einstellungen\n- Hosting-Angebote\n- Systeminformationen\n- E-Mail Management\n- Application Installer\nu.v.m\n\n# Dokumentation\n\nNachdem der Liveconfig-Server fertiggestellt und eingeschaltet ist, verbinde dich mit Hilfe unserer VNC Konsole (>\\_) auf den Bildschirm des Servers. Dort findest du Informationen bezüglich Zugangsdaten und Zugriff auf Liveconfig so wie weitere Schritte um die Installation zu vervollständigen.\n\nFür weitere Dokumentation kannst du das **[Liveconfig Wiki](https://www.liveconfig.com/wiki/de/start)** lesen.\n", "en": "# Overview\n\nLiveConfig is a unique and particularly resource-saving hosting control panel. It allows you to securely administer your servers via a modern, SSL-protected web interface. It automatically detects existing software packages and configures them using open source and customizable scripts. Multi-server capability, PHP independence, and user and rights management are just a few of the many advantages LiveConfig offers over other control panels. \n\n## Features\n\n- Resellers, customers and user management\n- webspace settings\n- PHP settings\n- hosting plans\n- system information\n- Email Management\n- application installer\nand much more\n\n# Documentation\n\nAfter the Liveconfig server is ready and turned on, connect to the server screen using our VNC console (>\\_). There you will find information about login credentials and access to Liveconfig and further steps to complete the installation.\n\nFor further documentation you can read the **[Liveconfig Wiki](https://www.liveconfig.com/wiki/de/start)**." }, "setup": { "storage_type": "storage_insane", "memory": 2, "capacity": 50, "cores": 1 }, "os": "Debian 9 (stretch)", "other_software": { "PHP": "7.0", "Dovecot": "2.2", "MariaDB": "10.1", "Apache": "2.4", "Postfix": "3.1", "ProFTPd": "1.3" }, "publisher": "Keppler IT GmbH", "version": "2.5", "category": "Adminpanel", "top": false, "licence": "Commercial", "short_description": { "de": "Schlankes Hosting Control Panel", "en": "Lightweight Hosting Control Panel" } }, "distro": "LiveConfig", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "afafa5d2-d625-4f81-81f8-e5801b60a6c8": { "description": "no swap", "ostype": "linux", "version": "Fedora 25 Server", "location_country": "de", "location_name": "de/fra", "capacity": 3, "create_time": "2017-03-06T11:24:42Z", "location_iata": "fra", "name": "Fedora 25 Server", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "afafa5d2-d625-4f81-81f8-e5801b60a6c8", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "Fedora", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "0825de86-36f4-4695-b016-b8505cbb7b47": { "description": "Redmine", "ostype": "1click", "version": "Ubuntu 16.04 LTS & Redmine 3", "location_country": "de", "location_name": "de/fra", "capacity": 3, "create_time": "2017-04-10T15:38:20Z", "location_iata": "fra", "name": "Redmine", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "0825de86-36f4-4695-b016-b8505cbb7b47", "change_time": "2019-02-08T17:18:36Z", "private": false, "metadata": { "icon": "/img/assets/logos_marketplace/redmine.png", "description": { "de": "# Übersicht\n\nRedmine ist eine webbasierte Projektmanagement Anwendung für große als auch kleine Projekte. Die in Ruby geschriebene Open-Source-Software kann flexibel eingesetzt werden und ist durch Plugins erweiterbar. Redmine gilt als professionelles Tool und wird von erfolgreichen Teams unter anderem für Projektplanung und -management, als Issue-Tracking-System, Wikis, zur Benutzer- und Ticketverwaltung und Dokumentenablage genutzt. Es hilft dabei die Projektarbeit durch Koordination und Bündelung von Aufgaben zu verbessern.\n\n## Features\n\nEinige der Features von Redmine sind:\n\n- Unterstützung mehrerer Projekte\n- Flexible rollenbasierte Zugriffskontrolle\n- Flexibles Problemverfolgungssystem\n- Gantt-Diagramm und Kalender\n- Verwaltung von Nachrichten, Dokumenten und Dateien\n- Feeds & E-Mail-Benachrichtigungen\n- Pro Projekt-Wiki\n- Pro Projekt-Foren\n- Zeiterfassung\n- Benutzerdefinierte Felder für Probleme, Zeiteinträge, Projekte und Benutzer\n- SCM-Integration (SVN, CVS, Git, Mercurial und Bazaar)\n- Issue-Erstellung per E-Mail\n- Unterstützung mehrerer LDAP-Authentifizierungen\n- Unterstützung der Benutzer-Selbstregistrierung\n- Mehrsprachige Unterstützung\n- Unterstützung mehrerer Datenbanken\n\n# Dokumentation\n\nNachdem der Redmine-Server fertiggestellt und eingeschaltet ist, verbinde dich mit Hilfe unserer VNC Konsole (>\\_) auf den Bildschirm des Servers. Dort findest du Informationen bezüglich Zugangsdaten und Zugriff auf Redmine.\n\nFür weitere Dokumentation kannst du den **[Redmine Guide](https://www.redmine.org/projects/redmine/wiki/Guide)** lesen.\n\n# Nutzungsbedingungen\n\nSiehe [GNU General Public License v2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) (GPL).\n", "en": "# Overview\n\nRedmine is a flexible project management web application. Written using the Ruby on Rails framework, it is cross-platform and cross-database.\n\nRedmine is open source and released under the terms of the [GNU General Public License v2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) (GPL).\n\n## Features\n\nSome of the main features of Redmine are:\n\n- Multiple projects support\n- Flexible role based access control\n- Flexible issue tracking system\n- Gantt chart and calendar\n- News, documents & files management\n- Feeds & email notifications\n- Per project wiki\n- Per project forums\n- Time tracking\n- Custom fields for issues, time-entries, projects and users\n- SCM integration (SVN, CVS, Git, Mercurial and Bazaar)\n- Issue creation via email\n- Multiple LDAP authentication support\n- User self-registration support\n- Multilanguage support\n- Multiple databases support\n\n# Documentation\n\nAfter the Redmine server is ready and turned on, connect to the server screen using our VNC console (>\\_). There you will find information regarding login credentials and access to Redmine.\n\nFor further documentation you can read the **[Redmine guide](https://www.redmine.org/projects/redmine/wiki/Guide)**.\n\n# Terms of use\n\nSee [GNU General Public License v2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) (GPL).\n" }, "setup": { "storage_type": "storage_insane", "memory": 2, "capacity": 50, "cores": 1 }, "os": "Ubuntu 16.04 LTS", "other_software": { "Python": "2.7", "MariaDB": "10.0", "Apache": "2.4" }, "publisher": "redmine.org", "version": "3.2", "category": "project management", "top": false, "licence": "GNU General Public License v2 (GPLv2)", "short_description": { "de": "Flexible Projektmanagement Anwendung", "en": "Flexible project management application" } }, "distro": "Redmine", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "dbb3e965-bfa0-411e-b324-86e82b3f36ec": { "description": null, "ostype": "linux", "version": "CentOS 7 Core (x86_64)", "location_country": "de", "location_name": "de/fra", "capacity": 3, "create_time": "2017-04-16T12:13:21Z", "location_iata": "fra", "name": "CentOS 7 (x86_64)", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "dbb3e965-bfa0-411e-b324-86e82b3f36ec", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "CentOS", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "9739b4db-7986-4c98-b337-6ff2f098e88e": { "description": "Marketplace Template - Ubuntu 16.04 LTS with Cloudplan", "ostype": "marketplace", "version": "Ubuntu 16.04 LTS", "location_country": "de", "location_name": "de/fra", "capacity": 50, "create_time": "2018-07-25T15:49:18Z", "location_iata": "fra", "name": "Cloudplan", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "9739b4db-7986-4c98-b337-6ff2f098e88e", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": { "icon": "/img/assets/logos_marketplace/cloudplan.png", "description": { "de": "# Übersicht\n\ncloudplan ist eine sichere private Cloud Lösung auf Peer-to-Peer Basis. Durch eine intelligente und selbst-organisierte P2P-Technologie ist ein Synchronisieren und Teilen von Unternehmensdaten bei 100 % Datensouveränität möglich. Daneben kannst du Remote Arbeitsplätze nahtlos und sicher Anbinden ohne ein VPN einrichten und betreiben zu müssen. So lassen sich lokal begrenzte oder globale Speicherstrukturen aufbauen, die aus heterogenen Hardware-Plattformen bestehen und beliebig skalierbar sind. cloudplan richtet sich vorwiegend an Unternehmen, die ihre Datenhoheit behalten wollen, kann jedoch auch von Einzelanwendern genutzt werden.\n\n## Features\n\n- Grenzenlose Synchronisation\n- Hybrid Cloud fähig\n- AES 256 Verschlüsselung\n- Automatisches Backup\n- Intelligente Lastverteilung\n- Rechteverwaltung auf Ordnerebene\n\n# Dokumentation\n\nNachdem der cloudplan-Server fertiggestellt und eingeschaltet ist, verbinde dich mit Hilfe unserer VNC Konsole (>\\_) auf den Bildschirm des Servers. Dort findest du Informationen bezüglich Zugangsdaten und Zugriff auf cloudplan so wie weitere Schritte um die Installation zu vervollständigen.\n\nFür weitere Dokumentation kannst du die **[cloudplan Dokumentation](https://portal.cloudplan.net/support/gettingstarted)** lesen.\n", "en": "# Overview\n\ncloudplan is a secure private cloud solution on a peer-to-peer basis. Intelligent and self-organized P2P technology makes it possible to synchronize and share company data with 100% data sovereignty. In addition, you can connect remote workstations seamlessly and securely without having to set up and operate a VPN. In this way, locally limited or global storage structures can be set up, which consist of heterogeneous hardware platforms and can be scaled as required. cloudplan is primarily aimed at companies that want to retain their data sovereignty, but can also be used by individual users.\n\n## Features\n\n- Boundless synchronization\n- Hybrid cloud capable\n- AES 256 encryption\n- Automatic backup\n- Intelligent load distribution\n- Rights management at folder level\n\n# Documentation\n\nAfter the cloud plan server is ready and turned on, connect to the server screen using our VNC console (>\\_). There you will find information regarding login credentials and access to cloudplan and further steps to complete the installation.\n\nFor more documentation you can read the **[cloudplan Documentation](https://portal.cloudplan.net/support/gettingstarted)**.\n" }, "setup": { "storage_type": "storage_insane", "memory": 2, "capacity": 50, "cores": 1 }, "os": "Debian 9", "other_software": [], "publisher": "cloudplan GmbH", "version": "1.0.161", "category": "Cloud Storage", "top": false, "licence": "Commercial", "short_description": { "de": "Sichere private Cloud Lösung", "en": "Secure private cloud solution" } }, "distro": "Cloudplan", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "af8c9961-1f27-487c-b19f-dc2b23d156c3": { "description": "Marketplace Template - Ubuntu 16.04 LTS with Kopano", "ostype": "marketplace", "version": "Ubuntu 16.04 LTS", "location_country": "de", "location_name": "de/fra", "capacity": 50, "create_time": "2018-07-25T15:49:18Z", "location_iata": "fra", "name": "Kopano", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "af8c9961-1f27-487c-b19f-dc2b23d156c3", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": { "icon": "/img/assets/logos_marketplace/kopano.png", "description": { "de": "# Übersicht\n\nKopano ist eine professionelle plattformunabhängige E-Mail und Collaboration Groupware für den Einsatz in Unternehmen und Teams. Die linux basierte Open-Source-Software gilt als echte und kostengünstige Alternative zu Microsoft Exchange. Neben den Groupware Kernfunktionen setzt die Software auf modernere Zusammenarbeitstechniken wie Meetings im Web oder Gruppenchats. Die leistungsstarke Software überzeugt durch einfache Bedienung und ist auf dem Desktop und mobil einsetzbar. \n\n## Features\n\n- Outlook-Anbindung mittels ActiveSync (Z-Push)\n- Zugriff über Outlook oder Webapp und DeskApp, im Outlook \"Look & Feel\"\n- Active-Sync Anbindung für die Echtzeit-Synchronisation mobiler Endgeräte\n- SSL-Verschlüsselung\n- Spam- und Virenfilter mit Webinterface\n- einfache Postfach/Mailserver-Integration aus vorhandenen Systemen\n\n# Dokumentation\n\nNachdem der Kopano-Server fertiggestellt und eingeschaltet ist, verbinde dich mit Hilfe unserer VNC Konsole (>\\_) auf den Bildschirm des Servers. Dort findest du Informationen bezüglich Zugangsdaten und Zugriff auf Kopano so wie weitere Schritte um die Installation zu vervollständigen.\n\nFür weitere Dokumentation kannst du die **[Kopano Knowledgebase](https://kb.kopano.io/)** lesen.\n", "en": "# Overview\n\nKopano is a professional platform-independent e-mail and collaboration groupware for use in companies and teams. The linux-based open source software is a real and cost-effective alternative to Microsoft Exchange. In addition to the groupware core functions, the software uses more modern collaboration techniques such as meetings on the web or group chats. The powerful software is easy to use and can be used on the desktop and mobile. \n\n## Features\n\n- Outlook connection via ActiveSync (Z-Push)\n- Access via Outlook or Webapp and DeskApp, in Outlook \"Look & Feel\"\n- Active-Sync connection for real-time synchronization of mobile devices\n- SSL encoding\n- Spam and virus filter with web interface\n- Simple mailbox/mail server integration from existing systems\n\n# Documentation\n\nAfter the Kopano server is ready and turned on, connect to the server screen using our VNC console (>\\_). There you will find information regarding login credentials and access to Kopano and further steps to complete the installation.\n\nFor further documentation you can read the **[Kopano Knowledgebase](https://kb.kopano.io/)**.\n" }, "setup": { "storage_type": "storage_insane", "memory": 2, "capacity": 50, "cores": 1 }, "os": "Debian 9 (stretch)", "other_software": { "PHP": "7.0", "MariaDB": "10.1", "NGINX": "1.10" }, "publisher": "Kopano GmbH", "version": "8.5", "category": "Collaboration", "top": false, "licence": "Commercial", "short_description": { "de": "Professionelle Kollaborations Groupware", "en": "Professional collaboration groupware" } }, "distro": "Kopano", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "48e7f519-84d5-4c9a-86db-010865902012": { "description": "SPLA-Licensed", "ostype": "windows", "version": "Windows Server 2016 Standard", "location_country": "de", "location_name": "de/fra", "capacity": 32, "create_time": "2016-10-24T14:50:23Z", "location_iata": "fra", "name": "Windows Server 2016", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": 800002, "current_price": 0, "object_uuid": "48e7f519-84d5-4c9a-86db-010865902012", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "Windows Server", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "b2e6b10f-5a77-4327-9f7e-9b9dea826bf1": { "description": "SPLA-Licensed", "ostype": "windows", "version": "Windows Server 2012 R2 Standard", "location_country": "de", "location_name": "de/fra", "capacity": 32, "create_time": "2015-10-12T14:11:22Z", "location_iata": "fra", "name": "Windows Server 2012 R2", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": 800001, "current_price": 0, "object_uuid": "b2e6b10f-5a77-4327-9f7e-9b9dea826bf1", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": {}, "distro": "Windows Server", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "42be618a-254e-41cf-a9a1-c97dae7cf5c7": { "description": "SPLA-Licensed", "ostype": "windows", "version": "Windows Server 2019 Standard", "location_country": "de", "location_name": "de/fra", "capacity": 30, "create_time": "2019-03-25T15:10:39Z", "location_iata": "fra", "name": "Windows Server 2019", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": 800003, "current_price": 0, "object_uuid": "42be618a-254e-41cf-a9a1-c97dae7cf5c7", "change_time": "2019-05-06T13:42:11Z", "private": false, "metadata": {}, "distro": "Windows Server", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "44ca25cc-7da8-479a-a957-dd9363e7c44a": { "description": "Marketplace Template - Ubuntu 16.04 LTS with Benno", "ostype": "marketplace", "version": "Ubuntu 16.04 LTS", "location_country": "de", "location_name": "de/fra", "capacity": 50, "create_time": "2018-07-25T15:49:18Z", "location_iata": "fra", "name": "Benno", "status": "active", "labels": [], "usage_in_minutes": 0, "license_product_no": null, "current_price": 0, "object_uuid": "44ca25cc-7da8-479a-a957-dd9363e7c44a", "change_time": "2019-01-03T17:06:49Z", "private": false, "metadata": { "icon": "/img/assets/logos_marketplace/benno.png", "description": { "de": "# Übersicht \n\nBenno ist ein Tool zur E-Mail Archivierung das eine revisionssichere und gesetzeskonforme Speicherung ermöglicht. Durch offene Schnittstellen ist es kompatibel mit allen gängigen Mailserver und Groupware-Lösungen. E-Mails werden nebst aller Anlagen und Kopfzeilen (Mailheader) indexiert und abgelegt. E-Mail-Anhänge wie bspw. PDF, MS Office, OpenDocument (LibreOffice, OpenOffice.org) usw. werden ebenso volltext-indexiert, wie die eigentliche E-Mail-Nachricht selbst. Dank der leistungsstarken Suche können E-Mails schnell und einfach aufgefunden werden. \n\n## Features\n\n- Modernes Design\n- Integrierte Benutzerverwaltung\n- Revisionssicher und gesetzeskonform\n- REST API\n\n# Dokumentation\n\nNachdem der Benno-Server fertiggestellt und eingeschaltet ist, verbinde dich mit Hilfe unserer VNC Konsole (>\\_) auf den Bildschirm des Servers. Dort findest du Informationen bezüglich Zugangsdaten und Zugriff auf Benno so wie weitere Schritte um die Installation zu vervollständigen.\n\nFür weitere Dokumentation kannst du das **[Benno Wiki](https://wiki.benno-mailarchiv.de/doku.php)** lesen.", "en": "# Overview \n\nBenno is a tool for e-mail archiving that enables audit-proof and legally compliant storage. Open interfaces make it compatible with all common mail servers and groupware solutions. Emails are indexed and stored along with all attachments and headers (mail headers). E-mail attachments such as PDF, MS Office, OpenDocument (LibreOffice, OpenOffice.org) etc. are indexed in full text, just like the actual e-mail message itself. Thanks to the powerful search function, e-mails can be found quickly and easily. \n\n## Features\n\n- Modern design\n- Integrated user management\n- audit-proof and in compliance with the law\n- REST API\n\n# Documentation\n\nAfter the Benno server is ready and turned on, connect to the server's screen using our VNC console (>\\_). There you will find information regarding login credentials and access to Benno and further steps to complete the installation.\n\nFor further documentation you can read the **[Benno Wiki](https://wiki.benno-mailarchiv.de/doku.php)**." }, "setup": { "storage_type": "storage_insane", "memory": 2, "capacity": 50, "cores": 1 }, "os": "Debian 9 (stretch)", "other_software": { "PHP": "7.0", "Apache": "2.4", "OpenJDK": "8" }, "publisher": "LWsystems GmbH", "version": "2.4", "category": "Archiving", "top": false, "licence": "Commercial", "short_description": { "de": "Tool zur E-Mail Archivierung", "en": "Email archiving tool" } }, "distro": "Benno", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" }, "1b3cb7fb-9988-4ba5-8537-b9d2ec8e5882": { "description": null, "ostype": null, "version": null, "location_country": "de", "location_name": "de/fra", "capacity": 50, "create_time": "2019-06-20T17:41:27Z", "location_iata": "fra", "name": "test.test", "status": "active", "labels": [], "usage_in_minutes": 272950, "license_product_no": null, "current_price": 1.20098, "object_uuid": "1b3cb7fb-9988-4ba5-8537-b9d2ec8e5882", "change_time": "2019-06-20T17:41:27Z", "private": true, "metadata": {}, "distro": null, "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/list_key_pairs.json0000664000175000017500000000144013570310635030377 0ustar kamikami00000000000000{ "sshkeys": { "f7360eb9-2d36-42cc-83da-71162bcb9396": { "name": "karl", "create_time": "2019-04-08T09:35:55Z", "status": "active", "object_uuid": "f7360eb9-2d36-42cc-83da-71162bcb9396", "user_uuid": "959440bd-88cf-4ff0-beef-8cf82b803749", "labels": [], "change_time": "2019-04-08T09:35:55Z", "sshkey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC" }, "b1682d3a-1869-4bdc-8ffe-e74a261d300c": { "name": "karl", "create_time": "2019-04-08T09:28:39Z", "status": "active", "object_uuid": "b1682d3a-1869-4bdc-8ffe-e74a261d300c", "user_uuid": "959440bd-88cf-4ff0-beef-8cf82b803749", "labels": [], "change_time": "2019-04-08T09:28:39Z", "sshkey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/list_locations.json0000664000175000017500000000073713570310635030414 0ustar kamikami00000000000000{ "locations": { "8328a5bc-e66e-4edc-8aae-2e2bf07fdb28": { "name": "de/fra2", "status": "active", "iata": "fra", "object_uuid": "8328a5bc-e66e-4edc-8aae-2e2bf07fdb28", "labels": [], "country": "de" }, "45ed677b-3702-4b36-be2a-a2eab9827950": { "name": "de/fra", "status": "active", "iata": "fra", "object_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "labels": [], "country": "de" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/list_nodes.json0000664000175000017500000000531613570310635027527 0ustar kamikami00000000000000{ "servers": { "1479405e-d46c-47a2-91e8-eb43951c899f": { "hardware_profile": "default", "relations": { "storages": [ { "storage_type": "storage", "last_used_template": "a5112c72-c9fa-4a23-8115-5f6303eb047b", "create_time": "2019-06-24T10:10:51Z", "capacity": 50, "lun": 0, "controller": 0, "target": 0, "object_uuid": "e66bb753-4a03-4ee2-a069-a601f393c9ee", "bootdevice": true, "object_name": "linux", "license_product_no": null, "bus": 0 } ], "networks": [ { "mac": "16:63:95:5d:1f:01", "network_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7", "network_type": "network", "mcast": null, "create_time": "2019-06-07T14:59:47Z", "public_net": true, "partner_uuid": "95a2980b-7012-43dd-81f2-07577cfcb9f0", "ordering": 0, "vlan": null, "firewall": null, "l2security": true, "firewall_template_uuid": null, "vxlan": null, "object_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7", "bootdevice": false, "object_name": "network", "l3security": [ "185.102.95.236/32" ] } ], "isoimages": [], "public_ips": [ { "object_uuid": "56b8d161-325b-4fd4-a453-6101cf563713", "ip": "185.102.95.236", "family": 4, "create_time": "2019-06-07T12:57:30Z", "prefix": "185.102.95.236/32" }, { "object_uuid": "0235e7c4-18c9-4b2f-a3c3-2d9624a67498", "ip": "2a06:2380:0:1::211", "family": 6, "create_time": "2019-06-07T14:59:47Z", "prefix": "2a06:2380:0:1::211/128" } ] }, "memory": 10, "location_iata": "fra", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "change_time": "2019-06-17T14:13:31Z", "object_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f", "labels": [], "usage_in_minutes_cores": 25030, "cores": 2, "console_token": "088f625818dc5b9114f8bee8e7f67d7b5510fc5159968a02752875f4b55ca911d59fd6cbe3eeb60358c0f353b1d7cbb9", "availability_zone": null, "location_name": "de/fra", "create_time": "2019-06-07T12:56:44Z", "location_country": "de", "legacy": false, "current_price": 17.89645, "power": false, "status": "active", "auto_recovery": true, "name": "test.test", "usage_in_minutes_memory": 125150 } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/list_volume_snapshots.json0000664000175000017500000000124013570310635032020 0ustar kamikami00000000000000{ "snapshots": { "d755de62-4d75-4d61-addd-a5c9743a5deb": { "change_time": "2019-06-24T13:02:55Z", "location_name": "de/fra", "status": "active", "parent_name": "linux", "create_time": "2019-06-24T13:02:55Z", "labels": [], "parent_uuid": "e66bb753-4a03-4ee2-a069-a601f393c9ee", "location_country": "de", "capacity": 50, "last_used_template": null, "object_uuid": "d755de62-4d75-4d61-addd-a5c9743a5deb", "location_iata": "fra", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "name": "linux Snapshot", "current_price": 5.5e-05, "usage_in_minutes": 50 } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/list_volumes.json0000664000175000017500000000215413570310635030106 0ustar kamikami00000000000000{ "storages": { "e66bb753-4a03-4ee2-a069-a601f393c9ee": { "snapshots": [], "capacity": 50, "relations": { "snapshot_schedules": [], "servers": [ { "create_time": "2019-06-24T10:10:51Z", "bootdevice": true, "lun": 0, "bus": 0, "object_name": "test.test", "target": 0, "object_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f", "controller": 0 } ] }, "storage_type": "storage", "last_used_template": "a5112c72-c9fa-4a23-8115-5f6303eb047b", "object_uuid": "e66bb753-4a03-4ee2-a069-a601f393c9ee", "license_product_no": null, "location_country": "de", "current_price": 3.09298, "create_time": "2019-06-14T17:31:10Z", "change_time": "2019-06-14T17:31:10Z", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "labels": [], "name": "linux", "usage_in_minutes": 702950, "location_name": "de/fra", "location_iata": "fra", "status": "active", "parent_uuid": null } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/list_volumes_empty.json0000664000175000017500000000002513570310635031317 0ustar kamikami00000000000000{ "storages": {} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/network_to_node.json0000664000175000017500000000204413570310635030557 0ustar kamikami00000000000000 { "1196529b-a8de-417f-ac95-0e13ef4fdfd7": { "delete_block": false, "relations": { "servers": [ { "bootdevice": false, "create_time": "2019-06-07T14:59:47Z", "ordering": 0, "l3security": [ "185.102.95.236/32" ], "mac": "16:63:95:5d:1f:01", "object_name": "test.test", "network_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7", "object_uuid": "1479405e-d46c-47a2-91e8-eb43951c899f" } ], "vlans": [] }, "labels": [], "network_type": "network", "change_time": "2019-04-08T09:10:08Z", "status": "active", "create_time": "2018-12-06T13:09:08Z", "location_uuid": "45ed677b-3702-4b36-be2a-a2eab9827950", "location_name": "de/fra", "name": "network", "location_iata": "fra", "l2security": true, "public_net": true, "location_country": "de", "object_uuid": "1196529b-a8de-417f-ac95-0e13ef4fdfd7" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/gridscale/volume_to_node.json0000664000175000017500000000000013570310635030363 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/0000775000175000017500000000000013600223624025106 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/cancel_package.json0000664000175000017500000000003213535474530030707 0ustar kamikami00000000000000{ "status" : "success" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/get_node.json0000664000175000017500000000051413535474530027600 0ustar kamikami00000000000000{ "host": "659", "rescue": "0", "fqdn": "server1.vr-cluster.org", "mbpkgid": "62291", "locked": "0", "os_id": "1613", "os": "Debian 6 i386 PV", "ip": "208.111.45.250", "installed": "0", "state": "DOWN", "package": "VR512", "ipv6": "2607:f740:10::f98", "city": "MAA - Chennai (Madras), India", "status": "TERMINATED" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/list_images.json0000664000175000017500000000430313535474530030314 0ustar kamikami00000000000000[ { "id": "1739", "os": "Gentoo 2012 (0619) i386", "description": "Gentoo 2012 0619 i386", "type": "gentoo", "subtype": "pv", "size": "840mb", "created": "2012-06-27 13:21:03", "updated": "2012-06-27 13:28:50", "bits": "32", "tech": "pv" }, { "id": "1613", "os": "CentOS 5.8 x64", "description": "CentOS 5.8 x64", "type": "centos", "subtype": "pv", "size": "1.2gb", "created": "2012-03-31 01:34:54", "updated": "2012-05-23 16:15:29", "bits": "32", "tech": "pv" }, { "id": "1676", "os": "Ubuntu Server 12.04 LTS 64 bit", "description": "Ubuntu 12.04 LTS x64", "type": "ubuntu", "subtype": "pv", "size": "800mb", "created": "2012-05-04 06:20:59", "updated": "2012-05-04 06:31:09", "bits": "64", "tech": "pv" }, { "id": "1667", "os": "Ubuntu Server 12.04 LTS 32 bit", "description": "Ubuntu 12.04 i386", "type": "ubuntu", "subtype": "pv", "size": "700mb", "created": "2012-05-04 06:18:10", "updated": "2012-05-04 06:31:08", "bits": "32", "tech": "pv" }, { "id": "1640", "os": "CentOS 6.2 x64", "description": "CentOS 6.2 x64", "type": "centos", "subtype": "pv", "size": "1.2gb", "created": "2012-03-31 01:36:44", "updated": "2012-03-31 01:39:25", "bits": "64", "tech": "pv" }, { "id": "1631", "os": "CentOS 6.2 i386", "description": "CentOS 6.2 i386", "type": "centos", "subtype": "pv", "size": "1.1gb", "created": "2012-03-31 01:36:15", "updated": "2012-03-31 01:38:50", "bits": "32", "tech": "pv" }, { "id": "1622", "os": "CentOS 5.8 i386", "description": "CentOS 5.8 i386", "type": "centos", "subtype": "pv", "size": "1.1gb", "created": "2012-03-31 01:35:30", "updated": "2012-03-31 01:38:49", "bits": "32", "tech": "pv" }, { "id": "721", "os": "Ubuntu 11.04 Server x64 PV", "description": "

Ubuntu 11.04 base server installation.<\/p>", "type": "ubuntu", "subtype": "pv", "size": "600mb", "created": "2011-05-01 06:21:08", "updated": "2011-05-01 13:21:08", "bits": "64", "tech": "pv" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/list_locations.json0000664000175000017500000000416013535474530031043 0ustar kamikami00000000000000{ "SJC - San Jose, CA": { "name": "SJC - San Jose, CA", "id": "3" }, "IAD - Reston, VA": { "name": "IAD - Reston, VA", "id": "13" }, "LAX - Los Angeles, CA": { "name": "LAX - Los Angeles, CA", "id": "21" }, "CHI - Chicago, IL": { "name": "CHI - Chicago, IL", "id": "31" }, "LGA - New York, NY": { "name": "LGA - New York, NY", "id": "41" }, "MAA - Chennai (Madras), India": { "name": "MAA - Chennai (Madras), India", "id": "61" }, "LHR - London, United Kingdom": { "name": "LHR - London, United Kingdom", "id": "71" }, "AMS - Amsterdam, NL": { "name": "AMS - Amsterdam, NL", "id": "72" }, "CDG - Paris, France": { "name": "CDG - Paris, France", "id": "82" }, "HKG - Hong Kong, HK": { "name": "HKG - Hong Kong, HK", "id": "83" }, "DFW - Dallas, TX": { "name": "DFW - Dallas, TX", "id": "101" }, "SVM - StrongVM, DDoS Protected": { "name": "SVM - StrongVM, DDoS Protected", "id": "121" }, "DEN - Denver, CO": { "name": "DEN - Denver, CO", "id": "122" }, "MIA - Miami, FL": { "name": "MIA - Miami, FL", "id": "123" }, "SEA - Seattle, WA": { "name": "SEA - Seattle, WA", "id": "124" }, "TOR - Toronto, CA": { "name": "TOR - Toronto, CA", "id": "127" }, "SYD - Sydney, AU": { "name": "SYD - Sydney, AU", "id": "137" }, "OTP - Bucharest, RO": { "name": "OTP - Bucharest, RO", "id": "146" }, "FRA - Frankfurt, DE": { "name": "FRA - Frankfurt, DE", "id": "164" }, "SIN - Singapore, SG": { "name": "SIN - Singapore, SG", "id": "173" }, "GRU - Sao Paulo, Brazil": { "name": "GRU - Sao Paulo, Brazil", "id": "182" }, "SJC2 - San Jose, CA": { "name": "SJC2 - San Jose, CA", "id": "227" }, "RDU - Raleigh, NC": { "name": "RDU - Raleigh, NC", "id": "236" }, "IAD3 - Ashburn, VA": { "name": "IAD3 - Ashburn, VA", "id": "245" }, "DFW2 - Dallas, TX": { "name": "DFW2 - Dallas, TX", "id": "281" }, "PHX - Phoenix, AZ": { "name": "PHX - Phoenix, AZ", "id": "290" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json0000664000175000017500000000264313535474530030164 0ustar kamikami00000000000000[{ "host": "659", "rescue": "0", "fqdn": "server1.vr-cluster.org", "mbpkgid": "62291", "locked": "0", "os": "Debian 6 i386 PV", "ip": "208.111.45.250", "installed": "0", "state": "DOWN", "package": "VR512", "ipv6": "2607:f740:10::f98", "city": "MAA - Chennai (Madras), India", "status": "TERMINATED", "os_id" : "1613", "location_id" : "3", "plan_id" : "51" }, { "host": "902", "rescue": "0", "fqdn": "newbuild.vr.com", "mbpkgid": "62327", "locked": "0", "os": "CentOS 5.8 x64", "ip": "208.111.39.118", "installed": "0", "state": "DOWN", "package": "VR512", "ipv6": "2607:f740:0:3f::f0d", "city": "SJC - San Jose, CA", "status": "TERMINATED", "os_id" : "1613", "location_id" : "3", "plan_id" : "51" }, { "host": "1010", "rescue": "0", "fqdn": "3test.build.com", "mbpkgid": "62300", "locked": "0", "os": "CentOS 6.2 x64", "ip": "208.111.40.179", "installed": "0", "state": "DOWN", "package": "VR512", "ipv6": "2607:f740:c::f4f", "city": "LAX3 - Los Angeles, CA", "status": "TERMINATED", "os_id" : "1613", "location_id" : "3", "plan_id" : "51" }, { "host": "1028", "rescue": "0", "fqdn": "libcloud2.node.com", "mbpkgid": "74567", "locked": "0", "os": "CentOS 5.8 x64", "ip": "209.177.157.99", "installed": "1", "state": "UP", "package": "VR512", "ipv6": "2607:f740:b::eff", "city": "IAD2- Reston, VA", "status": "RUNNING", "os_id" : "1613", "location_id" : "3", "plan_id" : "51" }] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/list_packages.json0000664000175000017500000000222513535474530030626 0ustar kamikami00000000000000[{ "mbpkgid": "4344", "package_status": "Active", "domU_package": "182", "name": "VR1G", "rescue": "0", "locked": "0", "state": "UP", "installed": "1", "locked_reason": null, "package": "VR1G", "ipv6": "2637:f740:b::33b", "city": "IAD - Reston, VA", "fqdn": "apibuild.vr.org", "uptime": "19 hours", "ip": "199.38.183.116", "domu_dom0": "1019", "os": " Debian 7.6 x64", "is_building": false }, { "mbpkgid": "176018", "package_status": "Active", "domU_package": "182", "name": "VR1G", "rescue": "0", "locked": "0", "state": "UP", "installed": "1", "locked_reason": null, "package": "VR1G", "ipv6": "2607:f740:c::b4d", "city": "LAX - Los Angeles, CA", "fqdn": "db.vr.org", "uptime": "566 days, 15 hours", "ip": "208.111.40.64", "domu_dom0": "532", "os": " Debian 7.6 x64", "is_building": false }, { "mbpkgid": "151472", "package_status": "Suspended", "domU_package": null, "name": "VR1G", "rescue": null, "locked": null, "state": null, "installed": null, "locked_reason": null, "package": null, "ipv6": "", "city": null, "fqdn": null, "uptime": false, "ip": null, "domu_dom0": null, "os": null, "is_building": false }] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json0000664000175000017500000000437113535474530030211 0ustar kamikami00000000000000[ { "plan_id": "31", "plan": "VR256", "ram": "256MB", "disk": "10GB", "transfer": "200GB", "price": "10.00", "available": "1167" }, { "plan_id": "41", "plan": "VR384", "ram": "384MB", "disk": "15GB", "transfer": "300GB", "price": "15.00", "available": "768" }, { "plan_id": "51", "plan": "VR512", "ram": "512MB", "disk": "20GB", "transfer": "400GB", "price": "20.00", "available": "620" }, { "plan_id": "61", "plan": "VR768", "ram": "768MB", "disk": "30GB", "transfer": "600GB", "price": "30.00", "available": "403" }, { "plan_id": "71", "plan": "VR1024", "ram": "1024MB", "disk": "40GB", "transfer": "800GB", "price": "40.00", "available": "304" }, { "plan_id": "81", "plan": "VR1280", "ram": "1280MB", "disk": "50GB", "transfer": "1000GB", "price": "50.00", "available": "234" }, { "plan_id": "91", "plan": "VR1536", "ram": "1536MB", "disk": "60GB", "transfer": "1200GB", "price": "60.00", "available": "190" }, { "plan_id": "101", "plan": "VR2048", "ram": "2048MB", "disk": "80GB", "transfer": "1600GB", "price": "80.00", "available": "138" }, { "plan_id": "128", "plan": "VRBL1G", "ram": "1024MB", "disk": "50GB", "transfer": "1000GB", "price": "150.00", "available": "34" }, { "plan_id": "111", "plan": "VR4048", "ram": "4048MB", "disk": "160GB", "transfer": "3200GB", "price": "160.00", "available": "60" }, { "plan_id": "137", "plan": "VRBL2G", "ram": "2048MB", "disk": "100GB", "transfer": "2000GB", "price": "200.00", "available": "16" }, { "plan_id": "146", "plan": "VRBL4G", "ram": "4048MB", "disk": "150GB", "transfer": "3000GB", "price": "300.00", "available": "8" }, { "plan_id": "119", "plan": "VR8096", "ram": "8096MB", "disk": "320GB", "transfer": "6400GB", "price": "320.00", "available": "11" }, { "plan_id": "155", "plan": "VRBL8G", "ram": "8096MB", "disk": "200GB", "transfer": "5000GB", "price": "400.00", "available": "4" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/node_reboot.json0000664000175000017500000000003213535474530030306 0ustar kamikami00000000000000{ "status" : "success" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/node_start.json0000664000175000017500000000003213535474530030151 0ustar kamikami00000000000000{ "status" : "success" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/node_stop.json0000664000175000017500000000003213535474530030001 0ustar kamikami00000000000000{ "status" : "success" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/order_package.json0000664000175000017500000000002413535474530030576 0ustar kamikami00000000000000{ "id": "62291" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/hostvirtual/unlink_package.json0000664000175000017500000000003213535474530030762 0ustar kamikami00000000000000{ "status" : "success" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/joyent/0000775000175000017500000000000013600223624024032 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/joyent/my_datasets.json0000664000175000017500000002246113535474530027262 0ustar kamikami00000000000000[{"id":"f953e97e-4991-11e1-9ea4-27c6e7e8afda","urn":"sdc:sdc:nodejs:1.3.3","name":"nodejs","os":"smartos","type":"smartmachine","description":"Node.js git-deploy PaaS dataset","default":false,"requirements":{},"version":"1.3.3","created":"2012-02-14T03:54:01+00:00"},{"id":"71101322-43a5-11e1-8f01-cf2a3031a7f4","urn":"sdc:sdc:ubuntu-10.04:1.0.1","name":"ubuntu-10.04","os":"linux","type":"virtualmachine","description":"Ubuntu 10.04 VM 1.0.1","default":false,"requirements":{},"version":"1.0.1","created":"2012-02-22T18:27:32+00:00"},{"id":"7a4f84be-df6d-11e0-a504-3f6609d83831","urn":"sdc:admin:windows2008r2:1.5.0","name":"windows2008r2","os":"windows","type":"virtualmachine","description":"Windows 2008r2 Enterprise Edition","default":false,"requirements":{"max_memory":32768,"min_memory":4096},"version":"1.5.0","created":"2012-02-16T19:31:01+00:00"},{"id":"e4cd7b9e-4330-11e1-81cf-3bb50a972bda","urn":"sdc:sdc:centos-6:1.0.1","name":"centos-6","os":"linux","type":"virtualmachine","description":"Centos 6 VM 1.0.1","default":false,"requirements":{},"version":"1.0.1","created":"2012-02-15T20:04:18+00:00"},{"id":"988c2f4e-4314-11e1-8dc3-2bc6d58f4be2","urn":"sdc:sdc:centos-5.7:1.2.1","name":"centos-5.7","os":"linux","type":"virtualmachine","description":"Centos 5.7 VM 1.2.1","default":false,"requirements":{},"version":"1.2.1","created":"2012-02-14T05:53:49+00:00"},{"id":"e6ac6784-44b3-11e1-8555-87c3dd87aafe","urn":"sdc:sdc:debian-6.03:1.0.0","name":"debian-6.03","os":"linux","type":"virtualmachine","description":"Debian 6.03 VM 1.0.0","default":false,"requirements":{},"version":"1.0.0","created":"2012-02-14T05:21:53+00:00"},{"id":"3f8a3d02-43e4-11e1-9565-7f82a075e289","urn":"sdc:sdc:fedora-14:1.0.1","name":"fedora-14","os":"linux","type":"virtualmachine","description":"Fedora 14 VM 1.0.1","default":false,"requirements":{},"version":"1.0.1","created":"2012-02-14T05:20:52+00:00"},{"id":"d239389c-7535-11e1-b60a-6f75edc139df","urn":"sdc:sdc:mongodb:1.2.4","name":"mongodb","os":"smartos","type":"smartmachine","description":"MongoDB SmartMachine","default":false,"requirements":{},"version":"1.2.4","created":"2012-03-23T22:33:31+00:00"},{"id":"98f38e14-6f83-11e1-bc32-2b9d0a8b6759","urn":"sdc:sdc:mongodb:1.1.1","name":"mongodb","os":"smartos","type":"smartmachine","description":"MongoDB SmartMachine","default":false,"requirements":{},"version":"1.1.1","created":"2012-03-16T16:54:14+00:00"},{"id":"64d81cee-689e-11e1-a130-232647306089","urn":"local:admin:stingray-standard-1gbps:1.2.0","name":"stingray-standard-1gbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager Hi-Throughput SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:40+00:00"},{"id":"29a2fb18-689d-11e1-a2a5-47b01f708bb0","urn":"local:admin:stingray-enterprise-1gbps:1.2.0","name":"stingray-enterprise-1gbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager Enterprise Hi-Throughput SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:12+00:00"},{"id":"27750b5c-689c-11e1-a67e-6331aba2c777","urn":"local:admin:stingray-enterprise-200mbps:1.2.0","name":"stingray-enterprise-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager Enterprise SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:19+00:00"},{"id":"56ffd3bc-689b-11e1-837f-735e255247ac","urn":"local:admin:stingray-standard-200mbps:1.2.0","name":"stingray-standard-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Traffic Manager SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:49+00:00"},{"id":"c79e581a-689a-11e1-91f3-932bbde56874","urn":"local:admin:stingray-lb-200mbps:1.2.0","name":"stingray-lb-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Load Balancer SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:26+00:00"},{"id":"4ca85e3a-689a-11e1-a5df-1b5ffe7065e9","urn":"local:admin:stingray-simple-lb-200mbps:1.2.0","name":"stingray-simple-lb-200mbps","os":"smartos","type":"smartmachine","description":"Riverbed Stingray v8.1 (formerly Zeus) Simple Load Balancer SmartMachine","default":false,"requirements":{},"version":"1.2.0","created":"2012-03-09T01:49:33+00:00"},{"id":"8c4c0f30-66df-11e1-a3f4-0f8e0a382b60","urn":"sdc:sdc:percona:1.3.9","name":"percona","os":"smartos","type":"smartmachine","description":"Percona SmartMachine","default":false,"requirements":{},"version":"1.3.9","created":"2012-03-05T16:41:01+00:00"},{"id":"618d80f8-66d5-11e1-998e-e384c47940f0","urn":"sdc:sdc:mongodb:1.0.9","name":"mongodb","os":"smartos","type":"smartmachine","description":"MongoDB SmartMachine","default":false,"requirements":{},"version":"1.0.9","created":"2012-03-05T15:29:21+00:00"},{"id":"a54da3a0-6319-11e1-a3d9-9fdedd2f9e17","urn":"sdc:sdc:riak:1.5.6","name":"riak","os":"smartos","type":"smartmachine","description":"Riak SmartMachine template","default":false,"requirements":{},"version":"1.5.6","created":"2012-03-01T16:18:13+00:00"},{"id":"81641caa-6321-11e1-a79a-731161c6d519","urn":"local:admin:riakeds:1.5.6","name":"riakeds","os":"smartos","type":"smartmachine","description":"Riak EDS SmartMachine template","default":false,"requirements":{},"version":"1.5.6","created":"2012-03-01T19:52:37+00:00"},{"id":"f4bc70ca-5e2c-11e1-8380-fb28785857cb","urn":"sdc:sdc:smartosplus64:3.1.0","name":"smartosplus64","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.1.0","created":"2012-03-02T15:30:58+00:00"},{"id":"a963d5d0-5e29-11e1-a4d7-a31977b1e6dd","urn":"sdc:sdc:smartosplus:3.1.0","name":"smartosplus","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.1.0","created":"2012-03-02T15:24:10+00:00"},{"id":"31bc4dbe-5e06-11e1-907c-5bed6b255fd1","urn":"sdc:sdc:smartos64:1.5.4","name":"smartos64","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.5.4","created":"2012-03-02T15:20:17+00:00"},{"id":"489754f2-5e01-11e1-8ff8-f770c2116b0d","urn":"sdc:sdc:smartos:1.5.4","name":"smartos","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.5.4","created":"2012-03-02T15:16:12+00:00"},{"id":"e05dbcac-1d44-11e1-b8ab-bf1bc04c2d65","urn":"sdc:sdc:smartosplus64:3.0.7","name":"smartosplus64","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.7","created":"2012-02-13T19:18:56+00:00"},{"id":"fcc5996a-1d34-11e1-899e-7bd98b87947a","urn":"sdc:sdc:smartosplus:3.0.7","name":"smartosplus","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.7","created":"2012-02-13T19:22:05+00:00"},{"id":"5fef6eda-05f2-11e1-90fc-13dac5e4a347","urn":"sdc:sdc:percona:1.2.2","name":"percona","os":"smartos","type":"smartmachine","description":"Percona SmartMachine","default":false,"requirements":{},"version":"1.2.2","created":"2012-02-13T19:23:12+00:00"},{"id":"34359ccc-21d2-2e4e-87e8-69fb36412008","urn":"sdc:sdc:windows2008r2standard:1.5.1","name":"windows2008r2standard","os":"windows","type":"virtualmachine","description":"windows2008r2standard VM image","default":false,"requirements":{"max_memory":32768,"min_memory":4096},"version":"1.5.1","created":"2012-03-13T18:25:53+00:00"},{"id":"a9380908-ea0e-11e0-aeee-4ba794c83c33","urn":"sdc:sdc:percona:1.0.7","name":"percona","os":"smartos","type":"smartmachine","description":"Percona SmartMachine","default":false,"requirements":{},"version":"1.0.7","created":"2012-02-13T19:24:17+00:00"},{"id":"df3589dc-df9a-11e0-a3a3-07ceee3e7d54","urn":"sdc:sdc:smartosplus64:3.0.4","name":"smartosplus64","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.4","created":"2012-02-13T19:27:27+00:00"},{"id":"aded640a-df98-11e0-b050-1f55ff3ddfa7","urn":"sdc:sdc:smartosplus:3.0.4","name":"smartosplus","os":"smartos","type":"smartmachine","description":"Generic multi-purpose SmartMachine template","default":false,"requirements":{},"version":"3.0.4","created":"2012-02-13T19:30:28+00:00"},{"id":"3fcf35d2-dd79-11e0-bdcd-b3c7ac8aeea6","urn":"sdc:sdc:mysql:1.4.1","name":"mysql","os":"smartos","type":"smartmachine","description":"MySQL SmartMachine","default":false,"requirements":{},"version":"1.4.1","created":"2012-02-13T19:32:51+00:00"},{"id":"141194fa-dd77-11e0-8539-27dd8d8264b8","urn":"sdc:sdc:smartos64:1.4.7","name":"smartos64","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.4.7","created":"2012-02-13T19:33:21+00:00"},{"id":"f8ea0bb8-dd75-11e0-87c3-af5352ad3bd6","urn":"sdc:sdc:smartos:1.4.7","name":"smartos","os":"smartos","type":"smartmachine","description":"Base template to build other templates on","default":false,"requirements":{},"version":"1.4.7","created":"2012-02-13T19:33:50+00:00"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/joyent/my_machines.json0000664000175000017500000000134413535474530027236 0ustar kamikami00000000000000[{"id":"2fb67f5f-53f2-40ab-9d99-b9ff68cfb2ab","name":"testlc1","type":"virtualmachine","state":"running","dataset":"sdc:sdc:ubuntu-10.04:1.0.1","ips":["165.225.129.129","10.112.1.130"],"memory":1024,"disk":30720,"metadata":{"root_authorized_keys":"ssh-rsa abc== JoyentSSH\n"},"created":"2012-04-11T04:08:32+00:00","updated":"2012-04-11T04:08:42+00:00"}, {"id":"2fb67f5f-53f2-40ab-9d99-b9ff68cfb2ab","name":"testlc2","type":"virtualmachine","state":"running","dataset":"sdc:sdc:ubuntu-10.04:1.0.1","ips":["165.225.129.128","10.112.1.131"],"memory":1024,"disk":30720,"metadata":{"root_authorized_keys":"ssh-rsa abc== Joyent SSH\n", "credentials": {"root": "abc"}},"created":"2012-04-11T04:08:32+00:00","updated":"2012-04-11T04:08:42+00:00"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/joyent/my_machines_create.json0000664000175000017500000000054613535474530030564 0ustar kamikami00000000000000{"id":"2fb67f5f-53f2-40ab-9d99-b9ff68cfb2ab","name":"testlc","type":"virtualmachine","state":"provisioning","dataset":"sdc:sdc:ubuntu-10.04:1.0.1","ips":["165.225.129.129","10.112.1.130"],"memory":1024,"disk":30720,"metadata":{"root_authorized_keys":"ssh-rsa abcd== Joyent SSH\n"},"created":"2012-04-11T04:08:27+00:00","updated":"2012-04-11T04:08:27+00:00"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/joyent/my_packages.json0000664000175000017500000000160413535474530027224 0ustar kamikami00000000000000[{"name":"Large 16GB","memory":16384,"disk":491520,"vcpus":3,"swap":32768,"default":false},{"name":"XL 8GB High CPU","memory":8192,"disk":245760,"vcpus":4,"swap":16384,"default":false},{"name":"XL 32GB","memory":32768,"disk":778240,"vcpus":4,"swap":65536,"default":false},{"name":"XXL 48GB","memory":49152,"disk":1048576,"vcpus":8,"swap":98304,"default":false},{"name":"XXXL 64GB ","memory":65536,"disk":1572864,"vcpus":12,"swap":131072,"default":false},{"name":"Medium 1GB High-CPU","memory":1024,"disk":61440,"vcpus":2,"swap":2048,"default":false},{"name":"Small 1GB","memory":1024,"disk":30720,"vcpus":1,"swap":2048,"default":true},{"name":"Medium 2GB","memory":2048,"disk":61440,"vcpus":1,"swap":4096,"default":false},{"name":"Medium 4GB","memory":4096,"disk":122880,"vcpus":1,"swap":8192,"default":false},{"name":"Large 8GB","memory":8192,"disk":245760,"vcpus":2,"swap":16384,"default":false}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/0000775000175000017500000000000013600223624024354 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_default.json0000664000175000017500000000007713535474530033122 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":17164,"id":2602} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail.json0000664000175000017500000000016013535474530033617 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"errorcode" : 431, "errortext" : "Unable to find service offering: 104"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/deployVirtualMachine_deployfail2.json0000664000175000017500000000007713535474530033710 0ustar kamikami00000000000000{ "deployvirtualmachineresponse" : {"jobid":17177,"id":2602} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/destroyVirtualMachine_default.json0000664000175000017500000000006613535474530033315 0ustar kamikami00000000000000{ "destroyvirtualmachineresponse" : {"jobid":17166} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_default.json0000664000175000017500000007257313535474530034146 0ustar kamikami00000000000000{"listavailableproducttypesresponse":{"count":112,"producttypes":[{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-829-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-829-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-829-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-829-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-829-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-829-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-829-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-829-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Centos 5.4 32bit","templateid":"829","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-830-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-830-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-830-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-830-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-830-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-830-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-830-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-830-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Centos 5.4 64bit","templateid":"830","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-867-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-867-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-867-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-867-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-867-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-867-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-867-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-867-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Debian 6 Squeeze 32bit","templateid":"867","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-880-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-880-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-880-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-880-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-880-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-880-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-880-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-880-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Debian 6 Squeeze 64bit","templateid":"880","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-881-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-881-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-881-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-881-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-881-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-881-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-881-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-881-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Fedora release 13 64 bit","templateid":"881","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-877-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-877-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-877-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-877-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-877-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-877-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-877-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-877-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 11.04 32bit","templateid":"877","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-878-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-878-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-878-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-878-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-878-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-878-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-878-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-878-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 11.04 64bit","templateid":"878","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-988-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-988-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-988-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-988-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-988-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-988-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-988-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-988-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2003 R2 32bit","templateid":"988","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-986-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-986-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-986-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-986-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-986-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-986-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-986-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-986-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2003 ENT 32bit","templateid":"986","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-989-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-989-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-989-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-989-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-989-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-989-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-989-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-989-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2008 ENT 32bit","templateid":"989","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-990-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-990-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-990-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-990-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-990-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-990-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-990-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-990-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2008 R2 64bit","templateid":"990","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-991-12-25","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"25","productid":"1-991-13-25","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-991-14-26","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"26","productid":"1-991-15-26","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-991-16-27","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"27","productid":"1-991-17-27","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-991-18-28","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"28","productid":"1-991-36-28","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"WIN 2008 R2 Mssql","templateid":"991","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1111-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1111-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1111-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1111-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1111-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1111-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1111-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1111-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 10.04 32bit","templateid":"1111","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1109-12-38","productstate":"available","serviceofferingdesc":"standard 1vCore 1GB RAM","serviceofferingid":"12","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"100GB","diskofferingid":"38","productid":"1-1109-13-38","productstate":"available","serviceofferingdesc":"standard 1vCore 2GB RAM","serviceofferingid":"13","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1109-14-39","productstate":"available","serviceofferingdesc":"standard 2vCore 2GB RAM","serviceofferingid":"14","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"200GB","diskofferingid":"39","productid":"1-1109-15-39","productstate":"available","serviceofferingdesc":"standard 2vCore 4GB RAM","serviceofferingid":"15","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1109-16-40","productstate":"available","serviceofferingdesc":"standard 4vCore 4GB RAM","serviceofferingid":"16","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"300GB","diskofferingid":"40","productid":"1-1109-17-40","productstate":"available","serviceofferingdesc":"standard 4vCore 8GB RAM","serviceofferingid":"17","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1109-18-41","productstate":"available","serviceofferingdesc":"standard 8vCore 8GB RAM","serviceofferingid":"18","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"},{"diskofferingdesc":"400GB","diskofferingid":"41","productid":"1-1109-36-41","productstate":"available","serviceofferingdesc":"standard 8vCore 16GB RAM","serviceofferingid":"36","templatedesc":"Ubuntu 10.04 64bit","templateid":"1109","zonedesc":"MOCKDONG","zoneid":"1"}]}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_nodisk.json0000664000175000017500000000217013535474530033773 0ustar kamikami00000000000000{"listavailableproducttypesresponse": {"count": 2, "producttypes": [{"diskofferingdesc": "100GB", "templatedesc": "Centos 5.4 32bit", "serviceofferingdesc": "premium 2vCore 2GB RAM", "productstate": "available", "product": "Standard", "zoneid": "eceb5d65-6571-4696-875f-5a17949f3317", "zonedesc": "KOR-Central A", "templateid": "d2241244-0b6c-444d-b075-72cfcd562826", "diskofferingid": "cc85e4dd-bfd9-4cec-aa22-cf226c1da92f", "serviceofferingid": "94341d94-ccd4-4dc4-9ccb-05c0c632d0b4", "productid": "eceb5d65-6571-4696-875f-5a17949f3317-d2241244-0b6c-444d-b075-72cfcd562826-94341d94-ccd4-4dc4-9ccb-05c0c632d0b4-cc85e4dd-bfd9-4cec-aa22-cf226c1da92f"}, {"diskofferingdesc": "20GB", "templatedesc": "Centos 5.4 32bit", "serviceofferingdesc": "premium 2vCore 2GB RAM", "productstate": "available", "product": "Standard", "zoneid": "eceb5d65-6571-4696-875f-5a17949f3317", "zonedesc": "KOR-Central A", "templateid": "d2241244-0b6c-444d-b075-72cfcd562826", "serviceofferingid": "94341d94-ccd4-4dc4-9ccb-05c0c632d0b4", "productid": "eceb5d65-6571-4696-875f-5a17949f3317-d2241244-0b6c-444d-b075-72cfcd562826-94341d94-ccd4-4dc4-9ccb-05c0c632d0b4-0"}]}} ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_notemplates.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listAvailableProductTypes_notemplates.0000664000175000017500000000011713535474530034144 0ustar kamikami00000000000000{ "listavailableproducttypesresponse" : { "count" : 0, "producttypes" : [] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listIpForwardingRules_default.json0000664000175000017500000000050013535474530033263 0ustar kamikami00000000000000{ "listipforwardingrulesresponse" : { "count":1 ,"ipforwardingrule" : [ {"id":"772fd410-6649-43ed-befa-77be986b8906","protocol":"tcp","virtualmachineid":"2600","virtualmachinename":"test","virtualmachinedisplayname":"test","ipaddressid":34000,"ipaddress":"1.1.1.116","startport":33,"endport":34,"state":"Active"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listPortForwardingRules_default.json0000664000175000017500000000075313535474530033651 0ustar kamikami00000000000000{ "listportforwardingrulesresponse" : {"count": 1, "portforwardingrule": [{"protocol": "tcp", "virtualmachineid": "7d8de712-aa7a-4901-a8b1-fd223f0ca459", "ipaddress": "178.170.71.253", "cidrlist": "", "tags": [], "ipaddressid": "50cd9456-d4db-4a48-8cf5-950dba8d2fdb", "virtualmachinedisplayname": "yoyo", "privateendport": "22", "state": "Active", "publicendport": "22", "privateport": "22", "virtualmachinename": "yoyo", "publicport": "22", "id": "4644652a-7573-4e50-aafb-48a171c9bcb2"}]}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listPublicIpAddresses_default.json0000664000175000017500000000241113535474530033225 0ustar kamikami00000000000000{ "listpublicipaddressesresponse" : { "publicipaddress" : [ {"id":34000,"ipaddress":"1.1.1.49","allocated":"2011-06-23T05:20:39+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33999,"ipaddress":"1.1.1.48","allocated":"2011-06-23T05:20:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33998,"ipaddress":"1.1.1.47","allocated":"2011-06-23T05:20:30+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33970,"ipaddress":"1.1.1.19","allocated":"2011-06-20T04:08:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":true,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listVirtualMachines_default.json0000664000175000017500000000321513535474530032761 0ustar kamikami00000000000000{ "listvirtualmachinesresponse" : { "virtualmachine" : [ {"id":2600,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:06:42+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"1.78%","networkkbsread":2,"networkkbswrite":2,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3891,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.116","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}, {"id":2601,"name":"test","displayname":"test","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:09:44+0000","state":"Starting","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"jobid":17147,"jobstatus":0,"nic":[{"id":3892,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.2.1","ipaddress":"1.1.1.203","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/listZones_default.json0000664000175000017500000000017413535474530030762 0ustar kamikami00000000000000{ "listzonesresponse" : { "zone" : [ {"id":1,"name":"Sydney","networktype":"Advanced","securitygroupsenabled":false} ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17164.json0000664000175000017500000000162713535474530032027 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17164,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17165.json0000664000175000017500000000172013535474530032022 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17165,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.14%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17166.json0000664000175000017500000000172213535474530032025 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17166,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Destroyed","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 10.04 Server x64 PV r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute Micro PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_17177.json0000664000175000017500000000010213535474530032016 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"jobid":17177,"jobstatus":2} } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_attachvolumejob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_attachvolumejob.js0000664000175000017500000000217313535474530034174 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.AttachVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","deviceid":5,"virtualmachineid":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmname":"ab2c18f6-00a6-43f8-9fe0-efecb3165dd7","vmdisplayname":"gre-kickstart","vmstate":"Running","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Ready","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"KVM","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering 1","diskofferingdisplaytext":"Disk offering 1 display name","storage":"Shared Storage CL01","attached":"2012-06-05T09:17:38+0200","destroyed":false,"isextractable":false}},"created":"2012-06-05T09:17:38+0200","jobid":"e07d6b9b-2b6c-45bd-840b-3c4c3d890168"} } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_createvolumejob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/queryAsyncJobResult_createvolumejob.js0000664000175000017500000000163413535474530034174 0ustar kamikami00000000000000{ "queryasyncjobresultresponse" : {"accountid":"be7d76b3-8823-49c0-86e1-29efd9ea1eb0","userid":"a8bd3087-edc1-4e94-8470-6830404b7292","cmd":"com.cloud.api.commands.CreateVolumeCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"volume":{"id":"60338035-92fb-4d27-98d4-b60ad4b38b87","name":"vol-0","zoneid":"58624957-a150-46a3-acbf-4088776161e5","zonename":"EQ-AMS2-Z01","type":"DATADISK","size":10737418240,"created":"2012-06-05T08:47:54+0200","state":"Allocated","account":"admin","domainid":"bfc35f83-8589-4e93-9150-d57e8479f772","domain":"ROOT","storagetype":"shared","hypervisor":"None","diskofferingid":"6345e3b7-227e-4209-8f8c-1f94219696e6","diskofferingname":"Disk offering","diskofferingdisplaytext":"Disk offering display name","storage":"none","destroyed":false,"isextractable":false}},"created":"2012-06-05T08:47:54+0200","jobid":"35416f6d-1b5b-4ceb-a7d4-aab0deede71b"} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ktucloud/rebootVirtualMachine_default.json0000664000175000017500000000006513535474530033115 0ustar kamikami00000000000000{ "rebootvirtualmachineresponse" : {"jobid":17165} } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/0000775000175000017500000000000013600223624023774 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_avail_datacenters.json0000664000175000017500000000122413535474530030511 0ustar kamikami00000000000000{ "ERRORARRAY": [], "DATA": [ { "LOCATION": "Dallas, TX, USA", "DATACENTERID": 2, "ABBR": "dallas" }, { "LOCATION": "Fremont, CA, USA", "DATACENTERID": 3, "ABBR": "fremont" }, { "LOCATION": "Atlanta, GA, USA", "DATACENTERID": 4, "ABBR": "atlanta" }, { "LOCATION": "Newark, NJ, USA", "DATACENTERID": 6, "ABBR": "newark" }, { "LOCATION": "London, England, UK", "DATACENTERID": 7, "ABBR": "london" }, { "LOCATION": "Tokyo, JP", "DATACENTERID": 8, "ABBR": "tokyo" } ], "ACTION": "avail.datacenters" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_avail_distributions.json0000664000175000017500000001356613535474530031132 0ustar kamikami00000000000000{ "ERRORARRAY": [], "DATA": [ { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 112, "IS64BIT": 1, "LABEL": "Arch Linux 2013.06", "MINIMAGESIZE": 500, "CREATE_DT": "2013-06-06 02:45:11.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 89, "IS64BIT": 1, "LABEL": "CentOS 6.2", "MINIMAGESIZE": 800, "CREATE_DT": "2011-07-19 11:38:20.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 78, "IS64BIT": 1, "LABEL": "Debian 6", "MINIMAGESIZE": 550, "CREATE_DT": "2011-02-08 16:54:31.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 109, "IS64BIT": 1, "LABEL": "Debian 7", "MINIMAGESIZE": 660, "CREATE_DT": "2013-05-08 11:31:32.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 114, "IS64BIT": 1, "LABEL": "Fedora 19", "MINIMAGESIZE": 750, "CREATE_DT": "2013-08-26 15:29:21.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 53, "IS64BIT": 1, "LABEL": "Gentoo", "MINIMAGESIZE": 1000, "CREATE_DT": "2009-04-04 00:00:00.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 115, "IS64BIT": 1, "LABEL": "openSUSE 12.3", "MINIMAGESIZE": 1024, "CREATE_DT": "2013-09-19 10:49:09.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 87, "IS64BIT": 1, "LABEL": "Slackware 13.37", "MINIMAGESIZE": 600, "CREATE_DT": "2011-06-05 15:11:59.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 65, "IS64BIT": 1, "LABEL": "Ubuntu 10.04 LTS", "MINIMAGESIZE": 450, "CREATE_DT": "2010-04-29 00:00:00.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 99, "IS64BIT": 1, "LABEL": "Ubuntu 12.04 LTS", "MINIMAGESIZE": 600, "CREATE_DT": "2012-04-26 17:25:16.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 111, "IS64BIT": 1, "LABEL": "Ubuntu 13.04", "MINIMAGESIZE": 770, "CREATE_DT": "2013-05-08 11:31:32.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 113, "IS64BIT": 0, "LABEL": "Arch Linux 2013.06 32bit", "MINIMAGESIZE": 500, "CREATE_DT": "2013-06-06 02:45:11.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 88, "IS64BIT": 0, "LABEL": "CentOS 6.2 32bit", "MINIMAGESIZE": 800, "CREATE_DT": "2011-07-19 11:38:20.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 77, "IS64BIT": 0, "LABEL": "Debian 6 32bit", "MINIMAGESIZE": 550, "CREATE_DT": "2011-02-08 16:54:31.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 108, "IS64BIT": 0, "LABEL": "Debian 7 32bit", "MINIMAGESIZE": 660, "CREATE_DT": "2013-05-08 11:31:32.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 72, "IS64BIT": 0, "LABEL": "Gentoo 32bit", "MINIMAGESIZE": 1000, "CREATE_DT": "2010-09-13 00:00:00.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 86, "IS64BIT": 0, "LABEL": "Slackware 13.37 32bit", "MINIMAGESIZE": 600, "CREATE_DT": "2011-06-05 15:11:59.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 64, "IS64BIT": 0, "LABEL": "Ubuntu 10.04 LTS 32bit", "MINIMAGESIZE": 450, "CREATE_DT": "2010-04-29 00:00:00.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 98, "IS64BIT": 0, "LABEL": "Ubuntu 12.04 LTS 32bit", "MINIMAGESIZE": 600, "CREATE_DT": "2012-04-26 17:25:16.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 110, "IS64BIT": 0, "LABEL": "Ubuntu 13.04 32bit", "MINIMAGESIZE": 770, "CREATE_DT": "2013-05-08 11:31:32.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 105, "IS64BIT": 1, "LABEL": "Arch Linux 2012.10", "MINIMAGESIZE": 500, "CREATE_DT": "2012-10-22 15:00:49.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 60, "IS64BIT": 1, "LABEL": "CentOS 5.6 64bit", "MINIMAGESIZE": 950, "CREATE_DT": "2009-08-17 00:00:00.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 100, "IS64BIT": 1, "LABEL": "Fedora 17", "MINIMAGESIZE": 800, "CREATE_DT": "2012-05-31 16:03:49.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 97, "IS64BIT": 1, "LABEL": "openSUSE 12.1", "MINIMAGESIZE": 1000, "CREATE_DT": "2012-04-13 11:43:30.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 107, "IS64BIT": 1, "LABEL": "Ubuntu 12.10", "MINIMAGESIZE": 660, "CREATE_DT": "2012-11-06 11:51:25.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 104, "IS64BIT": 0, "LABEL": "Arch Linux 2012.10 32bit", "MINIMAGESIZE": 500, "CREATE_DT": "2012-10-22 15:00:49.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 59, "IS64BIT": 0, "LABEL": "CentOS 5.6 32bit", "MINIMAGESIZE": 950, "CREATE_DT": "2009-08-17 00:00:00.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 101, "IS64BIT": 0, "LABEL": "Fedora 17 32bit", "MINIMAGESIZE": 800, "CREATE_DT": "2012-05-31 16:03:49.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 96, "IS64BIT": 0, "LABEL": "openSUSE 12.1 32bit", "MINIMAGESIZE": 1000, "CREATE_DT": "2012-04-13 11:43:30.0" }, { "REQUIRESPVOPSKERNEL": 1, "DISTRIBUTIONID": 106, "IS64BIT": 0, "LABEL": "Ubuntu 12.10 32bit", "MINIMAGESIZE": 660, "CREATE_DT": "2012-11-06 11:51:25.0" } ], "ACTION": "avail.distributions" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_avail_kernels.json0000664000175000017500000000511313535474530027660 0ustar kamikami00000000000000{ "ERRORARRAY": [], "ACTION": "avail.kernels", "DATA": [ { "LABEL": "Latest 2.6 Stable (2.6.18.8-linode19)", "ISXEN": 1, "KERNELID": 60 }, { "LABEL": "2.6.18.8-linode19", "ISXEN": 1, "KERNELID": 103 }, { "LABEL": "2.6.30.5-linode20", "ISXEN": 1, "KERNELID": 105 }, { "LABEL": "Latest 2.6 Stable (2.6.18.8-x86_64-linode7)", "ISXEN": 1, "KERNELID": 107 }, { "LABEL": "2.6.18.8-x86_64-linode7", "ISXEN": 1, "KERNELID": 104 }, { "LABEL": "2.6.30.5-x86_64-linode8", "ISXEN": 1, "KERNELID": 106 }, { "LABEL": "pv-grub-x86_32", "ISXEN": 1, "KERNELID": 92 }, { "LABEL": "pv-grub-x86_64", "ISXEN": 1, "KERNELID": 95 }, { "LABEL": "Recovery - Finnix (kernel)", "ISXEN": 1, "KERNELID": 61 }, { "LABEL": "2.6.18.8-domU-linode7", "ISXEN": 1, "KERNELID": 81 }, { "LABEL": "2.6.18.8-linode10", "ISXEN": 1, "KERNELID": 89 }, { "LABEL": "2.6.18.8-linode16", "ISXEN": 1, "KERNELID": 98 }, { "LABEL": "2.6.24.4-linode8", "ISXEN": 1, "KERNELID": 84 }, { "LABEL": "2.6.25-linode9", "ISXEN": 1, "KERNELID": 88 }, { "LABEL": "2.6.25.10-linode12", "ISXEN": 1, "KERNELID": 90 }, { "LABEL": "2.6.26-linode13", "ISXEN": 1, "KERNELID": 91 }, { "LABEL": "2.6.27.4-linode14", "ISXEN": 1, "KERNELID": 93 }, { "LABEL": "2.6.28-linode15", "ISXEN": 1, "KERNELID": 96 }, { "LABEL": "2.6.28.3-linode17", "ISXEN": 1, "KERNELID": 99 }, { "LABEL": "2.6.29-linode18", "ISXEN": 1, "KERNELID": 101 }, { "LABEL": "2.6.16.38-x86_64-linode2", "ISXEN": 1, "KERNELID": 85 }, { "LABEL": "2.6.18.8-x86_64-linode1", "ISXEN": 1, "KERNELID": 86 }, { "LABEL": "2.6.27.4-x86_64-linode3", "ISXEN": 1, "KERNELID": 94 }, { "LABEL": "2.6.28-x86_64-linode4", "ISXEN": 1, "KERNELID": 97 }, { "LABEL": "2.6.28.3-x86_64-linode5", "ISXEN": 1, "KERNELID": 100 }, { "LABEL": "2.6.29-x86_64-linode6", "ISXEN": 1, "KERNELID": 102 }, { "LABEL": "3.9.3-x86-linode52", "ISXEN": 1, "KERNELID": 137 }, { "LABEL": "3.9.3-x86_64-linode33", "ISXEN": 1, "KERNELID": 138 } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_avail_linodeplans.json0000664000175000017500000000635013535474530030531 0ustar kamikami00000000000000{ "ERRORARRAY": [], "DATA": [{ "CORES": 1, "PRICE": 10.00, "RAM": 1024, "XFER": 2000, "PLANID": 1, "LABEL": "Linode 1024", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 24, "HOURLY": 0.0150 }, { "CORES": 2, "PRICE": 20.00, "RAM": 2048, "XFER": 3000, "PLANID": 2, "LABEL": "Linode 2048", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 48, "HOURLY": 0.0300 }, { "CORES": 4, "PRICE": 40.00, "RAM": 4096, "XFER": 4000, "PLANID": 4, "LABEL": "Linode 4096", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 96, "HOURLY": 0.0600 }, { "CORES": 6, "PRICE": 80.00, "RAM": 8192, "XFER": 8000, "PLANID": 6, "LABEL": "Linode 8192", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 192, "HOURLY": 0.1200 }, { "CORES": 8, "PRICE": 160.00, "RAM": 16384, "XFER": 16000, "PLANID": 7, "LABEL": "Linode 16384", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 384, "HOURLY": 0.2400 }, { "CORES": 12, "PRICE": 320.00, "RAM": 32768, "XFER": 20000, "PLANID": 8, "LABEL": "Linode 32768", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 768, "HOURLY": 0.4800 }, { "CORES": 16, "PRICE": 480.00, "RAM": 49152, "XFER": 20000, "PLANID": 9, "LABEL": "Linode 49152", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 1152, "HOURLY": 0.7200 }, { "CORES": 20, "PRICE": 640.00, "RAM": 65536, "XFER": 20000, "PLANID": 10, "LABEL": "Linode 65536", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 1536, "HOURLY": 0.9600 }, { "CORES": 20, "PRICE": 960.00, "RAM": 98304, "XFER": 20000, "PLANID": 12, "LABEL": "Linode 98304", "AVAIL": { "3": 500, "2": 500, "7": 500, "6": 500, "4": 500, "8": 500 }, "DISK": 1920, "HOURLY": 1.4400 }], "ACTION": "avail.linodeplans" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_batch.json0000664000175000017500000000070313535474530026122 0ustar kamikami00000000000000[ { "ERRORARRAY": [], "DATA": [ { "IPADDRESSID": 5384, "RDNS_NAME": "li22-54.members.linode.com", "LINODEID": 8098, "ISPUBLIC": 1, "IPADDRESS": "66.228.43.47" }, { "IPADDRESSID": 5575, "RDNS_NAME": "li22-245.members.linode.com", "LINODEID": 8098, "ISPUBLIC": 1, "IPADDRESS": "75.127.96.245" } ], "ACTION": "linode.ip.list" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_linode_disk_list.json0000664000175000017500000000126713535474530030366 0ustar kamikami00000000000000{ "ERRORARRAY":[], "ACTION":"linode.disk.list", "DATA":[ { "UPDATE_DT":"2009-06-30 13:19:00.0", "DISKID":55319, "LABEL":"test label", "TYPE":"ext3", "LINODEID":8098, "ISREADONLY":0, "STATUS":1, "CREATE_DT":"2008-04-04 10:08:06.0", "SIZE":4096 }, { "UPDATE_DT":"2009-07-18 12:53:043.0", "DISKID":55320, "LABEL":"256M Swap Image", "TYPE":"swap", "LINODEID":8098, "ISREADONLY":0, "STATUS":1, "CREATE_DT":"2008-04-04 10:08:06.0", "SIZE":256 } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_linode_ip_list.json0000664000175000017500000000075313535474530030043 0ustar kamikami00000000000000{ "ACTION": "linode.ip.list", "DATA": [ { "IPADDRESS": "66.228.43.47", "IPADDRESSID": 5384, "ISPUBLIC": 1, "LINODEID": 8098, "RDNS_NAME": "li22-54.members.linode.com" }, { "IPADDRESS": "75.127.96.245", "IPADDRESSID": 5575, "ISPUBLIC": 1, "LINODEID": 8098, "RDNS_NAME": "li22-245.members.linode.com" } ], "ERRORARRAY": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/linode/_linode_list.json0000664000175000017500000000146413535474530027353 0ustar kamikami00000000000000{ "ERRORARRAY": [], "DATA": [ { "ALERT_CPU_ENABLED": 1, "ALERT_BWIN_ENABLED": 1, "ALERT_BWQUOTA_ENABLED": 1, "BACKUPWINDOW": 0, "ALERT_DISKIO_THRESHOLD": 1000, "DISTRIBUTIONVENDOR": "Debian", "WATCHDOG": 1, "DATACENTERID": 6, "STATUS": 1, "ALERT_DISKIO_ENABLED": 1, "CREATE_DT": "2012-05-04 19:31:30.0", "TOTALHD": 49152, "ALERT_BWQUOTA_THRESHOLD": 80, "TOTALRAM": 2048, "ALERT_BWIN_THRESHOLD": 5, "LINODEID": 8098, "ALERT_BWOUT_THRESHOLD": 5, "ALERT_BWOUT_ENABLED": 1, "BACKUPSENABLED": 1, "ALERT_CPU_THRESHOLD": 90, "PLANID": "2", "BACKUPWEEKLYDAY": 0, "LABEL": "api-node3", "LPM_DISPLAYGROUP": "test", "TOTALXFER": 3000 } ], "ACTION": "linode.list" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/maxihost/0000775000175000017500000000000013600223624024356 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/maxihost/images.json0000664000175000017500000000063613570310635026530 0ustar kamikami00000000000000{ "operating-systems": [{ "id": 297, "slug": "ubuntu_18_04_x64_lts", "operating_system": "Linux", "distro": "Ubuntu", "name": "Ubuntu (18.04 x64 LTS)", "version": "18.04 x64 LTS", "pricing": { "brl_month": 0, "usd_month": 0 } }] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/maxihost/keys.json0000664000175000017500000000135013570310635026230 0ustar kamikami00000000000000{ "ssh_keys": [{ "id": 68, "fingerprint": "77:08:a7:a5:f9:8c:e1:ab:7b:c3:d8:0c:cd:ac:8b:dd", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDllWt8eNqRWZeEVMXLOJsjs3rMmqwBbvEqTkpklPPMycMxYlTSOwrhQ47d1Fknt+/9PWEAYWB9YigP/HMv7wJfMgAaa9cmDivBFX31NIZYBjmgGXSqnpLsHeLGf7htAhGVu7hE+WYz+J04LnMKYLEv23DVqGaG1R6buKGJEbHVGlvJJ6SO0omTvB6r5xhRO8jgXq53Ubzvq2e8at73Htf/9c8lg6iC/iDTgZ8cGPUUj2b8YoUWY0g0rp3ljbngnjbUErF2LnlexiOrjWNLeVxLc9glkW1AkR06LgQmuouqEdmT98vPVZE8QMrdK5WZJkpxQzja3tMh3t7b1eAY6FaH", "name": "test_key" }], "links": { "self": "https://api.maxihost.com/account/keys?limit=1&page=1" }, "meta": { "pages": { "total": 1, "count": 1 } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/maxihost/node.json0000664000175000017500000000230113570310635026177 0ustar kamikami00000000000000{ "id": 1419, "description": "tester", "type": "Bare Metal", "type_id": 1, "label": "1826823414", "service_id": 6230, "power_status": null, "specs": { "cpu": "Dual Intel Xeon E5-2680v3", "disk": "2 x 1TB SSD", "ram": "128GB" }, "location": { "facility_name": "Equinix CH3", "facility_code": "CH3", "row_name": "314550", "rack_name": "Default Rack", "rack_position": "27" }, "operating_system": { "name": "Ubuntu (18.04 x64 LTS)", "slug": "ubuntu_18_04_x64_lts" }, "ips": [{ "id": 9043, "ip_address": "10.223.156.11", "ip_description": "Private IPMI", "device_id": 1379, "device_hostname": "tester", "device_label": "1826825814", "service_id": 0, "created_at": 1557343637, "updated_at": 1557343666 }, { "id": 9042, "ip_address": "185.233.186.01", "ip_description": "Public IPv4", "device_id": 1379, "device_hostname": "tester", "device_label": "1826825814", "service_id": 0, "created_at": 1557343657, "updated_at": 1557343657 }] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/maxihost/nodes.json0000664000175000017500000000310313570310635026363 0ustar kamikami00000000000000{ "devices": [{ "id": 1319, "description": "tester", "type": "Bare Metal", "type_id": 1, "label": "1826823414", "service_id": 6230, "power_status": null, "specs": { "cpu": "Dual Intel Xeon E5-2680v3", "disk": "2 x 1TB SSD", "ram": "128GB" }, "location": { "facility_name": "Equinix CH3", "facility_code": "CH3", "row_name": "314550", "rack_name": "Default Rack", "rack_position": "27" }, "operating_system": { "name": "Ubuntu (18.04 x64 LTS)", "slug": "ubuntu_18_04_x64_lts" }, "ips": [{ "id": 9043, "ip_address": "10.223.186.11", "ip_description": "Private IPMI", "device_id": 1379, "device_hostname": "tester", "device_label": "1826825814", "service_id": 0, "created_at": 1557343657, "updated_at": 1557343666 }, { "id": 9042, "ip_address": "185.233.186.11", "ip_description": "Public IPv4", "device_id": 1379, "device_hostname": "tester", "device_label": "1826825814", "service_id": 0, "created_at": 1557343657, "updated_at": 1557343657 }] }], "links": { "self": "https://api.maxihost.com/devices?limit=1&page=1" }, "meta": { "pages": { "total": 1, "count": 1 } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/maxihost/plans.json0000664000175000017500000000214013570310635026370 0ustar kamikami00000000000000{ "servers": [{ "id": 770, "slug": "spot_770", "name": "Spot", "line": "baremetal", "deploy_type": "automated", "specs": { "cpus": { "count": 2, "type": "Intel Xeon E5-2640v3", "cores": "N/A", "clock": "N/A" }, "memory": { "total": "64GB" }, "drives": [{ "count": 2, "size": "500GB", "type": "SSD" }] }, "regions": [{ "name": "Maxihost SP 1", "code": "MH1", "city": "Sao Paulo", "country": "Brazil", "in_stock": true }], "pricing": { "brl_month": 1200, "usd_month": 300 } }] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/maxihost/regions.json0000664000175000017500000000165413570310635026732 0ustar kamikami00000000000000{ "regions": [{ "slug": "CH3", "name": "Equinix CH3", "location": { "city": "Chicago", "country": "US" }, "available": 1, "features": ["bare_metal", "firewall", "ddos_protection"] }, { "slug": "MI1", "name": "Equinix MI1", "location": { "city": "Miami", "country": "US" }, "available": 1, "features": ["bare_metal", "firewall", "ddos_protection"] }, { "slug": "MH1", "name": "Maxihost MH1", "location": { "city": "Sao Paulo", "country": "BR" }, "available": 1, "features": ["bare_metal", "firewall", "ddos_protection"] }], "links": { "self": "https://api.maxihost.com/regions?limit=3&page=1" }, "meta": { "pages": { "total": 1, "count": 3 } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/meta/0000775000175000017500000000000013600223624023450 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/meta/helloworld.txt0000664000175000017500000000001513535474530026373 0ustar kamikami00000000000000Hello, World!apache-libcloud-2.8.0/libcloud/test/compute/fixtures/meta/unicode.json0000664000175000017500000000001613535474530026001 0ustar kamikami00000000000000{"test": "Ś"}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/meta/unicode.txt0000664000175000017500000000000213535474530025642 0ustar kamikami00000000000000Śapache-libcloud-2.8.0/libcloud/test/compute/fixtures/meta/unicode.xml0000664000175000017500000000004513535474530025632 0ustar kamikami00000000000000 Śapache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/0000775000175000017500000000000013600223624023455 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_dsa.key0000664000175000017500000000123413570310635026002 0ustar kamikami00000000000000-----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQDngaYDZ30c6/7cJgEEbtl8FgKdwhba1Z7oOrOn4MI/6C42G1bY wMuqZf4dBCglsdq39SHrcjbE8Vq54gPSOh3g4+uV9Rcg5IOoPLbwp2jQfF6f1FIb sx7hrDCIqUcQccPSxetPBKmXI9RN8rZLaFuQeTnI65BKM98Ruwvq6SI2LwIVAPDP hSeawaJI27mKqOfe5PPBSmyHAoGBAJMXxXmPD9sGaQ419DIpmZecJKBUAy9uXD8x gbgeDpwfDaFJP8owByCKREocPFfi86LjCuQkyUKOfjYMN6iHIf1oEZjB8uJAatUr FzI0ArXtUqOhwTLwTyFuUojE5own2WYsOAGByvgfyWjsGhvckYNhI4ODpNdPlxQ8 ZamaPGPsAoGARmR7CCPjodxASvRbIyzaVpZoJ/Z6x7dAumV+ysrV1BVYd0lYukmn jO1kKBWApqpH1ve9XDQYN8zgxM4b16L21kpoWQnZtXrY3GZ4/it9kUgyB7+NwacI BlXa8cMDL7Q/69o0d54U0X/NeX5QxuYR6OMJlrkQB7oiW/P/1mwjQgECFGI9QPSc h9pT9XHqn+1rZ4bK+QGA -----END DSA PRIVATE KEY----- ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_dsa_non_paramiko_recognized_header.keyapache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_dsa_non_paramiko_recognized_header.ke0000664000175000017500000000122413570310635034066 0ustar kamikami00000000000000-----BEGIN PRIVATE KEY----- MIIBuwIBAAKBgQDngaYDZ30c6/7cJgEEbtl8FgKdwhba1Z7oOrOn4MI/6C42G1bY wMuqZf4dBCglsdq39SHrcjbE8Vq54gPSOh3g4+uV9Rcg5IOoPLbwp2jQfF6f1FIb sx7hrDCIqUcQccPSxetPBKmXI9RN8rZLaFuQeTnI65BKM98Ruwvq6SI2LwIVAPDP hSeawaJI27mKqOfe5PPBSmyHAoGBAJMXxXmPD9sGaQ419DIpmZecJKBUAy9uXD8x gbgeDpwfDaFJP8owByCKREocPFfi86LjCuQkyUKOfjYMN6iHIf1oEZjB8uJAatUr FzI0ArXtUqOhwTLwTyFuUojE5own2WYsOAGByvgfyWjsGhvckYNhI4ODpNdPlxQ8 ZamaPGPsAoGARmR7CCPjodxASvRbIyzaVpZoJ/Z6x7dAumV+ysrV1BVYd0lYukmn jO1kKBWApqpH1ve9XDQYN8zgxM4b16L21kpoWQnZtXrY3GZ4/it9kUgyB7+NwacI BlXa8cMDL7Q/69o0d54U0X/NeX5QxuYR6OMJlrkQB7oiW/P/1mwjQgECFGI9QPSc h9pT9XHqn+1rZ4bK+QGA -----END PRIVATE KEY----- apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_ecdsa.key0000664000175000017500000000034313570310635026312 0ustar kamikami00000000000000-----BEGIN EC PRIVATE KEY----- MHcCAQEEIKB6ty3yVyKEnfF/zprx0qwC76MsMlHY4HXCnqho2eKioAoGCCqGSM49 AwEHoUQDQgAElI9mbdlaS+T9nHxY/59lFnn80EEecZDBHq4gLpccY8Mge5ZTMiMD ADRvOqQ5R98Sxst765CAqXmRtz8vwoD96g== -----END EC PRIVATE KEY----- ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_ecdsa_non_paramiko_recognized_header.keyapache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_ecdsa_non_paramiko_recognized_header.0000664000175000017500000000033513570310635034060 0ustar kamikami00000000000000-----BEGIN PRIVATE KEY----- MHcCAQEEIKB6ty3yVyKEnfF/zprx0qwC76MsMlHY4HXCnqho2eKioAoGCCqGSM49 AwEHoUQDQgAElI9mbdlaS+T9nHxY/59lFnn80EEecZDBHq4gLpccY8Mge5ZTMiMD ADRvOqQ5R98Sxst765CAqXmRtz8vwoD96g== -----END PRIVATE KEY----- apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_rsa.key0000664000175000017500000000321313570310635026017 0ustar kamikami00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAs0ya+QTUpUyAxbFWN81CbW23D7Fm8O1wxP3l0UPu9OO/dAES irxNxbBEanTGb8HMdaLEdLBlXaYAIlf8+YhG+c9o7kKe8kCR3j4hJ3x0x/fTVSTf mNQc7XIUaM9tuCGj/fO2zfn3fD5fztWAwssPm1+cyP3pAgvc/H03SNpdQG05ylZ+ 1I2QYymYtbjzGh9Nen6dN/aSDrZI7yIA1o3hsDoiY2Nb82l958UI3uJKaxGeBSpO Mshutar3gWa/v9F6uqHDTmFEqQdvQGdCHHyWuz98jMVUc0kvWjdH5q5X95CBZFQM uOQPNxn2aYjMaP7pU2jvfrU0sLpWT/tG8ZApJwIDAQABAoIBAECotZJr7YuW5TFl 3GPPP89aq5ObNDZaSjqgHUq0Ju5lW1uoL1mcwqcyA9ooNo+C4griIdq66jM1dALu nCoYvQ/Ffl+94rgWFQSCf05QEYUzmCCyZXgltjDi3P1XIIgwiYVBaIErTdaeX8ql MAQPWpd7iXzqJCc6w/zB4zgAl3Rt1Fb8GBFHlYf3VTpiU9LA5/IG04GoPk80OgiW 98lercisWT+nPrTMDu2GoEqqls8OkM9CcT5AgeXIpSF9nPmQgUQWXoqWkrZhD+eQ mOxCqpqzwkW/JdsUaBqhPAJtK/eBHTPAfsOabQ5G6/Un1HejN0GTIR0GJzTSEOvi blM3YuECgYEA53XL8c8S5ckc1BGfM22obY1daAVgFqsNpqVSV4OKKnRlcmtYaUXq 61vrQN/OG9Ogrr7FuL7HwavJnr3IbT8uET1/pUje/NQviERwSZWiNX++GUCSXUvq hSe9LZb3ezTEkUROdGXOfl+TfI/bhojsk6egaqqKAVv8LR92cwzMD28CgYEAxk8T x278NOLUn+F6ije186xpcI0JV+NydhXk40ViDHc7M2ycHNArc6iJzQIlQjkEDejK yae3c3QMVtszwONSd6wPkPr9bLbiiT0UlG5gpGAGyEyYZjMQukg2e8ImnwMVMm2l bJsrDI5CRq4G20CWPDqxzs8FTuX78tX4uewzJckCgYBmi1a2o8JAkZA3GDOLClsj Zgzq5+7BPDlJCldntDxDQNwtDAfYZASHD2szi7P5uhGnOZfJmKRRVnV14ajpVaNo OfHSXW2FX9BLM973itaZkyW6dFQkB104bvmuOAMez6sCnNuRUAVjEZ77AZUFjqYZ aJt2hmWr4n/f0d+dax8A+wKBgEVV7LJ0KZZMIM9txKyC4gk6pPsHNNcX3TNQYGDe J3P4VCicttCUMD0WFmgpceF/kd1TIWP0Uf35+z57EdNFJ9ZTwHWObAEQyI/3XTSw ivWt5XEu5rIE9LpM+U+4CEzchRLGp2obrqeLLb0Mp7UNFfolA3otg8ucOcUj7v0C ireRAoGAMM5MDDtWyduLH9srxC3PBKdD4Hi8dtzkQ9yAFYTJ0HB4vV7MmIZ2U2j7 x2KTrPc/go/Jm7+UOmVa4LNkdRvXxVOlAxH85Hqr+n74mm/dWcS4dDWrZvL+Sn+l GFa29M3Ix5SnlfFkZhijvTFLICC7XPTRj6uqVHscZVfENhAYGoU= -----END RSA PRIVATE KEY----- apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_rsa.pub0000664000175000017500000000061213570310635026015 0ustar kamikami00000000000000ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzTJr5BNSlTIDFsVY3zUJtbbcPsWbw7XDE/eXRQ+704790ARKKvE3FsERqdMZvwcx1osR0sGVdpgAiV/z5iEb5z2juQp7yQJHePiEnfHTH99NVJN+Y1BztchRoz224IaP987bN+fd8Pl/O1YDCyw+bX5zI/ekCC9z8fTdI2l1AbTnKVn7UjZBjKZi1uPMaH016fp039pIOtkjvIgDWjeGwOiJjY1vzaX3nxQje4kprEZ4FKk4yyG61qveBZr+/0Xq6ocNOYUSpB29AZ0IcfJa7P3yMxVRzSS9aN0fmrlf3kIFkVAy45A83GfZpiMxo/ulTaO9+tTSwulZP+0bxkCkn dummycomment ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_rsa_non_paramiko_recognized_header.keyapache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_rsa_non_paramiko_recognized_header.ke0000664000175000017500000000320313570310635034103 0ustar kamikami00000000000000-----BEGIN PRIVATE KEY----- MIIEogIBAAKCAQEAs0ya+QTUpUyAxbFWN81CbW23D7Fm8O1wxP3l0UPu9OO/dAES irxNxbBEanTGb8HMdaLEdLBlXaYAIlf8+YhG+c9o7kKe8kCR3j4hJ3x0x/fTVSTf mNQc7XIUaM9tuCGj/fO2zfn3fD5fztWAwssPm1+cyP3pAgvc/H03SNpdQG05ylZ+ 1I2QYymYtbjzGh9Nen6dN/aSDrZI7yIA1o3hsDoiY2Nb82l958UI3uJKaxGeBSpO Mshutar3gWa/v9F6uqHDTmFEqQdvQGdCHHyWuz98jMVUc0kvWjdH5q5X95CBZFQM uOQPNxn2aYjMaP7pU2jvfrU0sLpWT/tG8ZApJwIDAQABAoIBAECotZJr7YuW5TFl 3GPPP89aq5ObNDZaSjqgHUq0Ju5lW1uoL1mcwqcyA9ooNo+C4griIdq66jM1dALu nCoYvQ/Ffl+94rgWFQSCf05QEYUzmCCyZXgltjDi3P1XIIgwiYVBaIErTdaeX8ql MAQPWpd7iXzqJCc6w/zB4zgAl3Rt1Fb8GBFHlYf3VTpiU9LA5/IG04GoPk80OgiW 98lercisWT+nPrTMDu2GoEqqls8OkM9CcT5AgeXIpSF9nPmQgUQWXoqWkrZhD+eQ mOxCqpqzwkW/JdsUaBqhPAJtK/eBHTPAfsOabQ5G6/Un1HejN0GTIR0GJzTSEOvi blM3YuECgYEA53XL8c8S5ckc1BGfM22obY1daAVgFqsNpqVSV4OKKnRlcmtYaUXq 61vrQN/OG9Ogrr7FuL7HwavJnr3IbT8uET1/pUje/NQviERwSZWiNX++GUCSXUvq hSe9LZb3ezTEkUROdGXOfl+TfI/bhojsk6egaqqKAVv8LR92cwzMD28CgYEAxk8T x278NOLUn+F6ije186xpcI0JV+NydhXk40ViDHc7M2ycHNArc6iJzQIlQjkEDejK yae3c3QMVtszwONSd6wPkPr9bLbiiT0UlG5gpGAGyEyYZjMQukg2e8ImnwMVMm2l bJsrDI5CRq4G20CWPDqxzs8FTuX78tX4uewzJckCgYBmi1a2o8JAkZA3GDOLClsj Zgzq5+7BPDlJCldntDxDQNwtDAfYZASHD2szi7P5uhGnOZfJmKRRVnV14ajpVaNo OfHSXW2FX9BLM973itaZkyW6dFQkB104bvmuOAMez6sCnNuRUAVjEZ77AZUFjqYZ aJt2hmWr4n/f0d+dax8A+wKBgEVV7LJ0KZZMIM9txKyC4gk6pPsHNNcX3TNQYGDe J3P4VCicttCUMD0WFmgpceF/kd1TIWP0Uf35+z57EdNFJ9ZTwHWObAEQyI/3XTSw ivWt5XEu5rIE9LpM+U+4CEzchRLGp2obrqeLLb0Mp7UNFfolA3otg8ucOcUj7v0C ireRAoGAMM5MDDtWyduLH9srxC3PBKdD4Hi8dtzkQ9yAFYTJ0HB4vV7MmIZ2U2j7 x2KTrPc/go/Jm7+UOmVa4LNkdRvXxVOlAxH85Hqr+n74mm/dWcS4dDWrZvL+Sn+l GFa29M3Ix5SnlfFkZhijvTFLICC7XPTRj6uqVHscZVfENhAYGoU= -----END PRIVATE KEY----- apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_rsa_non_pem_format.key0000664000175000017500000000344713570310635031113 0ustar kamikami00000000000000-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn NhAAAAAwEAAQAAAQEA62PnwyPMECUdKQvMByS+PwgRp97IB1wIpeb9RdR8PC5HPzWHt/iO wtoXEK4M6dRJ0x+u66gVygHXoH+zydTLu/3SaFwUvuoFRsyDeQZWkHPqvkFOqaGfbr99Um h8crXJOeDi9sqI9JDZJAmJePLfHGQfv97lYWHSE7Pvp4cgM/CRqoGSMbfnHOPsLQujiFhe S7uMHqv6oNA2ClVOl8uUIw0SVBl/4crMh9e8hlHMR+UHmuUMwwXmlHrFsh7J6A2nyu1V6K MTOCLUpXX9LtN3XmvS+D6sfCzzc10L1jHAyswAN8abey1Z1V5jtGi2iSMRF4nccjGacn7p OxnYYZtF9wAAA9BhFsUwYRbFMAAAAAdzc2gtcnNhAAABAQDrY+fDI8wQJR0pC8wHJL4/CB Gn3sgHXAil5v1F1Hw8Lkc/NYe3+I7C2hcQrgzp1EnTH67rqBXKAdegf7PJ1Mu7/dJoXBS+ 6gVGzIN5BlaQc+q+QU6poZ9uv31SaHxytck54OL2yoj0kNkkCYl48t8cZB+/3uVhYdITs+ +nhyAz8JGqgZIxt+cc4+wtC6OIWF5Lu4weq/qg0DYKVU6Xy5QjDRJUGX/hysyH17yGUcxH 5Qea5QzDBeaUesWyHsnoDafK7VXooxM4ItSldf0u03dea9L4Pqx8LPNzXQvWMcDKzAA3xp t7LVnVXmO0aLaJIxEXidxyMZpyfuk7Gdhhm0X3AAAAAwEAAQAAAQEAhxaHzIK/ushB6ut9 ROA+WlgcIdYFv8t+nw9obOnb/oGkm87xu4/nBkY5FHZ+rLcLQyGctlt5Xbwe7lo7aOo5ng K1/PRTZ5lQO+hkz1Dm3vHXVyaNqWY65Ej6+A9E1GQlPpUkS/PCE3EJXNgoUAQ6LMX9PpUB 2RhVgr8yG1e+EG+2prcTZ5m++Z73kscoksJiAFwUqPfWLfNlHAYNVfchb/iaQHh++P9UJ8 VqiISXKrRGCl/sSE9rksmXeaAGdmgPlp0q16GKn5ISNwoc6PwybJTqedixXXDMtyQVM+EN z4w7+u2guKhP7OfZk5DyeKct2OSNhFdzni24F/EmZ4QlyQAAAIEA9s4pmYxrNXAroCi/1j 2S0dZL8KJowGkGZatNBFYZBJGyImRdzZ+5y1yEDFSGh6wzAGhRZmVJaVhHGhBLaULVj3Kl wZhuxSpLm0Yr1Pl9rYPn4JOpO+ExbcepQ0ghEB3RGtmHk2IpbZ2AHlTFHhTrwz19GFTDF7 +R1YfYb8zL7e8AAACBAPq0MFp4L5idhvliWdrG7DDeauwnmmSqRM2Zv8FgFloqsMHldkym c//vLDJ2cu3e2advOrsSOXZTHFjd6M0Nek/0r8MtrboYWjx6wBiwBCwNItBnvzVYm7OoOi HxcNLQnhFVCBn7qDDG/84jFM4MIJR66A3PGTnIMN1hrDiX/+LNAAAAgQDwXOZxZ8c/2O4y vaJ0Gnq3wfXTZRQ/At/CwKznAJXmbR6On3LiaiU7q9jSLXGuRcpcjUjfXCQgr4t7hBTFc9 5RJDe5J4wHdXIZPrLz1in0SnZ2q/KMb4UsYbfn8Ls6VCXPM0SYv0wJPbCetL0P0285bJiB teUhr+JIm0vxcpaz0wAAABdrYW1pQGthbWktZGVsbC1sYXRpdHVkZQEC -----END OPENSSH PRIVATE KEY----- apache-libcloud-2.8.0/libcloud/test/compute/fixtures/misc/test_rsa_non_pem_format.pub0000664000175000017500000000062513570310635031104 0ustar kamikami00000000000000ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDrY+fDI8wQJR0pC8wHJL4/CBGn3sgHXAil5v1F1Hw8Lkc/NYe3+I7C2hcQrgzp1EnTH67rqBXKAdegf7PJ1Mu7/dJoXBS+6gVGzIN5BlaQc+q+QU6poZ9uv31SaHxytck54OL2yoj0kNkkCYl48t8cZB+/3uVhYdITs++nhyAz8JGqgZIxt+cc4+wtC6OIWF5Lu4weq/qg0DYKVU6Xy5QjDRJUGX/hysyH17yGUcxH5Qea5QzDBeaUesWyHsnoDafK7VXooxM4ItSldf0u03dea9L4Pqx8LPNzXQvWMcDKzAA3xpt7LVnVXmO0aLaJIxEXidxyMZpyfuk7Gdhhm0X3 kami@kami-dell-latitude apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/0000775000175000017500000000000013600223624024643 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/list_images.json0000664000175000017500000002012413535474530030050 0ustar kamikami00000000000000{ "success": true, "total_count": 18, "subcode": 0, "message": "Your request was processed successfully.", "data": [ { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux CentOS 5.5 32-bit", "uri": "https://api.nephoscale.com/image/server/3/", "max_memory": 128, "id": 3, "is_default": true, "create_time": "2010-12-20 14:25:36", "architecture": "x86", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux CentOS 5.5 64-bit", "uri": "https://api.nephoscale.com/image/server/5/", "max_memory": 128, "id": 5, "is_default": true, "create_time": "2010-12-20 14:25:36", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Windows Server 2008 64-bit", "uri": "https://api.nephoscale.com/image/server/21/", "max_memory": 128, "id": 21, "is_default": true, "create_time": "2010-12-20 14:25:36", "architecture": "x86_64", "base_type": "windows" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Debian Server 5.05 32-bit", "uri": "https://api.nephoscale.com/image/server/23/", "max_memory": 128, "id": 23, "is_default": true, "create_time": "2010-12-20 16:51:20", "architecture": "x86", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Debian Server 5.05 64-bit", "uri": "https://api.nephoscale.com/image/server/25/", "max_memory": 128, "id": 25, "is_default": true, "create_time": "2010-12-20 16:55:42", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Windows Server 2003 Enterprise 64-bit", "uri": "https://api.nephoscale.com/image/server/33/", "max_memory": 128, "id": 33, "is_default": true, "create_time": "2011-03-02 14:20:49", "architecture": "x86_64", "base_type": "windows" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux CentOS 5.7 64-bit", "uri": "https://api.nephoscale.com/image/server/41/", "max_memory": 128, "id": 41, "is_default": true, "create_time": "2011-09-19 17:30:04", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Ubuntu Server 10.04 LTS 32-bit", "uri": "https://api.nephoscale.com/image/server/43/", "max_memory": 128, "id": 43, "is_default": true, "create_time": "2011-10-01 02:26:17", "architecture": "x86", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux CentOS 5.7 32-bit", "uri": "https://api.nephoscale.com/image/server/45/", "max_memory": 128, "id": 45, "is_default": true, "create_time": "2011-10-05 19:41:30", "architecture": "x86", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Ubuntu Server 10.04 LTS 64-bit", "uri": "https://api.nephoscale.com/image/server/49/", "max_memory": 128, "id": 49, "is_default": true, "create_time": "2011-10-08 05:01:10", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Debian Server 6.0.3 64-bit", "uri": "https://api.nephoscale.com/image/server/51/", "max_memory": 128, "id": 51, "is_default": true, "create_time": "2011-10-08 19:54:41", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Debian 5.0.9 64-bit", "uri": "https://api.nephoscale.com/image/server/55/", "max_memory": 128, "id": 55, "is_default": false, "create_time": "2011-10-13 12:53:36", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Debian 5.0.9 32-bit", "uri": "https://api.nephoscale.com/image/server/57/", "max_memory": 128, "id": 57, "is_default": false, "create_time": "2011-10-13 12:55:09", "architecture": "x86", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux CentOS 6.2 64-bit", "uri": "https://api.nephoscale.com/image/server/59/", "max_memory": 128, "id": 59, "is_default": true, "create_time": "2011-10-15 17:11:34", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux CentOS 5.8 64-bit", "uri": "https://api.nephoscale.com/image/server/64/", "max_memory": 128, "id": 64, "is_default": true, "create_time": "2012-03-28 19:54:10", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Ubuntu Server 12.04 LTS 64-bit", "uri": "https://api.nephoscale.com/image/server/75/", "max_memory": 128, "id": 75, "is_default": true, "create_time": "2012-05-18 08:41:03", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "cloud", "is_active": true, "friendly_name": "VOD Cloud Storage Proxy (FTP:HTTP)", "uri": "https://api.nephoscale.com/image/server/101/", "max_memory": 128, "id": 101, "is_default": false, "create_time": "2012-08-30 08:49:55", "architecture": "x86_64", "base_type": "linux" }, { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Debian 7.1 64-bit", "uri": "https://api.nephoscale.com/image/server/177/", "max_memory": 128, "id": 177, "is_default": true, "create_time": "2013-09-10 16:12:10", "architecture": "x86_64", "base_type": "linux" } ], "response": 200 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/list_keys.json0000664000175000017500000000124013535474530027554 0ustar kamikami00000000000000{ "success": true, "total_count": 2, "subcode": 0, "message": "Your request was processed successfully.", "data": [ { "name": "mistio-ssh", "key_group": 1, "uri": "https://api.nephoscale.com/key/sshrsa/72209/", "key_type": 2, "create_time": "2013-10-02 07:24:37", "id": 72209 }, { "name": "mistio-testing", "key_group": 4, "uri": "https://api.nephoscale.com/key/password/72211/", "key_type": 1, "create_time": "2013-10-02 07:27:10", "id": 72211 } ], "response": 200 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/list_locations.json0000664000175000017500000000154413535474530030603 0ustar kamikami00000000000000{ "success": true, "total_count": 2, "subcode": 0, "message": "Your request was processed successfully.", "data": [ { "datacenter": { "airport_code": "SJC", "name": "SJC-1", "uri": "https://api.nephoscale.com/datacenter/1/", "id": 1 }, "uri": "https://api.nephoscale.com/datacenter/zone/86945/", "id": 86945, "name": "SJC-1" }, { "datacenter": { "airport_code": "RIC", "name": "RIC-1", "uri": "https://api.nephoscale.com/datacenter/3/", "id": 3 }, "uri": "https://api.nephoscale.com/datacenter/zone/87729/", "id": 87729, "name": "RIC-1" } ], "response": 200 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/list_nodes.json0000664000175000017500000001276513535474530027727 0ustar kamikami00000000000000{ "success": true, "total_count": 2, "subcode": 0, "message": "Your request was processed successfully.", "data": [ { "server_keys": [ { "key_type": 2, "key_group": 1, "id": 71757, "uri": "https://api.nephoscale.com/key/sshrsa/71157/" } ], "name": "mongodb-staging", "zone": { "uri": "https://api.nephoscale.com/datacenter/zone/88211/", "id": 87729, "name": "RIC-1" }, "image": { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Ubuntu Server 10.04 LTS 64-bit", "uri": "https://api.nephoscale.com/image/server/49/", "max_memory": 128, "id": 49, "is_default": true, "create_time": "2011-10-08 05:01:10", "architecture": "x86_64", "has_agent": true, "base_type": "linux" }, "hostname": "mongodb-staging", "podzone": "P1A2", "uri": "https://api.nephoscale.com/server/cloud/87241/", "ipaddresses": "198.89.117.16", "power_status": "on", "create_time": "2013-09-25 07:38:53", "postinit_state": 1, "console_keys": [ { "key_type": 1, "key_group": 4, "id": 71761, "uri": "https://api.nephoscale.com/key/password/71761/" } ], "memory": 512, "service_type": { "sku": { "name": "CS05", "description": "Cloud Server 0.5 GB RAM, 1 Core" }, "uri": "https://api.nephoscale.com/server/type/cloud/5/", "friendly_name": "CS05 - 0.5GB, 1Core, 25GB", "id": 5, "billable_type": 1 }, "network_ports": [ { "macaddress": "00:16:3e:06:dc:41", "devname": "eth0", "network_domain": { "domain_type": 0, "name": "default_public_network_RIC" } }, { "macaddress": "00:16:3e:06:dc:45", "devname": "eth1", "network_domain": { "domain_type": 1, "name": "default_private_network_RIC" } } ], "id": 88241, "is_console_enabled": true }, { "server_keys": [ { "key_type": 2, "key_group": 1, "id": 72049, "uri": "https://api.nephoscale.com/key/sshrsa/72049/" } ], "name": "backup-server2", "zone": { "uri": "https://api.nephoscale.com/datacenter/zone/88751/", "id": 87729, "name": "RIC-1" }, "image": { "max_cpu": 64, "deployable_type": "both", "is_active": true, "friendly_name": "Linux Debian Server 6.0.3 64-bit", "uri": "https://api.nephoscale.com/image/server/51/", "max_memory": 128, "id": 51, "is_default": true, "create_time": "2011-10-08 19:54:41", "architecture": "x86_64", "has_agent": true, "base_type": "linux" }, "hostname": "backup-server2", "podzone": "P1A2", "uri": "https://api.nephoscale.com/server/cloud/88751/", "ipaddresses": "198.89.112.115", "power_status": "on", "create_time": "2013-10-02 05:02:50", "postinit_state": 1, "console_keys": [ { "key_type": 1, "key_group": 4, "id": 72165, "uri": "https://api.nephoscale.com/key/password/72165/" } ], "memory": 512, "service_type": { "sku": { "name": "CS05", "description": "Cloud Server 0.5 GB RAM, 1 Core" }, "uri": "https://api.nephoscale.com/server/type/cloud/5/", "friendly_name": "CS05 - 0.5GB, 1Core, 25GB", "id": 5, "billable_type": 1 }, "network_ports": [ { "macaddress": "00:16:3e:06:f5:2f", "devname": "eth0", "network_domain": { "domain_type": 0, "name": "default_public_network_RIC" } }, { "macaddress": "00:16:3e:06:f5:33", "devname": "eth1", "network_domain": { "domain_type": 1, "name": "default_private_network_RIC" } } ], "id": 88751, "is_console_enabled": true } ], "response": 200 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json0000664000175000017500000000071113535474530031500 0ustar kamikami00000000000000{ "success": true, "total_count": 1, "subcode": 0, "message": "Your request was processed successfully.", "data": [ { "name": "mistio-testing", "key_group": 4, "uri": "https://api.nephoscale.com/key/password/72211/", "key_type": 1, "create_time": "2013-10-02 07:27:10", "password": "23d493j5", "id": 72211 } ], "response": 200 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/list_sizes.json0000664000175000017500000001263513535474530027750 0ustar kamikami00000000000000{ "success": true, "total_count": 13, "subcode": 0, "message": "Your request was processed successfully.", "data": [ { "sku": { "name": "CS16.16", "description": "Cloud Server 16 GB RAM, 16 Cores" }, "storage": 800, "ram": 16384, "friendly_name": "CS16.16 - 16GB, 16Core, 800GB", "uri": "https://api.nephoscale.com/server/type/cloud/1/", "vcpus": 16, "id": 1, "billable_type": 1 }, { "sku": { "name": "CS1", "description": "Cloud Server 1 GB RAM, 1 Core" }, "storage": 50, "ram": 1024, "friendly_name": "CS1 - 1GB, 1Core, 50GB", "uri": "https://api.nephoscale.com/server/type/cloud/3/", "vcpus": 1, "id": 3, "billable_type": 1 }, { "sku": { "name": "CS05", "description": "Cloud Server 0.5 GB RAM, 1 Core" }, "storage": 25, "ram": 512, "friendly_name": "CS05 - 0.5GB, 1Core, 25GB", "uri": "https://api.nephoscale.com/server/type/cloud/5/", "vcpus": 1, "id": 5, "billable_type": 1 }, { "sku": { "name": "CS2.2", "description": "Cloud Server 2 GB RAM, 2 Cores" }, "storage": 100, "ram": 2048, "friendly_name": "CS2.2 - 2GB, 2Core, 100GB", "uri": "https://api.nephoscale.com/server/type/cloud/7/", "vcpus": 2, "id": 7, "billable_type": 1 }, { "sku": { "name": "CS4.4", "description": "Cloud Server 4 GB RAM, 4 Cores" }, "storage": 200, "ram": 4096, "friendly_name": "CS4.4 - 4GB, 4Core, 200GB", "uri": "https://api.nephoscale.com/server/type/cloud/9/", "vcpus": 4, "id": 9, "billable_type": 1 }, { "sku": { "name": "CS8.8", "description": "Cloud Server 8 GB RAM, 8 Cores" }, "storage": 400, "ram": 8192, "friendly_name": "CS8.8 - 8GB, 8Core, 400GB", "uri": "https://api.nephoscale.com/server/type/cloud/11/", "vcpus": 8, "id": 11, "billable_type": 1 }, { "sku": { "name": "CS025", "description": "Cloud Server 0.25 GB RAM" }, "storage": 15, "ram": 256, "friendly_name": "CS025 - 0.25GB, 10GB", "uri": "https://api.nephoscale.com/server/type/cloud/27/", "vcpus": 1, "id": 27, "billable_type": 1 }, { "sku": { "name": "CS2.1", "description": "Cloud Server 2 GB RAM, 1 Core" }, "storage": 75, "ram": 2048, "friendly_name": "CS2.1 - 2GB, 1Core, 75GB", "uri": "https://api.nephoscale.com/server/type/cloud/46/", "vcpus": 1, "id": 46, "billable_type": 1 }, { "sku": { "name": "CS4.2", "description": "Cloud Server 4 GB RAM, 2 Cores" }, "storage": 150, "ram": 4096, "friendly_name": "CS4.2 - 4GB, 2Core, 150GB", "uri": "https://api.nephoscale.com/server/type/cloud/48/", "vcpus": 2, "id": 48, "billable_type": 1 }, { "sku": { "name": "CS8.4", "description": "Cloud Server 8 GB RAM, 4 Cores" }, "storage": 300, "ram": 8192, "friendly_name": "CS8.4 - 8GB, 4Core, 300GB", "uri": "https://api.nephoscale.com/server/type/cloud/50/", "vcpus": 4, "id": 50, "billable_type": 1 }, { "sku": { "name": "CS16.8", "description": "Cloud Server 16 GB RAM, 8 Cores" }, "storage": 600, "ram": 16384, "friendly_name": "CS16.8 - 16GB, 8Core, 600GB", "uri": "https://api.nephoscale.com/server/type/cloud/52/", "vcpus": 8, "id": 52, "billable_type": 1 }, { "sku": { "name": "CS32.16", "description": "Cloud Server 32 GB RAM, 16 Cores" }, "storage": 1200, "ram": 32768, "friendly_name": "CS32.16 - 32GB, 16Core, 1200GB", "uri": "https://api.nephoscale.com/server/type/cloud/54/", "vcpus": 16, "id": 54, "billable_type": 1 }, { "sku": { "name": "CS32.8", "description": "Cloud Server 32 GB RAM, 8 Cores" }, "storage": 1000, "ram": 32768, "friendly_name": "CS32.8 - 32GB, 8Core, 1000GB", "uri": "https://api.nephoscale.com/server/type/cloud/56/", "vcpus": 8, "id": 56, "billable_type": 1 } ], "response": 200 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json0000664000175000017500000000151013535474530030431 0ustar kamikami00000000000000{ "success": true, "total_count": 1, "subcode": 0, "message": "Your request was processed successfully.", "data": [ { "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBs+gQwoeFNa+4pYz2AKz5Op7EqrzeP3YsyTKxx7P9gt4aSt5w8Z+lRn3p3CVG+th5i6lZqOxWgCZ1kp2KEKNbSsA2HWl3OwkY8IqHGSEeMrF+3A2Ncz88kUIAWzCswxPY4uqb/yA4EzEQDk7PJj7Q1DruObhOm7qyHT40n2KJ3TqHJQlV9XE3RcXSaQcwUt0YFXFMx8wkgy0NKqqSiQuH8RofyfnOABEzKAARGbcQjZWxh2ITzUmwMxUCBa0X5wvblgcE6/pRZN5Xq6NQr2XEU5Z48+mLy6asdasdwrM0v10Y7ojDL/TosK/8T5+d5yaRsvtBlBstDZhNWY31n5iCLxx user@mistio", "name": "mistio-ssh", "key_group": 1, "uri": "https://api.nephoscale.com/key/sshrsa/72209/", "key_type": 2, "create_time": "2013-10-02 07:24:37", "id": 72209 } ], "response": 200 } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nephoscale/success_action.json0000664000175000017500000000037613535474530030564 0ustar kamikami00000000000000{ "subcode": 0, "message": "Your request was processed successfully.", "data": { "id": 141229, "resource_type": "/job", "uri": "https://api.nephoscale.com/job/141229/" }, "response": 202, "success": true } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/0000775000175000017500000000000013600223624024026 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/audit_log.csv0000664000175000017500000001211713535474530026527 0ustar kamikami00000000000000UUID,Time,Create User,Department,Customer Defined 1,Customer Defined 2,Type,Name,Action,Details,Response Code af779880-0531-45d3-be56-df41c459aa09,2016-09-11 23:59:37,ashaw_plat,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Deploy Server,ATTEMPT: DEPLOY_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]', d127748c-948f-41f0-b6a7-c0b5a2438bd6,2016-09-12 00:06:00,OEC_SYSTEM,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Deploy Server,DEPLOY_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]',OK 85f978b2-0e2a-4ba3-a6ce-7567e329e842,2016-09-12 00:22:48,ashaw_plat,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Start Server,ATTEMPT: START_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]', afc67c82-381a-4ba1-b25e-2285a916d513,2016-09-12 00:23:00,OEC_SYSTEM,,,,SERVER,ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7],Start Server,START_SERVER 'ST2-DEV[10-0-0-5_8bf3420c-73cf-45ab-a923-a461ad87daf7]',OK 7378b530-9d37-4339-88d5-19428431fe07,2016-09-12 05:10:47,ashaw_plat,,,,IP_BLOCK,168.128.37.196,Add IP Block,ATTEMPT: ADD_PUBLIC_IP_BLOCK '168.128.37.196', f978f690-13e8-4d7d-8ce3-1ca7e232df69,2016-09-12 05:10:48,ashaw_plat,,,,IP_BLOCK,168.128.37.196,Add IP Block,ADD_PUBLIC_IP_BLOCK '168.128.37.196',OK 822b7483-bb59-4659-9ab1-7a1ad25bacd7,2016-09-12 05:10:58,ashaw_plat,,,,NAT_RULE,10.0.0.5,Create NAT Rule,ATTEMPT: CREATE_NAT_RULE '10.0.0.5'(requestId:au_20160912T151058137+1000_07422779-ec2a-448e-81f4-87a333b79f3c), 2f29ebd2-2ee0-463f-9a46-2e62f09fcc74,2016-09-12 05:10:59,ashaw_plat,,,,NAT_RULE,10.0.0.5,Create NAT Rule,CREATE_NAT_RULE '10.0.0.5'(requestId:au_20160912T151058137+1000_07422779-ec2a-448e-81f4-87a333b79f3c),OK 503aa140-6da9-4fbe-b94e-b118fc5a473a,2016-09-13 04:08:55,mgreenwood_plat,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ATTEMPT: ADD_NAT_RULE '10.208.136.11', bb73bb95-a20c-46f8-9962-3862496793ff,2016-09-13 04:09:00,OEC_SYSTEM,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ADD_NAT_RULE '10.208.136.11',OK 276ab194-ffb3-4516-920d-96cc068dfcfa,2016-09-13 04:11:54,mgreenwood_plat,,,,NAT_RULE,10.208.136.11,Delete NAT Rule,ATTEMPT: DELETE_NAT_RULE '10.208.136.11', 3bb0e6ad-48e1-4268-9423-4cd680edc404,2016-09-13 04:11:57,OEC_SYSTEM,,,,NAT_RULE,10.208.136.11,Delete NAT Rule,DELETE_NAT_RULE '10.208.136.11',OK f9f2684a-796c-4f28-9448-949900f8f4fb,2016-09-13 04:16:22,mgreenwood_plat,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ATTEMPT: ADD_NAT_RULE '10.208.136.11', 0bfbe81f-35fc-445e-a33e-f12a46c25115,2016-09-13 04:16:27,OEC_SYSTEM,,,,NAT_RULE,10.208.136.11,Add NAT Rule,ADD_NAT_RULE '10.208.136.11',OK 629da5f4-7fdc-4bc6-a408-66ab96f539c0,2016-09-13 04:27:19,mgreenwood_plat,,,,ACL_RULE,AD LDAP Port - For Testing,Add Acl Rule,ATTEMPT: Add Acl Rule AD LDAP Port - For Testing to network Aperture, ecee1409-ce7d-496d-a41b-67662d884598,2016-09-13 04:27:22,mgreenwood_plat,,,,ACL_RULE,AD LDAP Port - For Testing,Add Acl Rule,Add Acl Rule AD LDAP Port - For Testing to network Aperture,OK f6e84763-b911-4189-bf69-138e9a23de7a,2016-09-14 03:05:15,aakbar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK ef43056e-1cd0-48bf-80f6-12a4cad8e1c6,2016-09-14 03:05:24,aakbar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK 13f38aa4-a86c-45c2-909f-2a6b96c0c761,2016-09-14 03:13:21,aakbar_plat,,,,SERVER,CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244]',OK 22aa854c-17a2-4f48-82a1-c10a052dd932,2016-09-14 05:42:04,mkumar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK 6c7f3847-e2e8-47c8-8fd0-8c444015ad19,2016-09-14 05:51:58,mkumar_plat,,,,SERVER,CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244]',OK 69ddc5a5-b815-439b-9d32-a1d60345355b,2016-09-14 06:02:50,mkumar_plat,,,,SERVER,CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-CI[10-209-120-16_ce81b50b-70d4-44ae-94d8-c2af8c22b244]',OK 4ffa5524-926b-4747-9924-581c316b6a60,2016-09-14 06:05:49,mkumar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK 599718fe-f58c-439b-87ae-86fb1347708e,2016-09-14 06:06:21,mkumar_plat,,,,SERVER,CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62],Get Console Access Session Token,GENERATE_CONSOLE_ACCESS_SESSION_TOKEN 'CaaS-QA[10-209-120-14_e772c8c0-ee55-4e8f-82f9-22576b494a62]',OK apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/cg_by_src_network_domain.xml0000664000175000017500000000605213535474530031620 0ustar kamikami00000000000000 sdk_test2_cg A test consistency group DRS-ProdEng-East-ND1 DRS-ProdEng-West-ND1 src-sdk-test tgt-sdk-test 2018-11-12T20:53:10.000Z DRS_MODE 0 NORMAL CG-Re-IP-Scenario-2 CG-Re-IP-Scenario-2 DRS-ProdEng-East-ND1 DRS-ProdEng-West-ND1 Src-Re-IP-RHEL7 Tgt-Re-IP-RHEL7 2018-11-16T15:41:48.000Z DRS_MODE 0 NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/change_disk_size.xml0000664000175000017500000000060413535474530030054 0ustar kamikami00000000000000 EXPAND_DISK IN_PROGRESS Request to Expand Disk has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/change_disk_speed.xml0000664000175000017500000000061413535474530030203 0ustar kamikami00000000000000 CHANGE_DISK_SPEED IN_PROGRESS Request to Change Disk Speed has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/change_nic_networkadapter_response.xml0000664000175000017500000000052113535474530033667 0ustar kamikami00000000000000 CHANGE_NETWORK_ADAPTER IN_PROGRESS Request to Change Network Adapter for NIC with Id has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/create_preview_server.xml0000664000175000017500000000075013535474530031157 0ustar kamikami00000000000000 CREATE_SNAPSHOT_PREVIEW_SERVER IN_PROGRESS Request to Create Snapshot Preview Server has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/datacenter_snapshotWindows.xml0000664000175000017500000000203313535474530032165 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/deploy_customised_server.xml0000664000175000017500000000074213535474530031707 0ustar kamikami00000000000000 DEPLOY_UNCUSTOMIZED_SERVER IN_PROGRESS Request to deploy uncustomized Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/detailed_usage_report.csv0000664000175000017500000000531513535474530031114 0ustar kamikami00000000000000Name,Type,Location,Private IP Address,Status,"user:ATag","user:BTag","user:CTag",Start Time,End Time,Duration (Hours),CPU Type,CPU Count, RAM (GB), Storage (GB),Economy Storage (GB),CPU Hours,High Performance CPU Hours,RAM Hours,Storage Hours,Economy Storage Hours,Bandwidth-In (GB),Bandwidth-Out (GB),Subadmin Hours,Network Hours,Essentials Network Domain Hours,Advanced Network Domain Hours,VLAN Hours,Public IP Hours,Cloud Files Account Hours,Cloud Storage (GB) Server A,Server,NA1,10.162.12.16,Running,Bob,IT,,19/06/2014 04:16,19/06/2014 11:17,7.03,Standard,1,2,10,0,7.03,0,14.05,70.27,0,0,0,0,0,0,0,0,0,0,0 Server A,Server,NA1,10.162.12.16,Running,Bob,IT,,19/06/2014 11:17,20/06/2014 00:00,12.71,High Performance,1,2,10,0,0,12.71,0,127.06,0,0,0,0,0,0,0,0,0,0,0 Server B,Server,NA1,10.162.12.13,Running,Mary,IT,,19/06/2014 03:42,19/06/2014 11:18,7.61,Essentials,1,2,10,0,0,0,15.22,76.1,0,0,0,0,0,0,0,0,0,0,0 Server B,Server,NA1,10.162.12.13,Stopped,Mary,IT,,19/06/2014 11:18,19/06/2014 23:18,12,Essentials,1,2,10,0,0,0,0,120,0,0,0,0,0,0,0,0,0,0,0 Server B,Server,NA1,10.162.12.13,Stopped,Bob,IT,,19/06/2014 23:18,20/06/2014 00:00,0.689722222,Essentials,1,2,10,0,0,0,0,6.897222223,0,0,0,0,0,0,0,0,0,0,0 Customer Image A,Image,NA1,,Running,Bob,IT,,19/06/2014 03:30,20/06/2014 00:00,20.5,,0,0,10,0,0,0,0,205,0,0,0,0,0,0,0,0,0,0,0 Customer Image B,Image,NA1,,Running,Bob,IT,,19/06/2014 03:10,19/06/2014 03:12,0.04,,0,0,10,0,0,0,0,0.44,0,0,0,0,0,0,0,0,0,0,0 Joseph_F,Sub-Administrator,,,Running,Bob,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0 Lguy,Sub-Administrator,,,Running,Mary,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0 a network,Network,NA1,,Running,,IT,,19/06/2014 01:39,20/06/2014 00:00,22.34,,0,0,0,0,0,0,0,0,0,0,0.9,0,22.34,0,0,0,0,0,0 b network,Network,NA1,,Running,,IT,,19/06/2014 01:49,20/06/2014 00:00,22.18,,0,0,0,0,0,0,0,0,0,0,7.1,0,22.18,0,0,0,0,0,0 Rick's Network Domain,Network Domain,NA9,,Running,Bob,IT,,19/06/2014 04:19,20/06/2014 00:00,19.68,,0,0,0,0,0,0,0,0,0,0,7.1,0,22.18,19.68,0,0,0,0,0 Rick's VLAN,VLAN,NA9,,Running,Bob,IT,,19/06/2014 04:22,20/06/2014 00:00,19.63,,0,0,0,0,0,0,0,0,0,0,0,0,22.18,0,0,19.63,0,0,0 files1_koala,Cloud Files,,,Running,,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,24,52 testbed,Cloud Files,,,Running,,IT,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,0,0,0,0,0,0,0.01,0,0,0,0,0,0,24,100 Network: b network IP Block: 168.143.92.136(4),IpBlock,NA1,,Reserved,Mary,IT,,19/06/2014 11:47,20/06/2014 00:00,12.2,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48.82,0,0 TOTAL for 19/06/14,,,,,,,,19/06/2014 00:00,20/06/2014 00:00,24,,0,0,0,0,8,13,30,606,0,3,23,48,89,20,0,20,49,48,152apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/disable_server_snapshot_service.xml0000664000175000017500000000050413535474530033212 0ustar kamikami00000000000000 DISABLE_SNAPSHOT_SERVICE OK Snapshot Service has been disabled. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_create_cg.xml0000664000175000017500000000074513535474530027355 0ustar kamikami00000000000000 CREATE_CONSISTENCY_GROUP IN_PROGRESS Request to Create Consistency Group has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_delete_consistency_group.xml0000664000175000017500000000062213535474530032532 0ustar kamikami00000000000000 DELETE_CONSISTENCY_GROUP IN_PROGRESS Request to Delete Consistency Group has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_expand_journal.xml0000664000175000017500000000061013535474530030441 0ustar kamikami00000000000000 EXPAND_JOURNAL IN_PROGRESS Request to Expand DRS Journal Space has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_fail_create_cg_ineligible.xml0000664000175000017500000000061413535474530032526 0ustar kamikami00000000000000 CREATE_CONSISTENCY_GROUP INCOMPATIBLE_OPERATION The drsEligible flag for target Server aee58575-38e2-495f-89d3-854e6a886411 must be set. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_fail_create_cg_not_supported.xml0000664000175000017500000000060513535474530033330 0ustar kamikami00000000000000 CREATE_CONSISTENCY_GROUP OPERATION_NOT_SUPPORTED DRS is not supported between source Data Center NA9 and target Data Center NA12. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_fail_create_consistency_group.xml0000664000175000017500000000055313535474530033531 0ustar kamikami00000000000000 CREATE_CONSISTENCY_GROUP NAME_NOT_UNIQUE Another Consistency Group named 'sdk_test2_cg' already exists. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_initiate_failover.xml0000664000175000017500000000060413535474530031130 0ustar kamikami00000000000000 INITIATE_FAILOVER IN_PROGRESS Request to Initiate Failover has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_invalid_status.xml0000664000175000017500000000067013535474530030467 0ustar kamikami00000000000000 INITIATE_FAILOVER INVALID_STATUS You cannot Initiate Failover because Consistency Group with id 195a426b-4559-4c79-849e-f22cdf2bfb6e is not in PREVIEWING_SNAPSHOT Operation Status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_snap_shots_by_min_max_time.xml0000664000175000017500000001211313535474530033032 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_snapshots_by_min.xml0000664000175000017500000000724013535474530031015 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_start_failover_preview.xml0000664000175000017500000000061613535474530032223 0ustar kamikami00000000000000 START_PREVIEW_SNAPSHOT IN_PROGRESS Request to Start Preview Snapshot has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/drs_stop_failover_preview.xml0000664000175000017500000000061413535474530032051 0ustar kamikami00000000000000 STOP_PREVIEW_SNAPSHOT IN_PROGRESS Request to Stop Preview Snapshot has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/enable_snapshot_service.xml0000664000175000017500000000074113535474530031452 0ustar kamikami00000000000000 ENABLE_SNAPSHOT_SERVICE IN_PROGRESS Request to Enable Snapshot Service has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/exchange_nic_vlans_response.xml0000664000175000017500000000062013535474530032315 0ustar kamikami00000000000000 EXCHANGE_NIC_VLANS OK Request to exchange VLANs for Server with Id '1cec8cfb-69e7-4de9-8404-debf116f5242' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/geographic_regions.xml0000664000175000017500000000712113535474530030422 0ustar kamikami00000000000000 Africa afapi.opsourcecloud.net https://mea.mcp-services.net https://af-monitoring.mcp-services.net ftps-af.cloud-vpn.net Africa/Johannesburg ENABLED Asia Pacific apapi.opsourcecloud.net https://ap.mcp-services.net https://ap-monitoring.mcp-services.net ftps-ap.cloud-vpn.net Asia/Tokyo ENABLED Australia auapi.opsourcecloud.net https://au.mcp-services.net https://au-monitoring.mcp-services.net ftps-au.cloud-vpn.net Australia/Sydney ENABLED Canada api-canada.dimensiondata.com https://canada.mcp-services.net https://ca-monitoring.mcp-services.net ftps-canada.cloud-vpn.net America/Toronto ENABLED Europe euapi.opsourcecloud.net https://eu.mcp-services.net https://eu-monitoring.mcp-services.net ftps-eu.cloud-vpn.net Europe/Amsterdam ENABLED Indonesia idapi.opsourcecloud.net https://id.mcp-services.net https://id-monitoring.mcp-services.net ftps-id.cloud-vpn.net Asia/Jakarta NOT_ENABLED Israel ilapi.opsourcecloud.net https://il.mcp-services.net https://il-monitoring.mcp-services.net ftps-med-1.cloud-vpn.net Asia/Jerusalem NOT_ENABLED North America api.opsourcecloud.net https://na.mcp-services.net https://na-monitoring.mcp-services.net ftps-na.cloud-vpn.net America/New_York ENABLED apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/get_cg_by_name_or_id.xml0000664000175000017500000000315313535474530030663 0ustar kamikami00000000000000 sdk_test2_cg A test consistency group DRS-ProdEng-East-ND1 DRS-ProdEng-West-ND1 src-sdk-test tgt-sdk-test 2018-11-12T20:53:10.000Z DRS_MODE 0 NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_customerImage.xml0000664000175000017500000000614213535474530030534 0ustar kamikami00000000000000 ImportedCustomerImage 2 2015-11-19T14:29:02.000Z NORMAL CustomerImageWithPricedSoftwareLabels 1 MSSQL2008R2S 2015-11-03T15:25:34.000Z NORMAL CopiedCustomerImage 2 2015-11-11T17:17:00.000Z NORMAL ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_customerImage_2ffa36c8_1848_49eb_b0000664000175000017500000000176613535474530033056 0ustar kamikami00000000000000 CustomerImageWithPricedSoftwareLabels 1 MSSQL2008R2S 2015-11-03T15:25:34.000Z NORMAL ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_customerImage_5234e5c7_01de_4411_80000664000175000017500000000222313535474530032603 0ustar kamikami00000000000000 ImportedCustomerImage 2 2015-11-19T14:29:02.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_osImage.xml0000664000175000017500000000431313535474530027312 0ustar kamikami00000000000000 RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 2015-09-17T11:23:48.000Z T-RHEL-6-64-2-4-10 Win2012 DC 2 CPU Windows 2012 Datacenter 4 2015-09-17T11:44:43.000Z T-WIN-2012-DATACTR-64-2-4-50 Win2008 Std 32-bit 2 CPU Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition 4 MSSQL2008R2S 2014-11-20T12:54:22.000Z T-WIN-2008-ENT-32-2-4-50 ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_osImage_6b4fb0c7_a57b_4f58_b59c_990000664000175000017500000000127313535474530032541 0ustar kamikami00000000000000 Win2012 DC 2 CPU Windows 2012 Datacenter 4 2015-09-17T11:44:43.000Z T-WIN-2012-DATACTR-64-2-4-50 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_osImage_BAD_REQUEST.xml0000664000175000017500000000054113535474530031167 0ustar kamikami00000000000000 GET_OS_IMAGE RESOURCE_NOT_FOUND Server Image 2ffa36c8-1848-49eb-b4fa-9d908775f68c not found. ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/image_osImage_c14b1a46_2428_44c1_9c1a_b20000664000175000017500000000130013535474530032323 0ustar kamikami00000000000000 RedHat 6 64-bit 2 CPU RedHat 6.6 Enterprise (Santiago) 64-bit 4 2015-09-17T11:23:48.000Z T-RHEL-6-64-2-4-10 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/import_image_response.xml0000664000175000017500000000057213535474530031161 0ustar kamikami00000000000000 IMPORT_IMAGE IN_PROGRESS Request to import image has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/infrastructure_datacenter.xml0000664000175000017500000002351713535474530032045 0ustar kamikami00000000000000 US - West Santa Clara California US https://na3.cloud-vpn.net ftps-na.cloud-vpn.net High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Standard STD Standard Disk Speed Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. US - East Ashburn Virginia US https://na1.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed US - East 2 Ashburn Virginia US https://na5.cloud-vpn.net ftps-na.cloud-vpn.net High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Standard STD Standard Disk Speed Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. US - East 3 - MCP 2.0 Ashburn Virginia US https://na9.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. US - West - MCP 2.0 Santa Clara California US https://na12.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/infrastructure_datacenter_NA9.xml0000664000175000017500000000601413535474530032505 0ustar kamikami00000000000000 US - East 3 - MCP 2.0 Ashburn Virginia US https://na9.cloud-vpn.net ftps-na.cloud-vpn.net Standard STD Standard Disk Speed High Performance HPF Faster than Standard. Uses 15000 RPM disk with Fast Cache. Economy ECN Slower than Standard. Uses 7200 RPM disk without Fast Cache. Standard Standard CPU Speed High Performance Faster and more consistent than Standard. Suitable for applications that are more CPU intensive. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/initiate_manual_snapshot.xml0000664000175000017500000000074413535474530031652 0ustar kamikami00000000000000 INITIATE_MANUAL_SNAPSHOT IN_PROGRESS Request to Initiate Manual Snapshot has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/ip_address_list_create.xml0000664000175000017500000000070213535474530031255 0ustar kamikami00000000000000 CREATE_IP_ADDRESS_LIST OK IP Address List 'myAddressList' has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/ip_address_list_delete.xml0000664000175000017500000000061313535474530031255 0ustar kamikami00000000000000 DELETE_IP_ADDRESS_LIST OK IP Address List with Id 84e34850-595d-436e-a885-7cd37edb24a4 has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/ip_address_list_edit.xml0000664000175000017500000000057213535474530030744 0ustar kamikami00000000000000 EDIT_IP_ADDRESS_LIST OK IP Address List 'MyIpAddressList' has been edited successfully. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/ip_address_lists.xml0000664000175000017500000000431113535474530030115 0ustar kamikami00000000000000 TestIPList2 Test web server IP addresses list IPV4 NORMAL 2016-09-01T01:19:53.000Z TestIPList_sub_2 Test web server IP addresses list IPV4 NORMAL 2016-09-01T01:20:56.000Z Test_IP_Address_List_2 Test Description IPV4 NORMAL 2016-09-05T05:37:56.000Z Test_IP_Address_List_3 Test Description IPV4 NORMAL 2016-09-05T05:57:53.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/ip_address_lists_FILTERBYNAME.xml0000664000175000017500000000132013535474530032053 0ustar kamikami00000000000000 Test_IP_Address_List_3 Test Description IPV4 NORMAL 2016-09-05T05:57:53.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/list_consistency_groups.xml0000664000175000017500000000605213535474530031561 0ustar kamikami00000000000000 sdk_test2_cg A test consistency group DRS-ProdEng-East-ND1 DRS-ProdEng-West-ND1 src-sdk-test tgt-sdk-test 2018-11-12T20:53:10.000Z DRS_MODE 0 NORMAL CG-Re-IP-Scenario-2 CG-Re-IP-Scenario-2 DRS-ProdEng-East-ND1 DRS-ProdEng-West-ND1 Src-Re-IP-RHEL7 Tgt-Re-IP-RHEL7 2018-11-16T15:41:48.000Z DRS_MODE 0 NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/list_drs_snapshots.xml0000664000175000017500000001535513535474530030521 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/list_server_snapshots.xml0000664000175000017500000000326213535474530031231 0ustar kamikami00000000000000 2018-08-15T12:00:47.000Z 2019-08-15T12:00:47.000Z SYSTEM CRASH_CONSISTENT INDEX_VALID 4 vmx-10 NORMAL 2018-08-15T12:30:50.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/manual_snapshot_server.xml0000664000175000017500000000322213535474530031344 0ustar kamikami00000000000000 test auto_created_server 4 2018-11-15T19:23:36.000Z true true NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/networkWithLocation.xml0000664000175000017500000000325513535474530030606 0ustar kamikami00000000000000 4bba37be-506f-11e3-b29c-001517c4643e test-net1 Test Network. NA5 10.192.176.0 false 208e3a8e-9d2f-11e2-b29c-001517c4643e Test Network Network description NA9 10.172.74.0 false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_addPublicIpBlock.xml0000664000175000017500000000073013535474530031467 0ustar kamikami00000000000000 ADD_PUBLIC_IP_BLOCK OK Public IPv4 Address Block has been added successfully to Network Domain d3320077-c2ce-4523-8c65-d417e766077b. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_createFirewallRule.xml0000664000175000017500000000064613535474530032123 0ustar kamikami00000000000000 CREATE_FIREWALL_RULE OK Request create Firewall Rule 'My.Rule.2' successful apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_createNatRule.xml0000664000175000017500000000066013535474530031074 0ustar kamikami00000000000000 CREATE_NAT_RULE OK NAT Rule with Id d31c2db0-be6b-4d50-8744-9a7a534b5fba has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_deleteFirewallRule.xml0000664000175000017500000000056013535474530032115 0ustar kamikami00000000000000 DELETE_FIREWALL_RULE OK Firewall Rule (Id:84e34850-595d-436e-a885-7cd37edb24a4) has been deleted apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_deleteNatRule.xml0000664000175000017500000000055213535474530031073 0ustar kamikami00000000000000 DELETE_NAT_RULE OK NAT Rule with Id 2187a636-7ebb-49a1-a2ff-5d617f496dce has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_deleteNetworkDomain.xml0000664000175000017500000000064713535474530032307 0ustar kamikami00000000000000 DELETE_NETWORK_DOMAIN IN_PROGRESS Request to Delete Network Domain (Id: 8cdfd607-f429-4df6-9352- 162cfc0891be) has been accepted and is being processed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_deleteVlan.xml0000664000175000017500000000060713535474530030422 0ustar kamikami00000000000000 DELETE_VLAN IN_PROGRESS Request to Delete VLAN (Id:0e56433f-d808-4669-821d-812769517ff8) has been accepted and is being processed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_deployNetworkDomain.xml0000664000175000017500000000071713535474530032337 0ustar kamikami00000000000000 DEPLOY_NETWORK_DOMAIN IN_PROGRESS Request to Deploy Network Domain 'A Network Domain' has been accepted and is being processed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_deployVlan.xml0000664000175000017500000000067513535474530030461 0ustar kamikami00000000000000 DEPLOY_VLAN IN_PROGRESS Request to deploy VLAN 'Production VLAN' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_editFirewallRule.xml0000664000175000017500000000056013535474530031600 0ustar kamikami00000000000000 EDIT_FIREWALL_RULE OK Firewall Rule with id 1aa3d0ce-d95d-4296-8338-9717e0d37ff9 has been edited apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_editNetworkDomain.xml0000664000175000017500000000055313535474530031766 0ustar kamikami00000000000000 EDIT_NETWORK_DOMAIN OK Network Domain 'Development Network Domain' was edited successfully. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_editVlan.xml0000664000175000017500000000050013535474530030075 0ustar kamikami00000000000000 EDIT_VLAN OK VLAN 'test' was edited successfully apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_expandVlan.xml0000664000175000017500000000057213535474530030440 0ustar kamikami00000000000000 EXPAND_VLAN IN_PROGRESS Request to expand VLAN 'Production VLAN' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_firewallRule.xml0000664000175000017500000000247613535474530031002 0ustar kamikami00000000000000 b30c224c-c95b-4cd9-bb8b-bfdfb5486abf CCDEFAULT.BlockOutboundMailIPv4 DROP IPV4 TCP true NORMAL b30c224c-c95b-4cd9-bb8b-bfdfb5486abf SpecificSourceIP DROP IPV4 TCP true NORMAL ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_firewallRule_d0a20f59_77b9_4f28_0000664000175000017500000000105313535474530033055 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be CCDEFAULT.BlockOutboundMailIPv4 DROP IPV4 TCP true NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_natRule.xml0000664000175000017500000000141213535474530027744 0ustar kamikami00000000000000 484174a2-ae74-4658-9e56- 50fc90e086cf 10.0.0.15 165.180.12.18 2015-03-06T13:43:45.000Z NORMAL 484174a2-ae74-4658-9e56- 50fc90e086cf 10.0.0.16 165.180.12.19 2015-03-06T13:45:10.000Z NORMAL ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_natRule_2187a636_7ebb_49a1_a2ff_0000664000175000017500000000061213535474530032721 0ustar kamikami00000000000000 484174a2-ae74-4658-9e56-50fc90e086cf 10.0.0.16 165.180.12.19 2015-03-06T13:45:10.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_networkDomain.xml0000664000175000017500000000401513535474530031155 0ustar kamikami00000000000000 Aurora Project Aurora Demo Environments ADVANCED 168.128.2.136 2015-07-13T03:52:16.000Z NORMAL Test net domain description of my network ESSENTIALS 168.128.26.20 2015-07-15T03:36:00.000Z NORMAL another networkj net network netowkrm ESSENTIALS 168.128.26.22 2015-07-15T03:40:09.000Z NORMAL Imports Imported servers ADVANCED 168.128.2.69 2015-08-18T03:53:02.000Z NORMAL Platform R2.0 Lab (MCP 2.0) This is the R2.0 lab for Platform on MCP 2.0 ESSENTIALS 168.128.2.149 2015-08-25T01:39:22.000Z NORMAL ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_networkDomain_8cdfd607_f429_4df60000664000175000017500000000061013535474530033247 0ustar kamikami00000000000000 test test2 ESSENTIALS 168.128.26.20 2015-07-15T03:36:00.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_publicIpBlock.xml0000664000175000017500000000076613535474530031067 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be 168.128.4.18 2 2015-07-13T04:07:37.000Z NORMAL ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_publicIpBlock_4487241a_f0ca_11e30000664000175000017500000000057413535474530032765 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be 168.128.4.18 2 2015-07-13T04:07:37.000Z NORMAL ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_publicIpBlock_9945dc4a_bdce_11e40000664000175000017500000000057413535474530033222 0ustar kamikami00000000000000 8cdfd607-f429-4df6-9352-162cfc0891be 168.128.4.18 2 2015-07-13T04:07:37.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_removePublicIpBlock.xml0000664000175000017500000000057413535474530032242 0ustar kamikami00000000000000 REMOVE_PUBLIC_IP_BLOCK OK Public Ip Block bef4334a-844b-11e4-a91c-0030487e0302 has been removed successfully apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_vlan.xml0000664000175000017500000000247513535474530027304 0ustar kamikami00000000000000 Primary 10.0.0.1 2607:f480:111:1336:0:0:0:1 2015-07-13T03:52:45.000Z NORMAL Wi-Fi Wi-Fi 10.230.98.1 2607:f480:111:1199:0:0:0:1 2015-08-18T23:47:04.000Z NORMAL ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_vlan_0e56433f_d808_4669_821d_812769517ff8.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/network_vlan_0e56433f_d808_4669_821d_8120000664000175000017500000000117513535474530032223 0ustar kamikami00000000000000 Production VLAN test2 10.0.3.1 2607:f480:1111:1153:0:0:0:1 2015-02-13T10:56:44.000Z NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/oec_0_9_myaccount.xml0000664000175000017500000000303413535474530030062 0ustar kamikami00000000000000 testuser Test User Test User test@example.com 8a8f6abc-2745-4d8a-9cbc-8dabe5a7d0e4 create image reports server primary administrator network apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/port_list_create.xml0000664000175000017500000000063513535474530030131 0ustar kamikami00000000000000 CREATE_PORT_LIST OK Port List 'MyPortList' has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/port_list_delete.xml0000664000175000017500000000057713535474530030135 0ustar kamikami00000000000000 DELETE_PORT_LIST OK Port List with Id 84e34850-595d-436e-a885-7cd37edb24a4 has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/port_list_edit.xml0000664000175000017500000000053413535474530027611 0ustar kamikami00000000000000 EDIT_PORT_LIST OK Port List 'MyPortList' has been edited successfully. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/port_list_get.xml0000664000175000017500000000114313535474530027440 0ustar kamikami00000000000000 MyPortList Production Servers NORMAL 2015-06-21T18:54:42.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/port_list_lists.xml0000664000175000017500000000320513535474530030020 0ustar kamikami00000000000000 MyPortList Production Servers NORMAL 2015-06-21T18:54:42.000Z MyPortList2 Core functions NORMAL 2016-09-01T01:36:49.000Z Test_Port_List_1 Test Description NORMAL 2016-09-06T02:32:29.000Z apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/report_usageMonitoring.xml0000664000175000017500000000073713535474530031337 0ustar kamikami00000000000000Date,Location,Server,Server ID,Essentials Monitoring Hours,Advanced Monitoring Hours 2/24/15,NA5,Server A,5a2378ba-11de-11e5-ad2a-ca9798323470,14.25,0 2/24/15,NA5,Server B,6330a644-11de-11e5-ad2a-ca9798323470,0,8.64 2/25/15,NA5,Server A,5a2378ba-11de-11e5-ad2a-ca9798323470,24,0 2/25/15,NA5,Server B,6330a644-11de-11e5-ad2a-ca9798323470,0,24 2/26/15,NA5,Server A,5a2378ba-11de-11e5-ad2a-ca9798323470,17.59,6.41 2/26/15,NA5,Server B,6330a644-11de-11e5-ad2a-ca9798323470,2.11,21.89apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_GetServer.xml0000664000175000017500000000372313535474530030064 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true stopped SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 **OR** apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_addDisk.xml0000664000175000017500000000113313535474530027512 0ustar kamikami00000000000000 ADD_DISK IN_PROGRESS The request to add a 20 GB Standard Speed Disk on Server 'SERVER-1' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_addNic.xml0000664000175000017500000000074413535474530027340 0ustar kamikami00000000000000 ADD_NIC IN_PROGRESS The request to add NIC for VLAN 'Subsystem VLAN' on Server 'Production Mail Server' has been accepted and is being processed.. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_antiAffinityRule_list.xml0000664000175000017500000000525713535474530032472 0ustar kamikami00000000000000 ansible-test-image-rhel6 my new node ansible-custom-image-test-UAT my new node rhel-ansible-full-test RHEL Ansible Test rhel-ansible-full-test RHEL Ansible Test ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_antiAffinityRule_list_PAGINATED.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_antiAffinityRule_list_PAGINATED.x0000664000175000017500000000525513535474530033513 0ustar kamikami00000000000000 ansible-test-image-rhel6 my new node ansible-custom-image-test-UAT my new node rhel-ansible-full-test RHEL Ansible Test rhel-ansible-full-test RHEL Ansible Test apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_changeServerMonitoringPlan.xml0000664000175000017500000000056513535474530033454 0ustar kamikami00000000000000 CHANGE_SERVER_MONITORING_PLAN OK Monitoring on Server 'Production Server' has been changed to Service Plan 'ADVANCED'. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_cleanServer.xml0000664000175000017500000000064213535474530030424 0ustar kamikami00000000000000 CLEAN_SERVER IN_PROGRESS The request to clean a failed Server deployment for Server e75ead52-692f-4314-8725-c8a4f4d13a87 has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_clone_response.xml0000664000175000017500000000075513535474530031176 0ustar kamikami00000000000000 CLONE_SERVER IN_PROGRESS Request to Clone Server '9ed47330-5561-11e5-8c14-b8ca3a5d9ef8' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_createAntiAffinityRule.xml0000664000175000017500000000062413535474530032554 0ustar kamikami00000000000000 CREATE_ANTI_AFFINITY_RULE IN_PROGRESS Request to Create Anti-Affinity Rule has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_createAntiAffinityRule_FAIL.xml0000664000175000017500000000076113535474530033351 0ustar kamikami00000000000000 >CREATE_ANTI_AFFINITY_RULE CONFIGURATION_NOT_SUPPORTED Server 'ansible-test-image-rhel6' (id 22f3544a-c874-4930-a31c-e9e513e51114) is already used in another Anti-Affinity Rule (id 07e3621a-a920-4a9a-943c-d8021f27f418) apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_deleteAntiAffinityRule.xml0000664000175000017500000000061713535474530032555 0ustar kamikami00000000000000 DELETE_ANTI_AFFINITY_RULE IN_PROGRESS Request to Delete Anti-Affinity Rule has been accepted. Please use appropriate Get or List API for status. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_deleteAntiAffinityRule_FAIL.xml0000664000175000017500000000061013535474530033341 0ustar kamikami00000000000000 >CREATE_ANTI_AFFINITY_RULE RESOURCE_NOT_FOUND Anti-Affinity Rule '07e3621a-a920-4a9a-943c-d8021f27f418' not found apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_deleteServer.xml0000664000175000017500000000062713535474530030607 0ustar kamikami00000000000000 DELETE_SERVER IN_PROGRESS Request to Delete Server (Id:d577a691-e116-4913-a440- 022d2729fc84) has been accepted and is being processed apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_deleteServer_RESOURCEBUSY.xml0000664000175000017500000000050313535474530032612 0ustar kamikami00000000000000 DELETE_SERVER RESOURCE_BUSY Server is already busy apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_deployServer.xml0000664000175000017500000000070313535474530030634 0ustar kamikami00000000000000 DEPLOY IN_PROGRESS Request to deploy Server 'Production FTPS Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_disableServerMonitoring.xml0000664000175000017500000000055013535474530033011 0ustar kamikami00000000000000 DISABLE_SERVER_MONITORING OK Monitoring on Server 5783e93f-5370-44fc-a772-cd3c29a2ecaa has been disabled. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_editServerMetadata.xml0000664000175000017500000000050413535474530031725 0ustar kamikami00000000000000 EDIT_SERVER_METADATA OK Server 'Production Server' has been edited successfully. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_enableServerMonitoring.xml0000664000175000017500000000052513535474530032636 0ustar kamikami00000000000000 ENABLE_SERVER_MONITORING OK Monitoring on Server 'Production Server' has been enabled. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_powerOffServer.xml0000664000175000017500000000056613535474530031136 0ustar kamikami00000000000000 POWER_OFF_SERVER IN_PROGRESS Request to power off Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_powerOffServer_INPROGRESS.xml0000664000175000017500000000057013535474530032704 0ustar kamikami00000000000000 POWER_OFF_SERVER RESOURCE_BUSY Request to power off Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_rebootServer.xml0000664000175000017500000000056013535474530030633 0ustar kamikami00000000000000 REBOOT_SERVER IN_PROGRESS Request to reboot Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_rebootServer_RESOURCEBUSY.xml0000664000175000017500000000054613535474530032651 0ustar kamikami00000000000000 REBOOT_SERVER RESOURCE_BUSY Request to reboot Server 'Production Server' did not work, server is busy. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_reconfigureServer.xml0000664000175000017500000000052513535474530031652 0ustar kamikami00000000000000 RECONFIGURE_SERVER OK Request to reconfigure Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_removeDisk.xml0000664000175000017500000000065313535474530030265 0ustar kamikami00000000000000 REMOVE_DISK IN_PROGRESS Request to Remove disk '540c4d86-4d84-11e4-a91c-0030487e0302' from Server 'Server 1' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_removeNic.xml0000664000175000017500000000071213535474530030100 0ustar kamikami00000000000000 REMOVE_NIC IN_PROGRESS Request to Remove NIC 5999db1d-725c-46ba-9d4e-d33991e61ab1 for VLAN 'Subsystem VLAN' from Server 'Production Mail Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_resetServer.xml0000664000175000017500000000055613535474530030470 0ustar kamikami00000000000000 RESET_SERVER IN_PROGRESS Request to reset Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_server.xml0000664000175000017500000003075713535474530027473 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true PENDING_ADD DEPLOY_SERVER_WITH_DISK_SPEED 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE RECONFIGURE_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true UNKNOWN SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 21 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true false UNKNOWN SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true false NORMAL apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_server_NA3.xml0000664000175000017500000000623413535474530030125 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_server_e75ead52_692f_4314_8725_c80000664000175000017500000000336713535474530032472 0ustar kamikami00000000000000 Production Web Server Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE DEPLOY_SERVER 2015-12-02T11:07:40.000Z devuser1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_server_paginated.xml0000664000175000017500000000631713535474530031502 0ustar kamikami00000000000000 Production Web Server MCP 1 nopassword0 2 e9ec6eb4-4634-49de-b914-01eb74da5fb9 2015-08-11T16:51:05.000Z true true NORMAL Production Web Server MCP 2 Server to host our main web application. 4 MSSQL2008R2S 3ebf3c0f-90fe-4a8b-8585-6e65b316592c 2015-12-02T10:31:33.000Z true true PENDING_CHANGE SHUTDOWN_SERVER 2015-12-02T11:07:40.000Z devuser1 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_server_paginated_empty.xml0000664000175000017500000000022313535474530032706 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_shutdownServer.xml0000664000175000017500000000056413535474530031220 0ustar kamikami00000000000000 SHUTDOWN_SERVER IN_PROGRESS Request to shutdown Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_shutdownServer_INPROGRESS.xml0000664000175000017500000000056613535474530032775 0ustar kamikami00000000000000 SHUTDOWN_SERVER RESOURCE_BUSY Request to shutdown Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_startServer.xml0000664000175000017500000000055613535474530030503 0ustar kamikami00000000000000 START_SERVER IN_PROGRESS Request to start Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_startServer_INPROGRESS.xml0000664000175000017500000000056013535474530032251 0ustar kamikami00000000000000 START_SERVER RESOURCE_BUSY Request to start Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/server_updateVmwareTools.xml0000664000175000017500000000056613535474530031645 0ustar kamikami00000000000000 POWER_OFF_SERVER IN_PROGRESS Request to power off Server 'Production Server' has been accepted and is being processed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/summary_usage_report.csv0000664000175000017500000000152513535474530031035 0ustar kamikami00000000000000DAY,Location,CPU Hours,RAM Hours,Storage Hours,Performance Storage Hours,Bandwidth In,Bandwidth Out,Sub-Admin Hours,Network Hours,Public IP Hours,Cloud Files Account Hours,Cloud Files (GB Days),Software Units,Essentials Client Days,Advanced Client Days,Enterprise Client Days,Essentials Backups (GB),Advanced Backups (GB),Enterprise Backups (GB) 01/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 02/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 03/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 04/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 05/01/2013,NA1,144,288,3360,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 06/01/2013,NA1,172,344,3958,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 07/01/2013,NA1,205,410,4783,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0 08/01/2013,NA1,216,432,5136,264,0,0,72,24,0,0,0,0,0,0,0,0,0,0apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_applyTags.xml0000664000175000017500000000045113535474530027362 0ustar kamikami00000000000000 APPLY_TAGS OK Tag(s) successfully applied. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_applyTags_BADREQUEST.xml0000664000175000017500000000050213535474530031076 0ustar kamikami00000000000000 APPLY_TAGS RESOURCE_NOT_FOUND Tag Key(s) (ChangeNameTes) not found. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_createTagKey.xml0000664000175000017500000000057513535474530027775 0ustar kamikami00000000000000 CREATE_TAG_KEY OK Tag Key 'MyTestKey' has been created. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_createTagKey_BADREQUEST.xml0000664000175000017500000000051713535474530031510 0ustar kamikami00000000000000 CREATE_TAG_KEY NAME_NOT_UNIQUE Another Tag Key named 'MyTestKey' already exists. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_deleteTagKey.xml0000664000175000017500000000052413535474530027766 0ustar kamikami00000000000000 DELETE_TAG_KEY OK Tag Key (Id:4f921962-402d-438d-aa37-6f6a0392a1a9) has been deleted. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_deleteTagKey_BADREQUEST.xml0000664000175000017500000000047313535474530031510 0ustar kamikami00000000000000 DELETE_TAG_KEY RESOURCE_NOT_FOUND Tag Key fdafdsa not found. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_editTagKey.xml0000664000175000017500000000047013535474530027451 0ustar kamikami00000000000000 EDIT_TAG_KEY OK Tag Key 'ChangeNameTest' has been edited. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_editTagKey_BADREQUEST.xml0000664000175000017500000000060113535474530031164 0ustar kamikami00000000000000 EDIT_TAG_KEY NO_CHANGE At least one of name, description, valueRequired or displayOnReport must be changed from its current value. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_removeTag.xml0000664000175000017500000000045213535474530027350 0ustar kamikami00000000000000 REMOVE_TAGS OK Tag(s) successfully removed. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_removeTag_BADREQUEST.xml0000664000175000017500000000057013535474530031070 0ustar kamikami00000000000000 REMOVE_TAGS RESOURCE_NOT_FOUND Tag Key(s) (AaronTestModified) not applied to Server eb222a4a-fffd-4e4a-8346-1279ef621ab0. ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab30000664000175000017500000000036713535474530032406 0ustar kamikami00000000000000 LibcloudTest true true ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab30000664000175000017500000000052413535474530032401 0ustar kamikami00000000000000 GET_TAG_KEY RESOURCE_NOT_FOUND Tag Key 5ab77f5f-5aa9-426f-8459-4eab34e03d5 not found. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_tagKey_list.xml0000664000175000017500000000135313535474530027677 0ustar kamikami00000000000000 AaronTestModified Testing for VMWare true true LibcloudTest true true MyTestKey true true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_tagKey_list_SINGLE.xml0000664000175000017500000000052113535474530030734 0ustar kamikami00000000000000 LibcloudTest true true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/nttcis/tag_tag_list.xml0000664000175000017500000000254213535474530027227 0ustar kamikami00000000000000 SERVER 09242b55-3bc8-4cb7-b30c-4158267f58e6 App server NA9 5ab77f5f-5aa9-426f-8459-4eab34e03d54 ChangeNameTest No way! true true NETWORK_DOMAIN 1a16bf5e-583b-42c9-af94-a92d9ee1607f An Ho1a Demo NA9 d047c609-93d7-4bc5-8fc9-732c85840075 AaronTestModified Success true true SERVER 77da591d-b58e-43ef-8bc2-ddde3f732893 Test 1 NA9 d047c609-93d7-4bc5-8fc9-732c85840075 AaronTestModified Test VMware true true apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/0000775000175000017500000000000013600223624023637 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/create_node.json0000664000175000017500000000441313535474530027017 0ustar kamikami00000000000000{ "virtual_machine": { "add_to_marketplace": false, "admin_note": "", "allow_resize_without_reboot": true, "allowed_hot_migrate": true, "allowed_swap": true, "booted": true, "built": true, "cpu_priority": 100, "cpu_shares": 100, "cpu_sockets": 1, "cpu_threads": 1, "cpu_units": 1000, "cpus": 2, "created_at": "2015-01-16T02:06:19+07:00", "customer_network_id": "", "deleted_at": "", "edge_server_type": "", "enable_autoscale": false, "enable_monitis": false, "firewall_notrack": false, "hostname": "onapp-new-fred", "hypervisor_id": 24, "id": 652, "identifier": "456789", "initial_root_password": "passwd", "initial_root_password_encrypted": false, "ip_addresses": [ { "ip_address": { "address": "192.168.15.73", "broadcast": "192.168.15.255", "created_at": "2015-01-16T02:49:58+07:00", "customer_network_id": "", "disallowed_primary": false, "free": false, "gateway": "192.168.15.51", "hypervisor_id": "", "id": 2947, "ip_address_pool_id": "", "netmask": "255.255.255.0", "network_address": "192.168.15.0", "network_id": 39, "pxe": false, "updated_at": "2015-01-20T22:42:14+07:00", "user_id": "" } } ], "label": "onapp-new-fred", "local_remote_access_ip_address": "8.8.8.8", "local_remote_access_port": 5967, "locked": false, "memory": 8192, "min_disk_size": 5, "monthly_bandwidth_used": 1887, "note": "", "operating_system": "linux", "operating_system_distro": "ubunt", "preferred_hvs": [ 5, 4, 2, 3, 1, 6 ], "price_per_hour": 0.0, "price_per_hour_powered_off": 0.0, "recovery_mode": "", "remote_access_password": "passwd", "service_password": "", "state": "delivered", "storage_server_type": "", "strict_virtual_machine_id": "", "support_incremental_backups": false, "suspended": false, "template_id": 93, "template_label": "Ubuntu 12.04 x64", "total_disk_size": 410, "updated_at": "2015-02-28T07:54:47+07:00", "user_id": 136, "vip": "", "xen_id": 161 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/get_key_pair.json0000664000175000017500000000107713535474530027214 0ustar kamikami00000000000000{ "ssh_key": { "id": 1, "user_id": 123, "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8uuUqh0cXhx5s9AxlQHCWzQoS9w0qy/WN/I/CZuy4p+mQYhOYSqBi/aqf4/wySyOtzez785IGBriX24zk6vMcfSuB7wgHzCGZ433zAkdZu39nPPpCo3WWZmJ3GKYjEN+yNJNG8kR3OW3N0mRSId3ebFZoLUafli8sSt6XeXHgeLPfEvbpiEdKxHskRsZHP8JoM2tQD9Ms5/9KPbbhg4geeu9FO28kozacBdyQMS1db+45b9xz0L9GPYO0NasESq9cC4BvlhPvAFHDT1kio6DjjhZ5kUK7OcmRK+8/Jk+9cTSj9MzVMCwRni3HyA37/Mu4qBpDkR9sPwgJ9G/UY7ZP John@Johns-MacBook-Pro", "created_at": "2017-03-22T19:11:32.000+05:30", "updated_at": "2017-03-22T19:11:32.000+05:30" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/import_key_pair.json0000664000175000017500000000033013535474530027736 0ustar kamikami00000000000000{ "ssh_key": { "id": 3, "user_id": 123, "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8uuUq", "created_at": "2017-03-22T19:11:32.000+05:30", "updated_at": "2017-03-22T19:11:32.000+05:30" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/list_images.json0000664000175000017500000000244413535474530027051 0ustar kamikami00000000000000[ { "image_template": { "allow_resize_without_reboot": true, "allowed_hot_migrate": true, "allowed_swap": true, "application_server": false, "backup_server_id": "", "baremetal_server": true, "cdn": false, "checksum": "f3ea0b39051d9c5fef3f7661c6318111", "created_at": "2015-03-12T19:56:02+05:30", "disk_target_device": "--- xen: sda kvm: hd ", "draas": false, "ext4": false, "file_name": "centos-5.11-x64-1.1-xen.kvm.kvm_virtio.tar.gz", "id": 123456, "initial_password": "Password1", "initial_username": "root", "label": "CentOS 5.11 x64", "manager_id": "", "min_disk_size": 5, "min_memory_size": 256, "operating_system": "linux", "operating_system_arch": "x64", "operating_system_distro": "rhel", "operating_system_edition": "", "operating_system_tail": "", "parent_template_id": "", "properties": "", "remote_id": "", "resize_without_reboot_policy": {}, "smart_server": true, "state": "active", "template_size": 323924, "updated_at": "", "user_id": "", "version": "1.1", "virtualization": [ "xen", "kvm", "kvm_virtio" ], "type": "ImageTemplate" } } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/list_key_pairs.json0000664000175000017500000000224013535474530027564 0ustar kamikami00000000000000[ { "ssh_key": { "id": 1, "user_id": 123, "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8uuUqh0cXhx5s9AxlQHCWzQoS9w0qy/WN/I/CZuy4p+mQYhOYSqBi/aqf4/wySyOtzez785IGBriX24zk6vMcfSuB7wgHzCGZ433zAkdZu39nPPpCo3WWZmJ3GKYjEN+yNJNG8kR3OW3N0mRSId3ebFZoLUafli8sSt6XeXHgeLPfEvbpiEdKxHskRsZHP8JoM2tQD9Ms5/9KPbbhg4geeu9FO28kozacBdyQMS1db+45b9xz0L9GPYO0NasESq9cC4BvlhPvAFHDT1kio6DjjhZ5kUK7OcmRK+8/Jk+9cTSj9MzVMCwRni3HyA37/Mu4qBpDkR9sPwgJ9G/UY7ZP John@Johns-MacBook-Pro", "created_at": "2017-03-22T19:11:32.000+05:30", "updated_at": "2017-03-22T19:11:32.000+05:30" } }, { "ssh_key": { "id": 2, "user_id": 123, "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCx/N6Mm/8BapBlTPhjnrj06yyAKYDTfBgIOzhPzdq1rco6FS7JVUot3zY4pX3ZUkLJh5JDsNz9FyqyGpXBzO3G7QpDhGggjqfYxpsR9VQBDNC8YKpQdaa6j2s1yJsI0cb+/sQl9SC/9WyBCceK3mzPt5AsSzdY0hA2+jPYuCzvTT/S0qfsk2WyvA+fK7ue7yWD/8KSNQx2/xsP3GU+/Ck5D7w+8ck1oUVXAFoO/WUIEwbx5u9wurv73GsK6Pqgt1tjtNznS50JsyHmayeZzrX1hr33PE9IarlUzWAUj4zvpdDTpCm/u2f2UnmSJJ0cT45NUUG085WTyhy2ZHBz3jOT John@Johns-iMac", "created_at": "2017-03-24T14:31:24.000+05:30", "updated_at": "2017-03-24T14:31:24.000+05:30" } } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/list_nodes.json0000664000175000017500000000466513535474530026723 0ustar kamikami00000000000000[ { "virtual_machine": { "add_to_marketplace": false, "admin_note": "", "allow_resize_without_reboot": true, "allowed_hot_migrate": true, "allowed_swap": true, "booted": true, "built": true, "cpu_priority": 100, "cpu_shares": 100, "cpu_sockets": 1, "cpu_threads": 1, "cpu_units": 1000, "cpus": 2, "created_at": "2015-01-16T02:06:19+07:00", "customer_network_id": "", "deleted_at": "", "edge_server_type": "", "enable_autoscale": false, "enable_monitis": false, "firewall_notrack": false, "hostname": "onapp-fred", "hypervisor_id": 24, "id": 652, "identifier": "123456", "initial_root_password": "passwd", "initial_root_password_encrypted": false, "ip_addresses": [ { "ip_address": { "address": "192.168.15.72", "broadcast": "192.168.15.255", "created_at": "2015-01-16T02:49:58+07:00", "customer_network_id": "", "disallowed_primary": false, "free": false, "gateway": "192.168.15.51", "hypervisor_id": "", "id": 2947, "ip_address_pool_id": "", "netmask": "255.255.255.0", "network_address": "192.168.15.0", "network_id": 39, "pxe": false, "updated_at": "2015-01-20T22:42:14+07:00", "user_id": "" } } ], "label": "onapp-fred", "local_remote_access_ip_address": "9.9.9.9", "local_remote_access_port": 5967, "locked": false, "memory": 8192, "min_disk_size": 5, "monthly_bandwidth_used": 1887, "note": "", "operating_system": "linux", "operating_system_distro": "ubunt", "preferred_hvs": [ 5, 4, 2, 3, 1, 6 ], "price_per_hour": 0.0, "price_per_hour_powered_off": 0.0, "recovery_mode": "", "remote_access_password": "passwd", "service_password": "", "state": "delivered", "storage_server_type": "", "strict_virtual_machine_id": "", "support_incremental_backups": false, "suspended": false, "template_id": 93, "template_label": "Ubuntu 12.04 x64", "total_disk_size": 410, "updated_at": "2015-02-28T07:54:47+07:00", "user_id": 136, "vip": "", "xen_id": 161 } } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/onapp/profile.json0000664000175000017500000000042613535474530026207 0ustar kamikami00000000000000{ "user": { "id": 123, "identifier": "abcdef123345", "email": "abc@example.com", "first_name": "John", "last_name": "Smith", "status": "active", "created_at": "2017-03-22T20:39:36.000+07:00", "updated_at": "2017-03-22T20:39:36.000+07:00" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/0000775000175000017500000000000013600223624024470 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/auth_error.json0000664000175000017500000000014313535474530027546 0ustar kamikami00000000000000{ "type":"UNAUTHORIZED", "message":"The Token you are using is not valid", "errors":null }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/create_node.json0000664000175000017500000000171313535474530027650 0ustar kamikami00000000000000{ "id": "E7D36EC025C73796035BF4F171379025", "name": "Docs Content Test Server: CentOS 7-1", "description": "My server description", "status": { "state": "POWERED_ON", "percent": null }, "datacenter": { "id": "908DC2072407C94C8054610AD5A53B8C", "country_code": "US", "location": "United States of America" }, "creation_date": "2016-05-05T17:39:50+00:00", "image": { "id": "B5F778B85C041347BCDCFC3172AB3F3C", "name": "centos7-64std" }, "hardware": { "fixed_instance_size_id": "65929629F35BBFBA63022008F773F3EB", "vcore": 1, "cores_per_processor": 1, "ram": 1, "hdds": [ { "id": "CDB278D95A92CB4C379A9CAAD6759F02", "size": 40, "is_main": true } ] }, "ips": [ { "id": "FDBE99EDD57F8596CBF71B6B64BD0A92", "ip": "62.151.179.99" } ], "dvd": null, "snapshot": null, "alerts": [], "monitoring_policy": null, "private_networks": null }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/describe_firewall_policy.json0000664000175000017500000000113713535474530032424 0ustar kamikami00000000000000{ "id": "83522FC7DA9172F229E5352C587075BA", "name": "My firewall policy test", "description": "My firewall policy description", "state": "CONFIGURING", "creation_date": "2015-04-29T10:43:11+00:00", "default": 0, "rules": [ { "id": "DA5CC179ED00079AE7DE595F0073D86E", "protocol": "TCP", "port_from": 80, "port_to": 80, "source": "0.0.0.0" }, { "id": "0766EC674A0CD9D4EC0FA0B07978A649", "protocol": "TCP", "port_from": 443, "port_to": 443, "source": "0.0.0.0" } ], "server_ips": [], "cloudpanel_id": "FW99AA4_7" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/describe_id_firewall_policy.json0000664000175000017500000000010313535474530033070 0ustar kamikami00000000000000{ "id": "3C4F21EDFEEDD6ABB728EA5CE684E1AF", "name": "Windows" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/describe_server.json0000664000175000017500000000174713535474530030555 0ustar kamikami00000000000000{ "id": "srv_1", "cloudpanel_id": "958FA92", "name": "My Server 1", "description": "", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "creation_date": "2015-05-04T06:32:15+00:00", "first_password": "Fg52K21nz8", "status": { "state": "POWERED_OFF", "percent": null }, "hardware": { "fixed_instance_size_id": 0, "vcore": 1, "cores_per_processor": 1, "ram": 2, "hdds": [ { "id": "8C626C1A7005D0D1F527143C413D461E", "size": 40, "is_main": true } ] }, "image": { "id": "3C3B80327CBBD7F0023F793F666C24D0", "name": "w2008r2datacenter64std" }, "dvd": null, "snapshot": null, "ips": [ { "id": "8D135204687B9CF9E79E7A93C096E336", "ip": "10.4.140.213", "type": "IPV4", "reverse_dns": null, "firewall_policy": null, "load_balancers": [] } ], "alerts": [], "monitoring_policy": null, "private_networks": null }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/describe_shared_stoage.json0000664000175000017500000000133513535474530032050 0ustar kamikami00000000000000{ "id": "6AD2F180B7B666539EF75A02FE227084", "size": 200, "state": "ACTIVE", "description": "My shared storage description", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "cloudpanel_id": "vid35780", "size_used": "0.00", "cifs_path": "\\vid50995.nas1.lan\vid50995", "nfs_path": "vid50995.nas1.lan/:vid50995", "name": "My shared storage test rename", "creation_date": "2015-05-06T08:33:25+00:00", "servers": [ { "id": "638ED28205B1AFD7ADEF569C725DD85F", "name": "Mi servidor 1", "rights": "RW" }, { "id": "39AA65F5D5B02FA02D58173094EBAF95", "name": "My Server remame", "rights": "R" } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/ex_list_datacenters.json0000664000175000017500000000111213535474530031415 0ustar kamikami00000000000000[ { "id":"81DEF28500FBC2A973FC0C620DF5B721", "location":"Spain", "country_code":"ES", "default":0 }, { "id":"908DC2072407C94C8054610AD5A53B8C", "location":"United States of America", "country_code":"US", "default":1 }, { "id":"4EFAD5836CE43ACA502FD5B99BEE44EF", "location":"Germany", "country_code":"DE", "default":0 }, { "id":"5091F6D8CBFEF9C26ACE957C652D5D49", "location":"United Kingdom of Great Britain and Northern Ireland", "country_code":"GB", "default":0 } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/fixed_instance_sizes.json0000664000175000017500000000226113535474530031577 0ustar kamikami00000000000000[ { "name": "M", "id": "8C626C1A7005D0D1F527143C413D461E", "hardware": { "vcore": 1, "cores_per_processor": 1, "ram": 1, "unit": "GB", "hdds": [ { "size": 40, "unit": "GB", "is_main": true } ] } }, { "name": "L", "id": "8C626C1A7005D0D1F527143C413D461F", "hardware": { "vcore": 2, "cores_per_processor": 1, "ram": 2, "unit": "GB", "hdds": [ { "size": 80, "unit": "GiB", "is_main": true } ] } }, { "name": "XL", "id": "8C626C1A7005D0D1F527143C413D4620", "hardware": { "vcore": 2, "cores_per_processor": 1, "ram": 4, "unit": "GB", "hdds": [ { "size": 120, "unit": "GB", "is_main": true } ] } }, { "name": "XXL", "id": "8C626C1A7005D0D1F527143C413D4621", "hardware": { "vcore": 4, "cores_per_processor": 1, "ram": 8, "unit": "GB", "hdds": [ { "size": 160, "unit": "GiB", "is_main": true } ] } } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/get_image.json0000664000175000017500000000107113535474530027316 0ustar kamikami00000000000000{ "id": "6E1F2C70CCD3EE44ED194F4FFC47C4C9", "name": "w2012r2datacenter64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/get_server_image.json0000664000175000017500000000011113535474530030676 0ustar kamikami00000000000000{ "id": "76EBF29C1250167C8754B2B3D1C05F68", "name": "centos7-64std" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/list_firewall_policies.json0000664000175000017500000000245613535474530032134 0ustar kamikami00000000000000[ { "id": "83522FC7DA9172F229E5352C587075BA", "name": "My firewall policy test", "description": "My firewall policy description", "state": "CONFIGURING", "creation_date": "2015-04-29T10:43:11+00:00", "default": 0, "rules": [ { "id": "DA5CC179ED00079AE7DE595F0073D86E", "protocol": "TCP", "port_from": 80, "port_to": 80, "source": "0.0.0.0" }, { "id": "0766EC674A0CD9D4EC0FA0B07978A649", "protocol": "TCP", "port_from": 443, "port_to": 443, "source": "0.0.0.0" } ], "server_ips": [], "cloudpanel_id": "FW99AA4_7" }, { "id": "83522FC7DA9172F229E5352C587075B9", "name": "My firewall policy test 2", "description": "My firewall policy description", "state": "CONFIGURING", "creation_date": "2015-04-29T10:43:11+00:00", "default": 0, "rules": [ { "id": "DA5CC179ED00079AE7DE595F0073D86F", "protocol": "TCP", "port_from": 80, "port_to": 80, "source": "0.0.0.0" }, { "id": "0766EC674A0CD9D4EC0FA0B07978A64A", "protocol": "TCP", "port_from": 443, "port_to": 443, "source": "0.0.0.0" } ], "server_ips": [], "cloudpanel_id": "FW99AA4_7" } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/list_images.json0000664000175000017500000157330013535474530027707 0ustar kamikami00000000000000[ { "id": "6E1F2C70CCD3EE44ED194F4FFC47C4C9", "name": "w2012r2datacenter64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "B77E19E062D5818532EFF11C747BD104", "name": "w2012r2datacenter64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "7C5FA1D21B98DE39D7516333AAB7DA54", "name": "w2012r2datacenter64std+SQL2012express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "D2127B1C773877A693D718C78181D430", "name": "w2012r2datacenter64std+SQL2012web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "EB2C91E2DC1BA405C5C648ED9B9A7118", "name": "w2012r2datacenter64std+SQL2012std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "71653B14F25069950DD34AF6FE1AFEDD", "name": "Ubuntu 14.04", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu14.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "C14988A9ABC34EA64CD5AAC0D33ABCAF", "name": "ubuntu1404-64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu14.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "72A90ECC29F718404AC3093A3D78327C", "name": "ubuntu1404-64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu14.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "8E3BAA98E3DFD37857810E0288DD8FBA", "name": "centos6-32min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 32, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "E949B8557A0D95E3425088C496FD93F8", "name": "centos6-32std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "650D003D3FC8A8FE554330E869B39FC0", "name": "centos6-64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "C598EAD5691CDADD1501A2AF29A2E91C", "name": "centos6-64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "DCA5686F1FC5E8A6E0B32E5A68BBB499", "name": "w2008r2datacenter64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "E156EA0B6CE014FEAB8BEB8CC9E3BB77", "name": "w2008r2datacenter64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "3A3752FFAEA4C4F53EE701D29172E332", "name": "w2008r2datacenter64std+SQL2012express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "295D0663A4868F920332DCDC15F395A7", "name": "w2008r2datacenter64std+SQL2012web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Web Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "00A1CE098B4C6121A77B23262EAD4D76", "name": "w2008r2datacenter64std+SQL2012std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Standard Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "E4B7589997B1147CCC5764A204F49E94", "name": "Red Hat 6", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "RedHat6", "os_version": "RedHat", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "F89443811E6952AF6B15E87E647D781A", "name": "w2012r2datacenter64min+SQL2012express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "65F9A55A55A558F977CF55BDC70AF60E", "name": "w2012r2datacenter64min+SQL2012web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "20C66A769CFA8B98D9EDD509A6458641", "name": "w2012r2datacenter64min+SQL2012std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "06E189B1C60CB0F46501E49049C43B05", "name": "w2008r2datacenter64min+SQL2012express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "9717A92E43E2350072A77B00F2DF8CF5", "name": "w2008r2datacenter64min+SQL2012web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Web Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "79AFC562A2541DD8F904F8CF918B6899", "name": "w2008r2datacenter64min+SQL2012std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2012 Standard Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "087BB7F082A7DE2817100EAD53A3845D", "name": "centos6-32std+Plesk12unlimited", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "EC5DCA17E7CF86D968F60C222948C83F", "name": "centos6-64std+Plesk12unlimited", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "B5F778B85C041347BCDCFC3172AB3F3C", "name": "centos7-64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "7B9067380CB74BBDFE7F473DEEA2AF5C", "name": "centos7-64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "9B9A214D50A7EEE8D9E37295DF834F70", "name": "debian7-32min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 32, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "0D5A4BCDC5B47A33593239C2553F5ADC", "name": "debian7-32std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "CF8318BDB7EFE797C9C769272AAA5F5C", "name": "debian7-64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "EBA74A8ED3760AE376F1E26AC6744B3F", "name": "debian7-64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "07324CD1A116A7D66B0F56B240F58CD2", "name": "ubuntu1204-32min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu12.04", "os_version": "Ubuntu", "os_architecture": 32, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "D86A31798B9D8EB7DFC28FF377EF7E42", "name": "ubuntu1204-32std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu12.04", "os_version": "Ubuntu", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "806447A8DC74E7FD56C743877B4A61CD", "name": "ubuntu1204-64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu12.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "84E3B902821F911BE6B43FA36ADA8199", "name": "ubuntu1204-64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu12.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "DBC37D7DF1726331AFC8A2153FC80EF0", "name": "CentOS 7", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "61FA286137BD4E113DFEC6EE0BA5BEBD", "name": "FreeBSD 10", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Others", "os": "FreeBSD10", "os_version": "FreeBSD", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "31CEEE904708A5354F0D119CA3E1C3D7", "name": "FreeBSD 10", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Others", "os": "FreeBSD10", "os_version": "FreeBSD", "os_architecture": 32, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "18AE0A62911AD1CC145DF6A4D92BD354", "name": "Red Hat 7", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "RedHat7", "os_version": "RedHat", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "9FB167C5495AC815C3A3CBF273123879", "name": "w2012r2datacenter64std+SQL2014express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "31433BA1341A3EEED81ACE7DDDFA37BD", "name": "w2012r2datacenter64std+SQL2014web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "1921A315152482071F4B36E4D141EC8A", "name": "w2012r2datacenter64std+SQL2014std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "1B53FF641F19052859DA26CF799CC9D2", "name": "w2008r2datacenter64std+SQL2014express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "D5FA67DFD00DB9F4FBFC363374B93306", "name": "w2008r2datacenter64std+SQL2014web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Web Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "100E5AC8FA0690EBD9AE6937E5587991", "name": "w2008r2datacenter64std+SQL2014std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Standard Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "8B7DE48FF94B2407B7455B76F608F8CD", "name": "w2012r2datacenter64min+SQL2014express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "BCA00B58DD301EBC649FEAC96377E7DC", "name": "w2012r2datacenter64min+SQL2014web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "0398F06DE0FF331539842ADFB96279AB", "name": "w2012r2datacenter64min+SQL2014std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "F61E08E34CA0B44904A331A83EED6AE2", "name": "w2008r2datacenter64min+SQL2014express", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "729F1DB5BBB2EEC6EBC6651ABB19AE85", "name": "w2008r2datacenter64min+SQL2014web", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Web Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "1EAFCF5E37C3331590AC7E3266ECF12E", "name": "w2008r2datacenter64min+SQL2014std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2008R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2014 Standard Edition" }, { "name": "Windows 2012 Datacenter" } ], "version": null, "categories": [] }, { "id": "0735AA79194B274179A8FADE62208FED", "name": "Solaris 10", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Others", "os": "Solaris10", "os_version": "Solaris", "os_architecture": 32, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "E8F733BBB99D1313652F5690D87B0E77", "name": "Solaris 10", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Others", "os": "Solaris10", "os_version": "Solaris", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "F7E14983198CDC318267A5D0DEA330D8", "name": "centos7-64std+cpanel", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "cPanel 11" } ], "version": null, "categories": [] }, { "id": "6C902E5899CC6F7ED18595EBEB542EE1", "name": "Docker", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 30, "licenses": [], "version": null, "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "8ED1E267A9E1367F731B4AE624FDF1C0", "name": "W2012R2DATACENTER64STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "35A31E95A968545236B2584771D3B8CA", "name": "W2012R2DATACENTER64STD+SQL2012EXPRESS+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "698D35B35E01506574B4DA83A095C444", "name": "W2012R2DATACENTER64STD+SQL2012WEB+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2012 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "2E79303E264846125F7AD6877AE155B5", "name": "W2012R2DATACENTER64STD+SQL2012STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2012 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "F38F08898A742CF3046F8F825C9B199A", "name": "UBUNTU1404-64STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu14.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "AAC4EF1852B735A52D8D531381B81500", "name": "CENTOS7-64STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "051BC8159D2014F2B2D333E5D9BB671B", "name": "DEBIAN7-32STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "D04943D702F82A1FC29B42FD635ACB51", "name": "DEBIAN7-64STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "E5712C6F4ACFC3BCADFBBA2C0681E629", "name": "UBUNTU1204-32STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu12.04", "os_version": "Ubuntu", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "E935C4BAA226D7179FF3EB753B4F9323", "name": "UBUNTU1204-64STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu12.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "A94D4970684581C3CFC135AE80E1FC39", "name": "W2012R2DATACENTER64STD+SQL2014EXPRESS+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "BD727924A1E53F7D3B9D7B811F339D6B", "name": "W2012R2DATACENTER64STD+SQL2014WEB+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2014 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "95736E72DD3FFF9A825FF17ABBB96671", "name": "W2012R2DATACENTER64STD+SQL2014STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2014 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "C572494C271ED64142E5FD93E084BBFC", "name": "CentOS 6", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "2D593C41B3EB2BA345AFE806A5BA41A3", "name": "CentOS 6", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 32, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "5EDF485861FB263DDBB7C04867346A6E", "name": "Plesk", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "12.5", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE", "POPULAR" ] }, { "id": "96D5CEB497043FD54E834DEC4B8FF70A", "name": "cPanel", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [ { "name": "cPanel 11" } ], "version": null, "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "EAB1D06D1B78654A6E391FAC48BAA4B1", "name": "Sharelock", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.1.0pre-4-r04", "categories": [ "APPLICATION SECURITY", "PASSWORD MANAGEMENT" ] }, { "id": "2D012C80C31413503F1E31355CAA0240", "name": "WildFly", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "10.0.0-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "CACF27D3256071F13E471FCF5C25FCF7", "name": "SimpleInvoices", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2013.1.beta.8-3", "categories": [ "ACCOUNTING" ] }, { "id": "A2302EA99E2A7E894277C4CF124F8951", "name": "PROST", "available_datacenters": [ "4EFAD5836CE43ACA502FD5B99BEE44EF" ], "os_family": "Linux", "os": "Ubuntu14.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 40, "licenses": [], "version": null, "categories": [] }, { "id": "CA020E48664C63D5DBA879774B80632C", "name": "KNOPPIX_7.6.1_32BITS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Knoppix 7.6.1", "os_version": "Knoppix", "os_architecture": 32, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "E678D53FF49EA13026C8CAE565373858", "name": "KNOPPIX_7.6.1_64BITS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Knoppix 7.6.1", "os_version": "Knoppix", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "7BCAA13B5B5A9E11B496B3E2A7E49D7B", "name": "Debian 8", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 32, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "590C67467416363FFA6DAEBA939CE9AA", "name": "Debian 8", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "2193D3FE6136ECC25A2BCF5F506478A6", "name": "debian8-32min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 32, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "C4DA59C0E4D5C63E89536ABF309DD942", "name": "debian8-32std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "E9783B668B3E3D3C46A47B68ECA49858", "name": "DEBIAN8-32STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "FF696FFE6FB96FC54638DB47E9321E25", "name": "debian8-64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "868B25F5DDC3E110ACDEF034B1B81863", "name": "debian8-64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "74B24B20E8DC35548B3A11387C1B3BCD", "name": "DEBIAN8-64STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "6D9435667B9BFC6583C9D052F0F1D48B", "name": "ubuntu1604-32min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu16.04", "os_version": "Ubuntu", "os_architecture": 32, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "4871EEE48030E0E5FAE813B780760BCD", "name": "ubuntu1604-32std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu16.04", "os_version": "Ubuntu", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "753E3C1F859874AA74EB63B3302601F5", "name": "ubuntu1604-64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu16.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "4DBFA2D31B1A303A9CE0E4ECF8838FDE", "name": "ubuntu1604-64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu16.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "5FEDF374F19FE3BFA536DBC0660DDB1E", "name": "Publify", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.0-3", "categories": [ "BLOG" ] }, { "id": "A66EC633504CE600B9D659EA28082732", "name": "Squash", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20151209-4", "categories": [ "CODE REVIEW" ] }, { "id": "93DF6BD0351A6E1BF698896F95E8CFE4", "name": "REFINERY CMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-8", "categories": [ "CMS" ] }, { "id": "E08D613211F4CFC7367052614BA0E1E7", "name": "Spree", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.7-2", "categories": [ "E-COMMERCE" ] }, { "id": "3DEF9E1E82F8F14B7AC57595990E2E2E", "name": "OPEN EDX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160414-2", "categories": [ "COLLABORATION", "ELEARNING" ] }, { "id": "E8564D74944AC4F005E8CE951340D849", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.5.2.php56-0", "categories": [ "BLOG", "CMS" ] }, { "id": "49130A36E7961805F0F3494D47724625", "name": "CANVAS LMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2016.04.23.03-1", "categories": [ "ELEARNING" ] }, { "id": "040FBEF43407931C74EE074CCEC759AF", "name": "CENTOS6-64STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "FDB280E565E2CC9D210BBE0F7B688E45", "name": "CENTOS6-32STD+PLESK12.5UNLIMITED", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 32, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": null, "categories": [] }, { "id": "6044F1B4DCAAB9F877ED7BBE2B6F26BE", "name": "TYPO3", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.1.2-0", "categories": [ "CMS" ] }, { "id": "7C48549F3DED9540B7CE75F761C96F62", "name": "PostgreSQL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.5.3-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "D15BA431C4EBE5AAA454892309E69A44", "name": "Redis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.1-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "274A1F47D79E07587939BF90A7845176", "name": "Memcached", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.28-0", "categories": [ "CACHE", "INFRASTRUCTURE" ] }, { "id": "D1C6FCCBA91EDEA95B7F3EA3C4B0F91E", "name": "RabbitMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.3-0", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "332AEAC8F58655EF5C6CFC18BDEAB5BB", "name": "Redmine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.0-1-r05", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "POPULAR", "PROJECT MANAGEMENT" ] }, { "id": "1DDB874AC504E01DF1357D961274BEAE", "name": "OpenProject", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.19-1-r05", "categories": [ "PROJECT MANAGEMENT" ] }, { "id": "F213BAD2BC86F2383656606D1800070E", "name": "CHT1-GB-IMAGE", "available_datacenters": [ "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 64, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 30, "licenses": [], "version": null, "categories": [] }, { "id": "1DC90B8D32CC6DB41FE2ABA027381AEA", "name": "CHT1-DE-IMAGE_20160720", "available_datacenters": [ "4EFAD5836CE43ACA502FD5B99BEE44EF" ], "os_family": "Linux", "os": "Ubuntu16.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 30, "licenses": [], "version": null, "categories": [] }, { "id": "DA40BC2BC45E15117E723E07648AB74C", "name": "CHT1-ES-IMAGE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 30, "licenses": [], "version": null, "categories": [] }, { "id": "FD7D017C0BDD327F3DF206A85699FFF5", "name": "ocPortal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.28-0", "categories": [ "CMS" ] }, { "id": "74FECE8CC262CB31A11F051499B1B30E", "name": "NGINX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.1-1", "categories": [ "INFRASTRUCTURE" ] }, { "id": "F84262237686F207C9E961EEBF7F9A05", "name": "MyBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.8.7-2", "categories": [ "FORUM" ] }, { "id": "FB593AF3F89A8B26B0B6E78F2E232B39", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1.6-2", "categories": [ "E-COMMERCE", "POPULAR" ] }, { "id": "DE91B3C9C152C3A9189F170F9F0A8CD0", "name": "MediaWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.26.3-1", "categories": [ "WIKI" ] }, { "id": "2C0D250864B6EA5D0898A20A950D35ED", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.50-2", "categories": [ "CMS" ] }, { "id": "BAA7787F8931D571A572192E3F663384", "name": "Joomla!", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.0-1", "categories": [ "CMS", "POPULAR" ] }, { "id": "CB7DE59A819E818711A9E339E7C9E618", "name": "ownCloud", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.0-0", "categories": [ "MEDIA SHARING", "POPULAR" ] }, { "id": "DA24D87F4772BFE5FAB3EB112CA66A90", "name": "SugarCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.24-0", "categories": [ "CRM" ] }, { "id": "C86A0850D804AEB0222E486BE3208983", "name": "WORDPRESS MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.5.3-1", "categories": [ "BLOG", "CMS" ] }, { "id": "64D9900D1EA66D4FE4479B8C34EBB88B", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.5.3-1", "categories": [ "BLOG", "CMS", "POPULAR" ] }, { "id": "6AF74675A2203B02E0E2D717CA9EF9B1", "name": "phpBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.9-2", "categories": [ "FORUM" ] }, { "id": "F6363C60A8D4C25107419C6DC9071FEE", "name": "XOOPS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.7.2-3", "categories": [ "CMS" ] }, { "id": "D41BE971AC2EDC441F81972AA56BE301", "name": "OrangeHRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.2-2", "categories": [ "HUMAN RESOURCE MANAGEMENT" ] }, { "id": "91AF83F9EA73478EEC2DA5D11480FD9C", "name": "Mean", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.8-1", "categories": [ "INFRASTRUCTURE" ] }, { "id": "94118CB46246C958A542D5E21AE4098E", "name": "ResourceSpace", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.8-3", "categories": [ "MEDIA SHARING", "PHOTO SHARING", "VIDEO SHARING" ] }, { "id": "D9A859F560AA227DD07488945459DDFF", "name": "Odoo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.20160620-2", "categories": [ "CRM", "ERP", "POPULAR" ] }, { "id": "AC223698D543228BD97BB355112DC887", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.46v-1", "categories": [ "CHAT" ] }, { "id": "41BA5BD5A162B87C5275854CBF3BC4D3", "name": "Moodle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.1-1", "categories": [ "ELEARNING", "POPULAR" ] }, { "id": "2C191B48E1B1E678951CA83C7F14BA01", "name": "Ruby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.1-4", "categories": [ "INFRASTRUCTURE" ] }, { "id": "A20125D799D01E829AB996B73499501F", "name": "Hadoop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.2-1", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "C9C4E5912736CF2928BC412E8FD1DC1E", "name": "EXO PLATFORM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.0-4", "categories": [ "SOCIAL NETWORKING" ] }, { "id": "F823CA021043AE2D08913ED689994F6A", "name": "LET'S CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.4.7-1", "categories": [ "CHAT", "COLLABORATION", "SOCIAL NETWORKING" ] }, { "id": "53133AE1EB34BBD576A17F345CD95467", "name": "JRuby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.2.0-1", "categories": [ "INFRASTRUCTURE" ] }, { "id": "206A0FB72271162B051E7E6B61E0E3B9", "name": "Liferay", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0.1-2", "categories": [ "PORTAL SERVER" ] }, { "id": "3C54989CFAAC3866BA0D09595433B1DF", "name": "Openfire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.2-2", "categories": [ "CHAT" ] }, { "id": "704E8A5FAF76C2AFF2D6B747F2833E51", "name": "Neos", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.6-3", "categories": [ "CMS" ] }, { "id": "169077A5C3977104306F38F8E5799D21", "name": "Noalyss", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.9.0.0-4", "categories": [ "ACCOUNTING" ] }, { "id": "137727284539B72CB5CC594BDA11ACCA", "name": "PROCESSMAKER OPEN SOURCE EDITION", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.1.8-3", "categories": [ "BPM", "COLLABORATION" ] }, { "id": "54627DC0DBFBC1CAEAD9CB65B6335E14", "name": "OpenCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.0.0-2", "categories": [ "E-COMMERCE" ] }, { "id": "7E09821C352A16C055216BF337261172", "name": "OPEN ATRIUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.54-3", "categories": [ "CMS", "PROJECT MANAGEMENT" ] }, { "id": "75E9BF70942168A9F2A184830AD52C1E", "name": "Pootle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.3-1", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "EC1971DE44DDB26B228AAF7E3E09B0F9", "name": "Pimcore", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.1-5", "categories": [ "CMS" ] }, { "id": "9583B74D82356958FA0ECC6919D90336", "name": "phpList", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.5-1", "categories": [ "NEWSLETTER MANAGER" ] }, { "id": "FEB02845D85AA3CC2A044C34EF82990F", "name": "OSQA", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [ "FORUM" ] }, { "id": "B1E51217B6EACE01AAD94DAD749DA7D7", "name": "OXID ESHOP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.8-1", "categories": [ "E-COMMERCE" ] }, { "id": "57DA7F9377430796E2B460A1AB06CA47", "name": "Osclass", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.1-3", "categories": [ "ONLINE CLASSIFIEDS" ] }, { "id": "E0A1463DB2128078D70A1349AE588334", "name": "REPORTSERVER COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.2-2", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "0D8E437D6AC523E1FC861573A02A7003", "name": "RE:DASH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.10.1.1834-2", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "C38F0D74C3229E239CCD5ADBA8219D69", "name": "ProcessWire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.2-3", "categories": [ "CMS" ] }, { "id": "007CB21D4E96A2CB9B793055480CCBCC", "name": "SEO PANEL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.0-2", "categories": [ "ANALYTICS" ] }, { "id": "29CFB2921C4AABECE924C2BCBFF7529E", "name": "Roundcube", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.1.4-4", "categories": [ "EMAIL" ] }, { "id": "F60C3C16A160413FF80BD01141C3996A", "name": "REVIEW BOARD", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.6.1-1", "categories": [ "CODE REVIEW", "DEVELOPER TOOLS" ] }, { "id": "41EFA3047599548686F49E8A703F9272", "name": "SIMPLE MACHINES FORUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.0.12-1", "categories": [ "FORUM" ] }, { "id": "8CB1E54FE149D174B1F74A4B997E5685", "name": "Railo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.1.008-5", "categories": [ "APPLICATION SERVER" ] }, { "id": "A9CBCAD23493DCEABE71ED09AB31174D", "name": "Roller", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.1.2-8", "categories": [ "BLOG" ] }, { "id": "5EEAB74822AFF231207DDBDB11B92934", "name": "SilverStripe", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.4.0-1", "categories": [ "CMS", "FRAMEWORK" ] }, { "id": "0AE06ED19D4FA7BD7B41B799D4B96704", "name": "Sitecake", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.9-4", "categories": [ "CMS" ] }, { "id": "B77B7AEA1DAE36A579A8D81F24E126D2", "name": "Weblate", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5-1", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "2ECD76527ABD16DC6F2BED507912FFFD", "name": "TestLink", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.9.14-4", "categories": [ "DEVELOPER TOOLS", "TESTING" ] }, { "id": "A29E35300D2D6B8DA10498DB8CB08074", "name": "Tracks", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-9", "categories": [ "PLANNING" ] }, { "id": "9F4320B2D44D0FDDC883C4AA7B8F9EA0", "name": "Zurmo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.5-2", "categories": [ "CRM" ] }, { "id": "0D8E3D1102587B91FD1596B9868021D6", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.0.36-2", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "49AB84DBAD6764D59B5111B7DDCF8EE4", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.3.1-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "9DC423C7DA8A0A4FBD1DE6FBA85C17E2", "name": "Trac", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "WIKI" ] }, { "id": "A336C2CFE78C5156ADF556C2F666D1B1", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2.19-5", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "A9AAB71F0A765059E0D6D9274781724D", "name": "Plone", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.2-1", "categories": [ "CMS" ] }, { "id": "C9D63C05556580FE1722776B8E5F48DB", "name": "Magento", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.0-2", "categories": [ "E-COMMERCE", "POPULAR" ] }, { "id": "294D6E256D749277BEF89D1AFEDDB193", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.17-0", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "MOBILE DEVELOPMENT", "POPULAR" ] }, { "id": "FDAF02F6061C87FD39102336F7625831", "name": "LimeSurvey", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160728-0", "categories": [ "POLL MANAGEMENT" ] }, { "id": "232AF8315BCC0E8D9D626192D2BA64FE", "name": "MODX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.1pl-0", "categories": [ "CMS" ] }, { "id": "36A45A12E9214B4DB6B5098A4BD1A451", "name": "Phabricator", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160725-0", "categories": [ "BUG TRACKING", "CODE REVIEW", "PROJECT MANAGEMENT", "WIKI" ] }, { "id": "4639704650A3780F352738601C6989F7", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.16-0", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "04B99791EC464628DD6290698BC0F17C", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7-0", "categories": [ "CRM" ] }, { "id": "26A7389A2DBDDED651EFAA4E3835F377", "name": "Piwik", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.16.2-0", "categories": [ "ANALYTICS" ] }, { "id": "EC8EA218EC5089910C52D91F1E053F3F", "name": "X2ENGINE SALES CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.0.3-0", "categories": [ "CRM" ] }, { "id": "7F3616E0B7610AF28BB4D1E617E6D19F", "name": "NODE IMAGE_20160806", "available_datacenters": [ "908DC2072407C94C8054610AD5A53B8C" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 60, "licenses": [], "version": null, "categories": [] }, { "id": "003CE838ACDF71E5B2D43659A096291D", "name": "IMAGE UPDATED NODEJS", "available_datacenters": [ "908DC2072407C94C8054610AD5A53B8C" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 60, "licenses": [], "version": null, "categories": [] }, { "id": "724F9387EB2A18A75E67C48FB046A173", "name": "IMAGE UPDATED NODEJS", "available_datacenters": [ "908DC2072407C94C8054610AD5A53B8C" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 60, "licenses": [], "version": null, "categories": [] }, { "id": "CC714964F6A27F58A7E47485DE02E8AA", "name": "ActiveMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.14.0-0", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "11B0EC5C951798C72F8DB7B625D196EA", "name": "Akeneo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.20-3-r17", "categories": [ "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "1485D00FBCD691A400E6C43E88807FC7", "name": "ALFRESCO COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "201605-1-r17", "categories": [ "CMS", "DOCUMENT MANAGEMENT", "ECM" ] }, { "id": "AA88C22D5C13568A240A04A3EE6D13C9", "name": "Artifactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.0-1-r17", "categories": [ "BINARY REPOSITORY", "DEVELOPER TOOLS" ] }, { "id": "DFB6F45DE36E4E996D1C682811EF655D", "name": "Ametys", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.7.3-2-r17", "categories": [ "CMS" ] }, { "id": "7B92E60DEF5FF17E7CE4E73F1870ADD7", "name": "Cassandra", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.7-0-r17", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "705518F8C86BCA65295AB7935801A5E8", "name": "Chyrp", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.2-5-r17", "categories": [ "BLOG" ] }, { "id": "2C4C84938FA20C26942E5A7989423307", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.10-0-r17", "categories": [ "CRM" ] }, { "id": "7C631E3D8043517A2BC2680415B1CC71", "name": "Codiad", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.4-2-r17", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "8ACF1E7FC5A48ABFBC72863A1A45CB8C", "name": "CouchDB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1-5-r17", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "07B621A1D899DA27A7C18AAEACE74137", "name": "Coppermine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.5.42-1-r17", "categories": [ "PHOTO SHARING" ] }, { "id": "A81C74469B600C7628029547FFFAD4EA", "name": "concrete5", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.7.5.9-0-r17", "categories": [ "CMS" ] }, { "id": "7DB0DCB9B0769F2C1747F78362C4CA7A", "name": "Discourse", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.5.3-0-r17", "categories": [ "FORUM" ] }, { "id": "B5047C5C0BCBC106B1EBE1A66FE180F0", "name": "DokuWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160626a-1-r17", "categories": [ "WIKI" ] }, { "id": "430CAC94ED76DF72315F3F2F8F27F57D", "name": "Dolibarr", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.3-0-r17", "categories": [ "CRM", "ERP" ] }, { "id": "CD13429CD80B961B1ED99F51487E4B2B", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.1.8-0-r17", "categories": [ "CMS", "POPULAR" ] }, { "id": "C2A1BCC54B015AFDDBF4CAE308CA8B8B", "name": "Elasticsearch", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.5-1-r17", "categories": [ "SEARCH" ] }, { "id": "ABE80BF96BB73D8C50D2C2E59F4E9EC7", "name": "ERPNext", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.27.9-3-r17", "categories": [ "CRM", "ERP" ] }, { "id": "63069668ED8B221957F77E0F55EB0BBE", "name": "EZ PUBLISH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2014.11-4-r17", "categories": [ "CMS" ] }, { "id": "84228C364024B3606C50A65DBE772C62", "name": "Ghost", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.9.0-0-r17", "categories": [ "BLOG" ] }, { "id": "9625D6507B627024369B71B3A53FC6A8", "name": "FAT FREE CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.13.6-9-r17", "categories": [ "CRM" ] }, { "id": "AA7033295AC9D017B372ABE83A893326", "name": "GitLab", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.9.6-0-r17", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "207189765354E2C7DDFDD2D3C38040DF", "name": "Hadoop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.2-1-r17", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "A21A106D20008D432878351CAE872A1D", "name": "HORDE GROUPWARE WEBMAIL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.14-2-r17", "categories": [ "COLLABORATION", "EMAIL" ] }, { "id": "40A54EFAA7E4D2CA3A19D01AC90FCD28", "name": "JasperReports", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.3.0-1-r17", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "4B9E22B093F62EF8FC51A0DC953F3EEE", "name": "JBOSS AS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.2.0-4-r17", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "C38A935EED3E64FDA5E3139BC9DA19D3", "name": "Kafka", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.10.0.1-0-r17", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "729DA11C172C2A6294E8C322486CF15A", "name": "Joomla!", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.2-0-r17", "categories": [ "CMS" ] }, { "id": "2F3714CC0E84CB99EB54CC2538F58172", "name": "LET'S CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.4.7-1-r17", "categories": [ "CHAT", "COLLABORATION", "SOCIAL NETWORKING" ] }, { "id": "1BDD83C2B2F0C31B17A04A01575E36BB", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.46v-1-r17", "categories": [ "CHAT" ] }, { "id": "B0AD4786940840236B08C35EA90885AF", "name": "MODX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.1pl-0-r17", "categories": [ "CMS" ] }, { "id": "F7C18DC4E1B45C71FEC9C47E4A095982", "name": "MyBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.8.7-2-r17", "categories": [ "FORUM" ] }, { "id": "6C291BF1667016BE4A45E972F1760808", "name": "Neos", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.6-3-r17", "categories": [ "CMS" ] }, { "id": "096B56EBB3AF16E23644E97A9083DED6", "name": "NGINX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.1-1-r17", "categories": [ "INFRASTRUCTURE" ] }, { "id": "06D8DDC170731E1E4D53A91D5EA2EA0D", "name": "Noalyss", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.9.0.0-4-r17", "categories": [ "ACCOUNTING" ] }, { "id": "40AAA103CA41D486E20117C5DD66568A", "name": "Odoo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.20160620-2-r17", "categories": [ "CRM", "ERP" ] }, { "id": "854FD08E82BB00EB0097948AFFADBF13", "name": "OrangeHRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.2-2-r17", "categories": [ "HUMAN RESOURCE MANAGEMENT" ] }, { "id": "D231E0C17032F67F2D8691CE1E726A24", "name": "OpenProject", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.19-1-r17", "categories": [ "PROJECT MANAGEMENT" ] }, { "id": "992E0B00B702ADEE9E3AE3B0E2C99868", "name": "Osclass", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.1-3-r17", "categories": [ "ONLINE CLASSIFIEDS" ] }, { "id": "B5807A326C68B38FAA9362ACE08AFC40", "name": "OSQA", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [ "FORUM" ] }, { "id": "3F5FCB4DD7923159B0FD3608E4306C42", "name": "ownCloud", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.0-0-r17", "categories": [ "MEDIA SHARING" ] }, { "id": "D9A49296D136AA64C35001A9698B0052", "name": "OXID ESHOP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.8-1-r17", "categories": [ "E-COMMERCE" ] }, { "id": "E142BF5D5408569E9640A61C330B116C", "name": "Phabricator", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160725-0-r17", "categories": [ "BUG TRACKING", "CODE REVIEW", "PROJECT MANAGEMENT", "WIKI" ] }, { "id": "DB1DC9F88E498BFCFC953A5151442756", "name": "phpBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.9-2-r17", "categories": [ "FORUM" ] }, { "id": "03440FD53C0E1FEB3D8540AA0BBED374", "name": "Pimcore", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.1-5-r17", "categories": [ "CMS", "E-COMMERCE", "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "84ECBB02E2C800C16E2DC3D95FF6C34E", "name": "Piwik", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.16.2-0-r17", "categories": [ "ANALYTICS" ] }, { "id": "E575B3B1D03A59548B46167757BFED5A", "name": "Plone", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.2-1-r17", "categories": [ "CMS" ] }, { "id": "B4BC4F8E0911B59BF5EE28493A1F0818", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1.6-2-r17", "categories": [ "E-COMMERCE" ] }, { "id": "5A2C1381437270EBFEB5DA10C1F62E44", "name": "PROCESSMAKER OPEN SOURCE EDITION", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.1.8-3-r17", "categories": [ "BPM", "COLLABORATION" ] }, { "id": "75B3534710A5B853A6408CA4875DC06D", "name": "ProcessWire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.2-3-r17", "categories": [ "CMS" ] }, { "id": "BDA10DBDB712CCF46832DC1FB4D0A927", "name": "Pootle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.3-1-r17", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "6FEECAD19E36735195BC43EC302A40F6", "name": "phpList", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.5-1-r17", "categories": [ "NEWSLETTER MANAGER" ] }, { "id": "D82E69BE96A658CE9F20307621988AE9", "name": "RabbitMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.5-0-r17", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "EC6CB19716E4C3815D6E381BD9DD48CC", "name": "Publify", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.0-3-r17", "categories": [ "BLOG" ] }, { "id": "8C7AC5833364516F6F658472CAA8B382", "name": "Redis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.3-0-r17", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "DFB169364B2F5AC2D25D14E87E6CE216", "name": "Railo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.1.008-5-r17", "categories": [ "APPLICATION SERVER" ] }, { "id": "CDD88DFFEFC7EE1D8B424EB65EAA0D8B", "name": "Redmine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.0-1-r17", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "PROJECT MANAGEMENT" ] }, { "id": "0F01E141122CB410941492A47CF0B12D", "name": "REPORTSERVER COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.2-2-r17", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "0157F81454776BFBB8D4F5F5839F6E69", "name": "REFINERY CMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-9-r17", "categories": [ "CMS" ] }, { "id": "AB2EE4DB918B602164E3B359F5008346", "name": "ResourceSpace", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.8-3-r17", "categories": [ "MEDIA SHARING", "PHOTO SHARING", "VIDEO SHARING" ] }, { "id": "6F55B7A1CB8165416E72FB4EC4B31E45", "name": "Roller", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.1.2-8-r17", "categories": [ "BLOG" ] }, { "id": "F2196ABDFD64B55573B9F0F926467547", "name": "Roundcube", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.1.4-4-r17", "categories": [ "EMAIL" ] }, { "id": "5E122541ADD7F8C46B90423E61F0CA37", "name": "Ruby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.1-4-r17", "categories": [ "INFRASTRUCTURE" ] }, { "id": "FB7C9FDC9DE754EA14072278BA7B8034", "name": "SEO PANEL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.0-2-r17", "categories": [ "ANALYTICS" ] }, { "id": "C1F702D004852D911D2FC8DD31777A24", "name": "Sitecake", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.9-4-r17", "categories": [ "CMS" ] }, { "id": "808DCE112CB5608E2BB81586C0C2228F", "name": "Spree", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.7-2-r17", "categories": [ "E-COMMERCE" ] }, { "id": "110FED5DC89D9BFBCE7CA6D8375601D8", "name": "Squash", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20151209-4-r17", "categories": [ "CODE REVIEW" ] }, { "id": "24518F1E3047C04B491B5333A712C9E6", "name": "SugarCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.24-0-r17", "categories": [ "CRM" ] }, { "id": "A518ECEC924E6F099BC4EB724C09277C", "name": "TestLink", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.9.14-4-r17", "categories": [ "DEVELOPER TOOLS", "TESTING" ] }, { "id": "8380A0AAE041BB458FE78BF91018B7A4", "name": "Trac", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "WIKI" ] }, { "id": "5899941FA66B700CC78EA06CEBFD7B28", "name": "Tracks", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-9-r17", "categories": [ "PLANNING" ] }, { "id": "6C24674971A1FD051D0C6D2F6E5579B2", "name": "Weblate", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5-1-r17", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "55D16D4D84902505BBCDDDEEFF9BAE17", "name": "Zurmo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.5-2-r17", "categories": [ "CRM" ] }, { "id": "1E66A9D9EDEC0D9324DBF033280B6206", "name": "X2ENGINE SALES CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.0.4-0", "categories": [ "CRM" ] }, { "id": "D0BF11D16DE12DBB2F03B769F997868E", "name": "PostgreSQL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.5.4-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "05B9AE7CE2714F70A8854DADB923E697", "name": "IMAGE UPDATED NODEJS", "available_datacenters": [ "908DC2072407C94C8054610AD5A53B8C" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 32, "os_image_type": null, "type": "MY_IMAGE", "min_hdd_size": 60, "licenses": [], "version": null, "categories": [] }, { "id": "C85BD198EA9364778599592FF39FA049", "name": "HHVM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.9-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "C09108DE96BEAA6184FF366A02E8DE46", "name": "Mean", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.9-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "620FC561D9F94BB0B0146F168EB85136", "name": "Liferay", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0.2-0", "categories": [ "PORTAL SERVER" ] }, { "id": "379CAAB0ED5C4FAFACF9F034A69735CA", "name": "EspoCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.4-0", "categories": [ "CRM" ] }, { "id": "17A060B98D6E7F25707BF6C71F6096A7", "name": "SilverStripe", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.4.1-0", "categories": [ "CMS", "FRAMEWORK" ] }, { "id": "837C3D8111893C0C9964E0DDE7971915", "name": "ocPortal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.29-0", "categories": [ "CMS" ] }, { "id": "1373011804EF4A657035889D895226F6", "name": "CMS MADE SIMPLE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-0", "categories": [ "CMS" ] }, { "id": "18378C6A39E088EE7932D07006A7D20C", "name": "Diaspora", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.5.10.2-0", "categories": [ "SOCIAL NETWORKING" ] }, { "id": "12EC2D018628FDAB2ACCDA4D3FA55ADC", "name": "OPEN ATRIUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.68-0", "categories": [ "CMS", "PROJECT MANAGEMENT" ] }, { "id": "69E015EC1808F640F1F31F3D3526F0A1", "name": "MediaWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.27.1-0", "categories": [ "WIKI" ] }, { "id": "606DBF39FA1D3E9B6FF7E3B7A39752F3", "name": "AbanteCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2.8-0", "categories": [ "E-COMMERCE" ] }, { "id": "DF4F6AB724D6FB458716D651F7394B63", "name": "Openfire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.3-0", "categories": [ "CHAT" ] }, { "id": "409B5E9CCFCA214FC352C5808ABF96C1", "name": "LimeSurvey", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160817-0", "categories": [ "POLL MANAGEMENT" ] }, { "id": "03DC6FF3F27796E757B203CFDF6BD5FE", "name": "Memcached", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.31-0", "categories": [ "CACHE", "INFRASTRUCTURE" ] }, { "id": "5EE33F33187A783EFC9051B4DD9E074A", "name": "XOOPS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.8-0", "categories": [ "CMS" ] }, { "id": "4C91108B31F5F77D709B33241148672D", "name": "APACHE SOLR", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.2.0-0", "categories": [ "INFRASTRUCTURE", "SEARCH" ] }, { "id": "A80FF8BFAFD7A03866B197CE4FB1D486", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.18-0", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "MOBILE DEVELOPMENT" ] }, { "id": "DBE47B145016882FC946689C1BFF8079", "name": "EXO PLATFORM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.0-8", "categories": [ "SOCIAL NETWORKING" ] }, { "id": "41B2AE576124D0747F53715B3A3E252D", "name": "DreamFactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-0", "categories": [ "DEVELOPER TOOLS", "MOBILE DEVELOPMENT" ] }, { "id": "CF684312E2D8ACD884ACE2263E2FD91E", "name": "OPEN EDX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160414-4", "categories": [ "COLLABORATION", "ELEARNING" ] }, { "id": "FB5FADC8EAB7F8560BA94699211EED2E", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "5EFEB640001CE1B7FDC6AEAEFD4F1C29", "name": "TYPO3", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.3.0-0", "categories": [ "CMS" ] }, { "id": "30C78C33F5241ED6E0A30F8EAC650D7A", "name": "OPENSUSE_LEAP-42.1_64BITS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "OpenSuse Leap-42.1", "os_version": "OpenSuse", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "55BD7B087A069AAEE78D5FA36588A519", "name": "ARCHLINUX_2016.06.01-DUAL_64BITS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "ArchLinux 2016.06.01-dual", "os_version": "ArchLinux", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "39725DAAFD90265243241744C29B82F0", "name": "OPENSUSE_LEAP-42.1_64MIN", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "OpenSuse Leap-42.1", "os_version": "OpenSuse", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "FE87E4000FC94A6290599EA813431F9E", "name": "ArchLinux_Rolling_Release_64min", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "ArchLinux Rolling Release", "os_version": "ArchLinux", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "C5A349786169F140BCBC335675014C08", "name": "CoreOS_Stable_64std", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "CoreOS Stable", "os_version": "CoreOS", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "6AB60C7F28CF9D78191697BAA1A46C4F", "name": "Magento", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.1-0", "categories": [ "E-COMMERCE" ] }, { "id": "4A518A867FF37731FE64EF86AC98E3FA", "name": "Pimcore", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.0-0", "categories": [ "CMS", "E-COMMERCE", "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "0A82F54809F6AFC04CA371936D5686AC", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7.4-0", "categories": [ "CRM" ] }, { "id": "83C5B340E8227A5DA52DE1AD33369C9B", "name": "Elasticsearch", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.4.0-0", "categories": [ "SEARCH" ] }, { "id": "9DC8914F60D716DFE6733A761EA93828", "name": "Moodle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.1-2", "categories": [ "ELEARNING" ] }, { "id": "14C799C6DEE937B4317282D1AA126EFA", "name": "Shopware", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.6-0", "categories": [ "CMS", "E-COMMERCE" ] }, { "id": "9BC273C4C7E5980FBA0BA3CD4D55E783", "name": "WORDPRESS MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6-1", "categories": [ "BLOG", "CMS" ] }, { "id": "50E477771DC4AC8C1E93E0796EBC12C8", "name": "RE:DASH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.11.1.2095-0", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "56521A4ED64DD88FA0AF56F086C07C43", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.1-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "99044CEE5F93573A653ACC5225431EB7", "name": "REVIEW BOARD", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.6.1-2", "categories": [ "CODE REVIEW", "DEVELOPER TOOLS" ] }, { "id": "F1A014F8CF538A5262A1F5F8C4BD9FDB", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.0.37-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "0381C291860A658F775DE08A032E8C71", "name": "Sharelock", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.1.0pre-5", "categories": [ "APPLICATION SECURITY", "PASSWORD MANAGEMENT" ] }, { "id": "FFA938A78176DDF7AE790E0C9403741D", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.3.1-1", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "A673C801E3A479A5D63EA44E49D397BB", "name": "JRuby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.5.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "B1425A233077C5D769C19F8FFEA2DFB1", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1.7-0", "categories": [ "E-COMMERCE" ] }, { "id": "B35BB7EA283240172B46A0BB31026D28", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-0", "categories": [ "BLOG", "CMS" ] }, { "id": "BF6461B167C7A61B012BF9010B1EA0B3", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.1.9-0", "categories": [ "CMS" ] }, { "id": "75192D547D0461CDC97253B8857C1F0C", "name": "OpenCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0.2-0", "categories": [ "E-COMMERCE" ] }, { "id": "F910CE211AD2BC859F41403B94C42EBF", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.11-0", "categories": [ "CRM" ] }, { "id": "90151B99F7AFDE6C4328F1950A3C3EC5", "name": "WildFly", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "10.1.0-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "BBE7C30D9C5DDC1CD1BE1E4B309F38AA", "name": "DreamFactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-1", "categories": [ "DEVELOPER TOOLS", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "CBD1BB22D10E960001A75C8BF3D1B768", "name": "NGINX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.1-2", "categories": [ "INFRASTRUCTURE" ] }, { "id": "7BDABE3C41DD3E20D685D8AC36847880", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.47v-0", "categories": [ "CHAT" ] }, { "id": "DAF026809CF1A91F428F9720CBDE4A61", "name": "Moodle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.2-0", "categories": [ "ELEARNING" ] }, { "id": "903AF4782C188C069C661D7FDAAE8227", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.19-0", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "B506755C5F48FA7D2A0D873DF0ED4493", "name": "Ghost", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.10.1-0", "categories": [ "BLOG" ] }, { "id": "F5E8B877B38E2B03BF7E0E47CF9A7EDE", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.22-0", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "35A4FD155BB90DDF64C463D7DD0011EA", "name": "ECLIPSE CHE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.2-0", "categories": [ "COLLABORATION", "DEVELOPER TOOLS" ] }, { "id": "1F542168F6AEDEB8831A8F595C2079D0", "name": "Pimcore", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.1-0", "categories": [ "CMS", "E-COMMERCE", "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "F60FC0CB8526EAD747972C5AFEC1718C", "name": "EspoCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.5-0", "categories": [ "CRM" ] }, { "id": "FB7BCD8FDFEFD68F66EC95929CA2EFC6", "name": "TYPO3", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.3.1-0", "categories": [ "CMS" ] }, { "id": "C8E4E0566D199E2E0F217E3ED8562F4C", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.21-0", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "87C89931FB3CE60F4D5A840471130622", "name": "Codiad", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.5-0", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "CC49145B6893DAC56DF387BD9CE35155", "name": "DreamFactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-2", "categories": [ "DEVELOPER TOOLS", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "015E1594D0FC841719F59EE2B58C0A87", "name": "ResourceSpace", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.9-0", "categories": [ "MEDIA SHARING", "PHOTO SHARING", "VIDEO SHARING" ] }, { "id": "4F7467E3860543E0A8C09CE5304A7354", "name": "APACHE SOLR", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.2.1-0", "categories": [ "INFRASTRUCTURE", "SEARCH" ] }, { "id": "2A96D34A571CFB86E847F6AF6066383C", "name": "OpenProject", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.20-0", "categories": [ "PROJECT MANAGEMENT" ] }, { "id": "0DE02576F5118B72E621C4189C25A655", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.6.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "719124C209CE44E0FDD9704ADC24A16C", "name": "Shopware", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.7-0", "categories": [ "CMS", "E-COMMERCE" ] }, { "id": "3D68AF170B405DEF486951FDE9FC6B8B", "name": "ocPortal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.30-0", "categories": [ "CMS" ] }, { "id": "FA88509561903CD244F4D719111930FB", "name": "WP MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-2", "categories": [ "BLOG", "CMS" ] }, { "id": "230F941F659C727882B23D86B0CEF2F3", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-2", "categories": [ "BLOG", "CMS" ] }, { "id": "F2F1C86F7DFA8D00D2F1DC4563A364F7", "name": "Ghost", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.11.0-1", "categories": [ "BLOG" ] }, { "id": "4D48C7B5DD466847F539E27BA02A8532", "name": "Artifactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.0-2", "categories": [ "BINARY REPOSITORY", "DEVELOPER TOOLS" ] }, { "id": "66564263B7F1A8744DC488D185048333", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-3", "categories": [ "BLOG", "CMS" ] }, { "id": "66AB04CDBA615AA5F60CD6E0D7CB0A52", "name": "WP MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-3", "categories": [ "BLOG", "CMS" ] }, { "id": "0BBA2EA144128ADE93DA73580B734CB2", "name": "HHVM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.9-1", "categories": [ "INFRASTRUCTURE" ] }, { "id": "FD27DA95E73982955F6BD7FC2CF3239A", "name": "AbanteCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2.8-1", "categories": [ "E-COMMERCE" ] }, { "id": "32B0B16C9988E0DF89D8C214FAB2E2CB", "name": "SugarCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.24-1", "categories": [ "CRM" ] }, { "id": "AD9651BEA3F09D826BE1052FEBE83421", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7.4-1", "categories": [ "CRM" ] }, { "id": "02F49EFE3E972965B0E3E8E0CE0ED1B2", "name": "TestLink", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.9.15-1", "categories": [ "DEVELOPER TOOLS", "TESTING" ] }, { "id": "811336E891511883DCFB550C8D0A093C", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.0.M10-1", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "6DB7B9C04829632AB95C790AE3EDE774", "name": "TYPO3", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.3.1-1", "categories": [ "CMS" ] }, { "id": "F5FF86E8EEEC94DA1C40E420824F85A3", "name": "HORDE GROUPWARE WEBMAIL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.14-3", "categories": [ "COLLABORATION", "EMAIL" ] }, { "id": "0EA15A9E181987F9A02E5748CD11AD95", "name": "CouchDB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1-6", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "6F09214E7C7A219901B3A5B9276B4E18", "name": "Chyrp", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.2-6", "categories": [ "BLOG" ] }, { "id": "485C6C5D96CE16A126599622C22E1F09", "name": "Codiad", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.5-1", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "2333D742F6CF201C3F6D9755F542838A", "name": "Sharelock", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.1.0pre-6", "categories": [ "APPLICATION SECURITY", "PASSWORD MANAGEMENT" ] }, { "id": "55C69556A332CCD70D0F869FBDA88E45", "name": "concrete5", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.7.5.9-1", "categories": [ "CMS" ] }, { "id": "5A6E68A10ECEDA3F4B6553E48FE8D9CF", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.11-1", "categories": [ "CRM" ] }, { "id": "DF561A899416171BF4F41C2B4E2337FF", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.3.1-2", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "C4338CA733DFCAA02916F6565D3C55E4", "name": "ALFRESCO COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "201605-2", "categories": [ "CMS", "DOCUMENT MANAGEMENT", "ECM" ] }, { "id": "A3F640404604D33FD444C0E28250E605", "name": "CANVAS LMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2016.04.23.03-2", "categories": [ "ELEARNING" ] }, { "id": "0BF1F3F154DAFD7634966A556BF8864C", "name": "CMS MADE SIMPLE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-1", "categories": [ "CMS" ] }, { "id": "A3995BCEDC91E192E1EA71A4FB74205C", "name": "w2012r2datacenter64min+SQL2016express_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "DD6004F008BEDF3A1313C8BF34CC6D6F", "name": "w2012r2datacenter64min+SQL2016std_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2016 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "51E0E086634F8FC10FE14A5BE56480EB", "name": "w2012r2datacenter64min+SQL2016web_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2016 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "59A47BD0E5B7FEC4428ACD618F59F4D8", "name": "w2012r2datacenter64std+SQL2016express_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "8362DB3921707CD5A82E6785F94CC3FE", "name": "W2012R2DATACENTER64STD+SQL2016EXPRESS+PLESK12.5UNLIMITED_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "D3F03F0A986E284EE694DAB115CCAF9E", "name": "w2012r2datacenter64std+SQL2016std_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2016 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "E049BB25B951285385299614FD1B9D6B", "name": "W2012R2DATACENTER64STD+SQL2016STD+PLESK12.5UNLIMITED_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2016 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "13C42897A0F47333F6F1614BC0F56E27", "name": "w2012r2datacenter64std+SQL2016web_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia SQL Server 2016 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "CB5A3B438AB580B3DD01C535AA1C70D3", "name": "W2012R2DATACENTER64STD+SQL2016WEB+PLESK12.5UNLIMITED_20160415", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2016 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": null, "categories": [] }, { "id": "CF751676613E624750FCE6D9FBDB3DA5", "name": "Trac", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.1.6-6", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "WIKI" ] }, { "id": "138D26AB67933F34FFF19F20D3F0CE08", "name": "Roundcube", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.1.4-5", "categories": [ "EMAIL" ] }, { "id": "25BDDF69B7E4AC14D8A9943006C98ED8", "name": "SEO PANEL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.0-3", "categories": [ "ANALYTICS" ] }, { "id": "51FA4394401E6CC561421925FF406394", "name": "Shopware", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.7-1", "categories": [ "CMS", "E-COMMERCE" ] }, { "id": "2A1B4817980BA87BBB51535A850E40D6", "name": "Roller", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.1.2-9", "categories": [ "BLOG" ] }, { "id": "E6FCB501149C5F34447B7534B0620818", "name": "DokuWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160626a-2", "categories": [ "WIKI" ] }, { "id": "65DA533E7A371007F7CF3637F6EE488D", "name": "SilverStripe", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.4.1-1", "categories": [ "CMS", "FRAMEWORK" ] }, { "id": "36D10833D1269A4A0AAC5FAFC6878B1E", "name": "SIMPLE MACHINES FORUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.0.12-2", "categories": [ "FORUM" ] }, { "id": "9C8F83EDB6D2C2D7A8E62303B9914FFA", "name": "Ghost", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.11.0-2", "categories": [ "BLOG" ] }, { "id": "614B31410B6C25426C5532342079EE5F", "name": "Publify", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.0-4", "categories": [ "BLOG" ] }, { "id": "499D9B4912E9FE23B7412AD128A71904", "name": "MODX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.1pl-1-r26", "categories": [ "CMS" ] }, { "id": "9DCE0411BD55D64288C52041B13F4D42", "name": "Phabricator", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2016.30-1", "categories": [ "BUG TRACKING", "CODE REVIEW", "PROJECT MANAGEMENT", "WIKI" ] }, { "id": "A19D5FAFB06D60C86D99DE7C9901FB6D", "name": "Openfire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.3-1", "categories": [ "CHAT" ] }, { "id": "6D45892CC3E9662983E58E3D87504E93", "name": "OSQA", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [ "FORUM" ] }, { "id": "37C7CE879415DB34012A71E9C3DB8B12", "name": "OpenCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0.2-1", "categories": [ "E-COMMERCE" ] }, { "id": "024CA48EC98EA4288A61CF3A9FB88AC9", "name": "PROCESSMAKER OPEN SOURCE EDITION", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.1.8-4", "categories": [ "BPM", "COLLABORATION" ] }, { "id": "522E5B898051BB9036B020095E2C5BF6", "name": "ActiveMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.14.0-0-r26", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "6FC53E7FD6B0E87ABEECD2C4AC4913C5", "name": "Kafka", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.10.0.1-0-r26", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "FAC87774AA195A103CE53B25C9F45C58", "name": "EXO PLATFORM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.0-9", "categories": [ "SOCIAL NETWORKING" ] }, { "id": "109748035061094F268A221825EE0184", "name": "AbanteCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2.8-1-r26", "categories": [ "E-COMMERCE" ] }, { "id": "7479B1BCD0B133279BBB046552F9CE41", "name": "Akeneo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.20-3-r26", "categories": [ "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "E33A6C4BDACC80210CE75C906DC73912", "name": "ALFRESCO COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "201605-2-r26", "categories": [ "CMS", "DOCUMENT MANAGEMENT", "ECM" ] }, { "id": "7C5C2FFA2BD26B29F4A3A8C7FEF9E51F", "name": "Ametys", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.7.3-3-r26", "categories": [ "CMS" ] }, { "id": "E7D04F791BCD79B9F181395E35136937", "name": "Cassandra", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.7-0-r26", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "C01C0EBFB24718ACD7B6A6FC84E407C4", "name": "Chyrp", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.2-6-r26", "categories": [ "BLOG" ] }, { "id": "586E6422ACF06F7A9B2119DFF370C000", "name": "Artifactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.0-2-r26", "categories": [ "BINARY REPOSITORY", "DEVELOPER TOOLS" ] }, { "id": "9E3166A434D011BFDFECF85D34FEC85D", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.11-1-r26", "categories": [ "CRM" ] }, { "id": "C894255F9F1F7BA5AA87DDE035A0E1E7", "name": "CMS MADE SIMPLE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-1-r26", "categories": [ "CMS" ] }, { "id": "B18FE1A1A217364CC9F650C91FB3D114", "name": "Codiad", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.5-1-r26", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "74A8367BAD5E3B9096B6C1C27229CACA", "name": "concrete5", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.7.5.9-1-r26", "categories": [ "CMS" ] }, { "id": "D2BA96404301AB7863C7D752726D4B09", "name": "DokuWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160626a-2-r26", "categories": [ "WIKI" ] }, { "id": "9CED418F14E2DDCF1DCDAB16F94C6E4E", "name": "Coppermine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.5.42-3-r26", "categories": [ "PHOTO SHARING" ] }, { "id": "BB4CE46CC533C736E75AE69DBECBFAB5", "name": "CouchDB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1-6-r26", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "5FA77ECC752643CB469BBAFB42E1EA60", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.1-1-r26", "categories": [ "INFRASTRUCTURE" ] }, { "id": "4225740C3EE365674EBACC37577B5FBB", "name": "Discourse", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.5.3-1-r26", "categories": [ "FORUM" ] }, { "id": "F8E9CA0DB0B8131162DC57886C9B6FF8", "name": "Diaspora", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.5.10.2-1-r26", "categories": [ "SOCIAL NETWORKING" ] }, { "id": "CAD84CE431231DDFF4B216433A3EFD84", "name": "Dolibarr", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.3-1-r26", "categories": [ "CRM", "ERP" ] }, { "id": "CCA2854F26E5B34BDB0AEE37B0E5AB32", "name": "DreamFactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-4-r26", "categories": [ "DEVELOPER TOOLS", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "A0A955B6ACABC6A6F09B60F794A3FA07", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.1.10-0-r26", "categories": [ "CMS" ] }, { "id": "0A2487C91D6692A1A088DB4B2A2F3FD2", "name": "EspoCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.5-1-r26", "categories": [ "CRM" ] }, { "id": "450F03E34E1C15FE9CBA5E1D9042843B", "name": "ERPNext", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.27.9-4-r26", "categories": [ "CRM", "ERP" ] }, { "id": "7E870AB3935AB7A6BC338BF49FE362D2", "name": "ECLIPSE CHE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.2-1-r26", "categories": [ "COLLABORATION", "DEVELOPER TOOLS" ] }, { "id": "40A0B882ED133494234A21C8027E7CA1", "name": "FAT FREE CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.13.6-10-r26", "categories": [ "CRM" ] }, { "id": "28333E559F9400B4256B76821E3EE216", "name": "EZ PUBLISH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2014.11-4-r26", "categories": [ "CMS" ] }, { "id": "9C1B26C4858D2BF07A32C7988B2107C2", "name": "HORDE GROUPWARE WEBMAIL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.14-3-r26", "categories": [ "COLLABORATION", "EMAIL" ] }, { "id": "A6B5EA365A6A0E5B1B3725C50645B7EA", "name": "JBOSS AS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.2.0-5-r26", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "B647F54413F265AAA636C146E291D9C3", "name": "GitLab", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.9.6-1-r26", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "2F2FF25BA9994A4EDE1DEC165524650E", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.658-3-r26", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "68AB5D93197F6F24ECA9457A8EEDAC44", "name": "HHVM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.9-1-r26", "categories": [ "INFRASTRUCTURE" ] }, { "id": "B48FA6BB24F67D4EDAF7ABD099CFE3C3", "name": "Joomla!", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.2-1-r26", "categories": [ "CMS" ] }, { "id": "70835551BB3D77DA6438365AFFD64ABF", "name": "JRuby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.5.0-1-r26", "categories": [ "INFRASTRUCTURE" ] }, { "id": "A825119DA06B32186F7719811C77C74B", "name": "OPEN EDX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160414-5-r26", "categories": [ "COLLABORATION", "ELEARNING" ] }, { "id": "190733566A7DD7C4870938BA72E12C57", "name": "JasperReports", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.3.0-2-r26", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "FF2244A29705A4E259C61758B679ED0D", "name": "LimeSurvey", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160817-1-r26", "categories": [ "POLL MANAGEMENT" ] }, { "id": "DA72CEFA97A80389E586BCEBFE1EFD41", "name": "Liferay", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0.2-1-r26", "categories": [ "PORTAL SERVER" ] }, { "id": "3B6523A857FE3B0D327D217EA1849017", "name": "LET'S CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.4.7-2-r26", "categories": [ "CHAT", "COLLABORATION", "SOCIAL NETWORKING" ] }, { "id": "C421D8AFCC4952A143BDE93B5CC63A23", "name": "Magento", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.1-1-r26", "categories": [ "E-COMMERCE" ] }, { "id": "8C57186CCCE916F3C63E498F77507680", "name": "Memcached", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.31-1-r26", "categories": [ "CACHE", "INFRASTRUCTURE" ] }, { "id": "C2BADCD828DAFCD3BC8664BE43A8A87D", "name": "Moodle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.2-1-r26", "categories": [ "ELEARNING" ] }, { "id": "DAAC8D4718C161A80B722600A0440914", "name": "MyBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.8.7-3-r26", "categories": [ "FORUM" ] }, { "id": "CDBE5B21E22B6412580DC67664C72291", "name": "Noalyss", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.9.0.0-5-r26", "categories": [ "ACCOUNTING" ] }, { "id": "A9EC52AC8F832E58A09460D2ED0A8DB6", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.7.0-0-r26", "categories": [ "INFRASTRUCTURE" ] }, { "id": "77AE451E1CB946E2627F5D5C885FB896", "name": "NGINX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.1-3-r26", "categories": [ "INFRASTRUCTURE" ] }, { "id": "604B1B4978D7A968E89DFC7C8CB8CC15", "name": "OPEN ATRIUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.68-1-r26", "categories": [ "CMS", "PROJECT MANAGEMENT" ] }, { "id": "5EE93FE704B1287A686FD91761D19FE0", "name": "Neos", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.6-4-r26", "categories": [ "CMS" ] }, { "id": "D2C77CFB66243427F1AF1EC8A97E9F5B", "name": "ocPortal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.30-1-r26", "categories": [ "CMS" ] }, { "id": "F8B64744559AF5E578325F0416D5D02F", "name": "MediaWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.27.1-1-r26", "categories": [ "WIKI" ] }, { "id": "1BAF3057A7D51F5357A38CEB3C2D8EC6", "name": "OrangeHRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.2-3-r26", "categories": [ "HUMAN RESOURCE MANAGEMENT" ] }, { "id": "E48559090D8E7DD4B07D8CC7659BA40D", "name": "Osclass", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.1-4-r26", "categories": [ "ONLINE CLASSIFIEDS" ] }, { "id": "4B9827C6362B5CFD1D7333B4944A707E", "name": "OpenProject", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.20-0-r26", "categories": [ "PROJECT MANAGEMENT" ] }, { "id": "CD04664F04CE734E4A7A416C1DA72827", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.22-0-r26", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "E25BD5D06B90B8DCE18C9A274878E98D", "name": "OXID ESHOP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.8-2-r26", "categories": [ "E-COMMERCE" ] }, { "id": "15FB054795A16876B439FAC22617DE5F", "name": "phpBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.9-3-r26", "categories": [ "FORUM" ] }, { "id": "C874DF05EB7963D3D8A108083D82450C", "name": "phpList", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.5-2-r26", "categories": [ "NEWSLETTER MANAGER" ] }, { "id": "D622FF6671FC31C5A8BB6C2DA96F006F", "name": "ownCloud", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.1-0-r26", "categories": [ "MEDIA SHARING" ] }, { "id": "A4412F4FBE84001FDB6C7C393F7D58AE", "name": "Pimcore", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.1-1-r26", "categories": [ "CMS", "E-COMMERCE", "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "944573F3F14219FE74E262BEC37FF026", "name": "Plone", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.2-2-r26", "categories": [ "CMS" ] }, { "id": "6F8CFB4086E728B1C4CA4F61BDB6202A", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1.7-1-r26", "categories": [ "E-COMMERCE" ] }, { "id": "5B92154253C2539E3DDC74647D59E342", "name": "ProcessWire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.2-4-r26", "categories": [ "CMS" ] }, { "id": "8C643C5C69FE463A2E27331452C9FF07", "name": "Pootle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.3-2-r26", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "50131C55AE9E8AAFA4A42E3C1100CD55", "name": "RE:DASH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.11.1.2095-1-r26", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "12C7C258B191F84783CC112B025516D3", "name": "RabbitMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.5-1-r26", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "C870ADC95648D0519BF18997F00C4C18", "name": "Redmine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.0-2-r26", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "PROJECT MANAGEMENT" ] }, { "id": "E576784F8E28096070D5E549A37C4566", "name": "Railo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.1.008-6-r26", "categories": [ "APPLICATION SERVER" ] }, { "id": "2421422B9BD58E7AF09B3C8FB5311279", "name": "REFINERY CMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-10-r26", "categories": [ "CMS" ] }, { "id": "BD72E2EC5BF93DE7E361B884BDC23F2E", "name": "REPORTSERVER COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.2-3-r26", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "9BC57EEB364E74DF1914E4D64F99A973", "name": "ResourceSpace", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.9-1-r26", "categories": [ "MEDIA SHARING", "PHOTO SHARING", "VIDEO SHARING" ] }, { "id": "20A7D9C7F5DD761858AD93A3AA33EE81", "name": "REVIEW BOARD", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.6.1-3-r26", "categories": [ "CODE REVIEW", "DEVELOPER TOOLS" ] }, { "id": "8F3CE0757B455CE5FEA2ABA4B26567BF", "name": "Roundcube", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.1.4-5-r26", "categories": [ "EMAIL" ] }, { "id": "74EE53B233FF5917CC50F824D081FD00", "name": "Sharelock", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.1.0pre-6-r26", "categories": [ "APPLICATION SECURITY", "PASSWORD MANAGEMENT" ] }, { "id": "449E69D0978086679A33CC18D087E17E", "name": "Ruby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.1-5-r26", "categories": [ "INFRASTRUCTURE" ] }, { "id": "DF88FD8F7444603D8FF3EFCE77A7935C", "name": "Roller", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.1.2-9-r26", "categories": [ "BLOG" ] }, { "id": "8475038A28FA128E4E9ED7F29A1292A1", "name": "SilverStripe", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.4.1-1-r26", "categories": [ "CMS", "FRAMEWORK" ] }, { "id": "89E75566C86760F7EAB776916441D8D2", "name": "SEO PANEL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.0-3-r26", "categories": [ "ANALYTICS" ] }, { "id": "B87CDB8F374A62D1EA4BECBC7E135853", "name": "Sitecake", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.9-5-r26", "categories": [ "CMS" ] }, { "id": "6B2E9B6F3A78DE4EAFE6618D5B8D921D", "name": "APACHE SOLR", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.2.1-1-r26", "categories": [ "INFRASTRUCTURE", "SEARCH" ] }, { "id": "09E3DB12384FB854754213FFC77DE482", "name": "SugarCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.24-1-r26", "categories": [ "CRM" ] }, { "id": "921F26DEF65CB786A7B2C8C485C62E1F", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7.5-0-r26", "categories": [ "CRM" ] }, { "id": "CF272C4B3FFC034C64F9C738F2C63B7C", "name": "Spree", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.7-2-r26", "categories": [ "E-COMMERCE" ] }, { "id": "9978BB99D8F6544B980DB71A113F3F99", "name": "Squash", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20151209-4-r26", "categories": [ "CODE REVIEW" ] }, { "id": "5588E8E57B717EC72263C14EF0E9D598", "name": "TYPO3", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.3.1-1-r26", "categories": [ "CMS" ] }, { "id": "7B578C5853BBE2D0665503AB117F7581", "name": "Weblate", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5-2-r26", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "554DB66973A0E95243E328D7F5576127", "name": "WildFly", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "10.1.0-1-r26", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "E49BED8A0D73E752152C85DC3C129B1F", "name": "Tracks", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-10-r26", "categories": [ "PLANNING" ] }, { "id": "EA6C685C7D38CCDAC69F26575D6484C7", "name": "X2ENGINE SALES CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.0.4-1-r26", "categories": [ "CRM" ] }, { "id": "33755C6E102CD1682E0699D2E7587AF3", "name": "Zurmo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.5-3-r26", "categories": [ "CRM" ] }, { "id": "BAEE8A473FA43661825BA06AE51E00E2", "name": "XOOPS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.8-1-r26", "categories": [ "CMS" ] }, { "id": "6631A1589A2CC87FEA9B99AB07399281", "name": "Plesk", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE", "POPULAR" ] }, { "id": "85BD36869EC98AC0B07EE495D27EBF54", "name": "Plesk", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [] }, { "id": "C937934FFFF33ED2E4F0439FE2B01074", "name": "WP MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-4", "categories": [ "BLOG", "CMS" ] }, { "id": "9E6E9411145EC35CF40923492BDBCE6D", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-4", "categories": [ "BLOG", "CMS" ] }, { "id": "50BE5047022F1FCD059BF2222D95C15A", "name": "Redis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.4-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "F241D580B2955DC91865C87665AF3D4F", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.48v-0", "categories": [ "CHAT" ] }, { "id": "21A470E06662A886405432183217B088", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.3.2-0", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "62D6A1BD29DBECC7F753E64B95735075", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.24-0", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "8F6E8AE549F9D545CD0FA27AFCEF2E67", "name": "Elasticsearch", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.4.1-0", "categories": [ "SEARCH" ] }, { "id": "287F758A243DE44F2A1FFF0F942C133E", "name": "Odoo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.20160620-3", "categories": [ "CRM", "ERP" ] }, { "id": "A3916E8922C68CAF6F66DF6C055AC98D", "name": "Dolibarr", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.1-0", "categories": [ "CRM", "ERP" ] }, { "id": "C2A2E81D7E578FCE1CCC8A6168B674A1", "name": "EZ PUBLISH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2014.11-5", "categories": [ "CMS" ] }, { "id": "DFE58E41D26BAE94FC4268C9066FE839", "name": "Mean", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.10-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "0900040FB9B32C0CB2177DA83DE8C596", "name": "OpenProject", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.0.4-0", "categories": [ "PROJECT MANAGEMENT" ] }, { "id": "4B222A6379A5A394CD823165F2A18BC0", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.2-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "DB2814CA4DD9167D5758D8384ED32874", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.12-0", "categories": [ "CRM" ] }, { "id": "15BA7101912E24D4A23F2897ABA73323", "name": "Kafka", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.10.0.1-1", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "FE4E2E7A6B8EA38A7B1839BEB767A67B", "name": "ActiveMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.14.1-1", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "EF5ABBAB3F35D8F547F14620B023368C", "name": "Shopware", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.8-0", "categories": [ "CMS", "E-COMMERCE" ] }, { "id": "FF6FE275C0D0D3F408E37F4D1B19D496", "name": "Piwik", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.16.5-0", "categories": [ "ANALYTICS" ] }, { "id": "439A6D7EC2D7A3ED853EACCC5866735A", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.51-0", "categories": [ "CMS" ] }, { "id": "BDFBD8E74D32C7DE68371E4D934F9018", "name": "PostgreSQL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.6.0-1", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "E786E2D4A3DDF37A0AB43E653D8E07FF", "name": "PROCESSMAKER OPEN SOURCE EDITION", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1-0", "categories": [ "BPM", "COLLABORATION" ] }, { "id": "7A47E863F8E87F483AB514DE6CC2B887", "name": "Akeneo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.3-0", "categories": [ "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "C5559C10A3F42C222F073678802BB8E7", "name": "Squash", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20151209-5", "categories": [ "CODE REVIEW" ] }, { "id": "D2A60C479A551F5FF020FBDE925B0585", "name": "DreamFactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-5", "categories": [ "DEVELOPER TOOLS", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "4555879BA095784F5041BB16FD85C7FB", "name": "Cassandra", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "78C7F86CB11A65B3A2FFB4209BAA099A", "name": "Elasticsearch", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.4.1-1", "categories": [ "SEARCH" ] }, { "id": "4C3199325A7C8379069475AE9E806304", "name": "NGINX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.1-4", "categories": [ "INFRASTRUCTURE" ] }, { "id": "DBB877489986CC2E9724AA0DAEFB5A1D", "name": "Ghost", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.11.1-1", "categories": [ "BLOG" ] }, { "id": "F3489789EE360F2E0DC7DD8A3FCC0B6B", "name": "APACHE SOLR", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.2.1-2", "categories": [ "INFRASTRUCTURE", "SEARCH" ] }, { "id": "6EE79C7280841BFEF7025CE6C0B6DF69", "name": "ownCloud", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.1-1", "categories": [ "MEDIA SHARING" ] }, { "id": "8CD76029C54B67DF75F4ECE45BF7EA2C", "name": "Mean", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.10-1", "categories": [ "INFRASTRUCTURE" ] }, { "id": "EE60DD9CB8FC0C2BAAC38C137A7B8647", "name": "Magento", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.1-2", "categories": [ "E-COMMERCE" ] }, { "id": "BCC858E31C52BEAB5E128B27C2DDBDDD", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.0.37-2", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "4ED9CDACC24CF31F61B40BF2424929EC", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.658-4", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "03946C500881466B8E3A58CB58256088", "name": "Moodle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.2-2", "categories": [ "ELEARNING" ] }, { "id": "80EB2291B7A3060F610626B4EA2D9150", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.50v-0", "categories": [ "CHAT" ] }, { "id": "5D01A0C474523730E86E53E3EB8F1AB2", "name": "X2ENGINE SALES CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5-0", "categories": [ "CRM" ] }, { "id": "36CE5BB8488C8324C2EA7A14B12B5E14", "name": "Redmine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.1-0", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "PROJECT MANAGEMENT" ] }, { "id": "C1565D439CCB13BF213B463C050384A4", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.0.M11-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "8C1922EF80B8154B911E752D4B783F27", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.0.38-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "709C20286041E201EC7CBF9C500D9FC5", "name": "GitLab", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.12.6-0", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "E73BED20AB0CBABFC0C8500CAF19F13A", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.26-0", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "790666C6069E1CB028BB168E81D44231", "name": "Trac", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2rc1-0", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "WIKI" ] }, { "id": "218C1354E4A57FFC7190B71F4A02152B", "name": "debian8-64std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian8", "os_version": "Debian", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [] }, { "id": "CE6E8189E50A5CE8ABAA6A736B32C922", "name": "debian7-64std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Debian7", "os_version": "Debian", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [] }, { "id": "4963BBC25A4E297E59504D0D155E866A", "name": "ubuntu1604-64std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu16.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [] }, { "id": "5EF10B5B04FF47B2C973E03C86C90146", "name": "ubuntu1404-64std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu14.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [] }, { "id": "EA16F934113430299C192D18FB4A955F", "name": "ubuntu1204-64std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Ubuntu12.04", "os_version": "Ubuntu", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [] }, { "id": "C9E49D5ECFBE559B51D2AF4300F55B60", "name": "centos6-64std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos6", "os_version": "Centos", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 20, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" } ], "version": "Onyx", "categories": [] }, { "id": "ACA2989FEFD28042134170C39A593539", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-5", "categories": [ "BLOG", "CMS" ] }, { "id": "FE4A991E5E05C3F692DD7FED33BB54CC", "name": "Joomla!", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.4-0", "categories": [ "CMS" ] }, { "id": "2D18E0FE584505D31A1B0B0ADC4D8E76", "name": "Liferay", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0.2-1-r27", "categories": [ "PORTAL SERVER" ] }, { "id": "D40845DB28FDF6DE554219E71C753FEC", "name": "TYPO3", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.3.1-1-r27", "categories": [ "CMS" ] }, { "id": "887ACA72848DEDC26AC2F533E116E9FD", "name": "Akeneo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.4-0-r27", "categories": [ "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "1F647C54B53835475AB2F8B8984430D4", "name": "ALFRESCO COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "201605-2-r27", "categories": [ "CMS", "DOCUMENT MANAGEMENT", "ECM" ] }, { "id": "D0C0316634C4BFC185756CB9618A498A", "name": "Ametys", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.7.3-3-r27", "categories": [ "CMS" ] }, { "id": "57DDAB5E1C180E9C518466CB5A4397CB", "name": "Artifactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.0-2-r27", "categories": [ "BINARY REPOSITORY", "DEVELOPER TOOLS" ] }, { "id": "A8DA08CB599EB513B2B44248AFE7C805", "name": "ActiveMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.14.1-1-r27", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "EA9000EEA297CC8A8D0A315937E683BB", "name": "AbanteCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2.8-1-r27", "categories": [ "E-COMMERCE" ] }, { "id": "51D50EEFC90F9BDA2F46C38F74E45516", "name": "Cassandra", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9-1-r27", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "FE7960BADDAD5492775FDC7DCCBA44C4", "name": "CANVAS LMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2016.04.23.03-2-r27", "categories": [ "ELEARNING" ] }, { "id": "83EE5C89977B4ADE9929AD49CBC455FD", "name": "Chyrp", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.2-6-r27", "categories": [ "BLOG" ] }, { "id": "D0075666D41915899F45E2D68B8685C4", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.12-0-r27", "categories": [ "CRM" ] }, { "id": "913669D746B522935A52BBD1D6BE9EE1", "name": "CMS MADE SIMPLE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-1-r27", "categories": [ "CMS" ] }, { "id": "789B9F3C11425A29B741E41D14200614", "name": "Codiad", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.5-1-r27", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "6D1C69BD68472AA786ADDF050767C581", "name": "concrete5", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.7.5.9-1-r27", "categories": [ "CMS" ] }, { "id": "36059005F111DE5C274DFEAA1455F523", "name": "Coppermine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.5.44-0-r27", "categories": [ "PHOTO SHARING" ] }, { "id": "28CCD249C6E06994B2AD27AF3508C77B", "name": "CouchDB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1-6-r27", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "F58291DF0E75F69A782CC133A54CBA1A", "name": "Diaspora", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.5.10.2-1-r27", "categories": [ "SOCIAL NETWORKING" ] }, { "id": "D2FD5127D37D16B6A2BE642E26BEB21C", "name": "Discourse", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.5.3-1-r27", "categories": [ "FORUM" ] }, { "id": "93C18F17AAC1A1FC0846CB1E4FCC1A38", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.2-0-r27", "categories": [ "INFRASTRUCTURE" ] }, { "id": "36F4101089D6D56CA5F2BCE9F3D566A0", "name": "DokuWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160626a-2-r27", "categories": [ "WIKI" ] }, { "id": "BDA26ED7A0563704E0689AA9566EEA94", "name": "Dolibarr", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.1-0-r27", "categories": [ "CRM", "ERP" ] }, { "id": "BA390D602BCB8259245489D2073E0F70", "name": "DreamFactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.1-0-r27", "categories": [ "DEVELOPER TOOLS", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "073E21D844CD8AE7D5E85A88E5B0ADA6", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.1-0-r27", "categories": [ "CMS" ] }, { "id": "5F8D1EAE09CFE38D07E6F8A300F41944", "name": "ECLIPSE CHE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.2-1-r27", "categories": [ "COLLABORATION", "DEVELOPER TOOLS" ] }, { "id": "B6482A7609A16457CC0128A9F593F402", "name": "Elasticsearch", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.4.1-1-r27", "categories": [ "SEARCH" ] }, { "id": "0A40E20C114748BCACA4122691EC5B01", "name": "ELK", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.2-0-r27", "categories": [ "ANALYTICS" ] }, { "id": "A7542A75CCBA7EA033BD89C37C5EAFBA", "name": "ERPNext", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.27.9-4-r27", "categories": [ "CRM", "ERP" ] }, { "id": "D4D15CA145236B2D46676E06A69E46BC", "name": "EspoCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.7-0-r27", "categories": [ "CRM" ] }, { "id": "1A30D003A8F9F136F2F7076BBB00A10A", "name": "OPEN EDX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160414-5-r27", "categories": [ "COLLABORATION", "ELEARNING" ] }, { "id": "75DEED57C5C9D54CDB04F8A59940FA60", "name": "EXO PLATFORM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.0-9-r27", "categories": [ "SOCIAL NETWORKING" ] }, { "id": "F6C75E17378E8C27F277B5AE198BFD83", "name": "EZ PUBLISH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2014.11-5-r27", "categories": [ "CMS" ] }, { "id": "CB55CBAE27AFCFF6AC6873154E2AEA36", "name": "FAT FREE CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.13.6-10-r27", "categories": [ "CRM" ] }, { "id": "1D54D070265F32E1EF7AD44BB078E71B", "name": "Ghost", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.11.2-0-r27", "categories": [ "BLOG" ] }, { "id": "F996523C2BDBBE81AD846E1369B91CED", "name": "HHVM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.9-1-r27", "categories": [ "INFRASTRUCTURE" ] }, { "id": "0602B7ACDE1086E44DAA638B24BF906A", "name": "GitLab", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.12.6-0-r27", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "F304396E14C579C7E36DB7A2E5120225", "name": "HORDE GROUPWARE WEBMAIL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.14-3-r27", "categories": [ "COLLABORATION", "EMAIL" ] }, { "id": "0DCD6E50B4678FB3DB7E2DC3CD84FE64", "name": "JasperReports", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.3.0-2-r27", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "932E95E4ADE7D2E31BB454B2463A206E", "name": "JBOSS AS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.2.0-5-r27", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "A948D1958BDC57E6F6915FF33BA42183", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.658-4-r27", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "93BABCBC16771C224F1A306427A0B2CE", "name": "JRuby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.5.0-1-r27", "categories": [ "INFRASTRUCTURE" ] }, { "id": "8730EDBE19F67FDF19D57DA4F1B8C41E", "name": "Kafka", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.10.1.0-0-r27", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "22A2B2A1939E119F1B4AB25A818AD87E", "name": "LET'S CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.4.7-2-r27", "categories": [ "CHAT", "COLLABORATION", "SOCIAL NETWORKING" ] }, { "id": "E5ED3D517F9F5283E06ED16F8729565D", "name": "LimeSurvey", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160817-1-r27", "categories": [ "POLL MANAGEMENT" ] }, { "id": "260EE6C3D433B76C494A040DC58530D6", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.50v-0-r27", "categories": [ "CHAT" ] }, { "id": "2E992E333015B1078BCFAD091FFB4D7C", "name": "Magento", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.2-0-r27", "categories": [ "E-COMMERCE" ] }, { "id": "A391B4AFEC3240C19B79D143CC99299B", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.3.2-0-r27", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "5B3C79385D2874E64982FF275824DB00", "name": "Mean", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.10-1-r27", "categories": [ "INFRASTRUCTURE" ] }, { "id": "96D09B89D74EB4A4ECC16174B903AFCE", "name": "MediaWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.27.1-1-r27", "categories": [ "WIKI" ] }, { "id": "A45BE7259E8E8E1670654741A4EEF979", "name": "Memcached", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.32-0-r27", "categories": [ "CACHE", "INFRASTRUCTURE" ] }, { "id": "8B0F9491AA8D04AC98DD39E09C34822E", "name": "MODX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.1pl-1-r27", "categories": [ "CMS" ] }, { "id": "135D8FC34657ADCF860A787F63A2D47C", "name": "Moodle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.2-2-r27", "categories": [ "ELEARNING" ] }, { "id": "86555DAC5EF148AC69D31F16AC965FEC", "name": "MyBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.8.8-0-r27", "categories": [ "FORUM" ] }, { "id": "ADAD28FE5E58081523C7BDC2793247D6", "name": "Neos", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.6-4-r27", "categories": [ "CMS" ] }, { "id": "999B2F775295460CEE9A7BCD837F264E", "name": "NGINX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.2-0-r27", "categories": [ "INFRASTRUCTURE" ] }, { "id": "EE010A236F461D48D7AC694DFBE09600", "name": "Noalyss", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.9.0.0-5-r27", "categories": [ "ACCOUNTING" ] }, { "id": "36846B86BA2C748CBEEB6842B0631743", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.9.1-0-r27", "categories": [ "INFRASTRUCTURE" ] }, { "id": "2A265DF040DD4C706847D20C5454EE06", "name": "ocPortal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.31-0-r27", "categories": [ "CMS" ] }, { "id": "A0DF3154DEBE85BF224EB4027ABA260A", "name": "Odoo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.20160620-3-r27", "categories": [ "CRM", "ERP" ] }, { "id": "E1F6187500C04E9271BDECEA3AEE43D1", "name": "OpenCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0.2-1-r27", "categories": [ "E-COMMERCE" ] }, { "id": "2CA5CA407EE4E09BCE78253D8DA1BC1B", "name": "OPEN ATRIUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.68-1-r27", "categories": [ "CMS", "PROJECT MANAGEMENT" ] }, { "id": "98F17B3730FE36F6380C02DEA6F3FEA3", "name": "Openfire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.3-1-r27", "categories": [ "CHAT" ] }, { "id": "E2A891BE5CA77A9ED7ABBB119099FEF9", "name": "OrangeHRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.2-3-r27", "categories": [ "HUMAN RESOURCE MANAGEMENT" ] }, { "id": "2DCC330AB48E2917373ABD965997EBB0", "name": "OpenProject", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.0.4-0-r27", "categories": [ "PROJECT MANAGEMENT" ] }, { "id": "7F2E2EF6CEE47AA376BE134E6107452E", "name": "Osclass", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.1-4-r27", "categories": [ "ONLINE CLASSIFIEDS" ] }, { "id": "0B8EC318B2330E1FE631B891DEDA6E02", "name": "OSQA", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [ "FORUM" ] }, { "id": "6A516CA2A26E77575A22B2C34A297AD4", "name": "ownCloud", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.1-1-r27", "categories": [ "MEDIA SHARING" ] }, { "id": "643A0542807A33BE790DBA85318EAB4E", "name": "OXID ESHOP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.8-2-r27", "categories": [ "E-COMMERCE" ] }, { "id": "46CB70AFB69956F98785CEE2BC974B8C", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.22-0-r27", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "0C05E623FCDDBA29EA0A9510512899B9", "name": "Phabricator", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160725-0-r27", "categories": [ "BUG TRACKING", "CODE REVIEW", "PROJECT MANAGEMENT", "WIKI" ] }, { "id": "FE62077CE6B94E79A64B7ECEC2D36D22", "name": "phpBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.10-0-r27", "categories": [ "FORUM" ] }, { "id": "6BE9421C734A3801D142C71D3D2F1810", "name": "phpList", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.5-2-r27", "categories": [ "NEWSLETTER MANAGER" ] }, { "id": "A4759BD3D10D37A8B23010F49133CC74", "name": "Pimcore", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.1-1-r27", "categories": [ "CMS", "E-COMMERCE", "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "E577C89B9A5A0D976B0131C2781483AE", "name": "Piwik", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.16.5-0-r27", "categories": [ "ANALYTICS" ] }, { "id": "D96BB15FD6E866B9C82DFA34BB033422", "name": "Plone", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.2-2-r27", "categories": [ "CMS" ] }, { "id": "15E7ADAA193205BDD5F4D115340B0546", "name": "PostgreSQL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.6.0-1-r27", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "FEB6268FA8334ABF3A9AB7784A613D2F", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1.7-1-r27", "categories": [ "E-COMMERCE" ] }, { "id": "790DE3B60A9B7199C2EDB8CD6BD8AAF5", "name": "Pootle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.3-2-r27", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "6BC770366E7763FDD918E9308ABD49DF", "name": "PROCESSMAKER OPEN SOURCE EDITION", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1-0-r27", "categories": [ "BPM", "COLLABORATION" ] }, { "id": "C8397CD4162746D83C3A0486E2CEEB53", "name": "ProcessWire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.2-4-r27", "categories": [ "CMS" ] }, { "id": "4B6CE5EAA7450E8D6B8351604E03FD3B", "name": "RabbitMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.5-1-r27", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "B7047F2B421906363D72570D40094FB9", "name": "Railo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.1.008-6-r27", "categories": [ "APPLICATION SERVER" ] }, { "id": "725461607AA2751F3D1FE5254EA26FBA", "name": "RE:DASH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.11.1.2095-1-r27", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "9575916CB986942D48702C94152C1B84", "name": "Redis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.4-0-r27", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "1F44BCE9F0673E7C93A201770E53B8A7", "name": "Redmine", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.3.1-0-r27", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "PROJECT MANAGEMENT" ] }, { "id": "85234119BEEC3A91D632F9D29863B1DE", "name": "REFINERY CMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.5-10-r27", "categories": [ "CMS" ] }, { "id": "31F14B9551930C0279F5D2B11CFFF4CB", "name": "ResourceSpace", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.9-1-r27", "categories": [ "MEDIA SHARING", "PHOTO SHARING", "VIDEO SHARING" ] }, { "id": "9E8E066BEE478C6619680A58F4B8F0DD", "name": "REPORTSERVER COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.2-3-r27", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "A17C9E3597DC024BA811898C74BCF7FF", "name": "REVIEW BOARD", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.7-0-r27", "categories": [ "CODE REVIEW", "DEVELOPER TOOLS" ] }, { "id": "BDB18F5D3C57A8E99168DAB13D7F483F", "name": "Roller", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.1.2-9-r27", "categories": [ "BLOG" ] }, { "id": "8D2D7B64222176F365CB23CBF162AE9B", "name": "Roundcube", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.1.4-5-r27", "categories": [ "EMAIL" ] }, { "id": "92D2F75F76F98BC48DF90758FC0C0E48", "name": "SEO PANEL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.9.0-3-r27", "categories": [ "ANALYTICS" ] }, { "id": "F44D63EF71896A6205A7E09C34E1F651", "name": "Ruby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.1-6-r27", "categories": [ "INFRASTRUCTURE" ] }, { "id": "18FF8DF1B8427E513EBD32AB90493EF7", "name": "Sharelock", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.1.0pre-6-r27", "categories": [ "APPLICATION SECURITY", "PASSWORD MANAGEMENT" ] }, { "id": "EF83E8574E591EE3FF905C4AB570FB17", "name": "Shopware", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.9-0-r27", "categories": [ "CMS", "E-COMMERCE" ] }, { "id": "7DFED272C70ADC7300A22E098830F991", "name": "SilverStripe", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.4.1-1-r27", "categories": [ "CMS", "FRAMEWORK" ] }, { "id": "45A2FE7D8A9D935139FA3DF57AF8359E", "name": "SIMPLE MACHINES FORUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.0.12-2-r27", "categories": [ "FORUM" ] }, { "id": "1E75F8044B150AEFD3D0BDB43C38F552", "name": "Sitecake", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.9-5-r27", "categories": [ "CMS" ] }, { "id": "4CA88FAD5196FA4AF79CBBC148917E35", "name": "APACHE SOLR", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.2.1-2-r27", "categories": [ "INFRASTRUCTURE", "SEARCH" ] }, { "id": "81BE4F35DEF135EFB230B538F076121E", "name": "Spree", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.7-3-r27", "categories": [ "E-COMMERCE" ] }, { "id": "C3586557C1F379796E67F2693680A734", "name": "Squash", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20151209-5-r27", "categories": [ "CODE REVIEW" ] }, { "id": "134A68AE4C2B139CA337D9456B7D37A2", "name": "SugarCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.24-1-r27", "categories": [ "CRM" ] }, { "id": "40A61D89ADF92DBDE26C60C8E2990B06", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7.6-0-r27", "categories": [ "CRM" ] }, { "id": "80F15E41CC65E5CD93F40C34D684FE3D", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.0.38-0-r27", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "71E2388F94E9AC66ECA66B3AC8FF5C7A", "name": "Trac", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "WIKI" ] }, { "id": "414FF7AFDE56BF4A4F3AD82F3983122A", "name": "Weblate", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5-2-r27", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "60CFB9AB25B0A0A2146C09072CF1972E", "name": "WildFly", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "10.1.0-1-r27", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "ED6BE262EECE9854D1B93CF817F52849", "name": "Tracks", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.0-10-r27", "categories": [ "PLANNING" ] }, { "id": "3FA2DAA3F0F6055A34E0E79691BBCCDC", "name": "WP MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.1-5-r27", "categories": [ "BLOG", "CMS" ] }, { "id": "AF1AAECA3C6585302DF92087F07BEC7F", "name": "X2ENGINE SALES CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.0.4-1-r27", "categories": [ "CRM" ] }, { "id": "3DD71526B5DCF8DC1A9E1520D60C478B", "name": "Zurmo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.5-3-r27", "categories": [ "CRM" ] }, { "id": "622DDE4F402A18D3BBC24C037F2FD850", "name": "XOOPS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.8-1-r27", "categories": [ "CMS" ] }, { "id": "E5C9972F3CB07E717421446F0EE70D3B", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.23-0", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "3C633FD3A6819B1930F576A361F716FE", "name": "OPEN ATRIUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.69-0", "categories": [ "CMS", "PROJECT MANAGEMENT" ] }, { "id": "9762649FC3381B57AF9F374A0A24B446", "name": "Hadoop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.3-3", "categories": [ "DEVELOPER TOOLS" ] }, { "id": "A0FE88B4423A950C7178E1E8FEE00544", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1.8-0", "categories": [ "E-COMMERCE" ] }, { "id": "F0DF5BC92C095B06D0D5E007FDDE1211", "name": "TYPO3", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.3.1-2", "categories": [ "CMS" ] }, { "id": "564C2FD4C376935BA280DA2ECAA9872F", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.3.3-0", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "BCB1CE1B7EC5065B24496291271BE232", "name": "Piwik", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.17.0-0", "categories": [ "ANALYTICS" ] }, { "id": "429A6D79872F5E04A79B19F5EB654961", "name": "Dolibarr", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.2-0", "categories": [ "CRM", "ERP" ] }, { "id": "D767E69D919A0E838822E15771279A37", "name": "PostgreSQL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.6.1-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "F0C0DC4B55E0D421096C86A485C79A19", "name": "Redis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.5-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "02FB040E4296670D8C7C3A6C111F011D", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.24-0", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "5BFDAA22D74B49B4531F97706E7ADE4B", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.3-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "6A2ED08D58800058E230DB53552FA74F", "name": "Phabricator", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2016.30-2", "categories": [ "BUG TRACKING", "CODE REVIEW", "PROJECT MANAGEMENT", "WIKI" ] }, { "id": "437F2F5DE57835301986B59BCF2970CF", "name": "REVIEW BOARD", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.7-1", "categories": [ "CODE REVIEW", "DEVELOPER TOOLS" ] }, { "id": "619EF35946BE591CA126B440ABFDDFD9", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.2-0", "categories": [ "CMS" ] }, { "id": "B01C944993286A8B98983B196AA295CD", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.8.16-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "5CF6617FB2EFF1C707CABD28F5991282", "name": "GitLab", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.13.3-0", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "C2EC23DFECCA8ADA9E32C6CDE42916BB", "name": "Magento", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.9.3.0-1", "categories": [ "E-COMMERCE" ] }, { "id": "2BB5AD25BCC62B759E62369E27D79F3D", "name": "w2012r2datacenter64std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "F9F1BD7D594EEE31DE33B721BD9A38F9", "name": "w2012r2datacenter64std+SQL2012express+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "15E803427F8EC58265DFB79B5123A903", "name": "w2012r2datacenter64std+SQL2012std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2012 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "40B468FC2D33E617E976D806EE631AA5", "name": "w2012r2datacenter64std+SQL2012web+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2012 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "8E889505BA5C41A6A2C0699D683517F2", "name": "w2012r2datacenter64std+SQL2014express+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "212755161754FDCB16FE6DECE94D1414", "name": "w2012r2datacenter64std+SQL2014std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2014 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "96EE4D855D8518A0F64AFC0988675555", "name": "w2012r2datacenter64std+SQL2014web+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2014 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "0874EF09C70B5A8EBF1172AB8EB51ECA", "name": "w2012r2datacenter64std+SQL2016express+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "98121579738901E3A1EF79418C3CE098", "name": "w2012r2datacenter64std+SQL2016std+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2016 Standard Edition" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "6095163347569A6C1CEBE4FB7867CA23", "name": "w2012r2datacenter64std+SQL2016web+Plesk_Onyx", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Windows", "os": "Windows2012R2", "os_version": "WindowsDatacenter", "os_architecture": 64, "os_image_type": "STANDARD", "type": "IMAGE", "min_hdd_size": 40, "licenses": [ { "name": "Licencia Plesk 10.4 - Ilimitados dominios" }, { "name": "Licencia SQL Server 2016 Web Edition" }, { "name": "Windows 2012 Standard" } ], "version": "Onyx", "categories": [] }, { "id": "5611A8434E9126B2DF9FC10BF8B53001", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.2-1", "categories": [ "CMS" ] }, { "id": "5D985C749783B1B5FC90113A13BEE119", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.19.2-0", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "A95FF22FE64778EAF451D6A36046A785", "name": "REVIEW BOARD", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.7-2", "categories": [ "CODE REVIEW", "DEVELOPER TOOLS" ] }, { "id": "E5C1B4507CB1DB0430614D5A422604B0", "name": "REPORTSERVER COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.2-4", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "E013D508FBA69633C375C8ECBC03E911", "name": "Odoo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.20160620-5", "categories": [ "CRM", "ERP" ] }, { "id": "93D5909615C950358980532840AD3E86", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7.7-0", "categories": [ "CRM" ] }, { "id": "2114DEE9FEA37BC82AC663D82AE60DFA", "name": "Railo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.2.1.008-7", "categories": [ "APPLICATION SERVER" ] }, { "id": "557B62C5316CDCF628982FBCC6F2D2C1", "name": "ALFRESCO COMMUNITY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "201605-3", "categories": [ "CMS", "DOCUMENT MANAGEMENT", "ECM" ] }, { "id": "5FC292A268C4357CC6FBA2E62E700A35", "name": "ocPortal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.32-0", "categories": [ "CMS" ] }, { "id": "06A0221F7548F4136DEBAADBB6A6F576", "name": "phpList", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.6-0", "categories": [ "NEWSLETTER MANAGER" ] }, { "id": "9C926DA0F08D31F965F195CB1F94DBF4", "name": "ELK", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.2-1", "categories": [ "ANALYTICS" ] }, { "id": "4C9BB43FD892ADF6DB385500FE87CFFF", "name": "Memcached", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.33-0", "categories": [ "CACHE", "INFRASTRUCTURE" ] }, { "id": "B4650612AE04EA3DE7B2EE3546AC9C5B", "name": "Moodle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.1.3-0", "categories": [ "ELEARNING" ] }, { "id": "E81504B51585B56D51C34D0ED38B10C1", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.0.M13-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "5ABBB00C180F72FCA4ECF14871C55F15", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.51v-0", "categories": [ "CHAT" ] }, { "id": "489D5ACFC403D415BD3C97E71A3B7713", "name": "Shopware", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.10-0", "categories": [ "CMS", "E-COMMERCE" ] }, { "id": "F3F4112F6830DBB517A55A45549167E5", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0.73-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "5A6AA19D95342B69FD046E7FF85487F4", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.0.39-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "2A41533352EF507986D2C8C3DE1A50D4", "name": "JRuby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.6.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "50FE1ACC01FB7ED092944B054766AC6A", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.1.9-0", "categories": [ "E-COMMERCE" ] }, { "id": "9189AA239BFE5077CAC5A922B1E30C72", "name": "ELK", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.6.2-2", "categories": [ "ANALYTICS" ] }, { "id": "61DDF7A768E574910D59DDED450C0EEE", "name": "Ruby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.2.6-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "6A3271969FCAE8012759546259A0170C", "name": "Ruby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.2-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "7718D4E06E480AF3287CDBA159638D6E", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.52-0", "categories": [ "CMS" ] }, { "id": "F9892920939E94485B133B8C65649C9C", "name": "Artifactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.0-3", "categories": [ "BINARY REPOSITORY", "DEVELOPER TOOLS" ] }, { "id": "D5F2F4055037BAC658B095EFACB7CC92", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.3-0", "categories": [ "CMS" ] }, { "id": "48E49C57678DB18F168CE0447E780590", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.19.3-0", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "8F63B0C423FAABB9F56B9A226624DC58", "name": "ResourceSpace", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.9-2", "categories": [ "MEDIA SHARING", "PHOTO SHARING", "VIDEO SHARING" ] }, { "id": "8243CF166147E2B2C97B69F03E19AEE6", "name": "Piwik", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.17.1-0", "categories": [ "ANALYTICS" ] }, { "id": "5034C73770C4E17D069E60951601465E", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7.8-0", "categories": [ "CRM" ] }, { "id": "28AE86716FF25A6656A2AF8D5F53981F", "name": "X2ENGINE SALES CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.1-0", "categories": [ "CRM" ] }, { "id": "7A03B4CEBA1FE6DE0B2F1D1148D84D06", "name": "OXID ESHOP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.10.2-0", "categories": [ "E-COMMERCE" ] }, { "id": "4AB0209B3237865B686B653A2921A87E", "name": "LimeSurvey", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20161118-0", "categories": [ "POLL MANAGEMENT" ] }, { "id": "B08F1D394485A25976AE51DA9B69A3BE", "name": "Mean", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.11-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "2FB8FBE70C10C1DD2A23F5B5D64BA7ED", "name": "MODX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.2pl-0", "categories": [ "CMS" ] }, { "id": "4B48D90C05C00850288BC1F11103A9B3", "name": "RabbitMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.6-0", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "761C0A51F741969EEEE854EA7DFE0465", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.13-0", "categories": [ "CRM" ] }, { "id": "444A9048EA382A5931AE5AADF99DBE35", "name": "GitLab", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.14.0-0", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "41E3A00D9D8DCEB2FBA0A6F1D162D039", "name": "Trac", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2-0", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS", "WIKI" ] }, { "id": "B470B00FEC67D6C20A97EABD7BB38691", "name": "Akeneo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.5-0", "categories": [ "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "4FBB834D9DCAC41FB8E86DA188CB406B", "name": "Plone", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.0.6-0", "categories": [ "CMS" ] }, { "id": "3ACDE33A040B8192F0AAE12994D96079", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.3.4-0", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "A0CEA9B96CEB399142012F5964933D7C", "name": "Ruby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.3-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "38F0BFD9C3E66B3B55AD222222E297CC", "name": "Shopware", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.12-0", "categories": [ "CMS", "E-COMMERCE" ] }, { "id": "C97F46107C7A3ED0FFE54326E5B70624", "name": "Noalyss", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.9.1.5-0", "categories": [ "ACCOUNTING" ] }, { "id": "9A4919E81B2381D475219C3B8D90CA8C", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.7.0.2-0", "categories": [ "E-COMMERCE" ] }, { "id": "B51E94C9649C5AE7469EE6FD88D57CB5", "name": "MongoDB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.4.0-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "3D7E41CEF8BB78A4A9EDDCF13E9E9053", "name": "SilverStripe", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.5.0-0", "categories": [ "CMS", "FRAMEWORK" ] }, { "id": "FCE352FFDAD90E07EE9CF870FF850691", "name": "JFROG ARTIFACTORY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.9.0-4", "categories": [ "BINARY REPOSITORY", "DEVELOPER TOOLS" ] }, { "id": "D2B671B044ED0AB98C5DB7842212C11B", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.4-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "E301A548B015F640315033E956E16C7D", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.8.17-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "44734888C6F064D22F18ED86B1612E9F", "name": "MediaWiki", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.28.0-0", "categories": [ "WIKI" ] }, { "id": "D626FF632CD8D805605CE7D527E00FF7", "name": "ocPortal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.33-0", "categories": [ "CMS" ] }, { "id": "32255D1902F87D53FC91D2773E46B349", "name": "Zurmo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.0-0", "categories": [ "CRM" ] }, { "id": "4273B081213D70DCE14E772017BF4908", "name": "GitLab", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.14.3-0", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "E6B7469813798D0629F1FBA1A87466A0", "name": "Openfire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.0.4-0", "categories": [ "CHAT" ] }, { "id": "8E8F0CECA9A0F63428B65ABB1834F345", "name": "Jenkins", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.19.4-0", "categories": [ "CONTINUOUS INTEGRATION", "DEVELOPER TOOLS" ] }, { "id": "85D225790B3348445F16801AA3FA9B48", "name": "Redis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.6-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "6F7CECDD1FC26A602118D4A64B118ECD", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.9.2-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "40A5C3FB1FA1B4A2F569844728E85DCF", "name": "Squash", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20160301-0", "categories": [ "CODE REVIEW" ] }, { "id": "51833FE622E5C1D719E1688214D2890C", "name": "DreamFactory", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.4.1-2", "categories": [ "DEVELOPER TOOLS", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "2FEA5ED118B06C8673F6A03E64BE03A5", "name": "LimeSurvey", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20161205-0", "categories": [ "POLL MANAGEMENT" ] }, { "id": "5C19A6333F441B83FBC5184E605F35AD", "name": "OPEN ATRIUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.611-0", "categories": [ "CMS", "PROJECT MANAGEMENT" ] }, { "id": "BB31325CCBC7B60400177BD20EF0919D", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.14-0", "categories": [ "CRM" ] }, { "id": "CF8050EDB22A91AFEF7F3CCD56F5EFB7", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.4-0", "categories": [ "CMS" ] }, { "id": "6E08092CC8B3BB8BA7B3696F962042F9", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.2.1-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "6AC6A6FD6D09CCABA9D8495297984823", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.53-0", "categories": [ "CMS" ] }, { "id": "4518877E49A04BFEAC16BEE6B894F0E3", "name": "EspoCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.0-0", "categories": [ "CRM" ] }, { "id": "BB210DCBE4A56B5146DF73FE036E5455", "name": "Akeneo", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.6.6-0", "categories": [ "PRODUCT INFORMATION MANAGEMENT" ] }, { "id": "158308EF4AF66D9DF1810F3CBDE6F353", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "D4050B0ADDCFEA2D1C55E5E5AF22FB31", "name": "REFINERY CMS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.5-0", "categories": [ "CMS" ] }, { "id": "5A59D0F511E8A3EA90D64CCB6D13428F", "name": "ActiveMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.14.2-0", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "1C8A34EF47193DDDA4B6A816A6F11370", "name": "WP MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7-0", "categories": [ "BLOG", "CMS" ] }, { "id": "83D8DF2DAA6D865A0996AEE6129CF364", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7-0", "categories": [ "BLOG", "CMS" ] }, { "id": "EF11A41203805797DCD1974D7B9BEF7B", "name": "WordPress", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.php56-0", "categories": [ "BLOG", "CMS" ] }, { "id": "32D0CA8B499940E5C5FECC91D798809C", "name": "WP MULTISITE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.php56-0", "categories": [ "BLOG", "CMS" ] }, { "id": "BFBB161F64F7FFCF65E92E9BA59D249F", "name": "LAMP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.1.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "E07EDABD073B74A2120A19073B2AAF4E", "name": "LAPP Stack", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.1.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "48EC401FE1E042D7ECF1E77E6E08A1EB", "name": "TINY TINY RSS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20161213-0", "categories": [ "NEWS AGGREGATOR" ] }, { "id": "00D896BA4C60E0EE7DA29304784BD8AF", "name": "Mautic", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.4.0-0", "categories": [ "CRM", "EMAIL", "MARKETING AUTOMATION" ] }, { "id": "2000FB68A23FF6946B357C33ABFFCF45", "name": "PARSE SERVER", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.3.1-0", "categories": [ "DEVELOPER TOOLS", "FRAMEWORK", "Middleware", "MOBILE DEVELOPMENT" ] }, { "id": "148A577540578BBA1F4BC0FD87514266", "name": "OroCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.12-0", "categories": [ "CRM" ] }, { "id": "7CAB3EC8A7B05E23A791F64898FB7339", "name": "MySQL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.6.35-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "9F38B5A4EA5E1B047AC82A7DD5B071CA", "name": "LAPP Stack", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0.14-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "51D4F0C6DEB3548F7AF37E0FE89AF64A", "name": "LAMP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0.14-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "F452A101BD2D7BBC5B3C50C426BFFD01", "name": "LAPP Stack", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.6.29-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "2B7F44F10F8FC43235545A20224BF956", "name": "LAMP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.6.29-0", "categories": [ "INFRASTRUCTURE", "POPULAR" ] }, { "id": "3F0573F8D78C7892A6E5B48A99DA4E1B", "name": "Subversion", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.9.5-0", "categories": [ "DEVELOPER TOOLS", "VERSION CONTROL" ] }, { "id": "1A263D2EB4ED1660BF867AEF669B368D", "name": "Mahara", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "16.10.1-0", "categories": [ "COLLABORATION", "ELEARNING", "MEDIA SHARING", "SOCIAL NETWORKING" ] }, { "id": "89AA3CBFD6F4126FC49DD1E338779E24", "name": "TIKI WIKI CMS GROUPWARE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "16.1-0", "categories": [ "CMS", "COLLABORATION", "WIKI" ] }, { "id": "457F2884B4C9325B61DD76D3066EE99B", "name": "Joomla!", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.6.5-0", "categories": [ "CMS" ] }, { "id": "80FE9E61CDFD4478B61E05D45B1833F4", "name": "AbanteCart", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.2.9-0", "categories": [ "E-COMMERCE" ] }, { "id": "0B5BB1BBFB39C28F82DF9804DAF74E61", "name": "Osclass", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.7.0-0", "categories": [ "ONLINE CLASSIFIEDS" ] }, { "id": "FBCDC34C894FAD01D674D32C7034F1BF", "name": "HORDE GROUPWARE WEBMAIL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.2.17-0", "categories": [ "COLLABORATION", "EMAIL" ] }, { "id": "5D0E751261760562752B5F2C2135F076", "name": "SEO PANEL", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.10.0-0", "categories": [ "ANALYTICS" ] }, { "id": "0CB00AF85ACD62669FB67F979CD608C7", "name": "SilverStripe", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.5.1-0", "categories": [ "CMS", "FRAMEWORK" ] }, { "id": "7A28641A3FB33FE2A7FC5C1B45FC8970", "name": "Ametys", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.8.1-0", "categories": [ "CMS" ] }, { "id": "E29812D5DDF322090E1C082CD5A7E7FE", "name": "OPEN ATRIUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.612-0", "categories": [ "CMS", "PROJECT MANAGEMENT" ] }, { "id": "B64AF1A8DC39615CC0E3F6E72FC612A8", "name": "ActiveMQ", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.14.3-0", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "6AACE44F36E2C8E021B3E3C7EAF81A47", "name": "EspoCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.3.1-0", "categories": [ "CRM" ] }, { "id": "12DE0ED80AFC971C9A021D722A7C6B3A", "name": "X2ENGINE SALES CRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "6.5.2-0", "categories": [ "CRM" ] }, { "id": "9F078FEB476BFE64504A7B14178A8EE1", "name": "Kafka", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.10.1.1-0", "categories": [ "DEVELOPER TOOLS", "INFRASTRUCTURE" ] }, { "id": "7B9A2EA0BDBBCDB5A652FE0D07CF2FBF", "name": "OpenERP", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.0-25", "categories": [ "CRM", "ERP" ] }, { "id": "848F2BB1B6B278B4025B3606598123C3", "name": "SimpleInvoices", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2013.1.beta.8-6", "categories": [ "ACCOUNTING" ] }, { "id": "C01A9B6232FFC487039718DD17BE80D7", "name": "Openfire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.1.1-0", "categories": [ "CHAT" ] }, { "id": "C7F49E3713D9AE033539D628D737A577", "name": "Django", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.5-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "5753041EAF625B748F5E73CAB8DFAAC7", "name": "ERPNext", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.2.8-0", "categories": [ "CRM", "ERP" ] }, { "id": "517DCE1A168888C1B2C4C90FF7DCDE62", "name": "MyBB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.8.10-0", "categories": [ "FORUM" ] }, { "id": "9D2C3D429B0D54F252A103E7AB6C7200", "name": "SIMPLE MACHINES FORUM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.0.13-0", "categories": [ "FORUM" ] }, { "id": "2EE86FEC02DB90BC3119E5DA2CF7000A", "name": "JRuby", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.7.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "1A079A22FEA69AF9F8E7C64EA75138E8", "name": "concrete5", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "5.7.5.13-0", "categories": [ "CMS" ] }, { "id": "EEAB5D3832E8C49BBA49340532201FD9", "name": "Memcached", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.4.34-0", "categories": [ "CACHE", "INFRASTRUCTURE" ] }, { "id": "6AF9F672FE5548FD26BCBFEFF9FD26F5", "name": "MongoDB", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.4.1-0", "categories": [ "DATABASE", "INFRASTRUCTURE" ] }, { "id": "68336B1D12E86FB7CEF51E99A2C74910", "name": "NODE.JS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.4.0-0", "categories": [ "INFRASTRUCTURE" ] }, { "id": "347F8594499DE0DCE50DF8510C29478A", "name": "Tomcat", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.0.0.M17-0", "categories": [ "APPLICATION SERVER", "INFRASTRUCTURE" ] }, { "id": "4A76701EC59D8F1604C34A16F98C12D9", "name": "RE:DASH", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "0.12.0.2449-0", "categories": [ "ANALYTICS", "BUSINESS INTELLIGENCE" ] }, { "id": "FB0F1B12B84912918C73FEB83FF2732E", "name": "Pootle", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.7.6-0", "categories": [ "TRANSLATION TOOLS" ] }, { "id": "3E0D2DDAAA01CF64B46CA3DA2A9E9009", "name": "COREOS_1185.3.0_64BITS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "CoreOS 1185.3.4", "os_version": "CoreOS", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] }, { "id": "37DBEACD9864AF6C874692DDBAB9693C", "name": "SuiteCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "7.7.9-1", "categories": [ "CRM" ] }, { "id": "4F9916EAB74EB67E59FFBBFA8FC862A6", "name": "PrestaShop", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.7.0.4-1", "categories": [ "E-COMMERCE" ] }, { "id": "47A1E0F445CF1B3EAF7AA37BFEC99765", "name": "JFROG ARTIFACTORY", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.16.0-1", "categories": [ "BINARY REPOSITORY", "DEVELOPER TOOLS" ] }, { "id": "7254215DF4C13DDDB71ADA583A2559C9", "name": "Mantis", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.0.0-1", "categories": [ "BUG TRACKING", "DEVELOPER TOOLS" ] }, { "id": "6E60B13E6F1D73C2567F1B4B864D75FD", "name": "CiviCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "4.7.15-1", "categories": [ "CRM" ] }, { "id": "A0AC3AB893615424CD2CE6E019EAA50A", "name": "Mautic", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.1-1", "categories": [ "CRM", "EMAIL", "MARKETING AUTOMATION" ] }, { "id": "E3659A006A5181269F9FEBBC336DB1BD", "name": "LIVE HELPER CHAT", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.52v-1", "categories": [ "CHAT" ] }, { "id": "FEFFFEBBDD0468090534DC4F40161EB5", "name": "Mahara", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "16.10.2-1", "categories": [ "COLLABORATION", "ELEARNING", "MEDIA SHARING", "SOCIAL NETWORKING" ] }, { "id": "46ED61EA8D92FAF6DC63EF89FCB2005F", "name": "Drupal", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "8.2.5-1", "categories": [ "CMS" ] }, { "id": "BFB384CE8C41362CE7291CB4BC5AE3AA", "name": "ProcessWire", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.0.42-2", "categories": [ "CMS" ] }, { "id": "64E1B8118643E5CF588E16A825674224", "name": "phpList", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "3.2.7-1", "categories": [ "NEWSLETTER MANAGER" ] }, { "id": "C46867ACABEA255496F239853BB2D8F4", "name": "XOOPS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.8.1-1", "categories": [ "CMS" ] }, { "id": "D5B67125994531E839E4EE7426734D44", "name": "OroCRM", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "1.10.12-2", "categories": [ "CRM" ] }, { "id": "3E6F9D3607CC042AAC0424E3484C3A5E", "name": "LimeSurvey", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "20170116-0", "categories": [ "POLL MANAGEMENT" ] }, { "id": "BBF529CD3F61C3774E80A9E2ECA8BBA8", "name": "ownCloud", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "9.1.3-1", "categories": [ "MEDIA SHARING" ] }, { "id": "237298EF69A39DE18CF515FD9E1D28E8", "name": "MODX", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.5.4pl-1", "categories": [ "CMS" ] }, { "id": "3D089CC7EBB7BAE63F54FDF38E0E6A92", "name": "CMS MADE SIMPLE", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "Centos7", "os_version": "Centos", "os_architecture": 64, "os_image_type": null, "type": "APPLICATION", "min_hdd_size": 20, "licenses": [], "version": "2.1.6-1", "categories": [ "CMS" ] }, { "id": "64BDA5E918D983BF02CAD55C0E738080", "name": "OPENSUSE_LEAP-42.2_64MIN", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "OpenSuse Leap-42.2", "os_version": "OpenSuse", "os_architecture": 64, "os_image_type": "MINIMAL", "type": "IMAGE", "min_hdd_size": 20, "licenses": [], "version": null, "categories": [] }, { "id": "34D8E058F1EE61D056BE1F6704EB18A7", "name": "OPENSUSE_LEAP-42.2_64BITS", "available_datacenters": [ "81DEF28500FBC2A973FC0C620DF5B721", "908DC2072407C94C8054610AD5A53B8C", "4EFAD5836CE43ACA502FD5B99BEE44EF", "5091F6D8CBFEF9C26ACE957C652D5D49" ], "os_family": "Linux", "os": "OpenSuse Leap-42.2", "os_version": "OpenSuse", "os_architecture": 64, "os_image_type": "ISO_OS", "type": "ISO", "min_hdd_size": null, "licenses": [], "version": null, "categories": [] } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/list_load_balancer.json0000664000175000017500000000377413535474530031212 0ustar kamikami00000000000000[ { "id": "B23F1B4F84E983B4FEDD5459E877058A", "name": "My load balancer", "state": "CONFIGURING", "creation_date": "2015-03-03T11:12:00+00:00", "description": "My load balancer description", "ip": "10.5.138.52", "health_check_test": "TCP", "health_check_interval": 40, "health_check_path": null, "health_check_path_parser": null, "persistence": true, "persistence_time": 1200, "method": "ROUND_ROBIN", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "rules": [ { "id": "D7A0A7C445D844848EBB439C28B46183", "protocol": "TCP", "port_balancer": 22, "port_server": 22, "source": "0.0.0.0" }, { "id": "9AE836CDE379EEB361287F07B3300F84", "protocol": "TCP", "port_balancer": 85, "port_server": 85, "source": "0.0.0.0" } ], "server_ips": [], "cloudpanel_id": "LB99AA4_1" }, { "id": "B23F1B4F84E983B4FEDD5459E877058B", "name": "My Load Balancer II", "state": "CONFIGURING", "creation_date": "2015-03-03T11:12:00+00:00", "description": "My load balancer II description", "ip": "10.5.138.53", "health_check_test": "TCP", "health_check_interval": 40, "health_check_path": null, "health_check_path_parser": null, "persistence": true, "persistence_time": 1200, "method": "ROUND_ROBIN", "region": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "rules": [ { "id": "D7A0A7C445D844848EBB439C28B46184", "protocol": "TCP", "port_balancer": 22, "port_server": 22, "source": "0.0.0.0" }, { "id": "9AE836CDE379EEB361287F07B3300F85", "protocol": "TCP", "port_balancer": 9999, "port_server": 9999, "source": "0.0.0.0" } ], "server_ips": [], "cloudpanel_id": "LB99AA4_1" } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/list_monitoring_policies.json0000664000175000017500000000575313535474530032517 0ustar kamikami00000000000000[ { "id": "0F9A1604FC80EB625FC6AEE7394893BE", "name": "Default Policy", "description": "Default Policy Description", "default": 1, "state": "ACTIVE", "creation_date": "2014-10-29T07:52:46+00:00", "email": "", "agent": false, "servers": [ { "id": "E83777750130E1111AA89623B9557CAF", "name": "My Server 1" }, { "id": "CB22C6E0428239348A6B70BAE0D67E66", "name": "My Server 2" }, { "id": "6AAA2BD60813F419DEC8D69C6E4F6477", "name": "My Server 3" } ], "thresholds": { "cpu": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } }, "ram": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } }, "transfer": { "warning": { "value": 1000, "alert": false }, "critical": { "value": 2000, "alert": false } }, "internal_ping": { "warning": { "value": 50, "alert": false }, "critical": { "value": 100, "alert": false } } }, "ports": [], "processes": [], "cloudpanel_id": "mo99AA4_1" }, { "id": "C81F17AF6F6F6717372B79A882B25E92", "name": "My monitoring policy", "description": null, "default": 0, "state": "ACTIVE", "creation_date": "2015-02-26T07:23:42+00:00", "email": "", "agent": true, "servers": [], "thresholds": { "cpu": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } }, "ram": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } }, "disk": { "warning": { "value": 80, "alert": false }, "critical": { "value": 90, "alert": false } }, "transfer": { "warning": { "value": 1000, "alert": false }, "critical": { "value": 2000, "alert": false } }, "internal_ping": { "warning": { "value": 50, "alert": false }, "critical": { "value": 100, "alert": false } } }, "ports": [ { "id": "5F67F2706335AF34FFCDF71E5AF08B2B", "protocol": "TCP", "port": "22", "alert_when": false, "alert": true } ], "processes": [ { "id": "13CF2BEADA60230C6241C81C248F3C4B", "process": "test", "alert_when": false, "alert": true } ], "cloudpanel_id": "mo99AA4_2" } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/list_public_ips.json0000664000175000017500000000265013535474530030565 0ustar kamikami00000000000000[ { "id": "569FA2EC06DD48C9E8635F3384A018DB", "ip": "10.5.138.52", "type": "IPV4", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "assigned_to": { "id": "B23F1B4F84E983B4FEDD5459E877058A", "name": "My load balancer", "type": "LOAD_BALANCER" }, "reverse_dns": null, "is_dhcp": false, "state": "ACTIVE", "creation_date": "2015-03-03T11:12:10+00:00" }, { "id": "6F033A13C3EFCE0FB60783280A118D63", "ip": "10.5.133.191", "type": "IPV4", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "assigned_to": { "id": "BDAF0EC6A36E9E554B80B7E7365821F5", "name": "My Server 1", "type": "SERVER" }, "reverse_dns": null, "is_dhcp": true, "state": "ACTIVE", "creation_date": "2015-05-04T07:21:37+00:00" }, { "id": "39C73A57B33DAF2F9FA1EBEA4C301FCF", "ip": "10.5.138.81", "type": "IPV4", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "assigned_to": { "id": "B23F1B4F84E983B4FEDD5459E877058A", "name": "My load balancer", "type": "LOAD_BALANCER" }, "reverse_dns": null, "is_dhcp": false, "state": "ACTIVE", "creation_date": "2015-03-03T11:13:16+00:00" } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/list_servers.json0000664000175000017500000001173313535474530030127 0ustar kamikami00000000000000[ { "id":"8A7D5122BDC173B6E52223878CEF2748", "name":"Docs Content Ubuntu 16.04-1", "description":"", "status":{ "state":"POWERED_ON", "percent":null }, "datacenter":{ "id":"908DC2072407C94C8054610AD5A53B8C", "country_code":"US", "location":"United States of America" }, "creation_date":"2016-10-03T16:44:34+00:00", "image":{ "id":"4DBFA2D31B1A303A9CE0E4ECF8838FDE", "name":"ubuntu1604-64std" }, "hardware":{ "fixed_instance_size_id":"65929629F35BBFBA63022008F773F3EB", "vcore":1, "cores_per_processor":1, "ram":1, "hdds":[ { "id":"F92B0519D2F9A7EFA961F956C4B381B4", "size":40, "is_main":true } ] }, "ips":[ { "id":"9774FB2A6DCC45733B115A98FCD59CC6", "ip":"50.21.182.126" } ], "alerts":null }, { "id":"E7D36EC025C73796035BF4F171379025", "name":"Docs Content Test Server: CentOS 7-1", "description":"", "status":{ "state":"POWERED_ON", "percent":null }, "datacenter":{ "id":"908DC2072407C94C8054610AD5A53B8C", "country_code":"US", "location":"United States of America" }, "creation_date":"2016-05-05T17:39:50+00:00", "image":{ "id":"B5F778B85C041347BCDCFC3172AB3F3C", "name":"centos7-64std" }, "hardware":{ "fixed_instance_size_id":"65929629F35BBFBA63022008F773F3EB", "vcore":1, "cores_per_processor":1, "ram":1, "hdds":[ { "id":"CDB278D95A92CB4C379A9CAAD6759F02", "size":40, "is_main":true } ] }, "ips":[ { "id":"FDBE99EDD57F8596CBF71B6B64BD0A92", "ip":"62.151.179.99" } ], "alerts":null }, { "id":"DDDC4CCA34AAB08132FA1E40F9FEAC25", "name":"App Dev Server 5", "description":"", "status":{ "state":"POWERED_ON", "percent":null }, "datacenter":{ "id":"908DC2072407C94C8054610AD5A53B8C", "country_code":"US", "location":"United States of America" }, "creation_date":"2016-03-04T21:29:00+00:00", "image":{ "id":"96D5CEB497043FD54E834DEC4B8FF70A", "name":"centos7-64cpanel" }, "hardware":{ "fixed_instance_size_id":"65929629F35BBFBA63022008F773F3EB", "vcore":1, "cores_per_processor":1, "ram":1, "hdds":[ { "id":"5E23F849DD3D6A47615D8EE441FE74CC", "size":40, "is_main":true } ] }, "ips":[ { "id":"E193E9D2213088B3CCE8AD69646CEF18", "ip":"70.35.206.196" } ], "alerts":null }, { "id":"D5C5C1D01249DE9B88BE3DAE973AA090", "name":"Docs Test Server: CentOS 7-2", "description":"", "status":{ "state":"POWERED_ON", "percent":null }, "datacenter":{ "id":"908DC2072407C94C8054610AD5A53B8C", "country_code":"US", "location":"United States of America" }, "creation_date":"2016-10-24T18:13:41+00:00", "image":{ "id":"B5F778B85C041347BCDCFC3172AB3F3C", "name":"centos7-64std" }, "hardware":{ "fixed_instance_size_id":"3D4C49EAEDD42FBC23DB58FE3DEF464F", "vcore":1, "cores_per_processor":1, "ram":0.5, "hdds":[ { "id":"35F875003212E7F083728E4072A188B0", "size":30, "is_main":true } ] }, "ips":[ { "id":"1C79CF2066A5AEEACCB97A68FF41DD00", "ip":"74.208.88.88" } ], "alerts":null }, { "id":"FB1765588A90364835782061CE48BA8E", "name":"Docs Content Test Server Ubuntu 16.04-2", "description":"", "status":{ "state":"POWERED_ON", "percent":null }, "datacenter":{ "id":"908DC2072407C94C8054610AD5A53B8C", "country_code":"US", "location":"United States of America" }, "creation_date":"2016-11-28T21:45:50+00:00", "image":{ "id":"4DBFA2D31B1A303A9CE0E4ECF8838FDE", "name":"ubuntu1604-64std" }, "hardware":{ "fixed_instance_size_id":"65929629F35BBFBA63022008F773F3EB", "vcore":1, "cores_per_processor":1, "ram":1, "hdds":[ { "id":"B45F054C54B5AAE9C45253C6D0A47E74", "size":40, "is_main":true } ] }, "ips":[ { "id":"7D8EA6722183DA82AEDFA09AECE243C4", "ip":"70.35.206.233" } ], "alerts":null } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/list_shared_storages.json0000664000175000017500000000324313535474530031610 0ustar kamikami00000000000000[ { "id": "6AD2F180B7B666539EF75A02FE227084", "size": 200, "state": "ACTIVE", "description": "My shared storage test description", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "cloudpanel_id": "vid35780", "size_used": "0.00", "cifs_path": "vid50995.nas1.lanvid50995", "nfs_path": "vid50995.nas1.lan/:vid50995", "name": "My shared storage test", "creation_date": "2015-05-06T08:33:25+00:00", "servers": [ { "id": "638ED28205B1AFD7ADEF569C725DD85F", "name": "My server 1", "rights": "RW" } ] }, { "id": "4406CE4723BB441C7956E25C51CE8C1B", "size": 50, "state": "ACTIVE", "description": "My shared storage description", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "cloudpanel_id": "vid30534", "size_used": "0.00", "cifs_path": "vid50995.nas1.lanvid50995", "nfs_path": "vid50995.nas1.lan/:vid50995", "name": "My shared storage", "creation_date": "2015-03-17T11:57:48+00:00", "servers": [ ] }, { "id": "1A5418172DD3BD39F8010A6633F1018A", "size": 250, "state": "ACTIVE", "description": null, "cloudpanel_id": "vid19857", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "size_used": "0.00", "cifs_path": "vid50995.nas1.lanvid50995", "nfs_path": "vid50995.nas1.lan/:vid50995", "name": "My shared storage 2", "creation_date": "2015-05-05T09:36:31+00:00", "servers": [ ] } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/load_balancer.json0000664000175000017500000000164713535474530030154 0ustar kamikami00000000000000{ "id": "BD8318616581A9C3C53F94402503230F", "name": "My load balancer", "state": "CONFIGURING", "creation_date": "2015-05-04T07:26:24+00:00", "description": "My load balancer description", "ip": null, "health_check_test": "TCP", "health_check_interval": 40, "health_check_path": null, "health_check_path_parser": null, "persistence": true, "persistence_time": 1200, "method": "ROUND_ROBIN", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "rules": [ { "id": "BCFAF421227674B2B324F779C1163ECB", "protocol": "TCP", "port_balancer": 80, "port_server": 80, "source": "0.0.0.0" }, { "id": "7390C04142800E006FF1B0132FFD8F9A", "protocol": "TCP", "port_balancer": 9999, "port_server": 8888, "source": "0.0.0.0" } ], "server_ips": [], "cloudpanel_id": "LB99AA4_1" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/load_balancer_rule.json0000664000175000017500000000020613535474530031171 0ustar kamikami00000000000000{ "id": "BCFAF421227674B2B324F779C1163ECB", "protocol": "TCP", "port_balancer": 80, "port_server": 80, "source": "0.0.0.0" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/load_balancer_rules.json0000664000175000017500000000046213535474530031360 0ustar kamikami00000000000000[ { "id": "BCFAF421227674B2B324F779C1163ECB", "protocol": "TCP", "port_balancer": 80, "port_server": 80, "source": "0.0.0.0" }, { "id": "7390C04142800E006FF1B0132FFD8F9A", "protocol": "TCP", "port_balancer": 9999, "port_server": 8888, "source": "0.0.0.0" } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/load_balancer_server_ip.json0000664000175000017500000000014713535474530032224 0ustar kamikami00000000000000{ "id": "7C88E50FBC500A3D9D7F94E414255D6B", "ip": "123.46.79.100", "server_name": "My server 1" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/load_balancer_server_ips.json0000664000175000017500000000015013535474530032401 0ustar kamikami00000000000000{ "server_ips": [ "7C88E50FBC500A3D9D7F94E414255D6B", "7288E50FBC500A3D9D7F94E414255D6B" ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/monitoring_policy.json0000664000175000017500000000236313535474530031146 0ustar kamikami00000000000000{ "name": "Monitoring Policy", "description": "Monitoring Policy Description", "email": "test@test.com", "agent": false, "thresholds": { "disk": { "warning": { "value": 80, "alert": false }, "critical": { "value": 90, "alert": false } }, "transfer": { "warning": { "value": 1000, "alert": false }, "critical": { "value": 2000, "alert": false } }, "ram": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } }, "internal_ping": { "warning": { "value": 50, "alert": false }, "critical": { "value": 100, "alert": true } }, "cpu": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } } }, "ports": [ { "alert_if": "NOT_RESPONDING", "email_notification": true, "protocol": "TCP", "port": 443 } ], "processes": [ { "process": "httpdeamon", "alert_if": "NOT_RUNNING", "email_notification": false } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/monitoring_policy_port.json0000664000175000017500000000021413535474530032203 0ustar kamikami00000000000000{ "id": "663D21E232530D79E4E584104C400EE4", "protocol": "TCP", "port": 22, "alert_if": "RESPONDING", "email_notifications": true }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/monitoring_policy_ports.json0000664000175000017500000000047613535474530032400 0ustar kamikami00000000000000[ { "id": "663D21E232530D79E4E584104C400EE4", "protocol": "TCP", "port": 22, "alert_if": "RESPONDING", "email_notifications": true }, { "id": "663D21E232530D79E4E584104C400AAA", "protocol": "TCP", "port": 80, "alert_if": "NOT_RESPONDING", "email_notifications": true } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/monitoring_policy_process.json0000664000175000017500000000020413535474530032674 0ustar kamikami00000000000000{ "id": "663D21E232530D79E4E584104C400EE4", "process": "iexplorer", "alert_if": "NOT_RUNNING", "email_notifications": true }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/monitoring_policy_processes.json0000664000175000017500000000044413535474530033232 0ustar kamikami00000000000000[ { "id": "663D21E232530D79E4E584104C400EE4", "process": "iexplorer", "alert_if": "NOT_RUNNING", "email_notifications": true }, { "id": "663D21E232530D79E4E584104C400EE4", "process": "winword", "alert_if": "NOT_RUNNING", "email_notifications": true } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/monitoring_policy_servers.json0000664000175000017500000000024413535474530032713 0ustar kamikami00000000000000[ { "id": "C72CF0A681B0CCE7EC624DD194D585C6", "name": "My server 1" }, { "id": "4ECD9D188EB457317B2CF8F07885E7B4", "name": "My server 2" } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/public_ip.json0000664000175000017500000000053513535474530027347 0ustar kamikami00000000000000{ "id": "44972922D045B9648118AA80FF2A51C9", "ip": "10.4.140.155", "type": "IPV4", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "assigned_to": null, "reverse_dns": "example.com", "is_dhcp": false, "state": "ACTIVE", "creation_date": "2015-05-06T08:17:33+00:00" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/server_hardware.json0000664000175000017500000000030213535474530030554 0ustar kamikami00000000000000{ "fixed_instance_size_id": 0, "vcore": 1, "cores_per_processor": 1, "ram": 2, "hdds": [ { "id": "8C626C1A7005D0D1F527143C413D461E", "size": 40, "is_main": true } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/server_ip.json0000664000175000017500000000024313535474530027373 0ustar kamikami00000000000000{ "id": "01D4A802798AB77AA72DA2D05E1379E1", "ip": "10.5.135.140", "type": "IPV4", "reverse_dns": null, "firewall_policy": null, "load_balancers": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/server_ips.json0000664000175000017500000000026613535474530027563 0ustar kamikami00000000000000[ { "id": "01D4A802798AB77AA72DA2D05E1379E1", "ip": "10.5.135.140", "type": "IPV4", "reverse_dns": null, "firewall_policy": null, "load_balancers": [] } ]apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/shared_storage.json0000664000175000017500000000114313535474530030367 0ustar kamikami00000000000000{ "id": "6AD2F180B7B666539EF75A02FE227084", "size": 200, "state": "ACTIVE", "description": "My shared storage test description", "datacenter": { "id": "D0F6D8C8ED29D3036F94C27BBB7BAD36", "location": "USA", "country_code": "US" }, "cloudpanel_id": "vid35780", "size_used": "0.00", "cifs_path": "vid50995.nas1.lanvid50995", "nfs_path": "vid50995.nas1.lan/:vid50995", "name": "My shared storage test", "creation_date": "2015-05-06T08:33:25+00:00", "servers": [ { "id": "638ED28205B1AFD7ADEF569C725DD85F", "name": "My server 1", "rights": "RW" } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/oneandone/ttt.json0000664000175000017500000000240313535474530026210 0ustar kamikami00000000000000{ "name": "MonitoringPolicy_674", "description": "MonitoringPolicy_674 description", "email": "test-go-sdk@oneandone.com", "agent": true, "thresholds": { "cpu": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } }, "ram": { "warning": { "value": 90, "alert": false }, "critical": { "value": 95, "alert": false } }, "disk": { "warning": { "value": 80, "alert": false }, "critical": { "value": 90, "alert": false } }, "transfer": { "warning": { "value": 1000, "alert": false }, "critical": { "value": 2000, "alert": false } }, "internal_ping": { "warning": { "value": 50, "alert": false }, "critical": { "value": 100, "alert": true } } }, "ports": [ { "protocol": "TCP", "port": 443, "alert_if": "NOT_RESPONDING", "email_notification": true } ], "processes": [ { "process": "httpdeamon", "alert_if": "NOT_RUNNING", "email_notification": false } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/0000775000175000017500000000000013600223624025315 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/compute_15.xml0000664000175000017500000000062613535474530030037 0ustar kamikami00000000000000 15 Compute 15 ACTIVE apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/compute_25.xml0000664000175000017500000000036613535474530030041 0ustar kamikami00000000000000 25 Compute 25 none apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/compute_5.xml0000664000175000017500000000062313535474530027753 0ustar kamikami00000000000000 5 Compute 5 ACTIVE apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/computes.xml0000664000175000017500000000036213535474530027712 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/disk_15.xml0000664000175000017500000000025613535474530027314 0ustar kamikami00000000000000 15 Ubuntu 9.04 LAMP 2048 file:///images/ubuntu/jaunty.img apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/disk_5.xml0000664000175000017500000000025513535474530027232 0ustar kamikami00000000000000 5 Ubuntu 9.04 LAMP 2048 file:///images/ubuntu/jaunty.img apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/network_15.xml0000664000175000017500000000024013535474530030044 0ustar kamikami00000000000000 15 Network 15

192.168.1.0
256 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/network_5.xml0000664000175000017500000000023613535474530027770 0ustar kamikami00000000000000 5 Network 5
192.168.0.0
256
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/networks.xml0000664000175000017500000000026713535474530027733 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_1_4/storage.xml0000664000175000017500000000025313535474530027516 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/0000775000175000017500000000000013600223624025312 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/compute_15.xml0000664000175000017500000000141613535474530030032 0ustar kamikami00000000000000 15 Compute 15 small ACTIVE DISK hda 192.168.0.2 02:00:c0:a8:00:02 192.168.1.2 02:00:c0:a8:01:02 compute-15 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/compute_25.xml0000664000175000017500000000104213535474530030026 0ustar kamikami00000000000000 25 Compute 25 none none 192.168.0.3 02:00:c0:a8:00:03 192.168.1.3 02:00:c0:a8:01:03 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/compute_5.xml0000664000175000017500000000141213535474530027745 0ustar kamikami00000000000000 5 Compute 5 small ACTIVE DISK hda 192.168.0.1 02:00:c0:a8:00:01 192.168.1.1 02:00:c0:a8:01:01 compute-5 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/compute_collection.xml0000664000175000017500000000047313535474530031742 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/network_15.xml0000664000175000017500000000024013535474530030041 0ustar kamikami00000000000000 15 Network 15
192.168.1.0
256
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/network_5.xml0000664000175000017500000000023613535474530027765 0ustar kamikami00000000000000 5 Network 5
192.168.0.0
256
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/network_collection.xml0000664000175000017500000000035613535474530031757 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/storage_15.xml0000664000175000017500000000032413535474530030017 0ustar kamikami00000000000000 15 Ubuntu 9.04 LAMP OS Ubuntu 9.04 LAMP Description 2048 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/storage_5.xml0000664000175000017500000000032313535474530027735 0ustar kamikami00000000000000 5 Ubuntu 9.04 LAMP OS Ubuntu 9.04 LAMP Description 2048 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_2_0/storage_collection.xml0000664000175000017500000000036713535474530031734 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_0/0000775000175000017500000000000013600223624025313 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_0/network_15.xml0000664000175000017500000000027013535474530030045 0ustar kamikami00000000000000 15 Network 15
192.168.1.0
256 NO
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_0/network_5.xml0000664000175000017500000000026713535474530027772 0ustar kamikami00000000000000 5 Network 5
192.168.0.0
256 YES
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_0/network_collection.xml0000664000175000017500000000035613535474530031760 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_2/0000775000175000017500000000000013600223624025315 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_2/compute_5.xml0000664000175000017500000000141213535474530027750 0ustar kamikami00000000000000 5 Compute 5 small ACTIVE DISK hda 192.168.0.1 02:00:c0:a8:00:01 192.168.1.1 02:00:c0:a8:01:01 compute-5 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_2/instance_type_collection.xml0000664000175000017500000000114613535474530033134 0ustar kamikami00000000000000 small 1 1024 medium 4 4096 large 8 8192 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_6/0000775000175000017500000000000013600223624025321 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_6/compute_15.xml0000664000175000017500000000105213535474530030035 0ustar kamikami00000000000000 15 Compute 15 Test small ACTIVE FILE hda 192.168.122.2 02:00:c0:a8:7a:02 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_6/compute_5.xml0000664000175000017500000000131713535474530027760 0ustar kamikami00000000000000 5 Compute 5 Test small ACTIVE FILE hda FILE sda 192.168.122.2 02:00:c0:a8:7a:02 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_6/disk_10.xml0000664000175000017500000000025513535474530027312 0ustar kamikami00000000000000 10 Debian 7.1 LAMP 2048 file:///images/debian/wheezy.img apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_6/disk_15.xml0000664000175000017500000000024513535474530027316 0ustar kamikami00000000000000 15 Debian Sid 1024 file:///images/debian/sid.img apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_6/storage_5.xml0000664000175000017500000000063113535474530027746 0ustar kamikami00000000000000 5 test-volume oneadmin READY DATABLOCK Attached storage 1000 ext3 NO YES apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_8/0000775000175000017500000000000013600223624025323 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_collection.xml0000664000175000017500000000054713535474530033146 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_large.xml0000664000175000017500000000027713535474530032105 0ustar kamikami00000000000000 large 8 8192 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_medium.xml0000664000175000017500000000030113535474530032257 0ustar kamikami00000000000000 medium 4 4096 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/opennebula_3_8/instance_type_small.xml0000664000175000017500000000027713535474530032123 0ustar kamikami00000000000000 small 1 1024 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/0000775000175000017500000000000013600223624024511 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/300_multiple_choices.json0000664000175000017500000000051513535474530031332 0ustar kamikami00000000000000{"choices": [{"status": "CURRENT", "media-types": [{"base": "application/xml", "type": "application/vnd.openstack.compute+xml;version=2"}, {"base": "application/json", "type": "application/vnd.openstack.compute+json;version=2"}], "id": "v2.0", "links": [{"href": "http://50.56.213.226:8774/v2/v2.0/images/detail", "rel": "self"}]}]} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/_v1_1__auth.json0000664000175000017500000000270213535474530027505 0ustar kamikami00000000000000{ "auth": { "token": { "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", "expires": "2999-11-23T21:00:14-06:00" }, "serviceCatalog": { "cloudFilesCDN": [ { "region": "ORD", "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS", "v1Default": true }, { "region": "LON", "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS", "v1Default": false } ], "cloudFiles": [ { "region": "ORD", "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS", "v1Default": true, "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS" }, { "region": "LON", "publicURL": "https://storage101.lon1.clouddrive.com/v1/MossoCloudFS", "v1Default": false, "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS" } ], "cloudServers": [ { "publicURL": "https://servers.api.rackspacecloud.com/v1.0/slug", "v1Default": true } ] } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/_v1_1__auth_mssing_token.json0000664000175000017500000000076513535474530032274 0ustar kamikami00000000000000{"auth":{"token":{"expires":"2011-09-18T02:44:17.000-05:00"},"serviceCatalog":{"cloudFilesCDN":[{"region":"ORD","publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS","v1Default":true}],"cloudFiles":[{"region":"ORD","publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS","v1Default":true,"internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS"}],"cloudServers":[{"publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/slug","v1Default":true}]}}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/_v1_1__auth_unauthorized.json0000664000175000017500000000011013535474530032275 0ustar kamikami00000000000000{"unauthorized":{"message":"Username or api key is invalid","code":401}}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/_v2_0__auth.json0000664000175000017500000002213213535474530027504 0ustar kamikami00000000000000{ "access": { "token": { "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", "expires": "2999-11-23T21:00:14.000-06:00" }, "serviceCatalog": [ { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "version": { "versionInfo": "https://cdn2.clouddrive.com/v1/", "versionList": "https://cdn2.clouddrive.com/", "versionId": "1" } } ], "name": "cloudFilesCDN", "type": "rax:object-cdn" }, { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" }, { "region": "LON", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" } ], "name": "cloudFiles", "type": "object-store" }, { "endpoints": [ { "tenantId": "1337", "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", "version": { "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", "versionList": "https://servers.api.rackspacecloud.com/", "versionId": "1.0" } } ], "name": "cloudServers", "type": "compute" }, { "endpoints": [ { "region": "RegionOne", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" }, { "region": "fr1", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" } ], "name": "nova", "type": "compute" }, { "endpoints": [ { "region": "RegionOne", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" }, { "region": "fr1", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" } ], "name": "glance", "type": "image" }, { "endpoints": [ { "region": "RegionOne", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" }, { "region": "fr1", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" } ], "name": "neutron", "type": "network" }, { "endpoints": [ { "region": "RegionOne", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" }, { "region": "fr1", "tenantId": "1337", "publicURL": "https://test_endpoint.com/v2/1337", "versionInfo": "https://test_endpoint.com/v2/", "versionList": "https://test_endpoint.com/", "versionId": "2" } ], "name": "cinderv2", "type": "volumev2" }, { "endpoints": [ { "region": "DFW", "tenantId": "613469", "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", "versionList": "https://dfw.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "ORD", "tenantId": "613469", "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", "versionList": "https://ord.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "IAD", "tenantId": "613469", "publicURL": "https://iad.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://iad.servers.api.rackspacecloud.com/v2/", "versionList": "https://iad.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "SYD", "tenantId": "613469", "publicURL": "https://syd.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://syd.servers.api.rackspacecloud.com/v2/", "versionList": "https://syd.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "HKG", "tenantId": "613469", "publicURL": "https://hkg.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://hkg.servers.api.rackspacecloud.com/v2/", "versionList": "https://hkg.servers.api.rackspacecloud.com/", "versionId": "2" } ], "name": "cloudServersOpenStack", "type": "compute" }, { "endpoints": [ { "region": "DFW", "tenantId": "1337", "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/1337" } ], "name": "cloudServersPreprod", "type": "compute" } ], "user": { "id": "7", "roles": [ { "id": "identity:default", "description": "Default Role.", "name": "identity:default" } ], "name": "testuser" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/_v2_0__auth_deployment.json0000664000175000017500000001375313535474530031755 0ustar kamikami00000000000000{ "access": { "token": { "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", "expires": "2999-11-23T21:00:14.000-06:00" }, "serviceCatalog": [ { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "version": { "versionInfo": "https://cdn2.clouddrive.com/v1/", "versionList": "https://cdn2.clouddrive.com/", "versionId": "1" } } ], "name": "cloudFilesCDN", "type": "rax:object-cdn" }, { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" }, { "region": "LON", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" } ], "name": "cloudFiles", "type": "object-store" }, { "endpoints": [ { "tenantId": "slug", "publicURL": "https://servers.api.rackspacecloud.com/v1.0/slug", "version": { "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", "versionList": "https://servers.api.rackspacecloud.com/", "versionId": "1.0" } } ], "name": "cloudServers", "type": "compute" }, { "endpoints": [ { "region": "RegionOne", "tenantId": "slug", "publicURL": "https://127.0.0.1/v2/slug", "versionInfo": "https://127.0.0.1/v2/", "versionList": "https://127.0.0.1/", "versionId": "2" } ], "name": "nova", "type": "compute" }, { "endpoints": [ { "region": "DFW", "tenantId": "613469", "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/slug", "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", "versionList": "https://dfw.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "ORD", "tenantId": "613469", "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/slug", "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", "versionList": "https://ord.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "IAD", "tenantId": "613469", "publicURL": "https://iad.servers.api.rackspacecloud.com/v2/slug", "versionInfo": "https://iad.servers.api.rackspacecloud.com/v2/", "versionList": "https://iad.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "SYD", "tenantId": "613469", "publicURL": "https://syd.servers.api.rackspacecloud.com/v2/slug", "versionInfo": "https://syd.servers.api.rackspacecloud.com/v2/", "versionList": "https://syd.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "HKG", "tenantId": "613469", "publicURL": "https://hkg.servers.api.rackspacecloud.com/v2/slug", "versionInfo": "https://hkg.servers.api.rackspacecloud.com/v2/", "versionList": "https://hkg.servers.api.rackspacecloud.com/", "versionId": "2" } ], "name": "cloudServersOpenStack", "type": "compute" }, { "endpoints": [ { "region": "DFW", "tenantId": "slug", "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/slug" } ], "name": "cloudServersPreprod", "type": "compute" } ], "user": { "id": "7", "roles": [ { "id": "identity:default", "description": "Default Role.", "name": "identity:default" } ], "name": "testuser" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/_v2_0__auth_lon.json0000664000175000017500000000752613535474530030366 0ustar kamikami00000000000000{ "access": { "token": { "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", "expires": "2999-11-23T21:00:14.000-06:00" }, "serviceCatalog": [ { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://cdn2.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "version": { "versionInfo": "https://cdn2.clouddrive.com/v1/", "versionList": "https://cdn2.clouddrive.com/", "versionId": "1" } } ], "name": "cloudFilesCDN", "type": "rax:object-cdn" }, { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111", "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" } ], "name": "cloudFiles", "type": "object-store" }, { "endpoints": [ { "tenantId": "1337", "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", "version": { "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", "versionList": "https://servers.api.rackspacecloud.com/", "versionId": "1.0" } } ], "name": "cloudServers", "type": "compute" }, { "endpoints": [ { "region": "RegionOne", "tenantId": "1337", "publicURL": "https://127.0.0.1/v2/1337", "versionInfo": "https://127.0.0.1/v2/", "versionList": "https://127.0.0.1/", "versionId": "2" } ], "name": "nova", "type": "compute" }, { "endpoints": [ { "region": "LON", "tenantId": "613469", "publicURL": "https://lon.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://lon.servers.api.rackspacecloud.com/v2/", "versionList": "https://lon.servers.api.rackspacecloud.com/", "versionId": "2" } ], "name": "cloudServersOpenStack", "type": "compute" }, { "endpoints": [ { "region": "LON", "tenantId": "1337", "publicURL": "https://preprod.lon.servers.api.rackspacecloud.com/v2/1337" } ], "name": "cloudServersPreprod", "type": "compute" } ], "user": { "id": "7", "roles": [ { "id": "identity:default", "description": "Default Role.", "name": "identity:default" } ], "name": "testuser" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/_v3__auth.json0000664000175000017500000001562213535474530027274 0ustar kamikami00000000000000{ "token": { "methods": [ "password" ], "roles": [ { "id": "9fe2ff9ee4384b1894a90878d3e92bab", "name": "_member_" }, { "id": "b258b68172db4403892320f784c4d503", "name": "admin" } ], "expires_at": "2014-08-10T19:15:57.096078Z", "project": { "domain": { "id": "default", "name": "Default" }, "id": "9c4693dce56b493b9b83197d900f7fba", "name": "admin" }, "catalog": [ { "endpoints": [ { "url": "http://controller:8774/v2/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "internal", "id": "b3bfb29033ff4add9c97e523e1022794" }, { "url": "http://192.168.18.100:8774/v2/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "admin", "id": "b52ee215ded7473f94a46512cb94dbf1" }, { "url": "http://192.168.18.100:8774/v2/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "public", "id": "ca8a6e39b9334300bf036c0c4226a173" } ], "type": "compute", "id": "03f123b2253e4852a86b994f86489c0a" }, { "endpoints": [ { "url": "http://192.168.18.100:8776/v1/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "public", "id": "20bf617f334c4bcf82746820f5006599" }, { "url": "http://192.168.18.100:8776/v1/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "admin", "id": "2da639c26463424fa9775e0bf4e9f29e" }, { "url": "http://controller:8776/v2/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "internal", "id": "d568ed6f8c5a4649a6e68b7bcb86694b" } ], "type": "volume", "id": "47f77ba8f3864a03b66024e910ad7247" }, { "endpoints": [ { "url": "http://192.168.18.100:9696", "region": "regionOne", "interface": "admin", "id": "720303f92f81404aa80caa32cd9c7d23" }, { "url": "http://192.168.18.100:9696", "region": "regionOne", "interface": "public", "id": "8823b9edba354bb6bdc944a6b3bb5404" }, { "url": "http://controller:9696", "region": "regionOne", "interface": "internal", "id": "c2a522538037492dbec2173f271ecb32" } ], "type": "network", "id": "9bd61e09d372427f81eca9328f33c510" }, { "endpoints": [ { "url": "http://controller:5000/v2.0", "region": "regionOne", "interface": "internal", "id": "802622da0a874cac8fe2ec7a02d87c44" }, { "url": "http://192.168.18.100:35357/v2.0", "region": "regionOne", "interface": "admin", "id": "8a4eed85ddc748b18cc2b92e64291eb5" }, { "url": "http://192.168.18.100:5000/v2.0", "region": "regionOne", "interface": "public", "id": "9ef69c1600a944b9904f34efb6dc67eb" } ], "type": "identity", "id": "aef833a14f4240d0bbb699f0154add8e" }, { "endpoints": [ { "url": "http://192.168.18.100:9292", "region": "regionOne", "interface": "public", "id": "1aa84aebd3e2467e898e3c18428e3feb" }, { "url": "http://192.168.18.100:9292", "region": "regionOne", "interface": "admin", "id": "3f6aa4ffd0ec47d2862eee1648993bef" }, { "url": "http://192.168.200.1:9292", "region": "regionOne", "interface": "internal", "id": "9f66f90af36949479a6365680afabe12" } ], "type": "image", "id": "c0be10ea61e240f99567f328b9adf3d6" }, { "endpoints": [ { "url": "http://192.168.18.100:8776/v2/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "public", "id": "6c6b0990ccf84f1890e404fddad7b6e5" }, { "url": "http://192.168.18.100:8776/v2/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "admin", "id": "ab0f0bd770494d4399036867935c52ea" }, { "url": "http://controller:8776/v2/9c4693dce56b493b9b83197d900f7fba", "region": "regionOne", "interface": "internal", "id": "fc7c82deda034e52a544da7d00cd28de" } ], "type": "volumev2", "id": "e097b64d701e4ce29f2a69eed4e69856" } ], "extras": {}, "user": { "domain": { "id": "default", "name": "Default" }, "id": "55fba80f022b4855acfc700ae13b2b24", "name": "admin" }, "issued_at": "2014-08-10T18:15:57.096107Z" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_flavors_detail.xml0000664000175000017500000000103113535474530031677 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_images_detail.xml0000664000175000017500000000333313535474530031477 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_images_post.xml0000664000175000017500000000033213535474530031216 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_limits.xml0000664000175000017500000000151113535474530030205 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers.xml0000664000175000017500000000067513535474530030407 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail.xml0000664000175000017500000000070213535474530031720 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_ipv6.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_ipv0000664000175000017500000000071713535474530034245 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_missing.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_mis0000664000175000017500000000071013535474530034230 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_multiple_nodes.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_mul0000664000175000017500000000141313535474530034236 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_no_ip.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_no_0000664000175000017500000000071713535474530034222 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_pending.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_pen0000664000175000017500000000070713535474530034230 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_same_uuid.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_sam0000664000175000017500000000141213535474530034220 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_success.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_deployment_suc0000664000175000017500000000071013535474530034232 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_empty.xml0000664000175000017500000000017313535474530033140 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_detail_metadata.xml0000664000175000017500000000077413535474530033571 0ustar kamikami00000000000000 somevalue apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_ips.xml0000664000175000017500000000044713535474530031257 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_metadata.xml0000664000175000017500000000100013535474530032226 0ustar kamikami00000000000000 b d apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_servers_no_admin_pass.xml0000664000175000017500000000064213535474530033273 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_group.xml0000664000175000017500000000035413535474530032062 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups.xml0000664000175000017500000000040313535474530032240 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack/v1_slug_shared_ip_groups_detail.xml0000664000175000017500000000103113535474530033560 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/0000775000175000017500000000000013600223624026422 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v2/0000775000175000017500000000000013600223624026751 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v2/v2_0_tenants.json0000664000175000017500000000052213535474530032160 0ustar kamikami00000000000000{ "tenants": [ { "description": "test project", "enabled": true, "id": "a", "name": "test" }, { "description": "admin tenant", "enabled": true, "id": "b", "name": "admin" } ], "tenants_links": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/0000775000175000017500000000000013600223624026752 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_create_user.json0000664000175000017500000000037213535474530032573 0ustar kamikami00000000000000{ "user": { "name": "test2", "links": { "self": "http://192.168.18.100:5000/v3/users/c" }, "domain_id": "default", "enabled": true, "email": "test2@localhost", "id": "c" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_domains.json0000664000175000017500000000072613535474530031727 0ustar kamikami00000000000000{ "domains": [ { "links": { "self": "http://192.168.18.100:5000/v3/domains/default" }, "enabled": true, "description": "Owns users and tenants (i.e. projects) available on Identity API v2.", "name": "Default", "id": "default" } ], "links": { "self": "http://192.168.18.100:5000/v3/domains", "previous": null, "next": null } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_domains_default.json0000664000175000017500000000044713535474530033433 0ustar kamikami00000000000000{ "domain": { "links": { "self": "http://192.168.18.100:5000/v3/domains/default" }, "enabled": true, "description": "Owns users and tenants (i.e. projects) available on Identity API v2.", "name": "Default", "id": "default" } } ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_domains_default_users_a_roles.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_domains_default_users_0000664000175000017500000000053213535474530034036 0ustar kamikami00000000000000{ "links": { "self": "http://192.168.18.100:5000/v3/domains/default/users/a/roles", "previous": null, "next": null }, "roles": [ { "id": "d", "links": { "self": "http://192.168.18.100:5000/v3/roles/d" }, "name": "admin" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_projects.json0000664000175000017500000000243313535474530032123 0ustar kamikami00000000000000{ "links": { "self": "http://192.168.18.100:5000/v3/projects", "previous": null, "next": null }, "projects": [ { "description": "Test project", "links": { "self": "http://192.168.18.100:5000/v3/projects/a" }, "enabled": true, "id": "a", "domain_id": "default", "name": "divvy" }, { "description": "Admin Tenant", "links": { "self": "http://192.168.18.100:5000/v3/projects/b" }, "enabled": true, "id": "b", "domain_id": "default", "name": "admin" }, { "description": "Initial tenant", "links": { "self": "http://192.168.18.100:5000/v3/projects/c" }, "enabled": true, "id": "c", "domain_id": "default", "name": "first-tenant" }, { "description": "Service Tenant", "links": { "self": "http://192.168.18.100:5000/v3/projects/d" }, "enabled": true, "id": "d", "domain_id": "default", "name": "service" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_roles.json0000664000175000017500000000112413535474530031412 0ustar kamikami00000000000000{ "links": { "self": "http://192.168.18.100:5000/v3/roles", "previous": null, "next": null }, "roles": [ { "links": { "self": "http://192.168.18.100:5000/v3/roles/a" }, "enabled": "True", "description": "Default role for project membership", "name": "_member_", "id": "a" }, { "id": "b", "links": { "self": "http://192.168.18.100:5000/v3/roles/b" }, "name": "admin" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_users.json0000664000175000017500000001040313535474530031427 0ustar kamikami00000000000000{ "users": [ { "name": "cloud", "links": { "self": "http://192.168.18.100:5000/v3/users/a" }, "domain_id": "default", "enabled": true, "email": "openstack-test@localhost", "id": "a" }, { "name": "trove", "links": { "self": "http://192.168.18.100:5000/v3/users/1ec8cface8614a2786c99c87c7116f09" }, "domain_id": "default", "enabled": true, "email": "trove@localhost", "id": "1ec8cface8614a2786c99c87c7116f09" }, { "domain_id": "default", "name": "tomaz", "links": { "self": "http://192.168.18.100:5000/v3/users/458f20357227462e8a17355628984515" }, "id": "458f20357227462e8a17355628984515", "enabled": true, "email": "tomaz@tomaz.me", "default_project_id": "3130562cafe147f289bbb3b557f2e7ed" }, { "name": "admin", "links": { "self": "http://192.168.18.100:5000/v3/users/55fba80f022b4855acfc700ae13b2b24" }, "domain_id": "default", "enabled": true, "email": "openstack-test@localhost", "id": "55fba80f022b4855acfc700ae13b2b24" }, { "name": "nova", "links": { "self": "http://192.168.18.100:5000/v3/users/679c69c6cfd049ebb3ad85734dfea61a" }, "domain_id": "default", "enabled": true, "email": "nova@localhost", "id": "679c69c6cfd049ebb3ad85734dfea61a" }, { "name": "glance", "links": { "self": "http://192.168.18.100:5000/v3/users/6f10443170ad4daf81bff251944da9d7" }, "domain_id": "default", "enabled": true, "email": "glance@localhost", "id": "6f10443170ad4daf81bff251944da9d7" }, { "name": "ceilometer", "links": { "self": "http://192.168.18.100:5000/v3/users/747cf6a2bf75453f847f307823e8eac9" }, "domain_id": "default", "enabled": true, "email": "ceilometer@localhost", "id": "747cf6a2bf75453f847f307823e8eac9" }, { "name": "swift", "links": { "self": "http://192.168.18.100:5000/v3/users/a0081ee2f9674458bcd7731b6dcbf5f9" }, "domain_id": "default", "enabled": true, "email": "swift@localhost", "id": "a0081ee2f9674458bcd7731b6dcbf5f9" }, { "domain_id": "default", "name": "amann", "links": { "self": "http://192.168.18.100:5000/v3/users/aafb942e4c3d4fe1ba33088f3e7c5996" }, "id": "aafb942e4c3d4fe1ba33088f3e7c5996", "enabled": true, "email": "andrew@divvycloud.com", "default_project_id": "3130562cafe147f289bbb3b557f2e7ed" }, { "name": "heat", "links": { "self": "http://192.168.18.100:5000/v3/users/d16cad10e4f648e0bd9ab5a0359f6736" }, "domain_id": "default", "enabled": true, "email": "heat@localhost", "id": "d16cad10e4f648e0bd9ab5a0359f6736" }, { "name": "cinder", "links": { "self": "http://192.168.18.100:5000/v3/users/f3a4590b0d66497894ee9a3d73c09a95" }, "domain_id": "default", "enabled": true, "email": "cinder@localhost", "id": "f3a4590b0d66497894ee9a3d73c09a95" }, { "name": "neutron", "links": { "self": "http://192.168.18.100:5000/v3/users/fa9a7fedeb2844ff89e37d70a2519441" }, "domain_id": "default", "enabled": true, "email": "neutron@localhost", "id": "fa9a7fedeb2844ff89e37d70a2519441" } ], "links": { "self": "http://192.168.18.100:5000/v3/users", "previous": null, "next": null } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_a.json0000664000175000017500000000063013535474530031730 0ustar kamikami00000000000000{ "user": { "name": "cloud", "links": { "self": "http://192.168.18.100:5000/v3/users/a" }, "domain_id": "default", "enabled": true, "email": "openstack-test@localhost", "id": "a" }, "links": { "self": "http://192.168.18.100:5000/v3/users", "previous": null, "next": null } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_a_projects.json0000664000175000017500000000023613535474530033643 0ustar kamikami00000000000000{ "links": { "self": "http://192.168.18.100:5000/v3/users/a/projects", "previous": null, "next": null }, "projects": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_b.json0000664000175000017500000000056313535474530031736 0ustar kamikami00000000000000{ "user": { "name": "userwithoutemail", "links": { "self": "http://192.168.18.100:5000/v3/users/b" }, "domain_id": "default", "enabled": true, "id": "b" }, "links": { "self": "http://192.168.18.100:5000/v3/users", "previous": null, "next": null } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_users_c.json0000664000175000017500000000050213535474530031730 0ustar kamikami00000000000000{ "user": { "name": "userwithoutenabled", "links": { "self": "http://192.168.18.100:5000/v3/users/c" }, "domain_id": "default", "id": "c", "email": "c@example.com", "password_expires_at": null, "options": {} } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_identity/v3/v3_versions.json0000664000175000017500000000376713535474530032155 0ustar kamikami00000000000000{ "versions": { "values": [ { "status": "stable", "updated": "2013-03-06T00:00:00Z", "media-types": [ { "base": "application/json", "type": "application/vnd.openstack.identity-v3+json" }, { "base": "application/xml", "type": "application/vnd.openstack.identity-v3+xml" } ], "id": "v3.0", "links": [ { "href": "http://192.168.18.100:5000/v3/", "rel": "self" } ] }, { "status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [ { "base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json" }, { "base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml" } ], "id": "v2.0", "links": [ { "href": "http://192.168.18.100:5000/v2.0/", "rel": "self" }, { "href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby" }, { "href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby" } ] } ] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/0000775000175000017500000000000013600223624025256 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/README0000664000175000017500000000050313535474530026147 0ustar kamikami00000000000000The json responses contained in this directory are copied directly from the OpenStack 1.1 documentation at http://docs.openstack.org/trunk/openstack-compute/developer/openstack-compute-api-1.1/ as of this writing. The only exception is _os_quota_sets_aTenantId.json, which was captured (and perturbed) via packet capture. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_7.json0000664000175000017500000000056113535474530030227 0ustar kamikami00000000000000{"flavor": {"rxtx_quota": 2500, "name": "15.5GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/7", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/7", "rel": "bookmark"}], "ram": 16384, "vcpus": 8, "rxtx_cap": 200, "swap": 0, "disk": 620, "id": 7}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_flavors_detail.json0000664000175000017500000000571413535474530031330 0ustar kamikami00000000000000{"flavors": [{"rxtx_quota": 2500, "name": "15.5GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/7", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/7", "rel": "bookmark"}], "ram": 16384, "vcpus": 8, "rxtx_cap": 200, "swap": 0, "disk": 620, "id": 7}, {"rxtx_quota": 600, "name": "1GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/3", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/3", "rel": "bookmark"}], "ram": 1024, "vcpus": 1, "rxtx_cap": 30, "swap": 0, "disk": 40, "id": 3}, {"rxtx_quota": 150, "name": "256 slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/1", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/1", "rel": "bookmark"}], "ram": 256, "vcpus": 1, "rxtx_cap": 10, "swap": 0, "disk": 10, "id": 1, "OS-FLV-EXT-DATA:ephemeral": 40, "OS-FLV-WITH-EXT-SPECS:extra_specs": {"policy_class": "standard_flavor", "class": "standard1", "disk_io_index": "2", "number_of_data_disks": "0"}}, {"rxtx_quota": 1200, "name": "2GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/4", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/4", "rel": "bookmark"}], "ram": 2048, "vcpus": 2, "rxtx_cap": 60, "swap": 0, "disk": 80, "id": 4}, {"rxtx_quota": 2500, "name": "30GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/8", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/8", "rel": "bookmark"}], "ram": 30720, "vcpus": 8, "rxtx_cap": 400, "swap": 0, "disk": 1200, "id": 8}, {"rxtx_quota": 2500, "name": "4GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/5", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/5", "rel": "bookmark"}], "ram": 4096, "vcpus": 2, "rxtx_cap": 100, "swap": 0, "disk": 160, "id": 5}, {"rxtx_quota": 300, "name": "512 slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/2", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}], "ram": 512, "vcpus": 1, "rxtx_cap": 20, "swap": 0, "disk": 20, "id": 2}, {"rxtx_quota": 2500, "name": "8GB slice", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/flavors/6", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/6", "rel": "bookmark"}], "ram": 8192, "vcpus": 4, "rxtx_cap": 150, "swap": 0, "disk": 320, "id": 6}]} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip.json0000664000175000017500000000021413535474530030613 0ustar kamikami00000000000000{"floating_ip": {"instance_id": null, "ip": "10.3.1.42", "fixed_ip": null, "id": "09ea1784-2f81-46dc-8c91-244b4df75bde", "pool": "public"}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ip_pools.json0000664000175000017500000000010013535474530032021 0ustar kamikami00000000000000{"floating_ip_pools": [{"name": "public"}, {"name": "foobar"}]} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_floating_ips.json0000664000175000017500000000046513535474530031006 0ustar kamikami00000000000000{"floating_ips": [{"instance_id": null, "ip": "10.3.1.42", "fixed_ip": null, "id": "09ea1784-2f81-46dc-8c91-244b4df75bde", "pool": "public"}, {"instance_id": "fcfc96da-19e2-40fd-8497-f29da1b21143", "ip": "10.3.1.1", "fixed_ip": "172.16.21.4", "id": "04c5336a-0629-4694-ba30-04b0bdfa88a4", "pool": "public"}]} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_13.json0000664000175000017500000000113313535474530030071 0ustar kamikami00000000000000{"image": {"status": "ACTIVE", "updated": "2011-08-06T18:14:02Z", "name": "Windows 2008 SP2 x86 (B24)", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/13", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/13", "rel": "bookmark"}, {"href": "http://10.13.136.245:9292/rs-reach-project/images/13", "type": "application/vnd.openstack.image", "rel": "alternate"}], "created": "2011-08-06T18:13:11Z", "minDisk": "5", "progress": 100, "minRam": "256", "id": "13", "metadata": {"os_type": "windows"}}} ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_0000664000175000017500000000206313535474530032177 0ustar kamikami00000000000000{"image": {"status": "SAVING", "updated": "2012-01-05T19:42:20Z", "name": "new_image", "links": [{"href": "http://127.0.0.1/v1.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "rel": "self"}, {"href": "http://127.0.0.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "rel": "bookmark"}, {"href": "http://10.13.136.213:9292/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "type": "application/vnd.openstack.image", "rel": "alternate"}], "created": "2012-01-05T19:42:20Z", "minDisk": 0, "server": {"id": "a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "links": [{"href": "http://127.0.0.1/v1.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "rel": "self"}, {"href": "http://127.0.0.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "rel": "bookmark"}]}, "progress": 25, "minRam": 0, "id": "4949f9ee-2421-4c81-8b49-13119446008b", "metadata": {"instance_uuid": "a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "image_state": "creating", "user_id": "reach6", "instance_ref": "http://127.0.0.1/v1.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "image_type": "snapshot", "backup_type": null}}} ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_8af1a54e_a1b2_4df8_b747_4bec97abc799_members.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_8af1a54e_a1b2_4df8_b747_0000664000175000017500000000035113535474530032451 0ustar kamikami00000000000000{"status": "accepted", "created_at": "2018-03-02T14:19:38Z", "updated_at": "2018-03-02T14:20:37Z", "image_id": "8af1a54e-a1b2-4df8-b747-4bec97abc799", "member_id": "e2151b1fe02d4a8a2d1f5fc331522c0a", "schema": "/v2/schemas/member"} ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_9af1a54e_a1b2_4df8_b747_4bec97abc799_members.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_9af1a54e_a1b2_4df8_b747_0000664000175000017500000000035013535474530032451 0ustar kamikami00000000000000{"status": "pending", "created_at": "2018-03-02T14:19:38Z", "updated_at": "2018-03-02T14:19:38Z", "image_id": "9af1a54e-a1b2-4df8-b747-4bec97abc799", "member_id": "e2151b1fe02d4a8a2d1f5fc331522c0a", "schema": "/v2/schemas/member"} ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_d9a9cd9a_278a_444c_90a6_0000664000175000017500000001557513535474530032421 0ustar kamikami00000000000000{"members": [{"status": "accepted", "created_at": "2017-01-12T12:31:50Z", "updated_at": "2017-01-12T12:31:54Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "016926dff12345e8b10329f24c99745b", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:43:24Z", "updated_at": "2017-01-12T12:43:28Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "0cb96fe6d1a749a3b32733bf1fc5e3d8", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-19T08:06:33Z", "updated_at": "2017-01-19T08:06:58Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "0d6aa4aaa8624fa38621e23b84a583f6", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:19:38Z", "updated_at": "2017-01-12T12:19:41Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "0e3c876745274d13b6c2ab70f82f4503", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:15:44Z", "updated_at": "2017-01-12T12:15:47Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "13c07d734435bb1ea2faeeb23f8574c6", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-02-09T14:08:46Z", "updated_at": "2017-02-09T14:08:33Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "1a0ba874fcaf4a0c814dc85d2a2ef9bc", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-27T13:20:08Z", "updated_at": "2017-01-27T13:20:11Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "1ce2f38e23a44ab8bb6a2cc2b409de06", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:31:48Z", "updated_at": "2017-01-12T12:31:52Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "2b269ec4335745ef84562d4f1fabbb50", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T10:33:34Z", "updated_at": "2017-01-12T10:33:37Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "31eb590cf2014726bd3aa372f1e21383", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:27:14Z", "updated_at": "2017-01-12T12:27:17Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "32ab6a1cfa6f4c2da7233a27c7ab624c", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-19T08:24:39Z", "updated_at": "2017-01-19T08:24:42Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "3865bd651ee141c5b37b81e2333daaef", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-16T14:12:12Z", "updated_at": "2017-01-16T14:12:15Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "33a2b8475b3443738c443b94c3be6852", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-27T13:05:16Z", "updated_at": "2017-01-27T13:05:20Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "4b9aa0de831245e2b26f0b1b53d2b70b", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:21:31Z", "updated_at": "2017-01-12T12:21:34Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "4f1568969ad84c939cc9c396a43ad757", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:13:10Z", "updated_at": "2017-01-12T12:13:13Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "5a21d13639bc4141a3030c46e95e8ed4", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T10:13:37Z", "updated_at": "2017-01-12T10:13:40Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "679d169d15a8448a91cd66b1d34367d6", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-27T15:31:29Z", "updated_at": "2017-01-27T15:31:33Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "6c469adc3d464275abe13aabdd28b19a", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:30:29Z", "updated_at": "2017-01-12T12:30:32Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "6fbabd8cba81429cb35ff1df4bd2a62e", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-27T12:54:40Z", "updated_at": "2017-01-27T12:54:44Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "77a940af30ac444ea6734fd809138906", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-02-09T14:16:59Z", "updated_at": "2017-02-09T14:17:02Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "796deab733b14a3781f3f9cb07c834a5", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:12:41Z", "updated_at": "2017-01-12T12:12:44Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "84ee139deb75b133b5616571b989e780", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-02-09T14:01:22Z", "updated_at": "2017-02-09T14:01:26Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "88af7921eeda432ca47b09c0e6bd4aa3", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T10:56:07Z", "updated_at": "2017-01-12T10:56:10Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "ae394c8ecde5b09a8ba04aafefdac1e6", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:12:04Z", "updated_at": "2017-01-12T12:12:07Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "d146a26974104aa1ba3ba56bed8699dc", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-02-07T27:17:35Z", "updated_at": "2017-02-07T27:17:38Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "da1fe8eafd794ef8bda390dcf78c3927", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:21:27Z", "updated_at": "2017-01-12T12:21:21Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "da52660bdabf4adeab261a0fde666e80", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-19T08:22:21Z", "updated_at": "2017-01-19T08:22:24Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "e883313f4a864ef9933b3574f4ea3c42", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:31:51Z", "updated_at": "2017-01-12T12:31:54Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "ec9b3bcb5bac4f4ea3dd42afff28713a", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-12T12:15:08Z", "updated_at": "2017-01-12T12:15:12Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "fdfb81a8ffaa4f1d9d7b712ac3369332", "schema": "/v2/schemas/member"}, {"status": "accepted", "created_at": "2017-01-19T08:13:03Z", "updated_at": "2017-01-19T08:13:07Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "ffad303302884e96998c8d4564a263c2", "schema": "/v2/schemas/member"}], "schema": "/v2/schemas/members"} ././@LongLink0000000000000000000000000000023700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members_016926dff12345e8b10329f24c99745b.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_d9a9cd9a_278a_444c_90a6_0000664000175000017500000000035113535474530032403 0ustar kamikami00000000000000{"status": "accepted", "created_at": "2017-01-12T12:31:50Z", "updated_at": "2017-01-12T12:31:54Z", "image_id": "d9a9cd9a-278a-444c-90a6-d24b8c688a63", "member_id": "016926dff12345e8b10329f24c99745b", "schema": "/v2/schemas/member"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_detail.json0000664000175000017500000003166113535474530031121 0ustar kamikami00000000000000{ "images": [ { "status": "ACTIVE", "updated": "2011-08-06T18:14:02Z", "name": "Windows 2008 SP2 x86 (B24)", "server" : { "id": "52415800-8b69-11e0-9b19-734f335aa7b3", "name": "test-server", "links": [ { "rel": "self", "href": "http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3" }, { "rel": "bookmark", "href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f335aa7b3" } ] }, "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/13", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/13", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/13", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-06T18:13:11Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "13", "metadata": { "os_type": "windows" } }, { "status": "ACTIVE", "updated": "2011-08-06T18:13:11Z", "name": "Windows 2003 R2 x86 (B24)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/12", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/12", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/12", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-06T18:12:33Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "12", "metadata": { "os_type": "windows" } }, { "status": "ACTIVE", "updated": "2011-08-06T16:27:56Z", "name": "Windows 2008 SP2 x64 (B24)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/11", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/11", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/11", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-06T16:26:15Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "11", "metadata": { "os_type": "windows" } }, { "status": "ACTIVE", "updated": "2011-08-06T16:26:14Z", "name": "Windows 2008 R2 x64 (B24)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/10", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/10", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/10", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-06T16:24:51Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "10", "metadata": { "os_type": "windows" } }, { "status": "ACTIVE", "updated": "2011-08-06T16:24:51Z", "name": "Windows 2003 R2 x64 (B24)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/9", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/9", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/9", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-06T16:23:52Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "9", "metadata": { "os_type": "windows" } }, { "status": "ACTIVE", "updated": "2011-08-05T22:58:29Z", "name": "Ubuntu Natty (11.04)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/8", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/8", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/8", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:58:20Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "8", "metadata": {} }, { "status": "ACTIVE", "updated": "2011-08-05T22:58:19Z", "name": "Ubuntu Lucid (10.04)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/7", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/7", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:58:14Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "7", "metadata": {} }, { "status": "ACTIVE", "updated": "2011-08-05T22:58:14Z", "name": "Fedora 15", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/6", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/6", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/6", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:58:01Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "6", "metadata": {} }, { "status": "ACTIVE", "updated": "2011-08-05T22:58:00Z", "name": "Fedora 14", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/5", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/5", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/5", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:57:47Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "5", "metadata": {} }, { "status": "ACTIVE", "updated": "2011-08-05T22:57:47Z", "name": "Debian Squeeze (6.0)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/4", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/4", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/4", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:57:41Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "4", "metadata": {} }, { "status": "ACTIVE", "updated": "2011-08-05T22:57:40Z", "name": "Debian Lenny (5.0)", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/3", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/3", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/3", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:57:30Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "3", "metadata": {} }, { "status": "ACTIVE", "updated": "2011-08-05T22:57:30Z", "name": "CentOS 6.0", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/2", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/2", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/2", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:57:20Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "2", "metadata": {} }, { "status": "ACTIVE", "updated": "2011-08-05T22:56:20Z", "name": "CentOS 5.6", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/images/1", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/1", "rel": "bookmark" }, { "href": "http://10.13.136.170:9292/rs-reach-project/images/1", "type": "application/vnd.openstack.image", "rel": "alternate" } ], "created": "2011-08-05T22:56:03Z", "minDisk": 0, "progress": 100, "minRam": 0, "id": "1", "metadata": {} } ] } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_f24a3c1b-d52a-4116-91da-25b3eee8f55d.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_f24a3c1b-d52a-4116-91da-0000664000175000017500000000241213535474530032037 0ustar kamikami00000000000000{"status": "saving", "image_location": "snapshot", "image_state": "pending", "tags": [], "kernel_id": null, "container_format": "bare", "min_ram": 0, "ramdisk_id": null, "locations": [{"url": "file:///var/lib/glance/images/4949f9ee-2421-4c81-8b49-13119446008b", "metadata": {"mountpoint": "/var/lib/glance/images", "type": "nfs", "id": "NetApp1", "share_location": "nfs://some.ip.somewhere/blabla_data001"}}], "visibility": "private", "updated_at": "2017-11-28T10:19:49Z", "owner": "d85e344900774f5aad27e4e8e91205d6", "schema": "/v2/schemas/image", "file": "/v2/images/4949f9ee-2421-4c81-8b49-13119446008b/file", "min_disk": 40, "virtual_size": null, "base_image_ref": "5be2b652-a965-4ecb-a2b4-b9f83d7779e6", "size": 1256259584, "instance_uuid": "24f0a531-e45f-491b-86f2-3708dd45a478", "os_distro": "ubuntu", "user_id": "b0d846d9ac93452bb93857e0305584bd", "name": "new_image", "image_type": "snapshot", "checksum": "3530464d095c9d62771b99ebecd2d70b", "created_at": "2017-09-11T13:00:05Z", "disk_format": "qcow2", "id": "4949f9ee-2421-4c81-8b49-13119446008b", "protected": false, "os_type": "linux", "direct_url": "file:///var/lib/glance/images/4949f9ee-2421-4c81-8b49-13119446008b", "self": "/v2/images/4949f9ee-2421-4c81-8b49-13119446008b", "owner_id": "d85e344900774f5aad27e4e8e91205d6"} ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_f24a3c1b-d52a-4116-91da-25b3eee8f55e.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_f24a3c1b-d52a-4116-91da-0000664000175000017500000000241313535474530032040 0ustar kamikami00000000000000{"status": "active", "image_location": "snapshot", "image_state": "available", "tags": [], "kernel_id": null, "container_format": "bare", "min_ram": 0, "ramdisk_id": null, "locations": [{"url": "file:///var/lib/glance/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e", "metadata": {"mountpoint": "/var/lib/glance/images", "type": "nfs", "id": "NetApp1", "share_location": "nfs://some.ip.somewhere/blabla_data001"}}], "visibility": "shared", "updated_at": "2017-11-28T10:19:49Z", "owner": "d85e344900774f5aad27e4e8e91205d6", "schema": "/v2/schemas/image", "file": "/v2/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e/file", "min_disk": 40, "virtual_size": null, "base_image_ref": "5be2b652-a965-4ecb-a2b4-b9f83d7779e6", "size": 1256259584, "instance_uuid": "24f0a531-e45f-491b-86f2-3708dd45a478", "os_distro": "ubuntu", "user_id": "b0d846d9ac93452bb93857e0305584bd", "name": "hypernode", "image_type": "snapshot", "checksum": "3530464d095c9d62771b99ebecd2d70b", "created_at": "2017-09-11T13:00:05Z", "disk_format": "qcow2", "id": "f24a3c1b-d52a-4116-91da-25b3eee8f55e", "protected": false, "os_type": "linux", "direct_url": "file:///var/lib/glance/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e", "self": "/v2/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e", "owner_id": "d85e344900774f5aad27e4e8e91205d6"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_images_v2.json0000664000175000017500000000513713535474530030205 0ustar kamikami00000000000000{"images": [{"status": "active", "image_location": "snapshot", "image_state": "available", "tags": [], "kernel_id": null, "container_format": "bare", "min_ram": 0, "ramdisk_id": null, "locations": [{"url": "file:///var/lib/glance/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e", "metadata": {"mountpoint": "/var/lib/glance/images", "type": "nfs", "id": "NetApp1", "share_location": "nfs://some.ip.somewhere/com_osp_data001"}}], "visibility": "shared", "updated_at": "2017-11-28T10:19:49Z", "owner": "d85e344900774f5aad27e4e8e91205d6", "schema": "/v2/schemas/image", "file": "/v2/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e/file", "min_disk": 40, "virtual_size": null, "base_image_ref": "5be2b652-a965-4ecb-a2b4-b9f83d7779e6", "size": 1256259584, "instance_uuid": "24f0a531-e45f-491b-86f2-3708dd45a478", "os_distro": "ubuntu", "user_id": "b0d846d9ac93452bb93857e0305584bd", "name": "hypernode", "image_type": "snapshot", "checksum": "3530464d095c9d62771b99ebecd2d70b", "created_at": "2017-09-11T13:00:05Z", "disk_format": "qcow2", "id": "f24a3c1b-d52a-4116-91da-25b3eee8f55e", "protected": false, "os_type": "linux", "direct_url": "file:///var/lib/glance/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e", "self": "/v2/images/f24a3c1b-d52a-4116-91da-25b3eee8f55e", "owner_id": "d85e344900774f5aad27e4e8e91205d6"}, {"status": "active", "image_location": "snapshot", "image_state": "available", "tags": [], "kernel_id": null, "container_format": "bare", "min_ram": 0, "ramdisk_id": null, "locations": [{"url": "file:///var/lib/glance/images/4bd743f8-7e7d-4568-8f31-b3f06b90e70a", "metadata": {"mountpoint": "/var/lib/glance/images", "type": "nfs", "id": "NetApp1", "share_location": "nfs://some.ip.somewhere/com_osp_data001"}}], "visibility": "private", "updated_at": "2017-09-07T13:07:33Z", "owner": "d85e344900774f5aad27e4e8e91205d6", "schema": "/v2/schemas/image", "file": "/v2/images/4bd743f8-7e7d-4568-8f31-b3f06b90e70a/file", "min_disk": 40, "virtual_size": null, "base_image_ref": "5be2b652-a965-4ecb-a2b4-b9f83d7779e6", "size": 1248264192, "instance_uuid": "b4166e71-f40b-4a5b-a489-87601ab8a600", "os_distro": "ubuntu", "user_id": "b0d846d9ac93452bb93857e0305584bd", "name": "hypernode", "image_type": "snapshot", "checksum": "1969ec22f73d524eb766b4c308e2192a", "created_at": "2017-09-07T13:06:24Z", "disk_format": "qcow2", "id": "4bd743f8-7e7d-4568-8f31-b3f06b90e70a", "protected": false, "os_type": "linux", "direct_url": "file:///var/lib/glance/images/4bd743f8-7e7d-4568-8f31-b3f06b90e70a", "self": "/v2/images/4bd743f8-7e7d-4568-8f31-b3f06b90e70a", "owner_id": "d85e344900774f5aad27e4e8e91205d6"}], "schema": "/v2/schemas/images", "first": "/v2/images"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs.json0000664000175000017500000000161113535474530030652 0ustar kamikami00000000000000{ "keypairs": [ { "keypair": { "fingerprint": "22:0e:d6:f7:bd:5e:ee:49:cf:1f:10:d5:9c:a8:35:64", "name": "key1", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/ePvJuMEOc90gidxWN+8lYekv+S6j8SJhcQRBjE5DVs/M+3VXyJTQc6fguUS9c7o8GZXpP/0dwbVa9y76HeZs6In+XE1egoUyz4zLHQ5jUepFeekChpSlo6yQWI2SHUxJOshqPLOEU1XlrwvN0h5FcXGVV0x6DJgLZuCRS7oIxQ== Generated by Nova\n" } }, { "keypair": { "fingerprint": "5d:66:33:ae:99:0f:fb:cb:86:f2:bc:ae:53:99:b6:ed", "name": "key2", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCz5sy4u8KwAPAMPr+4bEMlU6BwpSD6eZVokwMclojqIz9nKAvQD9AEw/6ok9Xsn0oixBrCoW2HYsXIiUziufzheoGsZIzuj3D7Rpbtrft53FtICe5UtQrOo3WJb8bvbzpDDd7xYlb9PpQTXoxInzjgBW+Ox6OODx2NazTk7PHZDQ== Generated by Nova\n" } } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create.json0000664000175000017500000000252613535474530032203 0ustar kamikami00000000000000{ "keypair": { "fingerprint": "80:f8:03:a7:8e:c1:c3:b1:7e:c5:8c:50:04:5e:1c:5b", "name": "key0", "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQDPC4MDHBbUjeGZ4pK5svGxkFHJFdDatpMAYcW/fyDxsMbyiHnu\nUOxB0WJupUQd4tc7B8+MNOLzcZVQkUjIhhkb5qCbjcoOqzb59owtNCSi7TleaC6w\n15j1LJb3zdHVxEhGJ19I95DhOtiFRHp2Ik3bYV6p+uv0sQxfaqw3q5M3+QIDAQAB\nAoGAW2LqZfH9Bb7GSEUgnESmt8hKwSYW9KLHidCeFyNG6Ect2RlyMEWZsod4Gfxq\nb4KTm6Ob8XfagLeuv0wRQyklZUbyb4aurfn4hX0cpkxSPAVar8uG/0TJY1wswxfo\nkReZCq7CQFlt7w3Y1RHZyXo/inyAxohi393trVhIGAqdXp0CQQDt7/GeI5QWKjYj\nwe5kFTRowVJ+y61MP237Bz+YF5+pq28ikdLAMzdDOyd3LJTnBGJ/DK1ksfJDCSue\nEgdifYJrAkEA3sM1fRQB/PyyyCR1DcZGlOfc/OBCSG4aTMYOK+g0PnibKPj5wS6q\nuK8w1q+0CztpgKsmEtQ+H7H8Fva81S7wKwJANY7tNEuN6e9WgHYG00Byq6HYj/II\n8EDW4Mqg5ftrVSXhvkZUyi69IcUO/SRr4BR8l1yjKydjAPPvfYVRZDocQQJASHXr\nQkJt2yM/7IafZNmoP+ukIMW6CeF2wJ50IagoxmFo500FwOczNVwXYN5KjJTI3sfN\nXLaZdqnovHeKOTZJfQJAZ2HBnmgsLoFE6ONF492TXIs7JxJr8z4QUp1AXGUXcZmy\njuL3b9XW6K908Ev8uTSNzRo6TyGuYKGllp10K6A3bA==\n-----END RSA PRIVATE KEY-----\n", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDPC4MDHBbUjeGZ4pK5svGxkFHJFdDatpMAYcW/fyDxsMbyiHnuUOxB0WJupUQd4tc7B8+MNOLzcZVQkUjIhhkb5qCbjcoOqzb59owtNCSi7TleaC6w15j1LJb3zdHVxEhGJ19I95DhOtiFRHp2Ik3bYV6p+uv0sQxfaqw3q5M3+Q== Generated by Nova\n", "user_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_create_import.json0000664000175000017500000000113013535474530033563 0ustar kamikami00000000000000{ "keypair": { "fingerprint": "97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a", "name": "key3", "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzTJr5BNSlTIDFsVY3zUJtbbcPsWbw7XDE/eXRQ+704790ARKKvE3FsERqdMZvwcx1osR0sGVdpgAiV/z5iEb5z2juQp7yQJHePiEnfHTH99NVJN+Y1BztchRoz224IaP987bN+fd8Pl/O1YDCyw+bX5zI/ekCC9z8fTdI2l1AbTnKVn7UjZBjKZi1uPMaH016fp039pIOtkjvIgDWjeGwOiJjY1vzaX3nxQje4kprEZ4FKk4yyG61qveBZr+/0Xq6ocNOYUSpB29AZ0IcfJa7P3yMxVRzSS9aN0fmrlf3kIFkVAy45A83GfZpiMxo/ulTaO9+tTSwulZP+0bxkCkn dummycomment\n", "user_id": "dbdf4c6cab0c4ae78bef0bcdb03c2440" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_get_one.json0000664000175000017500000000122013535474530032346 0ustar kamikami00000000000000{"keypair": {"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDkRJ+f6VibLJJRPtuVM3g5ZCporVfoFJhRt8vcBbD4x/1h8OSBvWwuj9tKoZha0ijpGJIRW5HylRKYZPFL7gxlmqS9LM/lewx3c/fZItmP4kDYuXX2Dn9XwHFLS/bSy/JHVgnrHopHUH/2a57iUNe+QRrngEGz13N1S9If3EGDxIhZuO8S1BRLWK3SqtHjOQ6mWZOF6xAs3nwKaBNJTWVp6XUshzlcwWUA5nFysN9MVXX7t/J1qo+xcSAwt/ew8v6dZJcCQM+y30bQhPJzSN8LepN5tSTI4iEN0Y+LtNQDtCEYacr4qEFkAxj3CcSAeQVMaT/a7ps0xiHg9GnCbGsV Generated by Nova\n", "user_id": "1234", "name": "test-key-pair", "deleted": false, "created_at": "2013-12-07T15:17:16.000000", "updated_at": null, "fingerprint": "a9:55:e8:b8:49:45:7b:aa:a9:33:fb:97:86:79:2c:1b", "deleted_at": null, "id": 4567}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_keypairs_not_found.json0000664000175000017500000000011713535474530032725 0ustar kamikami00000000000000{"itemNotFound": {"message": "The resource could not be found.", "code": 404}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks.json0000664000175000017500000000036013535474530030677 0ustar kamikami00000000000000{"networks": [{"cidr": "127.0.0.0/24", "id": "f13e5051-feea-416b-827a-1a0acc2dad14", "label": "test1"}, {"id": "00000000-0000-0000-0000-000000000000", "label": "public"}, {"id": "11111111-1111-1111-1111-111111111111", "label": "private"}]} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_networks_POST.json0000664000175000017500000000014613535474530031546 0ustar kamikami00000000000000{"network": {"cidr": "127.0.0.0/24", "id": "ef2143d4-2353-4e3c-b577-0de372411f42", "label": "test1"}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_quota_sets_aTenantId.json0000664000175000017500000000032513535474530033142 0ustar kamikami00000000000000{"quota_set": {"metadata_items": 10, "injected_file_content_bytes": 1000, "injected_files": 10, "volumes": 0, "instances": 25, "gigabytes": 500, "cores": 50, "ram": 102400, "id": "aTenantId", "floating_ips": 10}} ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_group_rules_create.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_group_rules_create.0000664000175000017500000000040013535474530033744 0ustar kamikami00000000000000{ "security_group_rule": { "from_port": 14, "group": {}, "id": 2, "ip_protocol": "tcp", "ip_range": { "cidr": "0.0.0.0/0" }, "parent_group_id": 6, "to_port": 16 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups.json0000664000175000017500000000140613535474530032273 0ustar kamikami00000000000000{ "security_groups": [ { "description": "default", "id": 2, "name": "default", "rules": [], "tenant_id": "68" }, { "description": "FTP Client-Server - Open 20-21 ports", "id": 4, "name": "ftp", "rules": [ { "from_port": 20, "group": {}, "id": 1, "ip_protocol": "tcp", "ip_range": { "cidr": "0.0.0.0/0" }, "parent_group_id": 4, "to_port": 21 } ], "tenant_id": "68" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_security_groups_create.json0000664000175000017500000000025513535474530033617 0ustar kamikami00000000000000{ "security_group": { "description": "Test Security Group", "id": 6, "name": "test", "rules": [], "tenant_id": "68" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshot.json0000664000175000017500000000053613535474530030667 0ustar kamikami00000000000000{ "snapshot": { "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "display_name": "snap-001", "display_description": "Daily backup", "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", "status": "available", "size": 30, "created_at": "2012-02-29T03:50:07Z" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshot_rackspace.json0000664000175000017500000000053213535474530032677 0ustar kamikami00000000000000{ "snapshot": { "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "displayName": "snap-001", "displayDescription": "Daily backup", "volumeId": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", "status": "available", "size": 30, "createdAt": "2012-02-29T03:50:07Z" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json0000664000175000017500000000205213535474530031045 0ustar kamikami00000000000000{ "snapshots": [ { "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "display_name": "snap-001", "display_description": "Daily backup", "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", "status": "available", "size": 30, "created_at": "2012-02-29T03:50:07Z" }, { "id": "e479997c-650b-40a4-9dfe-77655818b0d2", "display_name": "snap-002", "display_description": "Weekly backup", "volume_id": "76b8950a-8594-4e5b-8dce-0dfa9c696358", "status": "available", "size": 25, "created_at": "2012-03-19T01:52:47Z" }, { "id": "4fbbdccf-e058-6502-8844-6feeffdf4cb5", "display_name": "snap-003", "display_description": "Another daily backup", "volume_id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "status": "available", "size": 30, "created_at": "2013-02-29T03:50:07Z" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json0000664000175000017500000000050213535474530032366 0ustar kamikami00000000000000{ "snapshot": { "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "display_name": "snap-001", "display_description": "Daily backup", "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", "status": "available", "size": 30, "created_at": "2012-02-29T03:50:07Z" } }././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create_rackspace.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create_rackspace.j0000664000175000017500000000047613535474530033674 0ustar kamikami00000000000000{ "snapshot": { "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "displayName": "snap-001", "displayDescription": "Daily backup", "volumeId": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", "status": "available", "size": 30, "createdAt": "2012-02-29T03:50:07Z" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_rackspace.json0000664000175000017500000000203613535474530033063 0ustar kamikami00000000000000{ "snapshots": [ { "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "displayName": "snap-001", "displayDescription": "Daily backup", "volumeId": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", "status": "available", "size": 30, "createdAt": "2012-02-29T03:50:07Z" }, { "id": "e479997c-650b-40a4-9dfe-77655818b0d2", "displayName": "snap-002", "displayDescription": "Weekly backup", "volumeId": "76b8950a-8594-4e5b-8dce-0dfa9c696358", "status": "available", "size": 25, "createdAt": "2012-03-19T01:52:47Z" }, { "id": "4fbbdccf-e058-6502-8844-6feeffdf4cb5", "displayName": "snap-003", "displayDescription": "Another daily backup", "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "status": "available", "size": 30, "createdAt": "2013-02-29T03:50:07Z" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes.json0000664000175000017500000000235513535474530030523 0ustar kamikami00000000000000{ "volumes": [ { "attachments": [ { "device": "/dev/vdb", "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "serverId": "12065", "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d" } ], "availabilityZone": "nova", "createdAt": "2013-06-24T11:20:13.000000", "displayDescription": "", "displayName": "test_volume_2", "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "metadata": {}, "size": 2, "snapshotId": null, "status": "available", "volumeType": "None" }, { "attachments": [ {} ], "availabilityZone": "nova", "createdAt": "2013-06-21T12:39:02.000000", "displayDescription": "some description", "displayName": "test_volume", "id": "cfcec3bc-b736-4db5-9535-4c24112691b5", "metadata": {}, "size": 50, "snapshotId": "01f48111-7866-4cd2-986a-e92683c4a363", "status": "some-unknown-state", "volumeType": "None" } ] } ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_cd76a3a1_c4ce_40f6_90000664000175000017500000000117513535474530032730 0ustar kamikami00000000000000{ "volume": { "attachments": [ { "device": "/dev/vdb", "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "serverId": "12065", "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d" } ], "availabilityZone": "nova", "createdAt": "2013-06-24T11:20:13.000000", "displayDescription": "", "displayName": "test_volume_2", "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "metadata": {}, "size": 2, "snapshotId": null, "status": "in-use", "volumeType": "None" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_os_volumes_create.json0000664000175000017500000000063713535474530032047 0ustar kamikami00000000000000{ "volume": { "attachments": [ {} ], "availabilityZone": "nova", "createdAt": "2013-06-28T12:22:39.616660", "displayDescription": null, "displayName": "test", "id": "43b7db44-0497-40fa-b817-c906f13bbea3", "metadata": {}, "size": 1, "snapshotId": null, "status": "creating", "volumeType": "None" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_port_v2.json0000664000175000017500000000171013535474530027715 0ustar kamikami00000000000000{ "port": { "status": "BUILD", "extra_dhcp_opts": [], "description": "Some port description", "allowed_address_pairs": [], "tags": [], "network_id": "123c8a8c-6427-4e8f-a805-2035365f4d43", "tenant_id": "abcdec85bee34bb0a44ab8255eb36abc", "created_at": "2018-07-04T14:38:18Z", "admin_state_up": true, "updated_at": "2018-07-05T14:40:43Z", "binding:vnic_type": "normal", "device_owner": "compute:nova", "name": "Some port name", "revision_number": 2036, "mac_address": "ba:12:12:8a:b2:73", "port_security_enabled": true, "project_id": "abcdec85bee34bb0a44ab8255eb36abc", "fixed_ips": [ { "subnet_id": "1231a12a-125b-4329-a3c5-312ea86a7577", "ip_address": "12.123.12.32" } ], "id": "126da55e-cfcb-41c8-ae39-a26cb8a7e723", "security_groups": [ "abcfb112-5b5c-4c6b-8b3f-dbaee57df440" ], "device_id": "95e75643-2008-123f-ad13-e20ea64e3c87" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_ports_v2.json0000664000175000017500000001566513535474530030116 0ustar kamikami00000000000000{ "ports": [ { "status": "BUILD", "extra_dhcp_opts": [], "description": "", "allowed_address_pairs": [], "tags": [], "network_id": "123c8a8c-6427-4e8f-a805-2035365f4d43", "tenant_id": "abcdec85bee34bb0a44ab8255eb36abc", "created_at": "2018-07-04T14:38:18Z", "admin_state_up": true, "updated_at": "2018-07-05T14:40:43Z", "binding:vnic_type": "normal", "device_owner": "compute:nova", "name": "", "revision_number": 2036, "mac_address": "ba:12:12:8a:b2:73", "port_security_enabled": true, "project_id": "abcdec85bee34bb0a44ab8255eb36abc", "fixed_ips": [ { "subnet_id": "1231a12a-125b-4329-a3c5-312ea86a7577", "ip_address": "12.123.12.32" } ], "id": "126da55e-cfcb-41c8-ae39-a26cb8a7e723", "security_groups": [ "abcfb112-5b5c-4c6b-8b3f-dbaee57df440" ], "device_id": "95e75643-2008-123f-ad13-e20ea64e3c87" }, { "status": "BUILD", "extra_dhcp_opts": [], "description": "porttest", "allowed_address_pairs": [], "tags": [], "network_id": "123c8a8c-6427-4e8f-a805-2035365f4d43", "tenant_id": "abcdec85bee34bb0a44ab8255eb36abc", "created_at": "2018-07-05T12:38:50Z", "admin_state_up": true, "updated_at": "2018-07-05T14:40:43Z", "binding:vnic_type": "normal", "device_owner": "compute:nova", "name": "porttest", "revision_number": 865, "mac_address": "ba:12:12:48:42:9b", "port_security_enabled": true, "project_id": "abcdec85bee34bb0a44ab8255eb36abc", "fixed_ips": [ { "subnet_id": "1231a12a-125b-4329-a3c5-312ea86a7577", "ip_address": "12.123.12.31" } ], "id": "a8f3ddbe-9b29-41ac-9c0a-9ea7cc012dfb", "security_groups": [ "abcfb112-5b5c-4c6b-8b3f-dbaee57df440" ], "device_id": "7b4743a6-f7f7-4764-9854-cf43312e6d49" }, { "status": "DOWN", "extra_dhcp_opts": [], "description": "", "allowed_address_pairs": [], "tags": [], "network_id": "123c8a8c-6427-4e8f-a805-2035365f4d43", "tenant_id": "abcdec85bee34bb0a44ab8255eb36abc", "created_at": "2018-07-05T13:09:27Z", "admin_state_up": true, "updated_at": "2018-07-05T13:29:38Z", "binding:vnic_type": "normal", "device_owner": "compute:nova", "name": "", "revision_number": 10, "mac_address": "ba:12:12:95:13:cc", "port_security_enabled": true, "project_id": "abcdec85bee34bb0a44ab8255eb36abc", "fixed_ips": [ { "subnet_id": "1231a12a-125b-4329-a3c5-312ea86a7577", "ip_address": "12.123.12.44" } ], "id": "bad9af6a-121d-4772-9ae0-7d127b712f5d", "security_groups": [ "abcfb112-5b5c-4c6b-8b3f-dbaee57df440" ], "device_id": "500d78d1-f84f-4949-12da-5205c1237121" }, { "status": "DOWN", "extra_dhcp_opts": [], "description": "testport", "allowed_address_pairs": [], "tags": [], "network_id": "123c8a8c-6427-4e8f-a805-2035365f4d43", "tenant_id": "abcdec85bee34bb0a44ab8255eb36abc", "created_at": "2018-07-05T11:59:13Z", "admin_state_up": true, "updated_at": "2018-07-05T12:39:48Z", "binding:vnic_type": "normal", "device_owner": "", "name": "testport", "revision_number": 32, "mac_address": "ba:12:12:6f:ea:12", "port_security_enabled": true, "project_id": "abcdec85bee34bb0a44ab8255eb36abc", "fixed_ips": [ { "subnet_id": "1231a12a-125b-4329-a3c5-312ea86a7577", "ip_address": "12.123.12.12" } ], "id": "c21297ca-4e68-4384-badf-10903cd2cbb0", "security_groups": [ "abcfb112-5b5c-4c6b-8b3f-dbaee57df440" ], "device_id": "" }, { "status": "DOWN", "extra_dhcp_opts": [], "description": "testport", "allowed_address_pairs": [], "tags": [], "network_id": "123c8a8c-6427-4e8f-a805-2035365f4d43", "tenant_id": "abcdec85bee34bb0a44ab8255eb36abc", "created_at": "2018-07-05T11:56:59Z", "admin_state_up": true, "updated_at": "2018-07-05T11:57:00Z", "binding:vnic_type": "normal", "device_owner": "", "name": "testport", "revision_number": 3, "mac_address": "ba:12:12:e6:03:ba", "port_security_enabled": true, "project_id": "abcdec85bee34bb0a44ab8255eb36abc", "fixed_ips": [ { "subnet_id": "1231a12a-125b-4329-a3c5-312ea86a7577", "ip_address": "12.123.12.28" } ], "id": "ca335147-273c-4c72-9bab-11a122a95ce1", "security_groups": [ "abcfb112-5b5c-4c6b-8b3f-dbaee57df440" ], "device_id": "" }, { "status": "DOWN", "extra_dhcp_opts": [], "description": "testport", "allowed_address_pairs": [], "tags": [], "network_id": "123c8a8c-6427-4e8f-a805-2035365f4d43", "tenant_id": "abcdec85bee34bb0a44ab8255eb36abc", "created_at": "2018-07-05T11:12:17Z", "admin_state_up": true, "updated_at": "2018-07-05T11:12:17Z", "binding:vnic_type": "normal", "device_owner": "", "name": "testport", "revision_number": 3, "mac_address": "ba:12:12:12:12:12", "port_security_enabled": true, "project_id": "abcdec85bee34bb0a44ab8255eb36abc", "fixed_ips": [ { "subnet_id": "1231a12a-125b-4329-a3c5-312ea86a7577", "ip_address": "12.123.12.12" } ], "id": "a128dec6-4f3a-45c4-a89c-678f69a72044", "security_groups": [ "abcfb112-5b5c-4c6b-8b3f-dbaee57df440" ], "device_id": "" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers.json0000664000175000017500000000475613535474530030030 0ustar kamikami00000000000000{ "server": { "id": "52415800-8b69-11e0-9b19-734f565bc83b", "tenantId": "1234", "userId": "5678", "name": "new-server-test", "created": "2010-11-11T12:00:00Z", "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0", "accessIPv4" : "67.23.10.138", "accessIPv6" : "::babe:67.23.10.138", "progress": 0, "status": "BUILD", "adminPass": "GFf1j9aP", "image" : { "id": "52415800-8b69-11e0-9b19-734f6f006e54", "name": "CentOS 5.2", "links": [ { "rel": "self", "href": "http://servers.api.openstack.org/v1.1/1234/images/52415800-8b69-11e0-9b19-734f6f006e54" }, { "rel": "bookmark", "href": "http://servers.api.openstack.org/1234/images/52415800-8b69-11e0-9b19-734f6f006e54" } ] }, "flavor" : { "id": "52415800-8b69-11e0-9b19-734f1195ff37", "name": "256 MB Server", "links": [ { "rel": "self", "href": "http://servers.api.openstack.org/v1.1/1234/flavors/52415800-8b69-11e0-9b19-734f1195ff37" }, { "rel": "bookmark", "href": "http://servers.api.openstack.org/1234/flavors/52415800-8b69-11e0-9b19-734f1195ff37" } ] }, "metadata": { "My Server Name": "Apache1" }, "addresses": { "public" : [ { "version": 4, "addr": "67.23.10.138" }, { "version": 6, "addr": "::babe:67.23.10.138" } ], "private" : [ { "version": 4, "addr": "10.176.42.19" }, { "version": 6, "addr": "::babe:10.176.42.19" } ] }, "links": [ { "rel": "self", "href": "http://servers.api.openstack.org/v1.1/1234/servers/52415800-8b69-11e0-9b19-734fcece0043" }, { "rel": "bookmark", "href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734fcece0043" } ] } } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12063_metadata_two_keys.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12063_metadata_two_keys0000664000175000017500000000016113535474530033361 0ustar kamikami00000000000000{ "metadata" : { "Server Label" : "Web Head 1", "Image Version" : "2.1" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064.json0000664000175000017500000000225313535474530030552 0ustar kamikami00000000000000{"server": {"status": "ACTIVE", "updated": "2011-10-11T00:44:20Z", "hostId": "a024053a6201e6c6c12660aab3d8fd879e332e663a5e1fdbc02a0307", "user_id": "rs-reach", "name": "lc-test", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12064", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12064", "rel": "bookmark"}], "addresses": {"public": [{"version": 4, "addr": "50.57.94.30"}, {"version": 6, "addr": "2001:4801:7808:52:16:3eff:fe77:32e3"}], "private": [{"version": 4, "addr": "10.182.64.29"}, {"version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe6e:b7e2"}]}, "tenant_id": "rs-reach-project", "image": {"id": "7", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark"}]}, "created": "2011-10-11T00:45:02Z", "uuid": "ec53630b-e4fb-442a-a748-c376f5c4345b", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 100, "flavor": {"id": "2", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}]}, "config_drive": "", "id": 12064, "metadata": {}}} ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064_updated_name_bob.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12064_updated_name_bob.0000664000175000017500000000224713535474530033213 0ustar kamikami00000000000000{"server": {"status": "ACTIVE", "updated": "2011-10-11T01:22:04Z", "hostId": "a024053a6201e6c6c12660aab3d8fd879e332e663a5e1fdbc02a0307", "user_id": "rs-reach", "name": "Bob", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12064", "rel": "self"}, {"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12064", "rel": "bookmark"}], "addresses": {"public": [{"version": 4, "addr": "50.57.94.30"}, {"version": 6, "addr": "2001:4801:7808:52:16:3eff:fe77:32e3"}], "private": [{"version": 4, "addr": "10.182.64.29"}, {"version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe6e:b7e2"}]}, "tenant_id": "rs-reach-project", "image": {"id": "7", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark"}]}, "created": "2011-10-11T00:45:02Z", "uuid": "ec53630b-e4fb-442a-a748-c376f5c4345b", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 100, "flavor": {"id": "2", "links": [{"href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark"}]}, "config_drive": "", "id": 12064, "metadata": {}}} ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12065_os_volume_attachments.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12065_os_volume_attachm0000664000175000017500000000032013535474530033365 0ustar kamikami00000000000000{ "volumeAttachment": { "device": "/dev/vdb", "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "serverId": "12065", "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d" } } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12086_console_output.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_12086_console_output.js0000664000175000017500000000007313535474530033361 0ustar kamikami00000000000000{ "output": "FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE" }././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_1c01300f-ef97-4937-8f03-ac676d6234be_os-security-groups.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_1c01300f-ef97-4937-8f030000664000175000017500000000140613535474530032014 0ustar kamikami00000000000000{ "security_groups": [ { "description": "default", "id": 2, "name": "default", "rules": [], "tenant_id": "68" }, { "description": "FTP Client-Server - Open 20-21 ports", "id": 4, "name": "ftp", "rules": [ { "from_port": 20, "group": {}, "id": 1, "ip_protocol": "tcp", "ip_range": { "cidr": "0.0.0.0/0" }, "parent_group_id": 4, "to_port": 21 } ], "tenant_id": "68" } ] } ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_26f7fbee_8ce1_4c28_887a0000664000175000017500000000271613535474530032567 0ustar kamikami00000000000000{ "server": { "status": "BUILD", "updated": "2011-11-30T16:39:19Z", "hostId": "", "user_id": "reach6", "name": "racktest", "links": [ { "href": "http://127.0.0.1/v1.1/68/servers/39d04103-984b-4a52-b4ec-ffec452e284c", "rel": "self" }, { "href": "http://127.0.0.1/68/servers/39d04103-984b-4a52-b4ec-ffec452e284c", "rel": "bookmark" } ], "created": "2011-11-30T16:39:18Z", "tenant_id": "68", "image": { "id": "fcf5582a-ad13-4d98-90a6-742116f1793c", "links": [ { "href": "http://127.0.0.1/68/images/fcf5582a-ad13-4d98-90a6-742116f1793c", "rel": "bookmark" } ] }, "addresses": {}, "accessIPv4": "", "accessIPv6": "", "key_name": "devstack", "progress": null, "flavor": { "id": "1", "links": [ { "href": "http://127.0.0.1/68/flavors/1", "rel": "bookmark" } ] }, "config_drive": "True", "id": "26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", "metadata": { "My Server Name" : "Apache1" }, "OS-DCF:diskConfig": "AUTO", "OS-EXT-AZ:availability_zone": "testaz" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create.json0000664000175000017500000000071113535474530031336 0ustar kamikami00000000000000{ "server": { "id": "26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", "links": [ { "href": "http://127.0.0.1/v1.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", "rel": "self" }, { "href": "http://127.0.0.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", "rel": "bookmark" } ], "adminPass": "racktestvJq7d3" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_create_disk_config.json0000664000175000017500000000076113535474530033702 0ustar kamikami00000000000000{ "server": { "OS-DCF:diskConfig": "MANUAL", "id": "26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", "links": [ { "href": "http://127.0.0.1/v1.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", "rel": "self" }, { "href": "http://127.0.0.1/68/servers/26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe", "rel": "bookmark" } ], "adminPass": "racktestvJq7d3" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail.json0000664000175000017500000001562313535474530031345 0ustar kamikami00000000000000{ "servers": [ { "status": "BUILD", "updated": "2011-10-11T00:50:04Z", "hostId": "912566d83a13fbb357ea3f13c629363d9f7e1ba3f925b49f3d2ab725", "user_id": "rs-reach", "name": "lc-test-2", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12065", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12065", "rel": "bookmark" } ], "addresses": { "public": [ { "version": 4, "addr": "50.57.94.35" }, { "version": 6, "addr": "2001:4801:7808:52:16:3eff:fe47:788a" } ], "private": [ { "version": 4, "addr": "10.182.64.34" }, { "version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe60:187d" } ], "mynetwork": [ { "version": 4, "addr": "12.16.18.28" } ], "mynetwork_public": [ { "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:79:90:aa", "OS-EXT-IPS:type": "floating", "addr": "192.168.3.3", "version": 4 } ], "mynetwork_private": [ { "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:79:90:aa", "OS-EXT-IPS:type": "fixed", "addr": "10.3.3.3", "version": 4 } ], "pubnet": [ { "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:79:90:aa", "OS-EXT-IPS:type": "fixed", "addr": "1.1.1.1", "version": 4 }, { "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:79:90:aa", "OS-EXT-IPS:type": "floating", "addr": "2.2.2.2", "version": 4 } ], "privnet": [ { "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:79:90:aa", "OS-EXT-IPS:type": "floating", "addr": "172.16.1.1", "version": 4 } ] }, "tenant_id": "rs-reach-project", "image": { "id": "7", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark" } ] }, "created": "2011-10-11T00:51:39Z", "uuid": "02786501-714e-40af-8342-9c17eccb166d", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 25, "flavor": { "id": "2", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark" } ] }, "fault": { "id": 1234, "instance_uuid": "ec53630b-e4fb-442a-a748-c376f5c4345b", "code": "500", "message": "test message", "details": "No valid host was found.", "host": "912566d83a13fbb357ea3f13c629363d9f7e1ba3f925b49f3d2ab725" }, "config_drive": "", "id": 12065, "metadata": {}, "OS-DCF:diskConfig": "AUTO", "OS-EXT-STS:task_state": "spawning", "OS-EXT-STS:vm_state": "active", "OS-EXT-STS:power_state": 1 }, { "status": "ACTIVE", "updated": "2011-10-11T00:44:20Z", "hostId": "a024053a6201e6c6c12660aab3d8fd879e332e663a5e1fdbc02a0307", "user_id": "rs-reach", "name": "lc-test", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/v1.1/rs-reach-project/servers/12064", "rel": "self" }, { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/servers/12064", "rel": "bookmark" } ], "addresses": { "public": [ { "version": 4, "addr": "50.57.94.30" }, { "version": 6, "addr": "2001:4801:7808:52:16:3eff:fe77:32e3" } ], "private": [ { "version": 4, "addr": "10.182.64.29" }, { "version": 6, "addr": "fec0:4801:7808:52:16:3eff:fe6e:b7e2" } ] }, "tenant_id": "rs-reach-project", "image": { "id": "7", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/images/7", "rel": "bookmark" } ] }, "created": "2011-10-11T00:45:02Z", "uuid": "ec53630b-e4fb-442a-a748-c376f5c4345b", "accessIPv4": "", "accessIPv6": "", "key_name": null, "progress": 100, "flavor": { "id": "2", "links": [ { "href": "http://alpha.ord.servers.api.rackspacecloud.com:8774/rs-reach-project/flavors/2", "rel": "bookmark" } ] }, "config_drive": "", "id": 12064, "metadata": {}, "OS-DCF:diskConfig": "AUTO", "OS-EXT-STS:task_state": "spawning", "OS-EXT-STS:vm_state": "active", "OS-EXT-STS:power_state": 1 } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_EMPTY.json0000664000175000017500000000002613535474530032312 0ustar kamikami00000000000000{ "servers": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_detail_ERROR_STATE.json0000664000175000017500000000471413535474530033255 0ustar kamikami00000000000000{ "servers": [ { "status": "ERROR", "updated": "2013-12-05T21:07:07Z", "hostId": "2a4a12656a7a57c10188e4ea37f9e09dfb99e3d628f4064f97761e09", "addresses": { "pool": [ { "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:be:f5:87", "version": 4, "addr": "192.168.3.4", "OS-EXT-IPS:type": "fixed" } ] }, "links": [ { "href": "http://192.168.0.1:8774/v2/dd3eca3de72846948f5d6d975660d325/servers/2d05bd68-3fbb-4b47-9f38-c690a5d93e45", "rel": "self" }, { "href": "http://192.168.0.1:8774/dd3eca3de72846948f5d6d975660d325/servers/2d05bd68-3fbb-4b47-9f38-c690a5d93e45", "rel": "bookmark" } ], "key_name": "my_key", "image": "", "OS-EXT-STS:task_state": null, "OS-EXT-STS:vm_state": "error", "OS-SRV-USG:launched_at": null, "flavor": { "id": "4", "links": [ { "href": "http://192.168.0.1:8774/dd3eca3de72846948f5d6d975660d325/flavors/4", "rel": "bookmark" } ] }, "id": "2d05bd68-3fbb-4b47-9f38-c690a5d93e45", "OS-SRV-USG:terminated_at": null, "OS-EXT-AZ:availability_zone": "nova", "user_id": "a75c583fa46148eaa020d3e88ab53802", "name": "test_vm", "created": "2013-12-02T18:40:36Z", "tenant_id": "dd3eca3de72846948f5d6d975660d325", "OS-DCF:diskConfig": "MANUAL", "os-extended-volumes:volumes_attached": [ { "id": "0056485c-ada5-4e44-9905-5b09a18b0139" } ], "accessIPv4": "", "accessIPv6": "", "fault": { "message": "The server has either erred or is incapable of performing the requested operation. (HTTP 500) (Request-ID: req-5ec1e01c-bc04-43e7-957d-c810d4357908)", "code": 500, "created": "2013-12-05T21:07:07Z" }, "OS-EXT-STS:power_state": 0, "config_drive": "", "metadata": {} } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_pause.json0000664000175000017500000000002513535474530031206 0ustar kamikami00000000000000{ "pause": null }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_resume.json0000664000175000017500000000002613535474530031372 0ustar kamikami00000000000000{ "resume": null }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_suspend.json0000664000175000017500000000002713535474530031554 0ustar kamikami00000000000000{ "suspend": null }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_servers_unpause.json0000664000175000017500000000002713535474530031553 0ustar kamikami00000000000000{ "unpause": null }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingip.json0000664000175000017500000000135513535474530031450 0ustar kamikami00000000000000{ "floatingip": { "router_id": null, "description": "for test", "dns_domain": "my-domain.org.", "dns_name": "myfip2", "created_at": "2016-12-21T11:55:50Z", "updated_at": "2016-12-21T11:55:53Z", "revision_number": 2, "project_id": "4969c491a3c74ee4af974e6d800c62de", "tenant_id": "4969c491a3c74ee4af974e6d800c62de", "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", "fixed_ip_address": null, "floating_ip_address": "10.3.1.42", "port_id": null, "id": "09ea1784-2f81-46dc-8c91-244b4df75bde", "status": "DOWN", "port_details": null, "tags": ["tag1,tag2"], "port_forwardings": [] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingips.json0000664000175000017500000000634713570310635031633 0ustar kamikami00000000000000{ "floatingips": [ { "router_id": null, "description": "for test", "dns_domain": "my-domain.org.", "dns_name": "myfip2", "created_at": "2016-12-21T11:55:50Z", "updated_at": "2016-12-21T11:55:53Z", "revision_number": 2, "project_id": "4969c491a3c74ee4af974e6d800c62de", "tenant_id": "4969c491a3c74ee4af974e6d800c62de", "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", "fixed_ip_address": null, "floating_ip_address": "10.3.1.42", "port_id": null, "id": "09ea1784-2f81-46dc-8c91-244b4df75bde", "status": "DOWN", "port_details": null, "tags": ["tag1,tag2"], "port_forwardings": [] }, { "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", "description": "for test", "dns_domain": "my-domain.org.", "dns_name": "myfip", "created_at": "2016-12-21T10:55:50Z", "updated_at": "2016-12-21T10:55:53Z", "revision_number": 1, "project_id": "4969c491a3c74ee4af974e6d800c62de", "tenant_id": "4969c491a3c74ee4af974e6d800c62de", "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", "fixed_ip_address": "10.0.0.3", "floating_ip_address": "10.3.1.1", "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", "id": "04c5336a-0629-4694-ba30-04b0bdfa88a4", "status": "ACTIVE", "port_details": { "status": "ACTIVE", "name": "", "admin_state_up": true, "network_id": "02dd8479-ef26-4398-a102-d19d0a7b3a1f", "device_owner": "compute:nova", "mac_address": "fa:16:3e:b1:3b:30", "device_id": "fcfc96da-19e2-40fd-8497-f29da1b21143" }, "tags": ["tag1,tag2"], "port_forwardings": [] }, { "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", "description": "for test", "dns_domain": "my-domain.org.", "dns_name": "myfip", "created_at": "2016-12-21T10:55:50Z", "updated_at": "2016-12-21T10:55:53Z", "revision_number": 1, "project_id": "4969c491a3c74ee4af974e6d800c62de", "tenant_id": "4969c491a3c74ee4af974e6d800c62de", "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", "fixed_ip_address": "10.0.0.4", "floating_ip_address": "10.3.1.2", "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", "id": "123c5336a-0629-4694-ba30-04b0bdfa88a4", "status": "ACTIVE", "port_details": { "status": "ACTIVE", "name": "", "admin_state_up": true, "network_id": "02dd8479-ef26-4398-a102-d19d0a7b3a1f", "device_owner": "compute:None", "mac_address": "fa:16:3e:b1:3b:30", "device_id": "cb4fba64-19e2-40fd-8497-f29da1b21143" }, "tags": ["tag3"], "port_forwardings": [] } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks.json0000664000175000017500000000426713535474530031175 0ustar kamikami00000000000000{ "networks": [ { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2016-03-08T20:19:41", "dns_domain": "my-domain.org.", "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", "ipv4_address_scope": null, "ipv6_address_scope": null, "l2_adjacency": false, "mtu": 1500, "name": "net1", "port_security_enabled": true, "project_id": "4fd44f30292945e481c7b8a0c8908869", "qos_policy_id": "6a8454ade84346f59e8d40665f878b2e", "revision_number": 1, "router:external": false, "shared": false, "status": "ACTIVE", "subnets": [ "54d6f61d-db07-451c-9ab3-b9609b6b6f0b" ], "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": true, "description": "", "is_default": false }, { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2016-03-08T20:19:41", "dns_domain": "my-domain.org.", "id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", "ipv4_address_scope": null, "ipv6_address_scope": null, "l2_adjacency": false, "mtu": 1500, "name": "net2", "port_security_enabled": true, "project_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "qos_policy_id": "bfdb6c39f71e4d44b1dfbda245c50819", "revision_number": 3, "router:external": false, "shared": false, "status": "ACTIVE", "subnets": [ "08eae331-0402-425a-923c-34f7cfe39c1b" ], "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": false, "description": "", "is_default": false } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_POST.json0000664000175000017500000000213713535474530032034 0ustar kamikami00000000000000{ "network": { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2016-03-08T20:19:41", "dns_domain": "my-domain.org.", "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", "ipv4_address_scope": null, "ipv6_address_scope": null, "l2_adjacency": false, "mtu": 1500, "name": "net1", "port_security_enabled": true, "project_id": "4fd44f30292945e481c7b8a0c8908869", "qos_policy_id": "6a8454ade84346f59e8d40665f878b2e", "revision_number": 1, "router:external": false, "shared": false, "status": "ACTIVE", "subnets": [ "54d6f61d-db07-451c-9ab3-b9609b6b6f0b" ], "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": true, "description": "", "is_default": false } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_public.json0000664000175000017500000000427113535474530032526 0ustar kamikami00000000000000{ "networks": [ { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2016-03-08T20:19:41", "dns_domain": "my-domain.org.", "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", "ipv4_address_scope": null, "ipv6_address_scope": null, "l2_adjacency": false, "mtu": 1500, "name": "public", "port_security_enabled": true, "project_id": "4fd44f30292945e481c7b8a0c8908869", "qos_policy_id": "6a8454ade84346f59e8d40665f878b2e", "revision_number": 1, "router:external": true, "shared": false, "status": "ACTIVE", "subnets": [ "54d6f61d-db07-451c-9ab3-b9609b6b6f0b" ], "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": true, "description": "", "is_default": false }, { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2016-03-08T20:19:41", "dns_domain": "my-domain.org.", "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", "ipv4_address_scope": null, "ipv6_address_scope": null, "l2_adjacency": false, "mtu": 1500, "name": "foobar", "port_security_enabled": true, "project_id": "4fd44f30292945e481c7b8a0c8908869", "qos_policy_id": "6a8454ade84346f59e8d40665f878b2e", "revision_number": 1, "router:external": true, "shared": false, "status": "ACTIVE", "subnets": [ "54d6f61d-db07-451c-9ab3-b9609b6b6f0b" ], "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "updated_at": "2016-03-08T20:19:41", "vlan_transparent": true, "description": "", "is_default": false } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__router.json0000664000175000017500000000233113570310635030621 0ustar kamikami00000000000000{ "router": { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2018-03-19T19:17:04Z", "description": "", "distributed": false, "external_gateway_info": { "enable_snat": true, "external_fixed_ips": [ { "ip_address": "172.24.4.6", "subnet_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf" }, { "ip_address": "2001:db8::9", "subnet_id": "0c56df5d-ace5-46c8-8f4c-45fa4e334d18" } ], "network_id": "ae34051f-aa6c-4c75-abf5-50dc9ac99ef3" }, "flavor_id": "f7b14d9a-b0dc-4fbe-bb14-a0f4970a69e0", "ha": false, "id": "f8a44de0-fc8e-45df-93c7-f79bf3b01c95", "name": "router1", "revision_number": 1, "routes": [], "status": "ACTIVE", "updated_at": "2018-03-19T19:17:22Z", "project_id": "0bd18306d801447bb457a46252d82d13", "tenant_id": "0bd18306d801447bb457a46252d82d13", "service_type_id": null, "tags": ["tag1,tag2"] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__router_interface.json0000664000175000017500000000065613570310635032651 0ustar kamikami00000000000000{ "id": "915a14a6-867b-4af7-83d1-70efceb146f9", "network_id": "91c013e2-d65a-474e-9177-c3e1799ca726", "port_id": "2dc46bcc-d1f2-4077-b99e-91ee28afaff0", "subnet_id": "a2f1f29d-571b-4533-907f-5803ab96ead1", "subnet_ids": [ "a2f1f29d-571b-4533-907f-5803ab96ead1" ], "project_id": "0bd18306d801447bb457a46252d82d13", "tenant_id": "0bd18306d801447bb457a46252d82d13", "tags": ["tag1,tag2"] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__routers.json0000664000175000017500000000553513570310635031015 0ustar kamikami00000000000000{ "routers": [ { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2018-03-19T19:17:04Z", "description": "", "distributed": false, "external_gateway_info": { "enable_snat": true, "external_fixed_ips": [ { "ip_address": "172.24.4.3", "subnet_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf" }, { "ip_address": "2001:db8::c", "subnet_id": "0c56df5d-ace5-46c8-8f4c-45fa4e334d18" } ], "network_id": "ae34051f-aa6c-4c75-abf5-50dc9ac99ef3" }, "flavor_id": "f7b14d9a-b0dc-4fbe-bb14-a0f4970a69e0", "ha": false, "id": "915a14a6-867b-4af7-83d1-70efceb146f9", "name": "router2", "revision_number": 1, "routes": [ { "destination": "179.24.1.0/24", "nexthop": "172.24.3.99" } ], "status": "ACTIVE", "updated_at": "2018-03-19T19:17:22Z", "project_id": "0bd18306d801447bb457a46252d82d13", "tenant_id": "0bd18306d801447bb457a46252d82d13", "service_type_id": null, "tags": ["tag1,tag2"] }, { "admin_state_up": true, "availability_zone_hints": [], "availability_zones": [ "nova" ], "created_at": "2018-03-19T19:17:04Z", "description": "", "distributed": false, "external_gateway_info": { "enable_snat": true, "external_fixed_ips": [ { "ip_address": "172.24.4.6", "subnet_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf" }, { "ip_address": "2001:db8::9", "subnet_id": "0c56df5d-ace5-46c8-8f4c-45fa4e334d18" } ], "network_id": "ae34051f-aa6c-4c75-abf5-50dc9ac99ef3" }, "flavor_id": "f7b14d9a-b0dc-4fbe-bb14-a0f4970a69e0", "ha": false, "id": "f8a44de0-fc8e-45df-93c7-f79bf3b01c95", "name": "router1", "revision_number": 1, "routes": [], "status": "ACTIVE", "updated_at": "2018-03-19T19:17:22Z", "project_id": "0bd18306d801447bb457a46252d82d13", "tenant_id": "0bd18306d801447bb457a46252d82d13", "service_type_id": null, "tags": ["tag1,tag2"] } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__security_group.json0000664000175000017500000000033213535474530032371 0ustar kamikami00000000000000{ "security_group": { "description": "Test Security Group", "id": 6, "name": "test", "security_group_rules": [], "tenant_id": "68" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__security_group_rule.json0000664000175000017500000000044413535474530033424 0ustar kamikami00000000000000{ "security_group_rule": { "security_group_id": 6, "direction": "ingress", "port_range_max": 16, "port_range_min": 14, "remote_ip_prefix": "0.0.0.0/0", "id": 2, "protocol": "tcp" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__security_groups.json0000664000175000017500000000141013535474530032552 0ustar kamikami00000000000000{ "security_groups": [ { "description": "default", "id": 2, "name": "default", "security_group_rules": [], "tenant_id": "68" }, { "description": "FTP Client-Server - Open 20-21 ports", "id": 4, "name": "ftp", "security_group_rules": [ { "security_group_id": 4, "direction": "ingress", "port_range_max": 21, "port_range_min": 20, "remote_ip_prefix": "0.0.0.0/0", "id": 1, "protocol": "tcp" } ], "tenant_id": "68" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__snapshot.json0000664000175000017500000000073513535474530031154 0ustar kamikami00000000000000{ "snapshot": { "status": "available", "os-extended-snapshot-attributes:progress": "100%", "description": "Daily backup", "created_at": "2013-02-25T04:13:17.07Z", "metadata": {}, "volume_id": "5aa119a8-d25b-45a7-8d1b-88e127885635", "os-extended-snapshot-attributes:project_id": "0c2eba2c5af04d3f9e9d0d410b371fde", "size": 1, "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "name": "test" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__snapshots.json0000664000175000017500000000330713535474530031335 0ustar kamikami00000000000000{ "snapshots": [ { "status": "available", "metadata": { "name": "test" }, "os-extended-snapshot-attributes:progress": "100%", "name": "snap-001", "volume_id": "373f7b48-c4c1-4e70-9acc-086b39073506", "os-extended-snapshot-attributes:project_id": "bab7d5c60cd041a0a36f7c4b6e1dd978", "created_at": "2012-02-29T03:50:07Z", "size": 1, "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "description": "volume snapshot" }, { "status": "available", "metadata": { "name": "test" }, "os-extended-snapshot-attributes:progress": "100%", "name": "test-volume-snapshot", "volume_id": "6edbc2f4-1507-44f8-ac0d-eed1d2608d38", "os-extended-snapshot-attributes:project_id": "bab7d5c60cd041a0a36f7c4b6e1dd978", "created_at": "2015-11-29T02:25:51.000000", "size": 1, "id": "4fbbdccf-e058-6502-8844-6feeffdf4cb5", "description": "volume snapshot" }, { "status": "available", "metadata": { "name": "test" }, "os-extended-snapshot-attributes:progress": "100%", "name": "test-volume-snapshot", "volume_id": "373f7b48-c4c1-4e70-9acc-086b39073506", "os-extended-snapshot-attributes:project_id": "bab7d5c60cd041a0a36f7c4b6e1dd978", "created_at": "2013-02-29T03:50:07Z", "size": 1, "id": "1fbbcccf-d058-4502-8844-6feeffdf4cb5", "description": "volume snapshot" } ] } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__snapshots_paginate_start.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__snapshots_paginate_start.0000664000175000017500000000363313535474530033532 0ustar kamikami00000000000000{ "snapshots_links": [ { "href": "https://api.example.com:8776/v2/abcdec85bee34bb0a44ab8255eb36fbd/snapshots?&marker=abcde279-4cc0-4b47-a4ee-ec9c9e474b1b", "rel": "next" } ], "snapshots": [ { "status": "available", "metadata": { "name": "test" }, "os-extended-snapshot-attributes:progress": "100%", "name": "snap-101", "volume_id": "473f7b48-c4c1-4e70-9acc-086b39073506", "os-extended-snapshot-attributes:project_id": "bab7d5c60cd041a0a36f7c4b6e1dd978", "created_at": "2012-02-29T03:50:07Z", "size": 1, "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5", "description": "volume snapshot" }, { "status": "available", "metadata": { "name": "test2" }, "os-extended-snapshot-attributes:progress": "100%", "name": "test-volume-snapshot2", "volume_id": "7edbc2f4-1507-44f8-ac0d-eed1d2608d38", "os-extended-snapshot-attributes:project_id": "bab7d5c60cd041a0a36f7c4b6e1dd978", "created_at": "2015-11-29T02:25:51.000000", "size": 1, "id": "5fbbdccf-e058-6502-8844-6feeffdf4cb5", "description": "volume snapshot" }, { "status": "available", "metadata": { "name": "test2" }, "os-extended-snapshot-attributes:progress": "100%", "name": "test-volume-snapshot", "volume_id": "473f7b48-c4c1-4e70-9acc-086b39073506", "os-extended-snapshot-attributes:project_id": "bab7d5c60cd041a0a36f7c4b6e1dd978", "created_at": "2013-02-29T03:50:07Z", "size": 1, "id": "2fbbcccf-d058-4502-8844-6feeffdf4cb5", "description": "volume snapshot" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__subnet.json0000664000175000017500000000203313535474530030606 0ustar kamikami00000000000000{ "subnet": { "name": "name", "enable_dhcp": true, "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", "segment_id": null, "project_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "dns_nameservers": [], "allocation_pools": [ { "start": "10.0.0.2", "end": "10.0.0.254" } ], "host_routes": [], "ip_version": 4, "gateway_ip": "10.0.0.1", "cidr": "10.0.0.0/24", "id": "08eae331-0402-425a-923c-34f7cfe39c1b", "created_at": "2016-10-10T14:35:34Z", "description": "", "ipv6_address_mode": null, "ipv6_ra_mode": null, "revision_number": 2, "service_types": [], "subnetpool_id": null, "tags": ["tag1,tag2"], "updated_at": "2016-10-10T14:35:34Z" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__subnets.json0000664000175000017500000000410513535474530030773 0ustar kamikami00000000000000{ "subnets": [ { "name": "private-subnet", "enable_dhcp": true, "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324", "segment_id": null, "project_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e", "dns_nameservers": [], "allocation_pools": [ { "start": "10.0.0.2", "end": "10.0.0.254" } ], "host_routes": [], "ip_version": 4, "gateway_ip": "10.0.0.1", "cidr": "10.0.0.0/24", "id": "08eae331-0402-425a-923c-34f7cfe39c1b", "created_at": "2016-10-10T14:35:34Z", "description": "", "ipv6_address_mode": null, "ipv6_ra_mode": null, "revision_number": 2, "service_types": [], "subnetpool_id": null, "tags": ["tag1,tag2"], "updated_at": "2016-10-10T14:35:34Z" }, { "name": "my_subnet", "enable_dhcp": true, "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", "segment_id": null, "project_id": "4fd44f30292945e481c7b8a0c8908869", "tenant_id": "4fd44f30292945e481c7b8a0c8908869", "dns_nameservers": [], "allocation_pools": [ { "start": "192.0.0.2", "end": "192.255.255.254" } ], "host_routes": [], "ip_version": 4, "gateway_ip": "192.0.0.1", "cidr": "192.0.0.0/8", "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b", "created_at": "2016-10-10T14:35:47Z", "description": "", "ipv6_address_mode": null, "ipv6_ra_mode": null, "revision_number": 2, "service_types": [], "subnetpool_id": null, "tags": ["tag1,tag2"], "updated_at": "2016-10-10T14:35:47Z" } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__volume.json0000664000175000017500000000077013535474530030623 0ustar kamikami00000000000000{ "volume": { "status": "available", "attachments": [], "availability_zone": "nova", "bootable": "false", "os-vol-host-attr:host": "ip-10-168-107-25", "source_volid": null, "snapshot_id": null, "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "description": "Super volume.", "name": "test", "created_at": "2013-02-25T02:40:21.000000", "volume_type": "None", "size": 1, "metadata": {} } }././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__volume_abc6a3a1_c4ce_40f6_9b9f_07a61508938d.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__volume_abc6a3a1_c4ce_40f60000664000175000017500000000120513535474530032643 0ustar kamikami00000000000000{ "volume": { "attachments": [ { "device": "/dev/vdb", "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "server_id": "12065", "volume_id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d" } ], "availability_zone": "nova", "created_at": "2013-06-24T11:20:13.000000", "display_description": "", "display_name": "test_volume_2", "id": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", "metadata": {}, "size": 2, "snapshot_id": null, "status": "in-use", "volume_type": "None" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__volumes.json0000664000175000017500000000311413535474530031001 0ustar kamikami00000000000000{ "volumes": [ { "status": "in-use", "attachments": [ { "server_id": "f4fda93b-06e0-4743-8117-bc8bcecd651b", "attachment_id": "3b4db356-253d-4fab-bfa0-e3626c0b8405", "volume_id": "6edbc2f4-1507-44f8-ac0d-eed1d2608d38", "device": "/dev/vdb", "id": "6edbc2f4-1507-44f8-ac0d-eed1d2608d38" } ], "availability_zone": "nova", "replication_status": "disabled", "snapshot_id": null, "id": "6edbc2f4-1507-44f8-ac0d-eed1d2608d38", "size": 2, "user_id": "32779452fcd34ae1a53a797ac8a1e064", "metadata": {}, "description": "", "name": "test-volume-attachments", "created_at": "2013-06-24T11:20:13.000000", "volume_type": "lvmdriver-1" }, { "status": "some-unknown-state", "migration_status": null, "attachments": [], "availability_zone": "nova", "replication_status": "disabled", "snapshot_id": "01f48111-7866-4cd2-986a-e92683c4a363", "id": "cfcec3bc-b736-4db5-9535-4c24112691b5", "size": 50, "user_id": "32779452fcd34ae1a53a797ac8a1e064", "metadata": {}, "description": "some description", "name": "test_volume", "bootable": "false", "created_at": "2013-06-21T12:39:02.000000", "volume_type": null } ] } ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/delete_floating_ip_167_138_123_111.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/openstack_v1.1/delete_floating_ip_167_138_123_10000664000175000017500000000000013535474530032614 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/0000775000175000017500000000000013600223624023316 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/auth_time_get.json0000664000175000017500000000001313535474530027034 0ustar kamikami000000000000001437075564 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/flavor_get.json0000664000175000017500000000050513535474530026354 0ustar kamikami00000000000000[{"id":"foo-id","disk":80,"name":"ovh.intel.ha.l","ram":8192,"vcpus":2,"region":"SBG1","type":"ovh.ceph.eg","inboundBandwidth":511,"osType":"Linux"},{"id":"bar-id","disk":80,"name":"ovh.intel.ha.l","ram":8192,"vcpus":2,"region":"SBG1","type":"ovh.ceph.eg", "outboundBandwidth": 511,"inboundBandwidth": 511,"osType":"Linux"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/flavor_get_detail.json0000664000175000017500000000014513535474530027676 0ustar kamikami00000000000000{"id":"foo-id","disk":80,"name":"ra.intel.ha.l","ram":8192,"vcpus":2,"region":"SBG-1","type":"ra.s"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/image_get.json0000664000175000017500000000027013535474530026144 0ustar kamikami00000000000000[{"id":"foo-id","name":"Debian 8","region":"SBG-1","visibility":"public","deprecated":false},{"id":"bar-id","name":"CentOs","region":"SBG-1","visibility":"public","deprecated":false}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/image_get_detail.json0000664000175000017500000000013413535474530027465 0ustar kamikami00000000000000{"id":"foo-id","name":"Debian 8","region":"SBG-1","visibility":"public","deprecated":false} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/instance_get.json0000664000175000017500000000114213535474530026665 0ustar kamikami00000000000000[{"id":"foo","name":"test_vm","ipAddresses":[{"networkId":"","version":4, "ip":"92.0.0.1","type":"public"}],"flavorId":"551dc104-4174-495a-af34-4aafe75f22ca","imageId":"1f3b49ad-3566-4838-93f8-b657a36b870f","sshKeyId":"6447567a6447746c655bad3d","status":"ACTIVE","created":"2015-05-29T11:20:48Z","region":"SBG1"}, {"id":"bar","name":"test_vm2","ipAddresses":[{"networkId":"","version":4, "ip":"92.0.0.2","type":"public"}],"flavorId":"551dc104-4174-495a-af34-4aafe75f22ca","imageId":"1f3b49ad-3566-4838-93f8-b657a36b870f","sshKeyId":"mykey","status":"ACTIVE","created":"2015-05-29T11:40:48Z","region":"SBG-1"}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/instance_get_detail.json0000664000175000017500000000302513535474530030211 0ustar kamikami00000000000000{"status":"ACTIVE","region":"SBG1","name":"test_vm","image":{"visibility":"public","status":"active","region":"SBG1","name":"Ubuntu12.04","minDisk":0,"size":2.19921875,"creationDate":"2016-06-01T07:39:56Z","minRam":0,"user":"ubuntu","id":"3031ed24-8337-4b09-94b5-e51c54bec6c8","type":"linux"},"created":"2016-10-05T19:17:14Z","sshKey":{"fingerPrint":"7d:25:ec:f9:53:91:95:13:45:f9:73:a1:33:f0:00:00","regions":["SBG1"],"name":"testkey","id":"6447567a6447746c65513d3d","publicKey":"ssh-rsaAAAAB3NzaC1yc2EAAAADAQABAAACAQC80oMgRmfbUzNWk/H2vlUl2ISHjLwIUFz+b9jB2hCXoWLluyQN4dZqebusWwUUpAzzBpUcrPLYKyPcI0H9eAJaieK1QQX7gfaWLZnvHgm64i3lkDM5HbXqxd5ZL7FqEb8UbYqiR0AK05/JCvz0ux0Qb1oXMKbs+cwYuWhTgr10tumbkSyv8MZ2hamtJt3W176F3NJuNBXTKvzWmFF6AFpdUQWMgbo86SKRlnR8Q+3YiTaaPxEXSpD120QYaDFWpdvVL+IMS5ywRrFqrDoHFbsUEPEjsPHSd/B7hbjacE8dkz5BxHAGse2vNrPzcTnvw2ovj4+xQymqH7nCxv4pD++YYzeLyhyU93Zq5e9Wp72zSSfqE4X8qJsGw+zj7RZThN/imRPrg+z96ZCIpxcvOt1gsQNXsHzF3dfThssO9JR/SjyTaGcy0yn7oyhI324YtwsaNmBXo3FdZTTaJ8MRHkwQolBvhCY74uHX6cZW38UHh1+O92ExLq4JWu1dx4r9o9yrkA78kl8IoXfstxr4dpAZQIh27Z+wqbw8cpwjvkDvFr1kcrK7aifhezpihrboizhgoibnzbnefnoapfnzpiafzipanfipzanfpznaipfzapfneirnsboiseibreiosbrioebgipapigbezpiabgipezbgpiabeiprbgzbg6jfGQ=="},"monthlyBilling":null,"id":"cc350b4a-b04b-41d2-959d-1f8f388877a2","ipAddresses":[{"networkId":"","version":4,"ip":"92.0.0.1","type":"public"}],"flavor":{"outboundBandwidth":102,"disk":10,"region":"SBG1","name":"vps-ssd-1","inboundBandwidth":102,"id":"98c1e679-5f2c-4069-b4da-4a4f7179b758","vcpus":1,"type":"ovh.vps-ssd","osType":"linux","ram":2000}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/instance_post.json0000664000175000017500000000216213535474530027076 0ustar kamikami00000000000000{"instanceId":"df4e55cb-90e6-4f20-a604-7084f311f498","name":"testvm","ipv4":"","created":"2015-07-16T22:35:55Z","status":"BUILD","flavor":{"id":"551dc104-4174-495a-af34-4aafe75f22ca","disk":30,"name":"ra.intel.sb.l","ram":4096,"vcpus":1,"region":"SBG-1","type":"ra.sb"},"image":{"id":"1f3b49ad-3566-4838-93f8-b657a36b870f","name":"Debian 8","region":"SBG-1","visibility":"","deprecated":false},"sshKey":{"publicKey":"ssh-dss AAAAB3NzaC1kc3MAAACBALDA8LBVhtEDgns2AFtF4hO7BckyFWUyuwCUy1Frh8UZSkrhRtfNcrbir/qcoql5psB8k1+qdqfq6RB/wYjXAqtoVNF+ydCgh5D0aWKSveYH9F/zuwyH+CGcu+fBLo/q6JAqnXziFluK9jcnu1vam3FvTD9nAsx5UYSvdTo+axlbAAAAFQCFBEBKWuCabLfUQpAoiMQSNpCsFQAAAIAVHwW6+LyDPyS/o6aV6icX0Gw8K9AG4zjj+OZWd0HxJP/Rn7ND1YrY63WC2vUAbmR0hrmoa3dS1Fw6553n+Ks41z9xzLydW8jLiopI655LrDtnMEzDpIYtr8idKq3j3IvmBfynvzhmb0r101agiMdEKsUJjGQbRAbL42pej5ee5gAAAIAbdNorJ2iFrcz8OyYi25Vjap+gqFGUYMwaHlta26WWf+ZHQdX/Kqsc4n4twkb94jjoj7doiBjN7aRAr9f3JEDUboTatpdOzanU9gSrryCBykz5RK016wwOU8fxdmaar/U47qEKa4TYwmYyA5UH+KmbYmJExC5ovXlI25oAbc1eQg== amonthe@amonthe","name":"mykey","fingerPrint":"75:19:bf:48:dc:31:5b:91:b2:e5:ba:3b:fa:dc:ef:a7","region":"BHS-1"},"region":"SBG-1"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/region_get.json0000664000175000017500000000002713535474530026345 0ustar kamikami00000000000000["SBG1","BHS1","GRA1"] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/ssh_get.json0000664000175000017500000000123113535474530025655 0ustar kamikami00000000000000[{"publicKey":"ssh-dss AAAAB3NzaC1kc3MAAACBALDA8LBVhtEDgns2AFtF4hO7BckyFWUyuwCUy1Frh8UZSkrhRtfNcrbir/qcoql5psB8k1+qdqfq6RB/wYjXAqtoVNF+ABCDE5D0aWKSveYH9F/zuwyABCDEu+fBLo/q6JAqnXziFluK9jcnu1vam3FvTABCDEx5UYSvdTo+axlbAAAAFQCFBEABCDEabLfUQpAoiMQSNpCsFQAAAIAVHwW6ABCDEyS/o6aV6icX0Gw8K9AG4zjj+OZWd0HxJP/RnABCDErY63WC2vUAbmR0hrmoa3dS1Fw6553n+Ks41z9xzLydWABCDEpI655LrDtnMEzDpIYtr8idKq3j3IvmBfynvzhmb0r101agiMdEKsUJjGQbRAbL42ABCDEe5gAAAIAbdNorJ2iFrcz8OyYi25Vjap+gqFGUYMwaHlta26WWf+ZHQABCDEsc4n4twkb94jjoj7doiBjN7aRABCDEJEDUboTatpdOzanU9gSrryCBykz5RK016wwOU8fxdmaar/U47qEKa4TYwmYyA5UH+KmbYmJExC5ovXlI25oAbc1eQg== user@host","name":"mykey","id":"ham-id","regions":["SGB1"]}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/ssh_get_detail.json0000664000175000017500000000122713535474530027204 0ustar kamikami00000000000000{"publicKey":"ssh-dss AAAAB3NzaC1kc3MAAACBALDA8LBVhtEDgns2AFtF4hO7BckyFWUyuwCUy1Frh8UZSkrhRtfNcrbir/qcoql5psB8k1+qdqfq6RB/wYjXAqtoVNF+ABCDE5D0aWKSveYH9F/zuwyABCDEu+fBLo/q6JAqnXziFluK9jcnu1vam3FvTABCDEx5UYSvdTo+axlbAAAAFQCFBEABCDEabLfUQpAoiMQSNpCsFQAAAIAVHwW6ABCDEyS/o6aV6icX0Gw8K9AG4zjj+OZWd0HxJP/RnABCDErY63WC2vUAbmR0hrmoa3dS1Fw6553n+Ks41z9xzLydWABCDEpI655LrDtnMEzDpIYtr8idKq3j3IvmBfynvzhmb0r101agiMdEKsUJjGQbRAbL42ABCDEe5gAAAIAbdNorJ2iFrcz8OyYi25Vjap+gqFGUYMwaHlta26WWf+ZHQABCDEsc4n4twkb94jjoj7doiBjN7aRABCDEJEDUboTatpdOzanU9gSrryCBykz5RK016wwOU8fxdmaar/U47qEKa4TYwmYyA5UH+KmbYmJExC5ovXlI25oAbc1eQg== user@host","name":"mykey","id":"ham-id","regions":["SGB1"]} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/volume_get.json0000664000175000017500000000027313535474530026374 0ustar kamikami00000000000000[{"id": "foo", "attachedTo": [], "created": "2015-08-09T15:13:59.459187Z", "name": "testvol", "description": "", "size": 10, "status": "creating", "region": "SBG-1", "type": "classic" }] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/volume_get_detail.json0000664000175000017500000000027113535474530027714 0ustar kamikami00000000000000{"id": "foo", "attachedTo": [], "created": "2015-08-09T15:13:59.459187Z", "name": "testvol", "description": "", "size": 10, "status": "creating", "region": "SBG-1", "type": "classic" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/volume_snapshot_get.json0000664000175000017500000000066713535474530030322 0ustar kamikami00000000000000[ { "volumeId": "foo", "status": "available", "region": "GRA1", "name": "", "description": "", "size": 10, "creationDate": "2016-10-10T17:33:02Z", "id": "foo-snap" }, { "volumeId": "bar", "status": "available", "region": "GRA1", "name": "", "description": "", "size": 10, "creationDate": "2016-10-09T17:33:02Z", "id": "bar-snap" } ] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/ovh/volume_snapshot_get_details.json0000664000175000017500000000030413535474530032013 0ustar kamikami00000000000000{ "volumeId": "foo", "status": "available", "region": "GRA1", "name": "", "description": "", "size": 10, "creationDate": "2016-10-10T17:33:02Z", "id": "foo-snap" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/0000775000175000017500000000000013600223624023771 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/associate_ip.json0000664000175000017500000000215613570310635027340 0ustar kamikami00000000000000{ "id": "aea4ee0c-675f-4b77-8337-8e13b868dd9c", "address_family": 4, "netmask": "255.255.255.255", "created_at": "2019-04-09T15:58:58Z", "details": null, "public": true, "cidr": 32, "management": false, "manageable": true, "enabled": true, "global_ip": true, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"] }, "assigned_to": { "href": "/devices/756db520-fa13-4a8c-858c-b3ceb60ce95f" }, "interface": { "href": "/ports/15506112-efa2-4467-9e03-4d038a1db2e2" }, "network": "147.75.40.2", "address": "147.75.40.2", "gateway": "147.75.40.2", "href": "/ips/aea4ee0c-675f-4b77-8337-8e13b868dd9c" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/attach_volume.json0000664000175000017500000000052513570310635027526 0ustar kamikami00000000000000{ "id": "f2909129-6445-4f7f-8fdf-65c9a1c342e9", "created_at": "2019-04-20T16:53:59Z", "volume": { "href": "/storage/a08aaf76-e0ce-43aa-b9cd-cce0d4ae4f4c" }, "device": { "href": "/devices/756db520-fa13-4a8c-858c-b3ceb60ce95f" }, "href": "/storage/attachments/f2909129-6445-4f7f-8fdf-65c9a1c342e9" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/bgp_config_project_1.json0000664000175000017500000000064613570310635030742 0ustar kamikami00000000000000{ "id": "02dde1ca-a360-4bc5-9c08-897bbd22536a", "status": "enabled", "deployment_type": "local", "asn": 65000, "md5": null, "route_object": null, "max_prefix": 10, "created_at": "2019-03-08T12:03:01Z", "requested_at": "2019-03-08T12:03:01Z", "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "sessions": [], "ranges": [], "href": "/bgp-configs/02dde1ca-a360-4bc5-9c08-897bbd22536a" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/bgp_config_project_2.json0000664000175000017500000000065113570310635030737 0ustar kamikami00000000000000{ "id": "6e3a1b3b-f8de-4d3c-9b4c-be097af6e199", "status": "requested", "deployment_type": "global", "asn": 65000, "md5": null, "route_object": null, "max_prefix": 10, "created_at": "2019-03-08T12:03:47Z", "requested_at": "2019-03-08T12:03:47Z", "project": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df" }, "sessions": [], "ranges": [], "href": "/bgp-configs/6e3a1b3b-f8de-4d3c-9b4c-be097af6e199" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/bgp_config_project_3.json0000664000175000017500000000000213570310635030726 0ustar kamikami00000000000000{}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/bgp_session_create.json0000664000175000017500000000067713570310635030541 0ustar kamikami00000000000000{ "id": "08f6b756-758b-4f1f-bfaf-b9b5479822d7", "status": "unknown", "learned_routes": [], "switch_name": "esr1.r04b01.ams1.packet.net", "default_route": null, "created_at": "2019-03-21T17:24:59Z", "updated_at": "2019-03-21T17:24:59Z", "device": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" }, "address_family": "ipv4", "href": "/bgp/sessions/08f6b756-758b-4f1f-bfaf-b9b5479822d7" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/bgp_session_get.json0000664000175000017500000000067413570310635030052 0ustar kamikami00000000000000{ "id": "08f6b756-758b-4f1f-bfaf-b9b5479822d7", "status": "down", "learned_routes": [], "switch_name": "esr1.r04b01.ams1.packet.net", "default_route": null, "created_at": "2019-03-21T17:24:59Z", "updated_at": "2019-03-21T17:25:10Z", "device": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" }, "address_family": "ipv4", "href": "/bgp/sessions/08f6b756-758b-4f1f-bfaf-b9b5479822d7" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/bgp_sessions.json0000664000175000017500000000101213570310635027361 0ustar kamikami00000000000000{ "bgp_sessions": [{ "id": "08f6b756-758b-4f1f-bfaf-b9b5479822d7", "status": "down", "learned_routes": [], "switch_name": "esr1.r04b01.ams1.packet.net", "default_route": null, "created_at": "2019-03-21T17:24:59Z", "updated_at": "2019-03-21T17:25:10Z", "device": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" }, "address_family": "ipv4", "href": "/bgp/sessions/08f6b756-758b-4f1f-bfaf-b9b5479822d7" }] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/create_volume.json0000664000175000017500000000200713570310635027522 0ustar kamikami00000000000000{ "id": "a08aaf76-e0ce-43aa-b9cd-cce0d4ae4f4c", "name": "volume-a08aaf76", "description": "test volume", "size": 10, "locked": false, "billing_cycle": "hourly", "state": "queued", "customdata": {}, "access": {}, "created_at": "2019-04-20T16:16:44Z", "updated_at": "2019-04-20T16:16:44Z", "project": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df" }, "facility": { "href": "/facilities/8e6470b3-b75e-47d1-bb93-45b225750975" }, "snapshot_policies": [], "attachments": [], "snapshots": [], "plan": { "id": "87728148-3155-4992-a730-8d1e6aca8a32", "slug": "storage_1", "name": "Standard", "description": "TBD", "line": "storage", "specs": {}, "legacy": true, "deployment_types": [], "available_in": [], "class": "storage_1", "pricing": { "hour": 0.000104 } }, "href": "/storage/a08aaf76-e0ce-43aa-b9cd-cce0d4ae4f4c" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/device_create.json0000664000175000017500000000420513535474530027462 0ustar kamikami00000000000000{ "userdata": null, "operating_system": { "distro": "coreos", "slug": "coreos_stable", "version": "stable", "name": "CoreOS (stable)" }, "locked": false, "tags": [], "href": "/devices/9f7eafab-CCCC-DDDD-EEEE-c2a686367791", "created_at": "2015-05-22T17:59:43Z", "hostname": "9f7eafab.packethost.net", "updated_at": "2015-05-22T17:59:43.972Z", "project": { "href": "/projects/746ea6dd-CCCC-DDDD-EEEE-728784671fbf" }, "provisioning_percentage": 0.0, "state": "queued", "billing_cycle": "hourly", "user": "core", "ip_addresses": [], "facility": { "id": "e1e9c52e-a0bc-4117-b996-0fc94843ea09" }, "id": "9f7eafab-6f6b-4ae4-988d-c2a686367791", "provisioning_events": [ { "body": "Provisioning started", "relationships": [], "interpolated": "Provisioning started", "created_at": null, "type": "provisioning.101", "id": null }, { "body": "Network configured", "relationships": [], "interpolated": "Network configured", "created_at": null, "type": "provisioning.102", "id": null }, { "body": "Configuration written, restarting device", "relationships": [], "interpolated": "Configuration written, restarting device", "created_at": null, "type": "provisioning.103", "id": null }, { "body": "Device phoned home and is ready to go", "relationships": [], "interpolated": "Device phoned home and is ready to go", "created_at": null, "type": "provisioning.110", "id": null }], "plan": { "slug": "baremetal_1", "description": "Our Type 1 configuration is a zippy general use server", "id": "6d1f1ffa-7912-4b78-b50d-88cc7c8ab40f", "pricing": { "hourly": 0.4 }, "line": "baremetal", "specs": { "nics": [{"count": 2, "type": "gigabit"}], "drives": [{"count": 2, "type": "SSD", "size": "120GB"}], "features": {"txt": true, "raid": true}, "cpus": [{"count": 1, "type": "Intel E3-1240 v3"}], "memory": {"total": "16GB"} }, "name": "Type 1" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/device_events.json0000664000175000017500000001312713570310635027520 0ustar kamikami00000000000000{ "events": [ { "id": "31256dd5-9e4c-4dbb-9989-bbc13da01958", "type": "power.200", "body": "Reboot operation queued", "state": null, "created_at": "2019-03-21T15:34:25Z", "relationships": [ { "href": "#e1fb1cd1-c507-4119-bff6-789ee11d8418" } ], "ip": "157.52.105.28", "modified_by": { "id": "bd4f24f3-33f0-46a6-9528-4e31e2ba6074", "full_name": "Dimitris Moraitis", "avatar_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm", "avatar_thumb_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm" }, "interpolated": "Reboot operation queued", "href": "/events/31256dd5-9e4c-4dbb-9989-bbc13da01958" }, { "id": "c1b136d1-6d55-45c8-b2b3-fb993e6fb55e", "type": "power.203", "body": "Device rebooted", "state": null, "created_at": "2019-03-21T15:34:25Z", "relationships": [ { "href": "#65ffb1c3-7123-4ac3-9768-3bd1789f6380" } ], "ip": null, "modified_by": null, "interpolated": "Device rebooted", "href": "/events/c1b136d1-6d55-45c8-b2b3-fb993e6fb55e" }, { "id": "580a5b8b-ac04-45b7-a16d-a8bcf199c6fa", "type": "power.204", "body": "Device powered on", "state": null, "created_at": "2019-03-05T18:21:50Z", "relationships": [ { "href": "#c38eccc8-2b1b-4eee-8a56-c2059530d35b" } ], "ip": null, "modified_by": null, "interpolated": "Device powered on", "href": "/events/580a5b8b-ac04-45b7-a16d-a8bcf199c6fa" }, { "id": "e4944204-9f09-49ce-aff3-4b2e64b5c9d2", "type": "power.201", "body": "Power operation started", "state": null, "created_at": "2019-03-05T18:21:39Z", "relationships": [ { "href": "#a042e3ba-b1cb-436a-b98d-d59d8d6fedde" } ], "ip": null, "modified_by": null, "interpolated": "Power operation started", "href": "/events/e4944204-9f09-49ce-aff3-4b2e64b5c9d2" }, { "id": "a072109c-5957-4b7e-9c98-0a6a90310cfd", "type": "power.200", "body": "Power on operation queued", "state": null, "created_at": "2019-03-05T18:21:39Z", "relationships": [ { "href": "#a0a02f25-461c-41d9-812f-4c17a08ece86" } ], "ip": "104.156.95.42", "modified_by": { "id": "446476b8-a835-414a-8e9c-84925cc72705", "full_name": "Markos Gogoulos", "avatar_url": "https://www.gravatar.com/avatar/fafa2cd3f9d378981e87a993661859b4?d=mm", "avatar_thumb_url": "https://www.gravatar.com/avatar/fafa2cd3f9d378981e87a993661859b4?d=mm" }, "interpolated": "Power on operation queued", "href": "/events/a072109c-5957-4b7e-9c98-0a6a90310cfd" }, { "id": "eb1a5f74-a48b-4632-a5b6-e20b1a3589ee", "type": "power.202", "body": "Device powered off", "state": null, "created_at": "2019-03-05T18:19:42Z", "relationships": [ { "href": "#e1ad01ed-deda-42f0-9c01-6262d54f66b4" } ], "ip": null, "modified_by": null, "interpolated": "Device powered off", "href": "/events/eb1a5f74-a48b-4632-a5b6-e20b1a3589ee" }, { "id": "71b9e370-4e15-4307-8c10-27d3585088eb", "type": "power.200", "body": "Power off operation queued", "state": null, "created_at": "2019-03-05T18:19:02Z", "relationships": [ { "href": "#090422c3-cc6e-4a83-947a-591016a21b2e" } ], "ip": "104.156.95.48", "modified_by": { "id": "446476b8-a835-414a-8e9c-84925cc72705", "full_name": "Markos Gogoulos", "avatar_url": "https://www.gravatar.com/avatar/fafa2cd3f9d378981e87a993661859b4?d=mm", "avatar_thumb_url": "https://www.gravatar.com/avatar/fafa2cd3f9d378981e87a993661859b4?d=mm" }, "interpolated": "Power off operation queued", "href": "/events/71b9e370-4e15-4307-8c10-27d3585088eb" }, { "id": "8d871c11-c59b-41bc-849c-8853b9f29252", "type": "power.201", "body": "Power operation started", "state": null, "created_at": "2019-03-05T18:19:02Z", "relationships": [ { "href": "#68469965-4801-4dde-831e-ca2cc27dda59" } ], "ip": null, "modified_by": null, "interpolated": "Power operation started", "href": "/events/8d871c11-c59b-41bc-849c-8853b9f29252" }, { "id": "13c330d5-5cc6-4a2d-8ada-b2c239171f50", "type": "power.200", "body": "Reboot operation queued", "state": null, "created_at": "2019-02-28T20:10:12Z", "relationships": [ { "href": "#7b95e08b-84d9-4e83-869e-ea98e7c052fd" } ], "ip": "104.156.95.25", "modified_by": { "id": "446476b8-a835-414a-8e9c-84925cc72705", "full_name": "Markos Gogoulos", "avatar_url": "https://www.gravatar.com/avatar/fafa2cd3f9d378981e87a993661859b4?d=mm", "avatar_thumb_url": "https://www.gravatar.com/avatar/fafa2cd3f9d378981e87a993661859b4?d=mm" }, "interpolated": "Reboot operation queued", "href": "/events/13c330d5-5cc6-4a2d-8ada-b2c239171f50" }, { "id": "68eab1cc-a9a0-4f23-8274-1d71043ed3e1", "type": "power.203", "body": "Device rebooted", "state": null, "created_at": "2019-02-28T20:10:12Z", "relationships": [ { "href": "#6b5506b9-d4c9-4467-9ec8-5e887f2f8ae8" } ], "ip": null, "modified_by": null, "interpolated": "Device rebooted", "href": "/events/68eab1cc-a9a0-4f23-8274-1d71043ed3e1" } ], "meta": { "first": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b/events?page=1" }, "previous": null, "self": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b/events?page=1" }, "next": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b/events?page=2" }, "last": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b/events?page=5" }, "current_page": 1, "last_page": 5, "total": 49 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/devices.json0000664000175000017500000000403713570310635026317 0ustar kamikami00000000000000{ "devices": [ { "id": "1e52437e-bbbb-cccc-dddd-74a9dfd3d3bb", "hostname": "test-node", "state": "active", "tags": [], "billing_cycle": "hourly", "user": "root", "userdata": "", "locked": false, "created_at": "2015-05-03T15:50:49Z", "updated_at": "2015-05-03T16:00:08Z", "operating_system": { "slug": "ubuntu_14_04", "name": "Ubuntu 14.04 LTS", "distro": "ubuntu", "version": "14.04" }, "project": { "href": "/projects/project-id" }, "facility": { "id": "e1e9c52e-a0bc-4117-b996-0fc94843ea09" }, "plan": { "id": "6d1f1ffa-7912-4b78-b50d-88cc7c8ab40f", "slug": "baremetal_1", "name": "Type 1", "description": "Our Type 1 configuration is a zippy general use server", "line": "baremetal", "specs": { "cpus": [{"count":1,"type":"Intel E3-1240 v3"}], "memory": {"total":"16GB" }, "drives": [{"count":2,"size":"120GB","type":"SSD"}], "nics": [{"count":2,"type":"gigabit"}], "features": {"raid":true, "txt":true} }, "pricing": { "hour":0.4 } }, "ip_addresses": [ { "address_family": 4,"netmask":"255.255.255.255","cidr":32,"address":"147.75.255.255","gateway":"147.75.255.255","public":true }, { "address_family": 6,"netmask":"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe","cidr":32,"address":"2604:EEEE::EE","gateway":"2604:1380::EE","public":true }, { "address_family": 4,"netmask":"255.255.255.255","cidr":32,"address":"10.0.0.255","gateway":"10.0.0.255","public":false } ], "href": "/devices/1e52437e-bbbb-cccc-dddd-74a9dfd3d3bb" } ], "meta": { "first": { "href":"/projects/project-id/devices?page=1" }, "previous":null, "self": { "href":"/projects/project-id/devices?page=1" }, "next": null, "last": { "href":"/projects/project-id/devices?page=1" }, "total": 1 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/devices_for_project.json0000664000175000017500000002476213570310635030722 0ustar kamikami00000000000000{ "devices": [ { "id": "905037a4-967c-4e81-b364-3a0603aa071b", "short_id": "905037a4", "hostname": "mistopenstack", "description": null, "state": "active", "tags": [], "image_url": null, "billing_cycle": "hourly", "user": "root", "iqn": "iqn.2018-04.net.packet:device.905037a4", "locked": false, "bonding_mode": 4, "created_at": "2018-04-02T18:02:39Z", "updated_at": "2019-03-21T15:35:18Z", "ipxe_script_url": null, "always_pxe": false, "storage": {}, "customdata": {}, "operating_system": { "id": "68bad60d-f5a7-45c2-ad09-573edaad3a3c", "slug": "centos_7", "name": "CentOS 7", "distro": "centos", "version": "7", "provisionable_on": [ "c1.large.arm", "baremetal_2a", "c1.small.x86", "baremetal_1", "c1.xlarge.x86", "baremetal_3", "c2.medium.x86", "d1f.optane.x86", "d1p.optane.x86", "g2.large.x86", "m1.xlarge.x86", "baremetal_2", "m2.xlarge.x86", "s1.large.x86", "baremetal_s", "t1.small.x86", "baremetal_0", "x1.small.x86", "baremetal_1e" ], "preinstallable": true, "pricing": {}, "licensed": false }, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": [ "baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2" ], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": [ "2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23" ] }, "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "ssh_keys": [ { "href": "/ssh-keys/54b6c270-b37f-4740-a06f-8287d7c7375a" }, { "href": "/ssh-keys/6a641836-f622-40a3-9156-a88112ee2e03" }, { "href": "/ssh-keys/7b982d07-0ea3-415e-a35c-3dfb6b358267" }, { "href": "/ssh-keys/23640808-0983-4b5c-b251-2f7715f5450a" }, { "href": "/ssh-keys/410f8090-8d2d-4bce-8855-43142503f3a4" }, { "href": "/ssh-keys/d8c9bfc1-0201-4e18-b70d-67333847f804" }, { "href": "/ssh-keys/2b361661-efaa-429e-8d22-30e64853efe4" }, { "href": "/ssh-keys/94a4d3d4-672a-4670-948b-feda8127758c" }, { "href": "/ssh-keys/632d69f1-52f4-435b-9424-3b1e8c725812" }, { "href": "/ssh-keys/733852c6-8cd0-41c3-bf2e-6aac7c7a7a35" }, { "href": "/ssh-keys/bfc69d73-c8c7-4027-8aed-7c6bd88eb278" }, { "href": "/ssh-keys/2b38c95c-02dc-4ce8-961c-9d2ce8763647" }, { "href": "/ssh-keys/97898a92-7df8-4e1f-8f87-9631f7de4a81" }, { "href": "/ssh-keys/22f9fd4c-ab3d-47f5-92ac-7d5703084d3d" }, { "href": "/ssh-keys/4dcb7264-25d2-42db-b25f-d5ebaa8b6410" }, { "href": "/ssh-keys/944bb692-3aa8-449e-9d29-3b4e1028b148" }, { "href": "/ssh-keys/cf8abbdd-a484-43c3-ba62-627a16594594" }, { "href": "/ssh-keys/2af51313-c514-4145-907f-f7445ca2e5ad" }, { "href": "/ssh-keys/e0af33d3-0e2c-456a-a4d6-206558de66d6" }, { "href": "/ssh-keys/502178f5-b985-466b-980e-f01ba028e5fc" }, { "href": "/ssh-keys/a46796e6-ee03-4aa5-bf71-f54344a1d1f9" }, { "href": "/ssh-keys/9af94154-e38f-4a77-8cd2-8e6455fc8129" }, { "href": "/ssh-keys/56b9d292-8ed8-43c5-8687-a436979d1ac0" }, { "href": "/ssh-keys/1fd6e5a9-966d-4937-89b2-e269ff1d447a" } ], "project_lite": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "volumes": [], "ip_addresses": [ { "id": "f73172c4-4955-4376-8089-aad2daaf16eb", "address_family": 4, "netmask": "255.255.255.254", "created_at": "2018-04-02T18:02:40Z", "details": null, "public": true, "cidr": 31, "management": true, "manageable": true, "enabled": true, "global_ip": null, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": [ "baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2" ], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": [ "2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23" ] }, "assigned_to": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" }, "interface": { "href": "/ports/115bb6c2-325d-4a70-ad07-c81f4d094000" }, "network": "147.75.102.192", "address": "147.75.102.193", "gateway": "147.75.102.192", "href": "/ips/f73172c4-4955-4376-8089-aad2daaf16eb" }, { "id": "366abb1f-3f79-42d7-8b0b-fab4950eca57", "address_family": 6, "netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", "created_at": "2018-04-02T18:02:40Z", "details": null, "public": true, "cidr": 127, "management": true, "manageable": true, "enabled": true, "global_ip": null, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": [ "baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2" ], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": [ "2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23" ] }, "assigned_to": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" }, "interface": { "href": "/ports/115bb6c2-325d-4a70-ad07-c81f4d094000" }, "network": "2604:1380:2000:c100::2", "address": "2604:1380:2000:c100::3", "gateway": "2604:1380:2000:c100::2", "href": "/ips/366abb1f-3f79-42d7-8b0b-fab4950eca57" }, { "id": "9addbf38-5c0c-47d6-b485-f8364b5b37c0", "address_family": 4, "netmask": "255.255.255.254", "created_at": "2018-04-02T18:02:40Z", "details": null, "public": false, "cidr": 31, "management": true, "manageable": true, "enabled": true, "global_ip": null, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": [ "baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2" ], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": [ "2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23" ] }, "assigned_to": { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" }, "interface": { "href": "/ports/115bb6c2-325d-4a70-ad07-c81f4d094000" }, "network": "10.80.144.130", "address": "10.80.144.131", "gateway": "10.80.144.130", "href": "/ips/9addbf38-5c0c-47d6-b485-f8364b5b37c0" } ], "plan": { "id": "6d1f1ffa-7912-4b78-b50d-88cc7c8ab40f", "slug": "baremetal_1", "name": "c1.small.x86", "description": "Our Type 1 configuration is a zippy general use server, with an Intel E3-1240 v3 processor and 32GB of RAM.", "line": "baremetal", "specs": { "cpus": [ { "count": 1, "type": "Intel E3-1240 v3" } ], "memory": { "total": "32GB" }, "drives": [ { "count": 2, "size": "120GB", "type": "SSD" } ], "nics": [ { "count": 2, "type": "1Gbps" } ], "features": { "raid": true, "txt": true } }, "legacy": false, "deployment_types": [ "on_demand", "spot_market" ], "available_in": [ { "href": "/facilities/2b70eb8f-fa18-47c0-aba7-222a842362fd" }, { "href": "/facilities/8ea03255-89f9-4e62-9d3f-8817db82ceed" }, { "href": "/facilities/8e6470b3-b75e-47d1-bb93-45b225750975" } ], "class": "c1.small.x86", "pricing": { "hour": 0.4 } }, "userdata": "", "switch_uuid": "d67ca07f", "network_ports": [ { "id": "115bb6c2-325d-4a70-ad07-c81f4d094000", "type": "NetworkBondPort", "name": "bond0", "data": { "bonded": true }, "network_type": "layer3", "native_virtual_network": null, "hardware": { "href": "/hardware/137a9e9b-3173-4372-b13c-e61b710adfeb" }, "virtual_networks": [], "connected_port": null, "href": "/ports/115bb6c2-325d-4a70-ad07-c81f4d094000" }, { "id": "458e6773-408e-4697-a289-11c19bd7e4cb", "type": "NetworkPort", "name": "eth0", "data": { "mac": "0c:c4:7a:b2:11:78", "bonded": true }, "bond": { "id": "115bb6c2-325d-4a70-ad07-c81f4d094000", "name": "bond0" }, "native_virtual_network": null, "hardware": { "href": "/hardware/137a9e9b-3173-4372-b13c-e61b710adfeb" }, "virtual_networks": [], "connected_port": { "href": "/ports/486ce54d-61ba-491e-b772-8e521060d802" }, "href": "/ports/458e6773-408e-4697-a289-11c19bd7e4cb" }, { "id": "ed4090dc-a08c-4f3d-8d4b-03c46cf84ef0", "type": "NetworkPort", "name": "eth1", "data": { "mac": "0c:c4:7a:b2:11:79", "bonded": true }, "bond": { "id": "115bb6c2-325d-4a70-ad07-c81f4d094000", "name": "bond0" }, "native_virtual_network": null, "hardware": { "href": "/hardware/137a9e9b-3173-4372-b13c-e61b710adfeb" }, "virtual_networks": [], "connected_port": { "href": "/ports/0b4e5127-7536-41d1-887f-6ec797204ed8" }, "href": "/ports/ed4090dc-a08c-4f3d-8d4b-03c46cf84ef0" } ], "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" } ], "meta": { "first": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5/devices?page=1" }, "previous": null, "self": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5/devices?page=1" }, "next": null, "last": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5/devices?page=1" }, "current_page": 1, "last_page": 1, "total": 1 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/facilities.json0000664000175000017500000000041113535474530027007 0ustar kamikami00000000000000{ "facilities": [ { "id": "e1e9c52e-a0bc-4117-b996-0fc94843ea09", "name": "Parsippany, NJ", "code": "ewr1", "features": ["baremetal"], "address": null, "href": "/facilities/e1e9c52e-a0bc-4117-b996-0fc94843ea09" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/ip_address.json0000664000175000017500000000231613570310635027010 0ustar kamikami00000000000000{ "facility": { "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL" }, "href": "/ips/01c184f5-1413-4b0b-9f6d-ac993f6c9241", "id": "01c184f5-1413-4b0b-9f6d-ac993f6c9241", "management": false, "address_family": 4, "customdata": {}, "gateway": "147.75.33.33", "details": null, "addon": true, "public": true, "available": "/ips/01c184f5-1413-4b0b-9f6d-ac993f6c9241/available", "project_lite": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "netmask": "255.255.255.240", "address": "147.75.33.34", "cidr": 28, "manageable": true, "network": "147.75.33.32", "created_at": "2017-12-29T10:59:59Z", "bill": true, "enabled": true, "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "assignments": [], "global_ip": false }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/ip_assignments.json0000664000175000017500000001450713570310635027723 0ustar kamikami00000000000000{ "ip_addresses": [{ "id": "ccf66471-c139-4204-927c-e005aac20308", "address_family": 4, "netmask": "255.255.255.248", "created_at": "2019-04-06T16:13:48Z", "details": null, "public": true, "cidr": 29, "management": true, "manageable": true, "enabled": true, "global_ip": null, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"] }, "assigned_to": { "href": "/devices/756db520-fa13-4a8c-858c-b3ceb60ce95f" }, "interface": { "href": "/ports/15506112-efa2-4467-9e03-4d038a1db2e2" }, "network": "147.75.204.216", "address": "147.75.204.218", "gateway": "147.75.204.217", "href": "/ips/ccf66471-c139-4204-927c-e005aac20308" }, { "id": "aea4ee0c-675f-4b77-8337-8e13b868dd9c", "address_family": 4, "netmask": "255.255.255.255", "created_at": "2019-04-09T15:58:58Z", "details": null, "public": true, "cidr": 32, "management": false, "manageable": true, "enabled": true, "global_ip": true, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"] }, "assigned_to": { "href": "/devices/756db520-fa13-4a8c-858c-b3ceb60ce95f" }, "interface": { "href": "/ports/15506112-efa2-4467-9e03-4d038a1db2e2" }, "network": "147.75.40.2", "address": "147.75.40.2", "gateway": "147.75.40.2", "href": "/ips/aea4ee0c-675f-4b77-8337-8e13b868dd9c" }, { "id": "60f6b4ba-3468-4aa2-8639-37c208c1b018", "address_family": 4, "netmask": "255.255.255.254", "created_at": "2019-04-08T10:49:22Z", "details": null, "public": true, "cidr": 31, "management": false, "manageable": true, "enabled": true, "global_ip": false, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"] }, "assigned_to": { "href": "/devices/756db520-fa13-4a8c-858c-b3ceb60ce95f" }, "interface": { "href": "/ports/15506112-efa2-4467-9e03-4d038a1db2e2" }, "network": "147.75.100.12", "address": "147.75.100.13", "gateway": "147.75.100.12", "href": "/ips/60f6b4ba-3468-4aa2-8639-37c208c1b018" }, { "id": "56cb4e97-508b-4869-b3e9-0a5b9454e75c", "address_family": 6, "netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", "created_at": "2019-04-06T16:13:48Z", "details": null, "public": true, "cidr": 127, "management": true, "manageable": true, "enabled": true, "global_ip": null, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"] }, "assigned_to": { "href": "/devices/756db520-fa13-4a8c-858c-b3ceb60ce95f" }, "interface": { "href": "/ports/15506112-efa2-4467-9e03-4d038a1db2e2" }, "network": "2604:1380:2000:5a00::", "address": "2604:1380:2000:5a00::1", "gateway": "2604:1380:2000:5a00::", "href": "/ips/56cb4e97-508b-4869-b3e9-0a5b9454e75c" }, { "id": "9e63854a-fa56-4f05-bf4a-28e54ee8d0d3", "address_family": 4, "netmask": "255.255.255.248", "created_at": "2019-04-06T16:13:48Z", "details": null, "public": false, "cidr": 29, "management": true, "manageable": true, "enabled": true, "global_ip": null, "customdata": {}, "project": {}, "project_lite": {}, "facility": { "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL", "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"] }, "assigned_to": { "href": "/devices/756db520-fa13-4a8c-858c-b3ceb60ce95f" }, "interface": { "href": "/ports/15506112-efa2-4467-9e03-4d038a1db2e2" }, "network": "10.80.58.0", "address": "10.80.58.2", "gateway": "10.80.58.1", "href": "/ips/9e63854a-fa56-4f05-bf4a-28e54ee8d0d3" }] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/node_bandwidth.json0000664000175000017500000001225413570310635027646 0ustar kamikami00000000000000{ "bandwidth": [{ "datapoints": [ [1052.032698, 1553194500], [1055.92461, 1553194560], [1050.016926, 1553194620], [1245.116514, 1553194680], [1034.070997, 1553194740], [1010.820992, 1553194800], [951.920896, 1553194860], [1148.937385, 1553194920], [1065.573677, 1553194980], [1094.001969, 1553195040], [1072.862652, 1553195100], [1034.897575, 1553195160], [1185.426244, 1553195220], [1042.176035, 1553195280], [997.822217, 1553195340], [1152.909521, 1553195400], [922.635817, 1553195460], [1105.585486, 1553195520], [1047.65336, 1553195580], [881.732485, 1553195640], [1110.465301, 1553195700], [916.823838, 1553195760], [1096.549182, 1553195820], [976.962368, 1553195880], [1025.246754, 1553195940], [1091.528324, 1553196000], [996.620406, 1553196060], [1246.460364, 1553196120], [1053.393289, 1553196180], [1142.337976, 1553196240], [1086.332225, 1553196300], [1024.480602, 1553196360], [1234.467001, 1553196420], [1082.616506, 1553196480], [1086.723205, 1553196540], [1112.280105, 1553196600], [965.456206, 1553196660], [1250.384913, 1553196720], [1086.283225, 1553196780], [951.436363, 1553196840], [1131.955347, 1553196900], [1150.404805, 1553196960], [1286.614545, 1553197020], [1154.660863, 1553197080], [1137.028738, 1553197140], [1117.174178, 1553197200], [1066.04981, 1553197260], [1029.530732, 1553197320], [1041.113197, 1553197380], [1111.102835, 1553197440], [1127.673851, 1553197500], [1215.903109, 1553197560], [1210.630661, 1553197620], [1252.226899, 1553197680], [1170.912932, 1553197740], [null, 1553197800], [1170.437927, 1553197860], [1172.572302, 1553197920], [1211.585068, 1553197980], [1233.890989, 1553198040] ], "target": "inbound", "tags": { "aggregatedBy": "sum", "name": "sumSeries(port_graphs.ams1.r04b01.esr1.snmp.if_octets.137a9e9b-3173-4372-b13c-e61b710adfeb.*.tx)" } }, { "datapoints": [ [67156.831912, 1553194500], [57623.730489, 1553194560], [67405.892198, 1553194620], [78231.821897, 1553194680], [66846.849647, 1553194740], [67790.149327, 1553194800], [57886.094865, 1553194860], [76756.910925, 1553194920], [67434.035079, 1553194980], [67356.660892, 1553195040], [67328.09619, 1553195100], [58194.381384, 1553195160], [77639.00637900001, 1553195220], [67131.05764300001, 1553195280], [67067.391321, 1553195340], [67966.786864, 1553195400], [57542.517921, 1553195460], [77412.270766, 1553195520], [67840.39929, 1553195580], [56609.998671, 1553195640], [77860.693942, 1553195700], [57295.253973000006, 1553195760], [77519.583025, 1553195820], [67373.184895, 1553195880], [67382.167208, 1553195940], [66387.07162999999, 1553196000], [59419.339432, 1553196060], [74900.485453, 1553196120], [67401.84082900001, 1553196180], [67144.668065, 1553196240], [68322.09083199999, 1553196300], [59302.568578, 1553196360], [75509.93379499999, 1553196420], [67320.626162, 1553196480], [67081.068903, 1553196540], [69223.298241, 1553196600], [58405.435035, 1553196660], [77068.310851, 1553196720], [65697.986408, 1553196780], [59492.110587, 1553196840], [67563.536622, 1553196900], [68411.859222, 1553196960], [74990.79763, 1553197020], [70011.950444, 1553197080], [66047.779855, 1553197140], [68602.36716299999, 1553197200], [58428.295839, 1553197260], [65968.97434, 1553197320], [67252.11346, 1553197380], [67783.156785, 1553197440], [69352.705059, 1553197500], [68064.90661600001, 1553197560], [67756.92176, 1553197620], [67751.32907299999, 1553197680], [67313.458015, 1553197740], [null, 1553197800], [68523.033516, 1553197860], [67122.56114399999, 1553197920], [68034.312268, 1553197980], [66906.68454, 1553198040] ], "target": "outbound", "tags": { "aggregatedBy": "sum", "name": "sumSeries(port_graphs.ams1.r04b01.esr1.snmp.if_octets.137a9e9b-3173-4372-b13c-e61b710adfeb.*.rx)" } }] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/operatingsystems.json0000664000175000017500000000100113535474530030307 0ustar kamikami00000000000000{ "operating_systems": [ { "slug": "centos_7", "name": "CentOS 7", "distro": "centos", "version": "7" }, { "slug": "coreos_stable", "name": "CoreOS (stable)", "distro": "coreos", "version": "stable" }, { "slug": "ubuntu_14_04", "name": "Ubuntu 14.04 LTS", "distro": "ubuntu", "version": "14.04" }, { "slug": "debian_7", "name": "Debian 7", "distro": "debian", "version": "7" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/plans.json0000664000175000017500000000110013535474530026004 0ustar kamikami00000000000000{ "plans": [ { "id": "6d1f1ffa-7912-4b78-b50d-88cc7c8ab40f", "slug": "baremetal_1", "name": "Type 1", "description": "Our Type 1 configuration is a zippy general use server", "line": "baremetal", "specs": { "cpus":[{"count":1,"type":"Intel E3-1240 v3"}], "memory":{"total":"16GB"}, "drives":[{"count":2,"size":"120GB","type":"SSD"}], "nics":[{"count":2,"type":"gigabit"}], "features":{"raid":true,"txt":true} }, "pricing": { "hourly":0.4,"monthly":250.0 } } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/project_events.json0000664000175000017500000000621013570310635027722 0ustar kamikami00000000000000{ "events": [ { "id": "6e91f6a7-b01b-479f-b5bb-1791e3a7840c", "type": "virtual_network.assigned", "body": "Dimitris assigned the VNID 1011 to \"%project%\" in ams1.", "state": null, "created_at": "2019-03-21T15:31:42Z", "relationships": [ { "href": "#0911cfa1-f089-46c1-80bd-e1c83ae57ba0" }, { "href": "#384585e9-7655-4c4b-b816-061a72fd256c" } ], "ip": "157.52.105.28", "modified_by": { "id": "bd4f24f3-33f0-46a6-9528-4e31e2ba6074", "full_name": "Dimitris Moraitis", "avatar_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm", "avatar_thumb_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm" }, "interpolated": "Dimitris assigned the VNID 1011 to \"Packet Integration Testing [Sponsored]\" in ams1.", "href": "/events/6e91f6a7-b01b-479f-b5bb-1791e3a7840c" }, { "id": "c4016ce2-9c53-4616-a087-029755292919", "type": "ip_reservation.assigned", "body": "Dimitris requested an IP range of /31 be added to \"%project%\" in ams1 and got assigned 147.75.100.12/31.", "state": null, "created_at": "2019-03-21T15:31:28Z", "relationships": [ { "href": "#495145fb-61ec-4483-80ef-cf6989b836cc" }, { "href": "#a38801d1-56db-4744-96f7-54a3bf4e9c8a" }, { "href": "#37d36535-e983-48d0-831a-5fc9d4143412" } ], "ip": "157.52.105.28", "modified_by": { "id": "bd4f24f3-33f0-46a6-9528-4e31e2ba6074", "full_name": "Dimitris Moraitis", "avatar_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm", "avatar_thumb_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm" }, "interpolated": "Dimitris requested an IP range of /31 be added to \"Packet Integration Testing [Sponsored]\" in ams1 and got assigned 147.75.100.12/31.", "href": "/events/c4016ce2-9c53-4616-a087-029755292919" }, { "id": "af57627a-4e41-4d50-8e1b-c80fee4f2284", "type": "bgp_config.requested", "body": "Global BGP was requested to be enabled on project \"%project%\"", "state": null, "created_at": "2019-03-08T12:03:47Z", "relationships": [ { "href": "#6935e72e-7822-485e-b87a-238a56282731" }, { "href": "#d6297ecd-f294-46b1-98c2-647bf55e31c8" } ], "ip": "157.52.92.50", "modified_by": { "id": "bd4f24f3-33f0-46a6-9528-4e31e2ba6074", "full_name": "Dimitris Moraitis", "avatar_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm", "avatar_thumb_url": "https://www.gravatar.com/avatar/702119decab6288093449009ab5af843?d=mm" }, "interpolated": "Global BGP was requested to be enabled on project \"Packet Integration Testing [Sponsored]\"", "href": "/events/af57627a-4e41-4d50-8e1b-c80fee4f2284" } ], "meta": { "first": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df/events?page=1" }, "previous": null, "self": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df/events?page=1" }, "next": null, "last": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df/events?page=1" }, "current_page": 1, "last_page": 1, "total": 3 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/project_ips.json0000664000175000017500000001726313570310635027223 0ustar kamikami00000000000000{ "ip_addresses": [ { "facility": { "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL" }, "href": "/ips/01c184f5-1413-4b0b-9f6d-ac993f6c9241", "id": "01c184f5-1413-4b0b-9f6d-ac993f6c9241", "management": false, "address_family": 4, "customdata": {}, "gateway": "147.75.33.33", "details": null, "addon": true, "public": true, "available": "/ips/01c184f5-1413-4b0b-9f6d-ac993f6c9241/available", "project_lite": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "netmask": "255.255.255.240", "address": "147.75.33.34", "cidr": 28, "manageable": true, "network": "147.75.33.32", "created_at": "2017-12-29T10:59:59Z", "bill": true, "enabled": true, "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "assignments": [], "global_ip": false }, { "facility": { "code": "ewr1", "features": ["baremetal", "storage", "backend_transfer", "layer_2", "global_ipv4"], "ip_ranges": ["2604:1380::/36", "147.75.192.0/21", "147.75.64.0/22", "147.75.72.0/22", "147.75.76.0/22", "147.75.104.0/22", "147.75.96.0/20"], "address": null, "id": "e1e9c52e-a0bc-4117-b996-0fc94843ea09", "name": "Parsippany, NJ" }, "href": "/ips/612f75c1-9563-46bd-8532-e118e16f8b69", "id": "612f75c1-9563-46bd-8532-e118e16f8b69", "management": false, "address_family": 4, "customdata": {}, "gateway": "147.75.194.213", "details": null, "addon": true, "public": true, "available": "/ips/612f75c1-9563-46bd-8532-e118e16f8b69/available", "project_lite": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "netmask": "255.255.255.252", "address": "147.75.194.214", "cidr": 30, "manageable": true, "network": "147.75.194.212", "created_at": "2015-11-23T17:19:28Z", "bill": true, "enabled": true, "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "assignments": [], "global_ip": false }, { "facility": { "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL" }, "href": "/ips/bad31403-3b39-4877-aa7e-a88109c4bd83", "id": "bad31403-3b39-4877-aa7e-a88109c4bd83", "management": false, "address_family": 4, "customdata": {}, "gateway": "147.75.205.225", "details": null, "addon": true, "public": true, "available": "/ips/bad31403-3b39-4877-aa7e-a88109c4bd83/available", "project_lite": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "netmask": "255.255.255.240", "address": "147.75.205.226", "cidr": 28, "manageable": true, "network": "147.75.205.224", "created_at": "2016-05-30T18:03:15Z", "bill": true, "enabled": true, "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "assignments": [], "global_ip": false }, { "facility": { "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL" }, "href": "/ips/6a308ab2-84b6-4bac-80f7-89396c7a8323", "id": "6a308ab2-84b6-4bac-80f7-89396c7a8323", "management": false, "address_family": 6, "customdata": {}, "gateway": "2604:1380:2000:c100::1", "details": null, "addon": false, "public": true, "available": "/ips/6a308ab2-84b6-4bac-80f7-89396c7a8323/available", "project_lite": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "netmask": "ffff:ffff:ffff:ff00:0000:0000:0000:0000", "address": "2604:1380:2000:c100::2", "cidr": 56, "manageable": true, "network": "2604:1380:2000:c100::", "created_at": "2017-12-29T11:11:39Z", "bill": false, "enabled": true, "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "assignments": [{ "href": "/ips/366abb1f-3f79-42d7-8b0b-fab4950eca57" }], "global_ip": null }, { "facility": { "code": "ams1", "features": ["baremetal", "storage", "global_ipv4", "backend_transfer", "layer_2"], "ip_ranges": ["2604:1380:2000::/36", "147.75.204.0/23", "147.75.100.0/22", "147.75.80.0/22", "147.75.32.0/23"], "address": { "href": "#0688e909-647e-4b21-bdf2-fc056d993fc5" }, "id": "8e6470b3-b75e-47d1-bb93-45b225750975", "name": "Amsterdam, NL" }, "href": "/ips/022114e7-d405-4fd6-839e-fdc67f28cc18", "id": "022114e7-d405-4fd6-839e-fdc67f28cc18", "management": false, "address_family": 4, "customdata": {}, "gateway": "10.80.144.129", "details": null, "addon": false, "public": false, "available": "/ips/022114e7-d405-4fd6-839e-fdc67f28cc18/available", "project_lite": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "netmask": "255.255.255.128", "address": "10.80.144.130", "cidr": 25, "manageable": true, "network": "10.80.144.128", "created_at": "2017-12-29T11:11:39Z", "bill": false, "enabled": true, "project": { "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" }, "assignments": [{ "href": "/ips/9addbf38-5c0c-47d6-b485-f8364b5b37c0" }], "global_ip": null }] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/projects.json0000664000175000017500000000562713570310635026534 0ustar kamikami00000000000000{ "projects": [ { "id": "3d27fd13-0466-4878-be22-9a4b5595a3df", "name": "Packet Integration Testing [Sponsored]", "created_at": "2019-02-07T17:33:22Z", "updated_at": "2019-02-07T17:33:51Z", "backend_transfer_enabled": false, "customdata": {}, "event_alert_configuration": null, "memberships": [], "invitations": [], "devices": [], "ssh_keys": [], "volumes": [], "members": [ { "href": "/users/446476b8-a835-414a-8e9c-84925cc72705" }, { "href": "/users/4b36e749-9218-4bf2-a64d-b47e0170e2ec" }, { "href": "/users/bd4f24f3-33f0-46a6-9528-4e31e2ba6074" } ], "transfers": [], "organization": { "href": "/organizations/1432653f-f993-47c5-949e-af3c0de48d70" }, "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df" }, { "id": "4a4bce6b-d2ef-41f8-95cf-0e2f32996440", "name": "Docker Cloud", "created_at": "2016-03-07T14:34:05Z", "updated_at": "2019-02-07T14:25:46Z", "backend_transfer_enabled": false, "customdata": {}, "event_alert_configuration": { "href": "#5bfd51ac-a8f3-4c96-af56-4d952e53f204" }, "memberships": [], "invitations": [], "devices": [], "ssh_keys": [], "volumes": [], "members": [ { "href": "/users/446476b8-a835-414a-8e9c-84925cc72705" }, { "href": "/users/4b36e749-9218-4bf2-a64d-b47e0170e2ec" }, { "href": "/users/bd4f24f3-33f0-46a6-9528-4e31e2ba6074" } ], "transfers": [], "organization": { "href": "/organizations/1432653f-f993-47c5-949e-af3c0de48d70" }, "href": "/projects/4a4bce6b-d2ef-41f8-95cf-0e2f32996440" }, { "id": "4b653fce-6405-4300-9f7d-c587b7888fe5", "name": "mist.io Integration [Sponsored]", "created_at": "2015-11-10T14:53:29Z", "updated_at": "2019-02-07T17:34:26Z", "backend_transfer_enabled": false, "customdata": {}, "event_alert_configuration": { "href": "#04a29153-a740-423f-a129-7134468797b9" }, "memberships": [], "invitations": [], "devices": [ { "href": "/devices/905037a4-967c-4e81-b364-3a0603aa071b" } ], "ssh_keys": [ { "href": "/ssh-keys/4dcb7264-25d2-42db-b25f-d5ebaa8b6410" }, { "href": "/ssh-keys/944bb692-3aa8-449e-9d29-3b4e1028b148" } ], "volumes": [], "members": [ { "href": "/users/446476b8-a835-414a-8e9c-84925cc72705" }, { "href": "/users/4b36e749-9218-4bf2-a64d-b47e0170e2ec" }, { "href": "/users/bd4f24f3-33f0-46a6-9528-4e31e2ba6074" } ], "transfers": [], "organization": { "href": "/organizations/1432653f-f993-47c5-949e-af3c0de48d70" }, "href": "/projects/4b653fce-6405-4300-9f7d-c587b7888fe5" } ], "meta": { "first": { "href": "/projects?page=1" }, "previous": null, "self": { "href": "/projects?page=1" }, "next": null, "last": { "href": "/projects?page=1" }, "current_page": 1, "last_page": 1, "total": 3 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/reserve_ip.json0000664000175000017500000000145113570310635027035 0ustar kamikami00000000000000{ "id": "31ae66fe-ee00-4f50-be25-60eeca8718ff", "address_family": 4, "netmask": "255.255.255.255", "created_at": "2019-04-06T23:05:17Z", "details": null, "public": true, "cidr": 32, "management": false, "manageable": true, "enabled": true, "global_ip": true, "customdata": {}, "addon": true, "bill": true, "project": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df" }, "project_lite": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df" }, "assignments": [], "facility": null, "network": "147.75.40.2", "address": "147.75.40.2", "gateway": "147.75.40.2", "available": "/ips/31ae66fe-ee00-4f50-be25-60eeca8718ff/available", "href": "/ips/31ae66fe-ee00-4f50-be25-60eeca8718ff" }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/sshkey_create.json0000664000175000017500000000142513535474530027532 0ustar kamikami00000000000000{ "id": "2c1a7f23-1dc6-4a37-948e-d9857d9f607c", "label": "ubuntu1404-201505221415a4c7757e-5198-4f49-82d4-35eb2d06eb27", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDI4pIqzpb5g3992h+yr527VRcaB68KE4vPjWPPoiQws49KIs2NMcOzS9QE4641uW1u5ML2HgQdfYKMF/YFGnI1Y6xV637DjhDyZYV9LasUH49npSSJjsBcsk9JGfUpNAOdcgpFzK8V90eiOrOC5YncxdwwG8pwjFI9nNVPCl4hYEu1iXdyysHvkFfS2fklsNjLWrzfafPlaen+qcBxygCA0sFdW/7er50aJeghdBHnE2WhIKLUkJxnKadznfAge7oEe+3LLAPfP+3yHyvp2+H0IzmVfYvAjnzliYetqQ8pg5ZW2BiJzvqz5PebGS70y/ySCNW1qQmJURK/Wc1bt9en root@libcloud.local.lan\n", "fingerprint": "aa:49:46:57:2a:07:64:56:33:07:ef:76:1d:54:a3:41", "created_at": "2015-05-22T18:15:04Z", "updated_at":"2015-05-22T18:15:04Z", "user": { "href":"/users/userid" }, "href": "/ssh-keys/2c1a7f23-1dc6-4a37-948e-d9857d9f607c" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/sshkeys.json0000664000175000017500000000472213535474530026375 0ustar kamikami00000000000000{ "ssh_keys":[ { "id": "2c1a7f23-1dc6-4a37-948e-d9857d9f607c", "label": "ubuntu1404-201505221415a4c7757e-5198-4f49-82d4-35eb2d06eb27", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDI4pIqzpb5g3992h+yr527VRcaB68KE4vPjWPPoiQws49KIs2NMcOzS9QE4641uW1u5ML2HgQdfYKMF/YFGnI1Y6xV637DjhDyZYV9LasUH49npSSJjsBcsk9JGfUpNAOdcgpFzK8V90eiOrOC5YncxdwwG8pwjFI9nNVPCl4hYEu1iXdyysHvkFfS2fklsNjLWrzfafPlaen+qcBxygCA0sFdW/7er50aJeghdBHnE2WhIKLUkJxnKadznfAge7oEe+3LLAPfP+3yHyvp2+H0IzmVfYvAjnzliYetqQ8pg5ZW2BiJzvqz5PebGS70y/ySCNW1qQmJURK/Wc1bt9en root@libcloud.local.lan\n", "fingerprint": "aa:49:46:57:2a:07:64:56:33:07:ef:76:1d:54:a3:41", "created_at": "2015-05-22T18:15:04Z", "updated_at":"2015-05-22T18:15:04Z", "user": { "href":"/users/userid" }, "href": "/ssh-keys/2c1a7f23-1dc6-4a37-948e-d9857d9f607c" }, { "id": "e5ee91f4-ecf7-4a68-9a4e-6443cf2d7eb0", "label": "ubuntu1404-201505212115f8161afd-7034-498f-aa04-a8d5562d3455", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc7qwbxJetidi4PnM0hxBLXfW+u/h2boNJZdEd5Bky2CRwIlMwPFqw3zEHrZyh05Ypw3wchvhxLVAC++5XbB7dbKPs7WAtQaZWiqJXVfacaIywyiuNgmdGv7V7gJLOZwLF1sFVisTjAtSLkroidzwX3Btxba+NcGlCVt2Zg2fPbHSUV4tnvzWpQsUBejoJ4pWxP84ty7GPymrRwnjm+qAztCy3RVGtrAAYp04Q/UeIZfi2TBrjZ8y39T8hx8RaQjA1H/+47IEDe+U7rJpxNR9tcZdEryhpH7YP5XFoHo8Y8IiLOKJo6gN0tK1zajoXw7/2oXdGE0Qqx2/VIvivdu6J root@libcloud.local.lan\n", "fingerprint": "83:b8:0a:30:08:5e:27:50:db:25:d7:a7:ff:ab:aa:0a", "created_at": "2015-05-22T01:15:04Z", "updated_at": "2015-05-22T01:15:04Z", "user": { "href":"/users/userid" }, "href": "/ssh-keys/e5ee91f4-ecf7-4a68-9a4e-6443cf2d7eb0" }, { "id": "561b54e7-4a2b-4832-a165-567ebb8c8bfb", "label": "ubuntu1404-201505211245623a7e97-0826-4f62-b337-e7fc592b748a", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCd+HRs6t4/n3LRnvzObeph2ggNNu7P+U8xMJNVE2qfjbrdJP26D4ELDVFbaSCBetYoU6G0IOlUnggZ4g7MPB6eicB5RZEOvAh58pIEgUqnWdZgDbLLY+ZGRwuaFAk6aof3bWDDqd3PUn+HtzNz3EK6Ow09vuYe1RFXLyUcDdb/LJG1bSUw/W+bEjBi/gMIcvomkSz5px40zJL4Bulqy3XPvJyxPweZbsT6LsQkBSstqTNkPH+IYWpUrOVoWy4+etVQ0OOWUXbgMyPtM5qh8JovhkQe5wn1bEV+Fw1LAJ5MF8UKr45k7hZrWfjuyCK1EA3o2Ptn+LpZW4CbCfKuFDg3 root@libcloud.local.lan\n", "fingerprint": "ed:17:56:d0:03:66:39:f6:3c:03:c5:e6:ec:ac:c4:32", "created_at": "2015-05-21T16:45:03Z", "updated_at": "2015-05-21T16:45:03Z", "user": { "href":"/users/userid" }, "href": "/ssh-keys/561b54e7-4a2b-4832-a165-567ebb8c8bfb" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/packet/volumes.json0000664000175000017500000000544313570310635026371 0ustar kamikami00000000000000{ "volumes": [ { "id": "a08aaf76-e0ce-43aa-b9cd-cce0d4ae4f4c", "name": "volume-a08aaf76", "description": "test volume", "size": 10, "locked": false, "billing_cycle": "hourly", "state": "active", "customdata": {}, "access": { "ips": [ "10.144.136.81", "10.144.140.205" ], "iqn": "iqn.2013-05.com.daterainc:tc:01:sn:a0fe42b1c3d239bc" }, "created_at": "2019-04-20T16:16:44Z", "updated_at": "2019-04-20T17:00:35Z", "project": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df" }, "facility": { "href": "/facilities/8e6470b3-b75e-47d1-bb93-45b225750975" }, "snapshot_policies": [], "attachments": [], "snapshots": [], "plan": { "id": "87728148-3155-4992-a730-8d1e6aca8a32", "slug": "storage_1", "name": "Standard", "description": "TBD", "line": "storage", "specs": {}, "legacy": true, "deployment_types": [], "available_in": [], "class": "storage_1", "pricing": { "hour": 0.000104 } }, "href": "/storage/a08aaf76-e0ce-43aa-b9cd-cce0d4ae4f4c" }, { "id": "74f11291-fde8-4abf-8150-e51cda7308c3", "name": "volume-74f11291", "description": null, "size": 10, "locked": false, "billing_cycle": "hourly", "state": "active", "customdata": {}, "access": { "ips": [ "10.144.136.49", "10.144.140.22" ], "iqn": "iqn.2013-05.com.daterainc:tc:01:sn:aeb3ffc6a28aa5a8" }, "created_at": "2019-04-12T16:11:49Z", "updated_at": "2019-04-20T17:23:51Z", "project": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df" }, "facility": { "href": "/facilities/8e6470b3-b75e-47d1-bb93-45b225750975" }, "snapshot_policies": [], "attachments": [ { "href": "/storage/attachments/2c16a96f-bb4f-471b-8e2e-b5820b9e1603" } ], "snapshots": [ { "href": "#07e762ee-9441-4bce-aad1-400572396ef0" }, { "href": "#b3e5bad7-a219-46d8-8835-b332e9aa4cd9" }, { "href": "#a6176d93-03d1-4a53-a2f3-58f01f48ee95" } ], "plan": { "id": "87728148-3155-4992-a730-8d1e6aca8a32", "slug": "storage_1", "name": "Standard", "description": "TBD", "line": "storage", "specs": {}, "legacy": true, "deployment_types": [], "available_in": [], "class": "storage_1", "pricing": { "hour": 0.000104 } }, "href": "/storage/74f11291-fde8-4abf-8150-e51cda7308c3" } ], "meta": { "first": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df/storage?page=1" }, "previous": null, "self": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df/storage?page=1" }, "next": null, "last": { "href": "/projects/3d27fd13-0466-4878-be22-9a4b5595a3df/storage?page=1" }, "current_page": 1, "last_page": 1, "total": 2 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/0000775000175000017500000000000013600223624025223 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/attach_volume.json0000664000175000017500000000175013535474530030767 0ustar kamikami00000000000000{ "id" : "vol-2", "type" : "volume", "href" : "/cloudapi/v4/datacenters/dc-1/volumes/vol-2", "metadata" : { "createdDate" : "2016-10-17T13:13:36Z", "createdBy" : "test@test.te", "etag" : "c1800ce349033f9cd2c095ea1ea4976a", "lastModifiedDate" : "2016-10-17T13:47:52Z", "lastModifiedBy" : "test@test.te", "state" : "BUSY" }, "properties" : { "name" : "libcloud Test", "type" : "HDD", "size" : 2, "image" : "bvol-img", "imagePassword" : null, "sshKeys": null, "bus" : "VIRTIO", "licenceType" : "UNKNOWN", "cpuHotPlug" : true, "cpuHotUnplug" : false, "ramHotPlug" : true, "ramHotUnplug" : false, "nicHotPlug" : true, "nicHotUnplug" : true, "discVirtioHotPlug" : true, "discVirtioHotUnplug" : true, "discScsiHotPlug" : false, "discScsiHotUnplug" : false, "deviceNumber" : 2 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/create_node.json0000664000175000017500000000223413535474530030402 0ustar kamikami00000000000000{ "id": "srv-2", "type": "server", "href": "cloudapi/v4/datacenters/f3f7ca3c-6f3d-4a4d-b3d6-15853ae5ba78/servers/srv-2", "metadata": { "createdDate": "2016-10-19T13:25:19Z", "createdBy": "test@test.te", "etag": "9bea2412ac556b402a07260fc0d1603f", "lastModifiedDate": "2016-10-19T13:25:19Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "libcloud Test", "cores": 1, "ram": 1024, "availabilityZone": "ZONE_1", "vmState": null, "bootCdrom": null, "bootVolume": null, "cpuFamily": "INTEL_XEON" }, "entities": { "volumes": { "id": "srv-2/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/f3f7ca3c-6f3d-4a4d-b3d6-15853ae5ba78/servers/srv-2/volumes", "items": [ { "id": "53abb4de-b37b-4025-b139-3e09141e20bb", "type": "volume", "href": "/cloudapi/v4/datacenters/srv-2/volumes/53abb4de-b37b-4025-b139-3e09141e20bb" } ] } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/create_volume.json0000664000175000017500000000177213535474530030772 0ustar kamikami00000000000000{ "id" : "vol-2", "type" : "volume", "href" : "/cloudapi/v4/datacenters/dc-1/volumes/vol-2", "metadata" : { "createdDate" : "2016-10-17T13:13:36Z", "createdBy" : "test@test.te", "etag" : "c1800ce349033f9cd2c095ea1ea4976a", "lastModifiedDate" : "2016-10-17T13:47:52Z", "lastModifiedBy" : "test@test.te", "state" : "BUSY" }, "properties" : { "name": "libcloud Test", "type": "HDD", "size": 2, "availabilityZone": "ZONE_3", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 3 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/create_volume_snapshot.json0000664000175000017500000000155413535474530032707 0ustar kamikami00000000000000{ "id": "sshot", "type": "snapshot", "href": "/cloudapi/v4/snapshots/sshot", "metadata": { "createdDate": "2016-10-26T11:38:45Z", "createdBy": "test@test.te", "etag": "01873262ac042b5f44ed33b4241225b4", "lastModifiedDate": "2016-10-26T11:38:45Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "libcloud Test", "description": "libcloud test snapshot", "location": "us/las", "size": 10, "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/error_resource_not_found.json0000664000175000017500000000021613535474530033243 0ustar kamikami00000000000000{ "httpStatus": 404, "messages": [{ "errorCode": "309", "message": "Resource does not exist" } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_create_datacenter.json0000664000175000017500000000105713535474530032265 0ustar kamikami00000000000000{ "id": "dc-1", "type": "datacenter", "href": "/cloudapi/v4/datacenters/dc-1", "metadata": { "createdDate": "2016-10-18T17:20:56Z", "createdBy": "test@test.te", "etag": "c2d3d4d9bbdc0fff7d3c5c3864a68a46", "lastModifiedDate": "2016-10-18T17:20:56Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "libcloud Test", "description": "libcloud test datacenter", "location": "us/las", "version": null, "features": [] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_create_firewall_rule.json0000664000175000017500000000127113535474530033005 0ustar kamikami00000000000000{ "id": "fwr-1", "type": "firewall-rule", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules/fwr-1", "metadata": { "createdDate": "2016-10-19T11:08:04Z", "createdBy": "test@test.te", "etag": "2a21551ba4adf85d9fb04b05a6938bcc", "lastModifiedDate": "2016-10-19T11:08:04Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "SSH", "protocol": "TCP", "sourceMac": "01:23:45:67:89:00", "sourceIp": null, "targetIp": null, "icmpCode": null, "icmpType": null, "portRangeStart": 22, "portRangeEnd": 22 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_create_ip_block.json0000664000175000017500000000105313535474530031731 0ustar kamikami00000000000000{ "id": "ipb-1", "type": "ipblock", "href": "/cloudapi/v4/ipblocks/ipb-1", "metadata": { "createdDate": "2016-10-26T15:05:36Z", "createdBy": "test@test.te", "etag": "acbf00bacf7ee48d4b8bc4e7413e1f30", "lastModifiedDate": "2016-10-26T15:05:36Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "ips": [ "11.12.13.14", "15.16.17.18" ], "location": "us/las", "size": 2, "name": "libcloud Test" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_create_lan.json0000664000175000017500000000071313535474530030723 0ustar kamikami00000000000000{ "id" : "10", "type" : "lan", "href" : "/cloudapi/v4/datacenters/dc-1/lans/10", "metadata" : { "createdDate": "2016-10-17T11:33:11Z", "createdBy": "test@test.te", "etag": "53b215b8ec0356a649955dab019845a4", "lastModifiedDate": "2016-10-18T15:13:44Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties" : { "name" : "libcloud Test", "public" : true } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_create_load_balancer.json0000664000175000017500000000246313535474530032723 0ustar kamikami00000000000000{ "id": "bal-1", "type": "loadbalancer", "href": "/cloudapi/v4/datacenters/dc-1/loadbalancers/bal-1", "metadata": { "createdDate": "2016-10-26T13:02:33Z", "createdBy": "test@test.te", "etag": "71e8df57a58615b9e15400ede4138b41", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "libcloud Test", "ip": null, "dhcp": true }, "entities": { "balancednics": { "id": "bal-1/balancednics", "type": "collection", "href": "cloudapi/v4/datacenters/dc-1/loadbalancers/bal-1/balancednics", "items": [{ "id": "nic-1", "type": "nic", "href": "cloudapi/v4/datacenters/dc-1/servers/bal-1/nics/nic-1", "metadata": { "createdDate": "2016-10-17T15:46:38Z", "createdBy": "test@test.te", "etag": "dbd8216137cf0ec9951170f93fa8fa53", "lastModifiedDate": "2016-10-17T18:19:43Z", "lastModifiedBy": "test@test.te", "state": "BUSY" } } ] } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_create_network_interface.json0000664000175000017500000000112113535474530033654 0ustar kamikami00000000000000{ "id": "nic-2", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/nics/nic-2", "metadata": { "createdDate": "2016-10-19T08:18:50Z", "createdBy": "test@test.te", "etag": "8679142b0b1b70c8b8c09a8b31e6ded9", "lastModifiedDate": "2016-10-19T08:18:50Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "libcloud Test", "mac": null, "ips": [ "10.0.0.1" ], "dhcp": true, "lan": 1, "firewallActive": null, "nat": null } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_datacenter.json0000664000175000017500000004352013535474530032603 0ustar kamikami00000000000000{ "id": "dc-1", "type": "datacenter", "href": "/cloudapi/v4/datacenters/dc-1", "metadata": { "createdDate": "2016-10-17T11:33:11Z", "createdBy": "test@test.test", "etag": "53b215b8ec0356a649955dab019845a4", "lastModifiedDate": "2016-10-18T15:13:44Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "description": "libcloud test datacenter", "location": "us/las", "version": 35, "features": [ "SSD", "MULTIPLE_CPU" ] }, "entities": { "servers": { "id": "dc-1/servers", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers", "items": [ { "id": "srv-1", "type": "server", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1", "metadata": { "createdDate": "2016-10-18T07:28:05Z", "createdBy": "test@test.test", "etag": "53b215b8ec0356a649955dab019845a4", "lastModifiedDate": "2016-10-18T15:13:44Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Made with a stray volume and included size.", "cores": 2, "ram": 4096, "availabilityZone": "AUTO", "vmState": "RUNNING", "bootCdrom": null, "bootVolume": { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "test@test.test", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Bootable and linkable", "type": "HDD", "size": 10, "image": "bvol-img", "imagePassword": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } }, "cpuFamily": "AMD_OPTERON" }, "entities": { "cdroms": { "id": "srv-1/cdroms", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/cdroms", "items": [] }, "volumes": { "id": "srv-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/volumes", "items": [ { "id": "d6688ced-700d-4c9c-a3a7-9f7170c5edc3", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/d6688ced-700d-4c9c-a3a7-9f7170c5edc3" }, { "id": "vol-2", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/vol-2" }, { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1" } ] }, "nics": { "id": "srv-1/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/nics", "items": [] } } }, { "id": "s-3", "type": "server", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3", "metadata": { "createdDate": "2016-10-17T11:33:20Z", "createdBy": "test@test.test", "etag": "f6c94daafaf8ef852e2dc4b82a903c7b", "lastModifiedDate": "2016-10-17T16:13:43Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Updated this node", "cores": 3, "ram": 3072, "availabilityZone": "AUTO", "vmState": "RUNNING", "bootCdrom": null, "bootVolume": { "id": "21d7e7de-5054-4041-b691-717aa8b3c799", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/21d7e7de-5054-4041-b691-717aa8b3c799", "metadata": { "createdDate": "2016-10-17T11:33:20Z", "createdBy": "test@test.test", "etag": "a9d0b923527efae5e7071e9118e9eece", "lastModifiedDate": "2016-10-17T11:33:20Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Image and location and size. - volume", "type": "HDD", "size": 50, "image": "bvol-img", "imagePassword": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } }, "cpuFamily": "INTEL_XEON" }, "entities": { "cdroms": { "id": "s-3/cdroms", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/cdroms", "items": [] }, "volumes": { "id": "s-3/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/volumes", "items": [ { "id": "21d7e7de-5054-4041-b691-717aa8b3c799", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/21d7e7de-5054-4041-b691-717aa8b3c799" } ] }, "nics": { "id": "s-3/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics", "items": [ { "id": "nic-1", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1" } ] } } } ] }, "volumes": { "id": "dc-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/volumes", "items": [ { "id": "vol-2", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/vol-2", "metadata": { "createdDate": "2016-10-18T15:13:44Z", "createdBy": "test@test.test", "etag": "a96f7781920c2890c25f967e66e6ee91", "lastModifiedDate": "2016-10-18T15:13:44Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Unnamed HDD Storage", "type": "HDD", "size": 10, "availabilityZone": "AUTO", "image": null, "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": null, "cpuHotPlug": false, "cpuHotUnplug": false, "ramHotPlug": false, "ramHotUnplug": false, "nicHotPlug": false, "nicHotUnplug": false, "discVirtioHotPlug": false, "discVirtioHotUnplug": false, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 2 } }, { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "test@test.test", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Bootable and linkable", "type": "HDD", "size": 10, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } }, { "id": "d6688ced-700d-4c9c-a3a7-9f7170c5edc3", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/d6688ced-700d-4c9c-a3a7-9f7170c5edc3", "metadata": { "createdDate": "2016-10-17T13:13:36Z", "createdBy": "test@test.test", "etag": "c1800ce349033f9cd2c095ea1ea4976a", "lastModifiedDate": "2016-10-17T13:47:52Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Updated storage name", "type": "HDD", "size": 40, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 3 } }, { "id": "21d7e7de-5054-4041-b691-717aa8b3c799", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/21d7e7de-5054-4041-b691-717aa8b3c799", "metadata": { "createdDate": "2016-10-17T11:33:20Z", "createdBy": "test@test.test", "etag": "a9d0b923527efae5e7071e9118e9eece", "lastModifiedDate": "2016-10-17T11:33:20Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Image and location and size. - volume", "type": "HDD", "size": 50, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } } ] }, "loadbalancers": { "id": "dc-1/loadbalancers", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/loadbalancers", "items": [] }, "lans": { "id": "dc-1/lans", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans", "items": [ { "id": "2", "type": "lan", "href": "/cloudapi/v4/datacenters/dc-1/lans/2", "metadata": { "createdDate": "2016-10-17T18:19:43Z", "createdBy": "test@test.test", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Switch for LAN 2", "public": false }, "entities": { "nics": { "id": "2/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans/2/nics", "items": [ { "id": "nic-1", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1" } ] } } } ] } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_firewall_rule.json0000664000175000017500000000127213535474530033323 0ustar kamikami00000000000000{ "id": "fw2", "type": "firewall-rule", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules/fw2", "metadata": { "createdDate": "2016-10-19T09:55:10Z", "createdBy": "test@test.te", "etag": "00bb5b86562db1ed19ca38697e485160", "lastModifiedDate": "2016-10-19T09:55:10Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "SSH", "protocol": "TCP", "sourceMac": "01:23:45:67:89:00", "sourceIp": null, "targetIp": null, "icmpCode": null, "icmpType": null, "portRangeStart": 22, "portRangeEnd": 22 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_image.json0000664000175000017500000000171013535474530031546 0ustar kamikami00000000000000{ "id": "img-2", "type": "image", "href": "/cloudapi/v4/images/img-2", "metadata": { "createdDate": "2015-10-09T12:06:34Z", "createdBy": "test@test.te", "etag": "bbf76112358af2fc5dd1bf21de8988db", "lastModifiedDate": "2015-11-11T15:23:20Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "vivid-server-cloudimg-amd64-disk1.img", "description": null, "location": "us/las", "size": 2, "cpuHotPlug": false, "cpuHotUnplug": false, "ramHotPlug": false, "ramHotUnplug": false, "nicHotPlug": false, "nicHotUnplug": false, "discVirtioHotPlug": false, "discVirtioHotUnplug": false, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "UNKNOWN", "imageType": "HDD", "imageAliases": [ ], "public": false } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_ip_block.json0000664000175000017500000000106513535474530032251 0ustar kamikami00000000000000{ "id": "ipb-2", "type": "ipblock", "href": "/cloudapi/v4/ipblocks/ipb-2", "metadata": { "createdDate": "2016-10-26T15:05:12Z", "createdBy": "test@test.te", "etag": "43e05b766899950bc8a5aeee0fd89b05", "lastModifiedDate": "2016-10-26T15:05:12Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "ips": [ "208.94.36.101", "192.152.28.137" ], "location": "us/las", "size": 2, "name": "libcloud Test" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_lan.json0000664000175000017500000000120013535474530031230 0ustar kamikami00000000000000{ "id" : "10", "type" : "lan", "href" : "/cloudapi/v4/datacenters/dc-1/lans/10", "metadata" : { "createdDate": "2016-10-17T11:33:11Z", "createdBy": "test@test.te", "etag": "53b215b8ec0356a649955dab019845a4", "lastModifiedDate": "2016-10-18T15:13:44Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties" : { "name" : "libcloud Test", "public" : true }, "entities": { "nics": { "id": "10/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans/10/nics" } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_load_balancer.json0000664000175000017500000000133413535474530033234 0ustar kamikami00000000000000{ "id": "bal-1", "type": "loadbalancer", "href": "/cloudapi/v4/datacenters/dc-2/loadbalancers/bal-1", "metadata": { "createdDate": "2016-10-26T13:02:33Z", "createdBy": "test@test.te", "etag": "71e8df57a58615b9e15400ede4138b41", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "ip": "111.112.113.114", "dhcp": true }, "entities": { "balancednics": { "id": "bal-1/balancednics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/loadbalancers/bal-1/balancednics" } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_location.json0000664000175000017500000000034013535474530032272 0ustar kamikami00000000000000{ "id": "us/las", "type": "location", "href": "/cloudapi/v4/locations/us/las", "properties": { "name": "lasvegas", "features": [ "SSD", "MULTIPLE_CPU" ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_network_interface.json0000664000175000017500000000153613535474530034203 0ustar kamikami00000000000000{ "id": "nic-2", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2", "metadata": { "createdDate": "2016-10-17T15:46:38Z", "createdBy": "test@test.te", "etag": "dbd8216137cf0ec9951170f93fa8fa53", "lastModifiedDate": "2016-10-17T18:19:43Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "mac": "02:01:0b:9d:4d:ce", "ips": [ "10.15.124.11" ], "dhcp": true, "lan": 2, "firewallActive": true, "nat": false }, "entities": { "firewallrules": { "id": "nic-1/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules" } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_node.json0000664000175000017500000000773213535474530031423 0ustar kamikami00000000000000{ "id": "srv-1", "type": "server", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1", "metadata": { "createdDate": "2016-10-18T07:28:05Z", "createdBy": "test@test.test", "etag": "e7cf186125f51f3d9511754a40dcd12c", "lastModifiedDate": "2016-10-18T07:28:05Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "cores": 1, "ram": 1024, "availabilityZone": "ZONE_1", "vmState": "RUNNING", "bootCdrom": null, "bootVolume": { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "test@test.test", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "type": "HDD", "size": 2, "image": "bvol-img", "imagePassword": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } }, "cpuFamily": "AMD_OPTERON" }, "entities": { "cdroms": { "id": "srv-1/cdroms", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/cdroms", "items": [] }, "volumes": { "id": "srv-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/volumes", "items": [ { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "test@test.test", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "type": "HDD", "size": 2, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } } ] }, "nics": { "id": "srv-1/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/nics", "items": [] } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_snapshot.json0000664000175000017500000000156113535474530032327 0ustar kamikami00000000000000{ "id": "sshot", "type": "snapshot", "href": "/cloudapi/v4/snapshots/sshot", "metadata": { "createdDate": "2016-10-26T11:38:45Z", "createdBy": "test@test.te", "etag": "01873262ac042b5f44ed33b4241225b4", "lastModifiedDate": "2016-10-26T11:38:45Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "description": "libcloud test snapshot", "location": "us/las", "size": 10, "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_describe_volume.json0000664000175000017500000000176613535474530032006 0ustar kamikami00000000000000{ "id": "vol-2", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/vol-2", "metadata": { "createdDate": "2016-10-17T13:13:36Z", "createdBy": "test@test.te", "etag": "c1800ce349033f9cd2c095ea1ea4976a", "lastModifiedDate": "2016-10-17T13:47:52Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "type": "HDD", "size": 2, "availabilityZone": "ZONE_3", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "UNKNOWN", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 3 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_attached_volumes.json0000664000175000017500000000536213535474530033215 0ustar kamikami00000000000000{ "id": "srv-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/volumes", "items": [ { "id": "d6688ced-700d-4c9c-a3a7-9f7170c5edc3", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/d6688ced-700d-4c9c-a3a7-9f7170c5edc3", "metadata": { "createdDate": "2016-10-17T13:13:36Z", "createdBy": "test@test.test", "etag": "c1800ce349033f9cd2c095ea1ea4976a", "lastModifiedDate": "2016-10-17T13:47:52Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "type": "HDD", "size": 2, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "UNKNOWN", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 2 } }, { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "test@test.test", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "type": "HDD", "size": 10, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_datacenters.json0000664000175000017500000000355213535474530032162 0ustar kamikami00000000000000{ "id": "datacenters", "type": "collection", "href": "/cloudapi/v4/datacenters/", "items": [ { "id": "dc-1", "type": "datacenter", "href": "/cloudapi/v4/datacenters/dc-1", "metadata": { "createdDate": "2016-10-14T07:24:59Z", "createdBy": "test@test.test", "etag": "bdddec2287cb7723e86ac088bf644606", "lastModifiedDate": "2016-10-17T15:27:25Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "description": "libcloud test datacenter", "location": "us/las", "version": 3, "features": [ "SSD", "MULTIPLE_CPU" ] }, "entities": { "servers": { "id": "983a45be-a9aa-427a-8117-271ce9f392bb/servers", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers" }, "volumes": { "id": "983a45be-a9aa-427a-8117-271ce9f392bb/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/volumes" }, "loadbalancers": { "id": "983a45be-a9aa-427a-8117-271ce9f392bb/loadbalancers", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/loadbalancers" }, "lans": { "id": "983a45be-a9aa-427a-8117-271ce9f392bb/lans", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans" } } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_firewall_rules.json0000664000175000017500000000553513535474530032707 0ustar kamikami00000000000000{ "id": "nic-2/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules", "items": [ { "id": "fwr-1", "type": "firewall-rule", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules/fwr-1", "metadata": { "createdDate": "2016-10-19T11:08:10Z", "createdBy": "test@test.te", "etag": "b91a2e082a7422dafb79d84a07fb2a28", "lastModifiedDate": "2016-10-19T11:19:04Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Test updated firewall rule", "protocol": "TCP", "sourceMac": null, "sourceIp": null, "targetIp": null, "icmpCode": null, "icmpType": null, "portRangeStart": 80, "portRangeEnd": 80 } }, { "id": "fw2", "type": "firewall-rule", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules/fw2", "metadata": { "createdDate": "2016-10-19T09:55:10Z", "createdBy": "test@test.te", "etag": "00bb5b86562db1ed19ca38697e485160", "lastModifiedDate": "2016-10-19T09:55:10Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "HTTPs (SSL)", "protocol": "TCP", "sourceMac": null, "sourceIp": null, "targetIp": null, "icmpCode": null, "icmpType": null, "portRangeStart": 443, "portRangeEnd": 443 } }, { "id": "6238b1e2-c706-4dc9-80a9-307fa0bd4287", "type": "firewall-rule", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules/6238b1e2-c706-4dc9-80a9-307fa0bd4287", "metadata": { "createdDate": "2016-10-19T09:55:10Z", "createdBy": "test@test.te", "etag": "00bb5b86562db1ed19ca38697e485160", "lastModifiedDate": "2016-10-19T09:55:10Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "HTTP Webserver", "protocol": "TCP", "sourceMac": null, "sourceIp": null, "targetIp": null, "icmpCode": null, "icmpType": null, "portRangeStart": 80, "portRangeEnd": 80 } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_ip_blocks.json0000664000175000017500000000303613535474530031627 0ustar kamikami00000000000000{ "id": "ipblocks", "type": "collection", "href": "/cloudapi/v4/ipblocks", "items": [ { "id": "ipb-1", "type": "ipblock", "href": "/cloudapi/v4/ipblocks/ipb-1", "metadata": { "createdDate": "2016-10-26T15:05:36Z", "createdBy": "test@test.te", "etag": "acbf00bacf7ee48d4b8bc4e7413e1f30", "lastModifiedDate": "2016-10-26T15:05:36Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "ips": [ "78.137.101.252", "78.137.101.251" ], "location": "us/las", "size": 2, "name": "Test IP Block One" } }, { "id": "ipb-2", "type": "ipblock", "href": "/cloudapi/v4/ipblocks/ipb-2", "metadata": { "createdDate": "2016-10-26T15:05:12Z", "createdBy": "test@test.te", "etag": "43e05b766899950bc8a5aeee0fd89b05", "lastModifiedDate": "2016-10-26T15:05:12Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "ips": [ "78.137.101.250" ], "location": "us/las", "size": 1, "name": "Test IP Block One" } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_lans.json0000664000175000017500000001774313535474530030631 0ustar kamikami00000000000000{ "id": "dc-1/lans", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans", "items": [ { "id": "1", "type": "lan", "href": "/cloudapi/v4/datacenters/dc-1/lans/1", "metadata": { "createdDate": "2016-10-24T08:03:22Z", "createdBy": "test@test.te", "etag": "1c30221454228d239f0610b6eb3f41d7", "lastModifiedDate": "2016-10-24T08:03:22Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "public": false }, "entities": { "nics": { "id": "1/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans/1/nics", "items": [ { "id": "dc5e1c66-7280-4a5c-8e13-51ce030e0980", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/d37abf6b-0980-4bf8-813b-b69863cf7b9e/nics/dc5e1c66-7280-4a5c-8e13-51ce030e0980", "metadata": { "createdDate": "2016-10-21T13:00:02Z", "createdBy": "test@test.te", "etag": "d8177b9c38b0366d26c28df0066ade9e", "lastModifiedDate": "2016-10-24T08:03:22Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Three", "mac": "02:01:49:87:3e:5f", "ips": [ "10.15.104.14" ], "dhcp": true, "lan": 1, "firewallActive": true, "nat": false }, "entities": { "firewallrules": { "id": "dc5e1c66-7280-4a5c-8e13-51ce030e0980/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/d37abf6b-0980-4bf8-813b-b69863cf7b9e/nics/dc5e1c66-7280-4a5c-8e13-51ce030e0980/firewallrules" } } }, { "id": "912324a6-c057-445d-84dd-8fea82dfa719", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/811ab72b-f7f3-427b-8220-f031eae34f63/nics/912324a6-c057-445d-84dd-8fea82dfa719", "metadata": { "createdDate": "2016-10-21T13:00:02Z", "createdBy": "test@test.te", "etag": "d8177b9c38b0366d26c28df0066ade9e", "lastModifiedDate": "2016-10-24T08:03:22Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Two", "mac": "02:01:af:48:34:06", "ips": [ "10.15.104.13" ], "dhcp": true, "lan": 1, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "912324a6-c057-445d-84dd-8fea82dfa719/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/811ab72b-f7f3-427b-8220-f031eae34f63/nics/912324a6-c057-445d-84dd-8fea82dfa719/firewallrules" } } }, { "id": "8d9fb87c-79f7-4c3c-8f7b-e2050a881b16", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/b1a64861-5819-498a-899a-a57126050952/nics/8d9fb87c-79f7-4c3c-8f7b-e2050a881b16", "metadata": { "createdDate": "2016-10-21T13:00:02Z", "createdBy": "test@test.te", "etag": "d8177b9c38b0366d26c28df0066ade9e", "lastModifiedDate": "2016-10-24T08:03:22Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Four", "mac": "02:01:7c:7b:0b:5a", "ips": [ "10.15.104.12" ], "dhcp": true, "lan": 1, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "8d9fb87c-79f7-4c3c-8f7b-e2050a881b16/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/b1a64861-5819-498a-899a-a57126050952/nics/8d9fb87c-79f7-4c3c-8f7b-e2050a881b16/firewallrules" } } }, { "id": "76d7965d-19e5-491f-8b2f-1c4a3ef127b5", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/77ef2301-b4df-46aa-8544-2dae76c9d7b5/nics/76d7965d-19e5-491f-8b2f-1c4a3ef127b5", "metadata": { "createdDate": "2016-10-21T13:00:02Z", "createdBy": "test@test.te", "etag": "eb2031a5e259fcb4f714646aca0282c6", "lastModifiedDate": "2016-10-24T08:03:22Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Five", "mac": "02:01:bb:ad:7d:58", "ips": [ "10.15.104.11" ], "dhcp": true, "lan": 1, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "76d7965d-19e5-491f-8b2f-1c4a3ef127b5/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/77ef2301-b4df-46aa-8544-2dae76c9d7b5/nics/76d7965d-19e5-491f-8b2f-1c4a3ef127b5/firewallrules" } } } ] } } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_load_balanced_nics.json0000664000175000017500000000464513535474530033435 0ustar kamikami00000000000000{ "id": "s-3/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics", "items": [ { "id": "nic-1", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1", "metadata": { "createdDate": "2016-10-17T15:46:38Z", "createdBy": "test@test.te", "etag": "dbd8216137cf0ec9951170f93fa8fa53", "lastModifiedDate": "2016-10-17T18:19:43Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "mac": "02:01:0b:9d:4d:ce", "ips": [ "10.15.124.11" ], "dhcp": false, "lan": 2, "firewallActive": true, "nat": false }, "entities": { "firewallrules": { "id": "nic-1/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1/firewallrules" } } }, { "id": "8f7ea845-cf40-49c8-9e93-68366f31d605", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/8f7ea845-cf40-49c8-9e93-68366f31d605", "metadata": { "createdDate": "2016-10-17T16:46:38Z", "createdBy": "test@test.te", "etag": "dbd8216137cf0ec9951170f93fa8fa54", "lastModifiedDate": "2016-10-17T19:19:43Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Another test network interface", "mac": "02:01:0b:9d:4d:dd", "ips": [ "10.15.124.12" ], "dhcp": false, "lan": 2, "firewallActive": true, "nat": false }, "entities": { "firewallrules": { "id": "8f7ea845-cf40-49c8-9e93-68366f31d605/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1/firewallrules" } } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_load_balancers.json0000664000175000017500000002564713535474530032627 0ustar kamikami00000000000000{ "id": "dc-2/loadbalancers", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/loadbalancers", "items": [ { "id": "bal-1", "type": "loadbalancer", "href": "/cloudapi/v4/datacenters/dc-2/loadbalancers/bal-1", "metadata": { "createdDate": "2016-10-26T13:02:33Z", "createdBy": "test@test.te", "etag": "71e8df57a58615b9e15400ede4138b41", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Test One", "ip": "111.112.113.114", "dhcp": true }, "entities": { "balancednics": { "id": "bal-1/balancednics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/loadbalancers/bal-1/balancednics", "items": [ { "id": "68e3bd55-55a1-4fa0-8903-8c3cf23ee30a", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-2/servers/92445f57-5378-4a5b-8b53-f0f36fb8e6ad/nics/68e3bd55-55a1-4fa0-8903-8c3cf23ee30a", "metadata": { "createdDate": "2016-10-26T13:02:33Z", "createdBy": "test@test.te", "etag": "20e915cf08106b7576f6b25b5c0a2bd6", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": null, "mac": "02:01:33:58:8d:e1", "ips": [ "162.254.25.6" ], "dhcp": true, "lan": 3, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "68e3bd55-55a1-4fa0-8903-8c3cf23ee30a/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/servers/92445f57-5378-4a5b-8b53-f0f36fb8e6ad/nics/68e3bd55-55a1-4fa0-8903-8c3cf23ee30a/firewallrules" } } } ] } } }, { "id": "24d24a20-1161-4870-8b49-434622a18875", "type": "loadbalancer", "href": "/cloudapi/v4/datacenters/dc-2/loadbalancers/24d24a20-1161-4870-8b49-434622a18875", "metadata": { "createdDate": "2016-10-26T13:02:33Z", "createdBy": "test@test.te", "etag": "71e8df57a58615b9e15400ede4138b41", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Test Two", "ip": "162.254.25.225", "dhcp": true }, "entities": { "balancednics": { "id": "24d24a20-1161-4870-8b49-434622a18875/balancednics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/loadbalancers/24d24a20-1161-4870-8b49-434622a18875/balancednics", "items": [ { "id": "0485e083-3461-447a-8c5a-392be3c76473", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-2/servers/7571b2d9-312a-45be-8d68-58c269c3911c/nics/0485e083-3461-447a-8c5a-392be3c76473", "metadata": { "createdDate": "2016-10-25T08:49:48Z", "createdBy": "test@test.te", "etag": "20e915cf08106b7576f6b25b5c0a2bd6", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": null, "mac": "02:01:6f:92:d0:63", "ips": [ "162.254.25.225" ], "dhcp": true, "lan": 5, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "0485e083-3461-447a-8c5a-392be3c76473/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/servers/7571b2d9-312a-45be-8d68-58c269c3911c/nics/0485e083-3461-447a-8c5a-392be3c76473/firewallrules" } } }, { "id": "2e9c54f4-85c0-4d10-8369-cf5e3a6e7b68", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-2/servers/ff3b523c-21bd-453d-80a3-c2bcdae1f509/nics/2e9c54f4-85c0-4d10-8369-cf5e3a6e7b68", "metadata": { "createdDate": "2016-10-25T14:01:03Z", "createdBy": "test@test.te", "etag": "20e915cf08106b7576f6b25b5c0a2bd6", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": null, "mac": "02:01:ce:53:f1:1a", "ips": [ "162.254.25.225" ], "dhcp": true, "lan": 5, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "2e9c54f4-85c0-4d10-8369-cf5e3a6e7b68/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/servers/ff3b523c-21bd-453d-80a3-c2bcdae1f509/nics/2e9c54f4-85c0-4d10-8369-cf5e3a6e7b68/firewallrules" } } }, { "id": "707d7aa4-8311-4a61-82a4-a80333e9ecc2", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-2/servers/2e77a9cc-2338-43e6-84bf-e4c2ff9be265/nics/707d7aa4-8311-4a61-82a4-a80333e9ecc2", "metadata": { "createdDate": "2016-10-25T15:36:06Z", "createdBy": "test@test.te", "etag": "20e915cf08106b7576f6b25b5c0a2bd6", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": null, "mac": "02:01:8b:77:cd:b6", "ips": [ "162.254.25.225" ], "dhcp": true, "lan": 5, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "707d7aa4-8311-4a61-82a4-a80333e9ecc2/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/servers/2e77a9cc-2338-43e6-84bf-e4c2ff9be265/nics/707d7aa4-8311-4a61-82a4-a80333e9ecc2/firewallrules" } } }, { "id": "710f6842-440d-4fdc-878e-0c329037d4a9", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-2/servers/fc0f7e86-a7de-4cee-84b5-409cc8b89ad2/nics/710f6842-440d-4fdc-878e-0c329037d4a9", "metadata": { "createdDate": "2016-10-25T14:01:03Z", "createdBy": "test@test.te", "etag": "20e915cf08106b7576f6b25b5c0a2bd6", "lastModifiedDate": "2016-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": null, "mac": "02:01:00:65:da:a9", "ips": [ "162.254.25.225" ], "dhcp": true, "lan": 5, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "710f6842-440d-4fdc-878e-0c329037d4a9/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-2/servers/fc0f7e86-a7de-4cee-84b5-409cc8b89ad2/nics/710f6842-440d-4fdc-878e-0c329037d4a9/firewallrules" } } } ] } } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_list_network_interfaces.json0000664000175000017500000000462413535474530033562 0ustar kamikami00000000000000{ "id": "s-3/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics", "items": [ { "id": "nic-1", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1", "metadata": { "createdDate": "2016-10-17T15:46:38Z", "createdBy": "test@test.te", "etag": "dbd8216137cf0ec9951170f93fa8fa53", "lastModifiedDate": "2016-10-17T18:19:43Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "mac": "02:01:0b:9d:4d:ce", "ips": [ "10.15.124.11" ], "dhcp": false, "lan": 2, "firewallActive": true, "nat": false }, "entities": { "firewallrules": { "id": "nic-1/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1/firewallrules" } } }, { "id": "8f7ea845-cf40-49c8-9e93-68366f31d605", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/8f7ea845-cf40-49c8-9e93-68366f31d605", "metadata": { "createdDate": "2016-10-17T16:46:38Z", "createdBy": "test@test.te", "etag": "dbd8216137cf0ec9951170f93fa8fa54", "lastModifiedDate": "2016-10-17T19:19:43Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "mac": "02:01:0b:9d:4d:dd", "ips": [ "10.15.124.12" ], "dhcp": false, "lan": 2, "firewallActive": true, "nat": false }, "entities": { "firewallrules": { "id": "8f7ea845-cf40-49c8-9e93-68366f31d605/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-1/firewallrules" } } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_rename_datacenter.json0000664000175000017500000000246313535474530032273 0ustar kamikami00000000000000{ "id": "dc-1", "type": "datacenter", "href": "/cloudapi/v4/datacenters/dc-1", "metadata" : { "createdDate": "2016-10-17T11:33:11Z", "createdBy": "test@test.test", "etag": "53b215b8ec0356a649955dab019845a4", "lastModifiedDate": "2016-10-18T15:13:44Z", "lastModifiedBy": "test@test.test", "state" : "BUSY" }, "properties" : { "name": "libcloud Test - RENAME", "description": "libcloud test datacenter", "location": "us/las", "version": 35, "features": [ "SSD", "MULTIPLE_CPU" ] }, "entities" : { "servers" : { "id": "dc-1/servers", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers" }, "volumes" : { "id": "dc-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/volumes" }, "loadbalancers" : { "id": "dc-1/loadbalancers", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/loadbalancers", "items": [] }, "lans" : { "id": "dc-1/lans", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans" } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_firewall_rule.json0000664000175000017500000000130013535474530033015 0ustar kamikami00000000000000{ "id": "fw2", "type": "firewall-rule", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules/fw2", "metadata": { "createdDate": "2016-10-19T09:55:10Z", "createdBy": "test@test.te", "etag": "00bb5b86562db1ed19ca38697e485160", "lastModifiedDate": "2016-10-19T09:55:10Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "SSH - RENAME", "protocol": "TCP", "sourceMac": "01:23:45:67:89:00", "sourceIp": null, "targetIp": null, "icmpCode": null, "icmpType": null, "portRangeStart": 22, "portRangeEnd": 22 } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_image.json0000664000175000017500000000166213535474530031256 0ustar kamikami00000000000000{ "id": "img-2", "type": "image", "href": "/cloudapi/v4/images/img-2", "metadata": { "createdDate": "2015-10-09T12:06:34Z", "createdBy": "test@test.te", "etag": "bbf76112358af2fc5dd1bf21de8988db", "lastModifiedDate": "2016-11-11T15:23:20Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "my-updated-image.img", "description": null, "location": "us/las", "size": 2, "cpuHotPlug": false, "cpuHotUnplug": false, "ramHotPlug": false, "ramHotUnplug": false, "nicHotPlug": false, "nicHotUnplug": false, "discVirtioHotPlug": false, "discVirtioHotUnplug": false, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "UNKNOWN", "imageType": "HDD", "imageAliases": [ ], "public": false } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_lan.json0000664000175000017500000000121213535474530030735 0ustar kamikami00000000000000{ "id" : "10", "type" : "lan", "href" : "/cloudapi/v4/datacenters/dc-1/lans/10", "metadata" : { "createdDate": "2016-10-17T11:33:11Z", "createdBy": "test@test.te", "etag": "53b215b8ec0356a649955dab019845a4", "lastModifiedDate": "2016-10-18T15:13:44Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties" : { "name" : "libcloud Test - RENAME", "public" : false }, "entities": { "nics": { "id": "10/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/lans/10/nics" } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_load_balancer.json0000664000175000017500000000100413535474530032730 0ustar kamikami00000000000000{ "id": "bal-1", "type": "loadbalancer", "href": "/cloudapi/v4/datacenters/dc-1/loadbalancers/bal-1", "metadata": { "createdDate": "2019-10-26T13:02:33Z", "createdBy": "test@test.te", "etag": "71e8df57a58615b9e15400ede4138b41", "lastModifiedDate": "2019-10-26T13:02:33Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "libcloud Test - RENAME", "ip": "123.124.125.126", "dhcp": true } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_network_interface.json0000664000175000017500000000154213535474530033702 0ustar kamikami00000000000000{ "id": "nic-2", "type": "nic", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2", "metadata": { "createdDate": "2016-10-19T08:18:55Z", "createdBy": "test@test.te", "etag": "56f8d8bbdc84faad4188f647a49a565b", "lastModifiedDate": "2016-10-19T09:44:59Z", "lastModifiedBy": "test@test.te", "state": "BUSY" }, "properties": { "name": "libcloud Test - RENAME", "mac": "02:01:68:c1:e8:88", "ips": [ "11.12.13.14" ], "dhcp": true, "lan": 1, "firewallActive": false, "nat": false }, "entities": { "firewallrules": { "id": "nic-2/firewallrules", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/s-3/nics/nic-2/firewallrules" } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_node.json0000664000175000017500000000246113535474530031117 0ustar kamikami00000000000000{ "id": "srv-1", "type": "server", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1", "metadata" : { "createdDate": "2016-10-18T07:28:05Z", "createdBy": "test@test.test", "etag": "e7cf186125f51f3d9511754a40dcd12c", "lastModifiedDate": "2016-10-18T07:28:05Z", "lastModifiedBy": "test@test.test", "state" : "BUSY" }, "properties" : { "name" : "libcloud Test RENAME", "cores" : 1, "ram" : 1024, "bootCdrom" : null, "availabilityZone": "ZONE_1", "vmState": "RUNNING", "bootVolume": { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1" }, "cpuFamily" : "AMD_OPTERON" }, "entities" : { "cdroms": { "id": "srv-1/cdroms", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/cdroms" }, "volumes": { "id": "srv-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/volumes" }, "nics": { "id": "srv-1/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/nics" } } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_snapshot.json0000664000175000017500000000160213535474530032025 0ustar kamikami00000000000000{ "id": "sshot", "type": "snapshot", "href": "/cloudapi/v4/snapshots/sshot", "metadata": { "createdDate": "2016-10-26T11:38:45Z", "createdBy": "test@test.te", "etag": "01873262ac042b5f44ed33b4241225b4", "lastModifiedDate": "2016-10-26T11:38:45Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test - RENAME", "description": "libcloud test snapshot - RENAME", "location": "us/las", "size": 10, "cpuHotPlug": true, "cpuHotUnplug": true, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/ex_update_volume.json0000664000175000017500000000177713535474530031512 0ustar kamikami00000000000000{ "id": "vol-2", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/vol-2", "metadata": { "createdDate": "2016-10-17T13:13:36Z", "createdBy": "test@test.te", "etag": "c1800ce349033f9cd2c095ea1ea4976a", "lastModifiedDate": "2016-10-17T13:47:52Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test - RENAME", "type": "HDD", "size": 5, "availabilityZone": "ZONE_3", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "UNKNOWN", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 3 } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/list_images.json0000664000175000017500000001660413535474530030440 0ustar kamikami00000000000000{ "id": "images", "type": "collection", "href": "/cloudapi/v4/images", "items": [ { "id": "img-2", "type": "image", "href": "/cloudapi/v4/images/img-2", "metadata": { "createdDate": "2016-06-02T11:33:49Z", "createdBy": "System", "etag": "9909709d99655c6f31aca789998d7d89", "lastModifiedDate": "2016-06-02T11:33:49Z", "lastModifiedBy": "System", "state": "AVAILABLE" }, "properties": { "name": "Test-Image-One-CDROM", "description": "", "location": "us/las", "size": 0.23, "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX", "imageType": "CDROM", "imageAliases": [ ], "public": false } }, { "id": "img-1", "type": "image", "href": "/cloudapi/v4/images/img-1", "metadata": { "createdDate": "2014-11-14T15:22:19Z", "createdBy": "System", "etag": "957e0eac7456fa7554e73bf0d18860eb", "lastModifiedDate": "2014-11-14T15:22:19Z", "lastModifiedBy": "System", "state": "AVAILABLE" }, "properties": { "name": "Test-Image-Two-CDROM", "description": "", "location": "us/las", "size": 4, "cpuHotPlug": false, "cpuHotUnplug": false, "ramHotPlug": false, "ramHotUnplug": false, "nicHotPlug": false, "nicHotUnplug": false, "discVirtioHotPlug": false, "discVirtioHotUnplug": false, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "OTHER", "imageType": "CDROM", "imageAliases": [ ], "public": true } }, { "id": "62c525d9-b2cf-11e5-afa0-52540066fee9", "type": "image", "href": "/cloudapi/v4/images/62c525d9-b2cf-11e5-afa0-52540066fee9", "metadata": { "createdDate": "2016-01-04T10:39:08Z", "createdBy": "System", "etag": "28cb3e31d2ef98d37b367fe15d40373e", "lastModifiedDate": "2016-01-04T10:39:08Z", "lastModifiedBy": "System", "state": "AVAILABLE" }, "properties": { "name": "Test-Image-Three-CDROM", "description": "", "location": "us/las", "size": 0.37, "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX", "imageType": "CDROM", "imageAliases": [ ], "public": true } }, { "id": "e2c323ba-3c6d-11e6-9336-52540005ab80", "type": "image", "href": "/cloudapi/v4/images/e2c323ba-3c6d-11e6-9336-52540005ab80", "metadata": { "createdDate": "2016-06-27T13:48:53Z", "createdBy": "System", "etag": "216e2beb5e9bb5f7c3233ca3d0c4e9b2", "lastModifiedDate": "2016-06-27T13:48:53Z", "lastModifiedBy": "System", "state": "AVAILABLE" }, "properties": { "name": "Test-Image-Four-HDD", "description": "", "location": "us/las", "size": 0.28, "cpuHotPlug": false, "cpuHotUnplug": false, "ramHotPlug": false, "ramHotUnplug": false, "nicHotPlug": false, "nicHotUnplug": false, "discVirtioHotPlug": false, "discVirtioHotUnplug": false, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "OTHER", "imageType": "HDD", "imageAliases": [ ], "public": false } }, { "id": "f1d2be4a-7937-11e4-8053-52540066fee9", "type": "image", "href": "/cloudapi/v4/images/f1d2be4a-7937-11e4-8053-52540066fee9", "metadata": { "createdDate": "2014-12-01T08:56:31Z", "createdBy": "System", "etag": "fd23753bfae52a11bbdfdd478296cb2a", "lastModifiedDate": "2014-12-01T08:56:31Z", "lastModifiedBy": "System", "state": "AVAILABLE" }, "properties": { "name": "Test-Image-Two-HDD", "description": "", "location": "us/las", "size": 0.45, "cpuHotPlug": false, "cpuHotUnplug": false, "ramHotPlug": false, "ramHotUnplug": false, "nicHotPlug": false, "nicHotUnplug": false, "discVirtioHotPlug": false, "discVirtioHotUnplug": false, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX", "imageType": "HDD", "imageAliases": [ ], "public": true } }, { "id": "dfa08a48-7937-11e4-8053-52540066fee9", "type": "image", "href": "/cloudapi/v4/images/dfa08a48-7937-11e4-8053-52540066fee9", "metadata": { "createdDate": "2014-12-01T08:56:00Z", "createdBy": "System", "etag": "66da22f2893f1de8945c27e11bbc7ebf", "lastModifiedDate": "2014-12-01T08:56:00Z", "lastModifiedBy": "System", "state": "AVAILABLE" }, "properties": { "name": "Test-Image-Three-HDD", "description": "", "location": "de/fra", "size": 0.08, "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX", "imageType": "HDD", "imageAliases": [ ], "public": true } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/list_locations.json0000664000175000017500000001037713535474530031167 0ustar kamikami00000000000000{ "id" : "locations", "type" : "collection", "href" : "https://api.profitbricks.com/cloudapi/v4/locations", "items" : [ { "id" : "us/las", "type" : "location", "href" : "https://api.profitbricks.com/cloudapi/v4/locations/de/fkb", "properties" : { "name" : "karlsruhe", "features" : [ "SSD", "MULTIPLE_CPU" ], "imageAliases" : [ "centos:6_iso", "opensuse:latest", "opensuse:42.3_iso", "centos:7_iso", "clearos:latest_iso", "debian:8_iso", "clonezilla:latest_iso", "windows:latest", "centos:7", "debian:7", "fedora:25_iso", "gparted:latest_iso", "grml:latest_iso", "opensuse:13.2_iso", "opensuse:42.1_iso", "opensuse:42.2_iso", "ubuntu:14.04_iso", "ubuntu:16.04_iso", "ubuntu:17.04_iso", "zenloadbalancer:latest_iso", "mssql:2012_trial_iso", "windows:virtiodriver_iso", "windows:2008r2_iso", "windows:2012r2_iso", "windows:2013_recovery_iso", "windows:2016_iso", "windows:2008r2", "windows:2012r2", "centos:6", "debian:9", "debian:latest", "ubuntu:16.04", "windows:2016", "centos:latest", "debian:8", "debian:testing", "fedora:25", "fedora:latest", "ubuntu:14.04", "ubuntu:latest", "debian:9_iso", "fedora:26_iso", "opensuse:13.2" ] } }, { "id" : "de/fra", "type" : "location", "href" : "https://api.profitbricks.com/cloudapi/v4/locations/de/fra", "properties" : { "name" : "frankfurt", "features" : [ "SSD", "MULTIPLE_CPU" ], "imageAliases" : [ "centos:6_iso", "opensuse:42.3_iso", "windows:2012r2", "centos:7_iso", "clearos:latest_iso", "windows:latest", "clonezilla:latest_iso", "debian:7", "debian:9", "fedora:25_iso", "gparted:latest_iso", "grml:latest_iso", "opensuse:13.2_iso", "ubuntu:16.04", "opensuse:42.1_iso", "opensuse:42.2_iso", "windows:2016", "ubuntu:14.04_iso", "ubuntu:16.04_iso", "ubuntu:17.04_iso", "zenloadbalancer:latest_iso", "mssql:2012_trial_iso", "windows:virtiodriver_iso", "windows:2008r2_iso", "windows:2012r2_iso", "windows:2013_recovery_iso", "windows:2016_iso", "centos:6", "debian:latest", "fedora:latest", "ubuntu:14.04", "windows:2008r2", "centos:7", "centos:latest", "debian:8", "debian:testing", "fedora:25", "ubuntu:latest", "debian:8_iso", "debian:9_iso", "fedora:26_iso", "opensuse:13.2", "opensuse:latest" ] } }, { "id" : "us/las", "type" : "location", "href" : "https://api.profitbricks.com/cloudapi/v4/locations/us/las", "properties" : { "name" : "lasvegas", "features" : [ "SSD", "MULTIPLE_CPU" ], "imageAliases" : [ "centos:6_iso", "opensuse:latest", "opensuse:42.3_iso", "windows:2016", "centos:7_iso", "clearos:latest_iso", "windows:latest", "clonezilla:latest_iso", "centos:7", "centos:latest", "debian:latest", "fedora:25_iso", "gparted:latest_iso", "grml:latest_iso", "opensuse:13.2_iso", "ubuntu:latest", "opensuse:42.1_iso", "opensuse:42.2_iso", "windows:2008r2", "opensuse:13.2", "ubuntu:14.04_iso", "ubuntu:16.04_iso", "ubuntu:17.04_iso", "zenloadbalancer:latest_iso", "mssql:2012_trial_iso", "windows:virtiodriver_iso", "windows:2008r2_iso", "windows:2012r2_iso", "windows:2013_recovery_iso", "windows:2016_iso", "debian:9", "debian:testing", "ubuntu:16.04", "windows:2012r2", "centos:6", "debian:7", "debian:8", "fedora:25", "fedora:latest", "ubuntu:14.04", "debian:8_iso", "debian:9_iso", "fedora:26_iso" ] } }, { "id" : "us/ewr", "type" : "location", "href" : "https://api.profitbricks.com/cloudapi/v4/locations/us/ewr", "properties" : { "name" : "newark", "features" : [ "SSD", "MULTIPLE_CPU" ], "imageAliases" : [ "centos:6_iso", "opensuse:13.2", "opensuse:latest", "opensuse:42.3_iso", "windows:2008r2", "centos:7_iso", "clearos:latest_iso", "debian:9_iso", "fedora:26_iso", "clonezilla:latest_iso", "windows:2012r2", "windows:2016", "windows:latest", "centos:6", "centos:7", "centos:latest", "debian:latest", "fedora:25_iso", "gparted:latest_iso", "grml:latest_iso", "opensuse:13.2_iso", "fedora:latest", "ubuntu:14.04", "ubuntu:16.04", "opensuse:42.1_iso", "opensuse:42.2_iso", "ubuntu:14.04_iso", "ubuntu:16.04_iso", "ubuntu:17.04_iso", "zenloadbalancer:latest_iso", "mssql:2012_trial_iso", "windows:virtiodriver_iso", "windows:2008r2_iso", "windows:2012r2_iso", "windows:2013_recovery_iso", "windows:2016_iso", "debian:testing", "fedora:25", "debian:7", "debian:8", "debian:9", "ubuntu:latest", "debian:8_iso" ] } } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/list_nodes.json0000664000175000017500000001523613535474530030303 0ustar kamikami00000000000000{ "id": "dc-1/servers", "type": "collection", "href": "/cloudapi/v4/datacenters/9e9cb896-e8e7-4f52-a808-ac808baac814/servers", "items": [ { "id": "srv-1", "type": "server", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1", "metadata": { "createdDate": "2016-10-18T07:28:05Z", "createdBy": "test@test.te", "etag": "e7cf186125f51f3d9511754a40dcd12c", "lastModifiedDate": "2016-10-18T07:28:05Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "cores": 1, "ram": 1024, "availabilityZone": "AUTO", "vmState": "RUNNING", "bootCdrom": null, "bootVolume": { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "matfin@stackpointcloud.com", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "type": "HDD", "size": 2, "image": "bvol-img", "imagePassword": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } }, "cpuFamily": "AMD_OPTERON" }, "entities": { "cdroms": { "id": "srv-1/cdroms", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/cdroms", "items": [] }, "volumes": { "id": "srv-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/volumes", "items": [ { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1" } ] }, "nics": { "id": "srv-1/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/nics", "items": [] } } }, { "id": "srv-1", "type": "server", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1", "metadata": { "createdDate": "2016-10-18T07:28:05Z", "createdBy": "test@test.te", "etag": "e7cf186125f51f3d9511754a40dcd12c", "lastModifiedDate": "2016-10-18T07:28:05Z", "lastModifiedBy": "matfin@stackpointcloud.com", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "cores": 1, "ram": 1024, "availabilityZone": "AUTO", "vmState": "RUNNING", "bootCdrom": null, "bootVolume": { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "matfin@stackpointcloud.com", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "libcloud Test", "type": "HDD", "size": 2, "image": "bvol-img", "imagePassword": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } }, "cpuFamily": "AMD_OPTERON" }, "entities": { "cdroms": { "id": "srv-1/cdroms", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/cdroms", "items": [] }, "volumes": { "id": "srv-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/volumes", "items": [ { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1" } ] }, "nics": { "id": "srv-1/nics", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/servers/srv-1/nics", "items": [] } } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/list_snapshots.json0000664000175000017500000000244313535474530031211 0ustar kamikami00000000000000{ "id": "snapshots", "type": "collection", "href": "/cloudapi/v4/snapshots", "items": [ { "id": "sshot", "type": "snapshot", "href": "/cloudapi/v4/snapshots/sshot", "metadata": { "createdDate": "2016-10-26T11:38:45Z", "createdBy": "test@test.te", "etag": "01873262ac042b5f44ed33b4241225b4", "lastModifiedDate": "2016-10-26T11:38:45Z", "lastModifiedBy": "test@test.te", "state": "AVAILABLE" }, "properties": { "name": "Balancer Testing 1 Storage-Snapshot-10/26/2016", "description": "Created from \"Balancer Testing 1 Storage\" in Data Center \"Snapshot\"", "location": "us/las", "size": 10, "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "licenceType": "LINUX" } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/profitbricks/list_volumes.json0000664000175000017500000001010613535474530030654 0ustar kamikami00000000000000{ "id": "dc-1/volumes", "type": "collection", "href": "/cloudapi/v4/datacenters/dc-1/volumes", "items": [ { "id": "bvol-1", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/bvol-1", "metadata": { "createdDate": "2016-10-18T07:20:41Z", "createdBy": "test@test.test", "etag": "33f6b8d506e7ad756e8554b915f29c61", "lastModifiedDate": "2016-10-18T07:20:41Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Test", "type": "HDD", "size": 10, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } }, { "id": "d6688ced-700d-4c9c-a3a7-9f7170c5edc3", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/d6688ced-700d-4c9c-a3a7-9f7170c5edc3", "metadata": { "createdDate": "2016-10-17T13:13:36Z", "createdBy": "test@test.test", "etag": "c1800ce349033f9cd2c095ea1ea4976a", "lastModifiedDate": "2016-10-17T13:47:52Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Updated storage name", "type": "HDD", "size": 40, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": null, "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": null } }, { "id": "21d7e7de-5054-4041-b691-717aa8b3c799", "type": "volume", "href": "/cloudapi/v4/datacenters/dc-1/volumes/21d7e7de-5054-4041-b691-717aa8b3c799", "metadata": { "createdDate": "2016-10-17T11:33:20Z", "createdBy": "test@test.test", "etag": "a9d0b923527efae5e7071e9118e9eece", "lastModifiedDate": "2016-10-17T11:33:20Z", "lastModifiedBy": "test@test.test", "state": "AVAILABLE" }, "properties": { "name": "Image and location and size. - volume", "type": "HDD", "size": 50, "availabilityZone": "AUTO", "image": "bvol-img", "imagePassword": null, "sshKeys": null, "bus": "VIRTIO", "licenceType": "LINUX", "cpuHotPlug": true, "cpuHotUnplug": false, "ramHotPlug": true, "ramHotUnplug": false, "nicHotPlug": true, "nicHotUnplug": true, "discVirtioHotPlug": true, "discVirtioHotUnplug": true, "discScsiHotPlug": false, "discScsiHotUnplug": false, "deviceNumber": 1 } } ] }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/0000775000175000017500000000000013600223624025072 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_distributions.json0000664000175000017500000000162613535474530031230 0ustar kamikami00000000000000{ "get_distros_response" : { "status_message" : null , "status_code" : 200 , "error_info" : null , "response_type" : "OK" , "human_readable_message" : "Here are the distros we are offering on new orders." , "response_display_duration_type" : "REGULAR" , "distro_infos" : [{ "distro_code" : "lenny" , "distro_description" : "Debian 5.0 (aka Lenny, RimuHosting recommended distro)"} , { "distro_code" : "centos5" , "distro_description" : "Centos5"} , { "distro_code" : "ubuntu904" , "distro_description" : "Ubuntu 9.04 (Jaunty Jackalope, from 2009-04)"} , { "distro_code" : "ubuntu804" , "distro_description" : "Ubuntu 8.04 (Hardy Heron, 5 yr long term support (LTS))"} , { "distro_code" : "ubuntu810" , "distro_description" : "Ubuntu 8.10 (Intrepid Ibex, from 2008-10)"} , { "distro_code" : "fedora10" , "distro_description" : "Fedora 10"}] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_orders.json0000664000175000017500000000171713535474530027625 0ustar kamikami00000000000000{ "get_orders_response" : { "status_message" : null , "status_code" : 200 , "error_info" : null , "response_type" : "OK" , "human_readable_message" : "Found 15 orders" , "response_display_duration_type" : "REGULAR", "about_orders" : [{ "order_oid" : 88833465 , "domain_name" : "api.ivan.net.nz" , "slug" : "order-88833465-api-ivan-net-nz" , "billing_oid" : 96122465 , "is_on_customers_own_physical_server" : false , "vps_parameters" : { "memory_mb" : 160 , "disk_space_mb" : 4096 , "disk_space_2_mb" : 0} , "host_server_oid" : "764" , "server_type" : "VPS" , "data_transfer_allowance" : { "data_transfer_gb" : 30 , "data_transfer" : "30"} , "billing_info" : { "monthly_recurring_fee": 19.99 } , "allocated_ips" : { "primary_ip" : "1.2.3.4" , "secondary_ips" : ["1.2.3.5","1.2.3.6"]} , "running_state" : "RUNNING" }] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_orders_new_vps.json0000664000175000017500000000441213535474530031361 0ustar kamikami00000000000000{ "post_new_vps_response" : { "status_message" : null , "status_code" : 200 , "error_info" : null , "response_type" : "OK" , "human_readable_message" : null , "response_display_duration_type" : "REGULAR" , "setup_messages" : ["Using user-specified billing data: Wire Transfer" , "Selected user as the owner of the billing details: Ivan Meredith" , "No VPS paramters provided, using default values."] , "about_order" : { "order_oid" : 52255865 , "domain_name" : "api.ivan.net.nz" , "slug" : "order-52255865-api-ivan-net-nz" , "billing_oid" : 96122465 , "is_on_customers_own_physical_server" : false , "vps_parameters" : { "memory_mb" : 160 , "disk_space_mb" : 4096 , "disk_space_2_mb" : 0} , "host_server_oid" : "764" , "server_type" : "VPS" , "data_transfer_allowance" : { "data_transfer_gb" : 30 , "data_transfer" : "30"} , "billing_info" : { "monthly_recurring_fee" : 19.99 } , "allocated_ips" : { "primary_ip" : "74.50.57.80", "secondary_ips" : []} , "running_state" : "RUNNING"} , "new_order_request" : { "billing_oid" : 96122465 , "user_oid" : 0 , "host_server_oid" : null , "vps_order_oid_to_clone" : 0 , "ip_request" : { "num_ips" : 1, "extra_ip_reason" : ""} , "vps_parameters" : { "memory_mb" : 160 , "disk_space_mb" : 4096 , "disk_space_2_mb" : 0} , "pricing_plan_code" : "MIRO1B" , "instantiation_options" : { "control_panel" : "webmin" , "domain_name" : "api.ivan.net.nz" , "password" : "aruxauce27" , "distro" : "lenny"}} , "running_vps_info" : { "pings_ok" : true , "current_kernel" : "default" , "current_kernel_canonical" : "2.6.30.5-xenU.i386" , "last_backup_message" : "" , "is_console_login_enabled" : false , "console_public_authorized_keys" : null , "is_backup_running" : false , "is_backups_enabled" : true , "next_backup_time" : { "ms_since_epoch": 1256446800000, "iso_format" : "2009-10-25T05:00:00Z", "users_tz_offset_ms" : 46800000} , "vps_uptime_s" : 31 , "vps_cpu_time_s" : 6 , "running_state" : "RUNNING" , "is_suspended" : false} } } ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_ne0000664000175000017500000000070313535474530033406 0ustar kamikami00000000000000{ "delete_server_response" : { "status_message" : null , "status_code" : 200 , "error_info" : null , "response_type" : "OK" , "human_readable_message" : "Server removed" , "response_display_duration_type" : "REGULAR" , "cancel_messages" : ["api.ivan.net.nz is being shut down." , "A $7.98 credit has been added to your account." , "If you need to un-cancel the server please contact our support team."] } } ././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_net_nz_vps_running_state.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_orders_order_88833465_api_ivan_ne0000664000175000017500000000301113535474530033401 0ustar kamikami00000000000000{ "put_running_state_response" : { "status_message" : null , "status_code" : 200 , "error_info" : null , "response_type" : "OK" , "human_readable_message" : "api.ivan.net.nz restarted. After the reboot api.ivan.net.nz is pinging OK." , "response_display_duration_type" : "REGULAR" , "is_restarted" : true , "is_pinging" : true , "running_vps_info" : { "pings_ok" : true , "current_kernel" : "default" , "current_kernel_canonical" : "2.6.30.5-xenU.i386" , "last_backup_message" : "" , "is_console_login_enabled" : false , "console_public_authorized_keys" : null , "is_backup_running" : false , "is_backups_enabled" : true , "next_backup_time" : { "ms_since_epoch": 1256446800000, "iso_format" : "2009-10-25T05:00:00Z", "users_tz_offset_ms" : 46800000} , "vps_uptime_s" : 19 , "vps_cpu_time_s" : 5 , "running_state" : "RUNNING" , "is_suspended" : false} , "host_server_info" : { "is_host64_bit_capable" : true , "default_kernel_i386" : "2.6.30.5-xenU.i386" , "default_kernel_x86_64" : "2.6.30.5-xenU.x86_64" , "cpu_model_name" : "Intel(R) Xeon(R) CPU E5506 @ 2.13GHz" , "host_num_cores" : 1 , "host_xen_version" : "3.4.1" , "hostload" : [1.45 , 0.56 , 0.28] , "host_uptime_s" : 3378276 , "host_mem_mb_free" : 51825 , "host_mem_mb_total" : 73719 , "running_vpss" : 34} , "running_state_messages" : null } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/rimuhosting/r_pricing_plans.json0000664000175000017500000000234513535474530031155 0ustar kamikami00000000000000{"get_pricing_plans_response" : { "status_message" : null , "status_code" : 200 , "error_info" : null , "response_type" : "OK" , "human_readable_message" : "Here some pricing plans we are offering on new orders.  Note we offer most disk and memory sizes.  So if you setup a new server feel free to vary these (e.g. different memory, disk, etc) and we will just adjust the pricing to suit.  Pricing is in USD.  If you are an NZ-based customer then we would need to add GST." , "response_display_duration_type" : "REGULAR" , "pricing_plan_infos" : [{ "pricing_plan_code" : "MiroVPSLowContention" , "pricing_plan_description" : "MiroVPS Semi-Dedicated Server (Dallas)" , "monthly_recurring_fee" : 32.54 , "monthly_recurring_amt" : { "amt" : 35.0 , "currency" : "CUR_AUD" , "amt_usd" : 32.54} , "minimum_memory_mb" : 950 , "minimum_disk_gb" : 20 , "minimum_data_transfer_allowance_gb" : 75 , "see_also_url" : "http://rimuhosting.com/order/serverdetails.jsp?plan=MiroVPSLowContention" , "server_type" : "VPS" , "offered_at_data_center" : { "data_center_location_code" : "DCDALLAS" , "data_center_location_name" : "Dallas" } }] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/0000775000175000017500000000000013600223624024332 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/create_image.json0000664000175000017500000000110213535474530027637 0ustar kamikami00000000000000{ "image": { "arch": "arm", "creation_date": "2014-05-22T12:56:56.984011+00:00", "extra_volumes": "[]", "from_image": null, "from_server": null, "id": "98bf3ac2-a1f5-471d-8c8f-1b706ab57ef0", "marketplace_key": null, "modification_date": "2014-05-22T12:56:56.984011+00:00", "name": "my_image", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "public": false, "root_volume": { "size": 25000000000, "id": "f0361e7b-cbe4-4882-a999-945192b7171b", "volume_type": "l_ssd", "name": "vol-0-1" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/create_node.json0000664000175000017500000000173613535474530027517 0ustar kamikami00000000000000{ "server": { "bootscript": null, "creation_date": "2014-05-22T12:57:22.514299+00:00", "dynamic_ip_required": true, "id": "741db378", "image": { "id": "85917034-46b0-4cc5-8b48-f0a2245e357e", "name": "ubuntu working" }, "location": null, "name": "my_server", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "private_ip": null, "public_ip": null, "enable_ipv6": true, "state": "stopped", "ipv6": null, "commercial_type": "VC1S", "arch": "x86_64", "tags": [ "test", "www" ], "volumes": { "0": { "export_uri": null, "id": "d9257116-6919-49b4-a420-dcfdff51fcb1", "name": "vol simple snapshot", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "server": { "id": "3cb18e2d-f4f7-48f7-b452-59b88ae8fc8c", "name": "my_server" }, "size": 10000000000, "volume_type": "l_ssd" } } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/create_volume.json0000664000175000017500000000056413535474530030077 0ustar kamikami00000000000000{ "volume": { "creation_date": "2014-05-22T12:57:22.514299+00:00", "modification_date": "2014-05-22T12:57:22.514299+00:00", "export_uri": null, "id": "c675f420-cfeb-48ff-ba2a-9d2a4dbe3fcd", "name": "volume-0-3", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "server": null, "size": 10000000000, "volume_type": "l_ssd" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/create_volume_snapshot.json0000664000175000017500000000064013535474530032011 0ustar kamikami00000000000000{ "snapshot": { "base_volume": { "id": "f929fe39-63f8-4be8-a80e-1e9c8ae22a76", "name": "vol simple snapshot" }, "creation_date": "2014-05-22T12:10:05.596769+00:00", "id": "f0361e7b-cbe4-4882-a999-945192b7171b", "name": "snapshot-0-1", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "size": 10000000000, "state": "snapshotting", "volume_type": "l_ssd" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/error.json0000664000175000017500000000007413535474530026372 0ustar kamikami00000000000000{"message": "Authentication error", "type": "invalid_auth"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/error_invalid_image.json0000664000175000017500000000013613535474530031241 0ustar kamikami00000000000000{"message": "\"01234567-89ab-cdef-fedc-ba9876543210\" not found", "type": "unknown_resource"} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/get_image.json0000664000175000017500000000104313535474530027157 0ustar kamikami00000000000000{ "image": { "arch": "arm", "creation_date": "2014-05-22T12:56:56.984011+00:00", "extra_volumes": "[]", "from_image": null, "from_server": null, "id": "12345", "marketplace_key": null, "modification_date": "2014-05-22T12:56:56.984011+00:00", "name": "my_image", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "public": false, "root_volume": { "size": 25000000000, "id": "f0361e7b-cbe4-4882-a999-945192b7171b", "volume_type": "l_ssd", "name": "vol-0-1" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_availability.json0000664000175000017500000000030613535474530030744 0ustar kamikami00000000000000{ "servers": { "X64-120GB": { "availability": "scarce" }, "START1-XS": { "availability": "available" }, "ARM64-4GB": { "availability": "shortage" } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_images.json0000664000175000017500000000222113535474530027535 0ustar kamikami00000000000000{ "images": [ { "arch": "arm", "creation_date": "2014-05-22T12:56:56.984011+00:00", "extra_volumes": "[]", "from_image": null, "from_server": null, "id": "12345", "marketplace_key": null, "modification_date": "2014-05-22T12:56:56.984011+00:00", "name": "my_image", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "public": false, "root_volume": { "size": 50000000000, "id": "f0361e7b-cbe4-4882-a999-945192b7171b", "volume_type": "l_ssd", "name": "vol-0-1" } }, { "arch": "arm", "creation_date": "2014-05-22T12:57:22.514299+00:00", "extra_volumes": "[]", "from_image": null, "from_server": null, "id": "54321", "marketplace_key": null, "modification_date": "2014-05-22T12:57:22.514299+00:00", "name": "my_image_1", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "public": false, "root_volume": { "size": 25000000000, "id": "f0361e7b-cbe4-4882-a999-945192b7171b", "volume_type": "l_ssd", "name": "vol-0-2" } } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_nodes.json0000664000175000017500000000365013535474530027407 0ustar kamikami00000000000000{ "servers": [ { "bootscript": null, "arch": "arm", "creation_date": "2014-05-22T12:57:22.514299+00:00", "dynamic_public_ip": false, "id": "741db378", "image": { "id": "85917034-46b0-4cc5-8b48-f0a2245e357e", "name": "ubuntu working" }, "location": null, "name": "my_server", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "private_ip": null, "public_ip": null, "state": "running", "tags": [ "test", "www" ], "volumes": { "0": { "export_uri": null, "id": "c1eb8f3a-4f0b-4b95-a71c-93223e457f5a", "name": "vol simple snapshot", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "server": { "id": "741db378-6b87-46d4-a8c5-4e46a09ab1f8", "name": "my_server" }, "size": 10000000000, "volume_type": "l_ssd" } } }, { "bootscript": null, "arch": "arm", "creation_date": "2014-05-22T12:57:22.514299+00:00", "dynamic_public_ip": false, "id": "0e9f85af", "image": { "id": "85917034-46b0-4cc5-8b48-f0a2245e357e", "name": "ubuntu working" }, "location": null, "name": "my_server", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "private_ip": null, "public_ip": null, "state": "running", "tags": [ "test", "www" ], "volumes": { "0": { "export_uri": null, "id": "fb09bb31-ecd9-4dff-8b55-b6e45715199d", "name": "vol simple snapshot", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "server": { "id": "0e9f85af-b6aa-401e-a00d-484f832c5024", "name": "my_server" }, "size": 10000000000, "volume_type": "l_ssd" } } } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_nodes_empty.json0000664000175000017500000000002413535474530030615 0ustar kamikami00000000000000{ "servers": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_sizes.json0000664000175000017500000000340213535474530027427 0ustar kamikami00000000000000{ "servers": { "X64-120GB": { "baremetal": false, "monthly_price": null, "volumes_constraint": { "min_size": 500000000000, "max_size": 1000000000000 }, "network": { "interfaces": [ { "internal_bandwidth": null, "internet_bandwidth": 1073741824 } ], "sum_internal_bandwidth": null, "sum_internet_bandwidth": 1073741824, "ipv6_support": true }, "hourly_price": null, "ncpus": 12, "ram": 128849018880, "arch": "x86_64", "alt_names": [] }, "START1-XS": { "baremetal": false, "monthly_price": 1.99, "volumes_constraint": { "min_size": 25000000000, "max_size": 25000000000 }, "network": { "interfaces": [ { "internal_bandwidth": null, "internet_bandwidth": 104857600 } ], "sum_internal_bandwidth": null, "sum_internet_bandwidth": 104857600, "ipv6_support": true }, "hourly_price": 0.004, "ncpus": 1, "ram": 1073741824, "arch": "x86_64", "alt_names": [] }, "ARM64-4GB": { "baremetal": false, "monthly_price": 5.99, "volumes_constraint": { "min_size": 100000000000, "max_size": 100000000000 }, "network": { "interfaces": [ { "internal_bandwidth": null, "internet_bandwidth": 209715200 } ], "sum_internal_bandwidth": null, "sum_internet_bandwidth": 209715200, "ipv6_support": true }, "hourly_price": 0.012, "ncpus": 6, "ram": 4294967296, "arch": "arm64", "alt_names": [] } } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_volume_snapshots.json0000664000175000017500000000155613535474530031713 0ustar kamikami00000000000000{ "snapshots": [ { "base_volume": { "id": "f929fe39-63f8-4be8-a80e-1e9c8ae22a76", "name": "vol simple snapshot" }, "creation_date": "2014-05-22T12:11:06.055998+00:00", "id": "6f418e5f-b42d-4423-a0b5-349c74c454a4", "name": "snapshot-0-1", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "size": 10000000000, "state": "snapshotting", "volume_type": "l_ssd" }, { "base_volume": { "id": "f929fe39-63f8-4be8-a80e-1e9c8ae22a76", "name": "vol simple snapshot" }, "creation_date": "2014-05-22T12:13:09.877961+00:00", "id": "c6ff5501-eb35-44b8-aa01-8777211a830b", "name": "snapshot-0-2", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "size": 10000000000, "state": "snapshotting", "volume_type": "l_ssd" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_volumes.json0000664000175000017500000000142013535474530027762 0ustar kamikami00000000000000{ "volumes": [ { "export_uri": null, "creation_date": "2014-05-22T12:56:56.984011+00:00", "modification_date": "2014-05-22T12:56:56.984011+00:00", "id": "f929fe39-63f8-4be8-a80e-1e9c8ae22a76", "name": "volume-0-1", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "server": null, "size": 10000000000, "volume_type": "l_ssd" }, { "export_uri": null, "creation_date": "2014-05-22T12:56:56.984011+00:00", "modification_date": "2014-05-22T12:56:56.984011+00:00", "id": "0facb6b5-b117-441a-81c1-f28b1d723779", "name": "volume-0-2", "organization": "000a115d-2852-4b0a-9ce8-47f1134ba95a", "server": null, "size": 20000000000, "volume_type": "l_ssd" } ] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/list_volumes_empty.json0000664000175000017500000000002413535474530031177 0ustar kamikami00000000000000{ "volumes": [] } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/reboot_node.json0000664000175000017500000000025013535474530027534 0ustar kamikami00000000000000{ "task": { "description": "server_reboot", "href_from": "/servers/741db378/action", "id": "741db378", "progress": "0", "status": "pending" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/token_info.json0000664000175000017500000000045313535474530027375 0ustar kamikami00000000000000{ "token": { "creation_date": "2014-05-22T08:06:51.742826+00:00", "expires": "2014-05-20T14:05:06.393875+00:00", "id": "token", "inherits_user_perms": true, "permissions": [], "roles": { "organization": null, "role": null }, "user_id": "5bea0358" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/scaleway/user_info.json0000664000175000017500000000052513535474530027233 0ustar kamikami00000000000000{ "user": { "email": "jsnow@got.com", "firstname": "John", "fullname": "John Snow", "id": "5bea0358", "lastname": "Snow", "organizations": null, "roles": null, "ssh_public_keys": [{ "fingerprint": "f5:d1:78:ed:28:72:5f:e1:ac:94:fd:1f:e0:a3:48:6d", "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDGk5 example" }] } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/0000775000175000017500000000000013600223624024532 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/SoftLayer_Account.xml0000664000175000017500000000060213535474530030651 0ustar kamikami00000000000000 faultCode SoftLayer_Account faultString Failed Call apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/empty.xml0000664000175000017500000000006013535474530026421 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/fail.xml0000664000175000017500000000056513535474530026210 0ustar kamikami00000000000000 faultCode fail faultString Failed Call ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests0000664000175000017500000011053313535474530034070 0ustar kamikami00000000000000 accountId 282402 createDate 2013-11-06T14:38:36+01:00 dedicatedAccountHostOnlyFlag 0 domain example.com fullyQualifiedDomainName libcloud-testing1.example.com hostname libcloud-testing1 id 2875152 lastPowerStateId lastVerifiedDate maxCpu 1 maxCpuUnits CORE maxMemory 2048 metricPollDate modifyDate 2013-11-06T14:41:25+01:00 startCpus 1 statusId 1001 uuid ab98fc82-9d74-bc34-6701-f88957ebbba8 billingItem allowCancellationFlag 1 cancellationDate categoryCode guest_core createDate 2013-11-06T14:38:38+01:00 currentHourlyCharge .112 cycleStartDate 2013-11-06T14:43:20+01:00 description 1 x 2.0 GHz Core domainName example.com hostName libcloud-testing1 hourlyRecurringFee .056 hoursUsed 2 id 16447700 laborFee 0 laborFeeTaxRate .21 lastBillDate 2013-11-06T14:43:20+01:00 modifyDate 2013-11-06T14:43:20+01:00 nextBillDate 2013-11-28T07:00:00+01:00 oneTimeFee 0 oneTimeFeeTaxRate .21 orderItemId 22662589 parentId recurringFee .112 recurringFeeTaxRate .21 recurringMonths 1 serviceProviderId 1 setupFee 0 setupFeeTaxRate .21 resourceTableId 2875152 datacenter id 168642 longName San Jose 1 name sjc01 globalIdentifier 9ee84f87-e558-4548-9b89-fe7d997706b8 operatingSystem hardwareId id 2200995 manufacturerLicenseInstance passwords createDate 2013-11-06T14:38:56+01:00 id 1856975 modifyDate 2013-11-06T14:38:56+01:00 password L3TJVubf port softwareId 2200995 username root softwareLicense id 1523 softwareDescriptionId 1163 softwareDescription controlPanel 0 id 1163 longDescription Debian / Debian / 7.0.0-64 Minimal for CCI manufacturer Debian name Debian operatingSystem 1 referenceCode DEBIAN_7_64 upgradeSoftwareDescriptionId upgradeSwDescId version 7.0.0-64 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root powerState keyName RUNNING name Running primaryBackendIpAddress 10.55.43.130 primaryIpAddress 50.23.95.202 accountId 282402 createDate 2013-11-06T15:14:52+01:00 dedicatedAccountHostOnlyFlag 0 domain example.com fullyQualifiedDomainName libcloud-testing2.example.com hostname libcloud-testing2 id 2875213 lastPowerStateId lastVerifiedDate maxCpu 1 maxCpuUnits CORE maxMemory 2048 metricPollDate modifyDate 2013-11-06T15:17:56+01:00 startCpus 1 statusId 1001 uuid 8f10bea1-3e26-70d7-d581-0d9e820eae0c billingItem allowCancellationFlag 1 cancellationDate categoryCode guest_core createDate 2013-11-06T15:14:55+01:00 currentHourlyCharge .056 cycleStartDate 2013-11-06T15:19:50+01:00 description 1 x 2.0 GHz Core domainName example.com hostName libcloud-testing2 hourlyRecurringFee .056 hoursUsed 1 id 16447908 laborFee 0 laborFeeTaxRate .21 lastBillDate 2013-11-06T15:19:50+01:00 modifyDate 2013-11-06T15:19:50+01:00 nextBillDate 2013-11-28T07:00:00+01:00 oneTimeFee 0 oneTimeFeeTaxRate .21 orderItemId 22663091 parentId recurringFee .056 recurringFeeTaxRate .21 recurringMonths 1 serviceProviderId 1 setupFee 0 setupFeeTaxRate .21 resourceTableId 2875213 datacenter id 168642 longName San Jose 1 name sjc01 globalIdentifier 5c704e34-6ee7-4efe-9722-af9d406fa930 operatingSystem hardwareId id 2201027 manufacturerLicenseInstance softwareLicense id 1523 softwareDescriptionId 1163 softwareDescription controlPanel 0 id 1163 longDescription Debian / Debian / 7.0.0-64 Minimal for CCI manufacturer Debian name Debian operatingSystem 1 referenceCode DEBIAN_7_64 upgradeSoftwareDescriptionId upgradeSwDescId version 7.0.0-64 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root powerState keyName INITIATING name Running primaryBackendIpAddress 10.55.43.131 primaryIpAddress 50.23.95.203 accountId 282402 createDate 2013-11-06T15:36:53+01:00 dedicatedAccountHostOnlyFlag 0 domain example.com fullyQualifiedDomainName libcloud-testing.example.com hostname libcloud-testing id 2875273 lastPowerStateId lastVerifiedDate maxCpu 1 maxCpuUnits CORE maxMemory 2048 metricPollDate modifyDate 2013-11-06T15:39:35+01:00 startCpus 1 statusId 1001 uuid f86371c5-103b-34d3-ae27-e4dafa1c4718 billingItem allowCancellationFlag 1 cancellationDate categoryCode guest_core createDate 2013-11-06T15:36:55+01:00 currentHourlyCharge .056 cycleStartDate 2013-11-06T15:41:31+01:00 description 1 x 2.0 GHz Core domainName example.com hostName libcloud-testing hourlyRecurringFee .056 hoursUsed 1 id 16448162 laborFee 0 laborFeeTaxRate .21 lastBillDate 2013-11-06T15:41:31+01:00 modifyDate 2013-11-06T15:41:31+01:00 nextBillDate 2013-11-28T07:00:00+01:00 oneTimeFee 0 oneTimeFeeTaxRate .21 orderItemId 22663578 parentId recurringFee .056 recurringFeeTaxRate .21 recurringMonths 1 serviceProviderId 1 setupFee 0 setupFeeTaxRate .21 resourceTableId 2875273 datacenter id 168642 longName San Jose 1 name sjc01 globalIdentifier e8ab9d1c-edd8-4a1a-a13c-ff74838b5ab6 operatingSystem hardwareId id 2201049 manufacturerLicenseInstance passwords createDate 2013-11-06T15:37:10+01:00 id 1857066 modifyDate 2013-11-06T15:37:10+01:00 password HmyHw89J port softwareId 2201049 username root softwareLicense id 1523 softwareDescriptionId 1163 softwareDescription controlPanel 0 id 1163 longDescription Debian / Debian / 7.0.0-64 Minimal for CCI manufacturer Debian name Debian operatingSystem 1 referenceCode DEBIAN_7_64 upgradeSoftwareDescriptionId upgradeSwDescId version 7.0.0-64 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root powerState keyName RUNNING name Running primaryBackendIpAddress 10.55.43.132 primaryIpAddress 50.23.95.204 ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getD0000664000175000017500000000417213535474530033741 0ustar kamikami00000000000000 id 2 name dal05 longName Dallas 5 id 3 name dal01 longName Dallas id 18171 name sea01 longName Seattle id 37473 name wdc01 longName Washington, DC id 12345 name newcity01 longName New City apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Account_getSshKeys.xml0000664000175000017500000000356213535474530033601 0ustar kamikami00000000000000 id 1 key ssh-key label test1 fingerprint 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 id 2 key ssh-key label test2 fingerprint 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_createObject.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_create0000664000175000017500000000224513535474530034011 0ustar kamikami00000000000000 id 1 key ssh-key label my-key-pair label my-key-pair fingerprint 1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_deleteObject.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_delete0000664000175000017500000000054413535474530034010 0ustar kamikami00000000000000 status success ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_getObject.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_getObj0000664000175000017500000000172613535474530033763 0ustar kamikami00000000000000 id 1 key ssh-key label test1 fingerprint 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObj0000664000175000017500000000470613535474530034011 0ustar kamikami00000000000000 accountId 12345 createDate 2013-01-01T19:31:22-06:00 dedicatedAccountHostOnlyFlag 0 domain domain.com fullyQualifiedDomainName hostname.domain.com hostname hostname id 123456 lastPowerStateId lastVerifiedDate maxCpu 2 maxCpuUnits CORE maxMemory 2048 metricPollDate modifyDate privateNetworkOnlyFlag 0 startCpus 2 statusId 1001 globalIdentifier f47ac10b-58cc-4372-a567-0e02b2c3d479 managedResourceFlag 0 powerState keyName HALTED name Halted ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreate0000664000175000017500000117065513535474530034026 0ustar kamikami00000000000000 blockDevices itemPrice hourlyRecurringFee 0 recurringFee 0 item description 25 GB (SAN) template blockDevices device 0 diskImage capacity 25 localDiskFlag 0 itemPrice hourlyRecurringFee .025 recurringFee 18 item description 100 GB (SAN) template blockDevices device 0 diskImage capacity 100 localDiskFlag 0 itemPrice hourlyRecurringFee .012 recurringFee 8 item description 10 GB (SAN) template blockDevices device 2 diskImage capacity 10 localDiskFlag 0 itemPrice hourlyRecurringFee .015 recurringFee 10 item description 20 GB (SAN) template blockDevices device 2 diskImage capacity 20 localDiskFlag 0 itemPrice hourlyRecurringFee .016 recurringFee 11 item description 25 GB (SAN) template blockDevices device 2 diskImage capacity 25 localDiskFlag 0 itemPrice hourlyRecurringFee .017 recurringFee 12 item description 30 GB (SAN) template blockDevices device 2 diskImage capacity 30 localDiskFlag 0 itemPrice hourlyRecurringFee .019 recurringFee 14 item description 40 GB (SAN) template blockDevices device 2 diskImage capacity 40 localDiskFlag 0 itemPrice hourlyRecurringFee .021 recurringFee 16 item description 50 GB (SAN) template blockDevices device 2 diskImage capacity 50 localDiskFlag 0 itemPrice hourlyRecurringFee .023 recurringFee 17 item description 75 GB (SAN) template blockDevices device 2 diskImage capacity 75 localDiskFlag 0 itemPrice hourlyRecurringFee .025 recurringFee 18 item description 100 GB (SAN) template blockDevices device 2 diskImage capacity 100 localDiskFlag 0 itemPrice hourlyRecurringFee .028 recurringFee 19 item description 125 GB (SAN) template blockDevices device 2 diskImage capacity 125 localDiskFlag 0 itemPrice hourlyRecurringFee .03 recurringFee 20 item description 150 GB (SAN) template blockDevices device 2 diskImage capacity 150 localDiskFlag 0 itemPrice hourlyRecurringFee .035 recurringFee 21 item description 175 GB (SAN) template blockDevices device 2 diskImage capacity 175 localDiskFlag 0 itemPrice hourlyRecurringFee .04 recurringFee 22 item description 200 GB (SAN) template blockDevices device 2 diskImage capacity 200 localDiskFlag 0 itemPrice hourlyRecurringFee .05 recurringFee 25 item description 250 GB (SAN) template blockDevices device 2 diskImage capacity 250 localDiskFlag 0 itemPrice hourlyRecurringFee .06 recurringFee 32.5 item description 300 GB (SAN) template blockDevices device 2 diskImage capacity 300 localDiskFlag 0 itemPrice hourlyRecurringFee .07 recurringFee 40 item description 350 GB (SAN) template blockDevices device 2 diskImage capacity 350 localDiskFlag 0 itemPrice hourlyRecurringFee .08 recurringFee 45 item description 400 GB (SAN) template blockDevices device 2 diskImage capacity 400 localDiskFlag 0 itemPrice hourlyRecurringFee .1 recurringFee 50 item description 500 GB (SAN) template blockDevices device 2 diskImage capacity 500 localDiskFlag 0 itemPrice hourlyRecurringFee .15 recurringFee 75 item description 750 GB (SAN) template blockDevices device 2 diskImage capacity 750 localDiskFlag 0 itemPrice hourlyRecurringFee .2 recurringFee 100 item description 1,000 GB (SAN) template blockDevices device 2 diskImage capacity 1000 localDiskFlag 0 itemPrice hourlyRecurringFee .25 recurringFee 150 item description 1,500 GB (SAN) template blockDevices device 2 diskImage capacity 1500 localDiskFlag 0 itemPrice hourlyRecurringFee .3 recurringFee 200 item description 2,000 GB (SAN) template blockDevices device 2 diskImage capacity 2000 localDiskFlag 0 itemPrice hourlyRecurringFee .012 recurringFee 8 item description 10 GB (SAN) template blockDevices device 3 diskImage capacity 10 localDiskFlag 0 itemPrice hourlyRecurringFee .015 recurringFee 10 item description 20 GB (SAN) template blockDevices device 3 diskImage capacity 20 localDiskFlag 0 itemPrice hourlyRecurringFee .016 recurringFee 11 item description 25 GB (SAN) template blockDevices device 3 diskImage capacity 25 localDiskFlag 0 itemPrice hourlyRecurringFee .017 recurringFee 12 item description 30 GB (SAN) template blockDevices device 3 diskImage capacity 30 localDiskFlag 0 itemPrice hourlyRecurringFee .019 recurringFee 14 item description 40 GB (SAN) template blockDevices device 3 diskImage capacity 40 localDiskFlag 0 itemPrice hourlyRecurringFee .021 recurringFee 16 item description 50 GB (SAN) template blockDevices device 3 diskImage capacity 50 localDiskFlag 0 itemPrice hourlyRecurringFee .023 recurringFee 17 item description 75 GB (SAN) template blockDevices device 3 diskImage capacity 75 localDiskFlag 0 itemPrice hourlyRecurringFee .025 recurringFee 18 item description 100 GB (SAN) template blockDevices device 3 diskImage capacity 100 localDiskFlag 0 itemPrice hourlyRecurringFee .028 recurringFee 19 item description 125 GB (SAN) template blockDevices device 3 diskImage capacity 125 localDiskFlag 0 itemPrice hourlyRecurringFee .03 recurringFee 20 item description 150 GB (SAN) template blockDevices device 3 diskImage capacity 150 localDiskFlag 0 itemPrice hourlyRecurringFee .035 recurringFee 21 item description 175 GB (SAN) template blockDevices device 3 diskImage capacity 175 localDiskFlag 0 itemPrice hourlyRecurringFee .04 recurringFee 22 item description 200 GB (SAN) template blockDevices device 3 diskImage capacity 200 localDiskFlag 0 itemPrice hourlyRecurringFee .05 recurringFee 25 item description 250 GB (SAN) template blockDevices device 3 diskImage capacity 250 localDiskFlag 0 itemPrice hourlyRecurringFee .06 recurringFee 32.5 item description 300 GB (SAN) template blockDevices device 3 diskImage capacity 300 localDiskFlag 0 itemPrice hourlyRecurringFee .07 recurringFee 40 item description 350 GB (SAN) template blockDevices device 3 diskImage capacity 350 localDiskFlag 0 itemPrice hourlyRecurringFee .08 recurringFee 45 item description 400 GB (SAN) template blockDevices device 3 diskImage capacity 400 localDiskFlag 0 itemPrice hourlyRecurringFee .1 recurringFee 50 item description 500 GB (SAN) template blockDevices device 3 diskImage capacity 500 localDiskFlag 0 itemPrice hourlyRecurringFee .15 recurringFee 75 item description 750 GB (SAN) template blockDevices device 3 diskImage capacity 750 localDiskFlag 0 itemPrice hourlyRecurringFee .2 recurringFee 100 item description 1,000 GB (SAN) template blockDevices device 3 diskImage capacity 1000 localDiskFlag 0 itemPrice hourlyRecurringFee .25 recurringFee 150 item description 1,500 GB (SAN) template blockDevices device 3 diskImage capacity 1500 localDiskFlag 0 itemPrice hourlyRecurringFee .3 recurringFee 200 item description 2,000 GB (SAN) template blockDevices device 3 diskImage capacity 2000 localDiskFlag 0 itemPrice hourlyRecurringFee .012 recurringFee 8 item description 10 GB (SAN) template blockDevices device 4 diskImage capacity 10 localDiskFlag 0 itemPrice hourlyRecurringFee .015 recurringFee 10 item description 20 GB (SAN) template blockDevices device 4 diskImage capacity 20 localDiskFlag 0 itemPrice hourlyRecurringFee .016 recurringFee 11 item description 25 GB (SAN) template blockDevices device 4 diskImage capacity 25 localDiskFlag 0 itemPrice hourlyRecurringFee .017 recurringFee 12 item description 30 GB (SAN) template blockDevices device 4 diskImage capacity 30 localDiskFlag 0 itemPrice hourlyRecurringFee .019 recurringFee 14 item description 40 GB (SAN) template blockDevices device 4 diskImage capacity 40 localDiskFlag 0 itemPrice hourlyRecurringFee .021 recurringFee 16 item description 50 GB (SAN) template blockDevices device 4 diskImage capacity 50 localDiskFlag 0 itemPrice hourlyRecurringFee .023 recurringFee 17 item description 75 GB (SAN) template blockDevices device 4 diskImage capacity 75 localDiskFlag 0 itemPrice hourlyRecurringFee .025 recurringFee 18 item description 100 GB (SAN) template blockDevices device 4 diskImage capacity 100 localDiskFlag 0 itemPrice hourlyRecurringFee .028 recurringFee 19 item description 125 GB (SAN) template blockDevices device 4 diskImage capacity 125 localDiskFlag 0 itemPrice hourlyRecurringFee .03 recurringFee 20 item description 150 GB (SAN) template blockDevices device 4 diskImage capacity 150 localDiskFlag 0 itemPrice hourlyRecurringFee .035 recurringFee 21 item description 175 GB (SAN) template blockDevices device 4 diskImage capacity 175 localDiskFlag 0 itemPrice hourlyRecurringFee .04 recurringFee 22 item description 200 GB (SAN) template blockDevices device 4 diskImage capacity 200 localDiskFlag 0 itemPrice hourlyRecurringFee .05 recurringFee 25 item description 250 GB (SAN) template blockDevices device 4 diskImage capacity 250 localDiskFlag 0 itemPrice hourlyRecurringFee .06 recurringFee 32.5 item description 300 GB (SAN) template blockDevices device 4 diskImage capacity 300 localDiskFlag 0 itemPrice hourlyRecurringFee .07 recurringFee 40 item description 350 GB (SAN) template blockDevices device 4 diskImage capacity 350 localDiskFlag 0 itemPrice hourlyRecurringFee .08 recurringFee 45 item description 400 GB (SAN) template blockDevices device 4 diskImage capacity 400 localDiskFlag 0 itemPrice hourlyRecurringFee .1 recurringFee 50 item description 500 GB (SAN) template blockDevices device 4 diskImage capacity 500 localDiskFlag 0 itemPrice hourlyRecurringFee .15 recurringFee 75 item description 750 GB (SAN) template blockDevices device 4 diskImage capacity 750 localDiskFlag 0 itemPrice hourlyRecurringFee .2 recurringFee 100 item description 1,000 GB (SAN) template blockDevices device 4 diskImage capacity 1000 localDiskFlag 0 itemPrice hourlyRecurringFee .25 recurringFee 150 item description 1,500 GB (SAN) template blockDevices device 4 diskImage capacity 1500 localDiskFlag 0 itemPrice hourlyRecurringFee .3 recurringFee 200 item description 2,000 GB (SAN) template blockDevices device 4 diskImage capacity 2000 localDiskFlag 0 itemPrice hourlyRecurringFee .012 recurringFee 8 item description 10 GB (SAN) template blockDevices device 5 diskImage capacity 10 localDiskFlag 0 itemPrice hourlyRecurringFee .015 recurringFee 10 item description 20 GB (SAN) template blockDevices device 5 diskImage capacity 20 localDiskFlag 0 itemPrice hourlyRecurringFee .016 recurringFee 11 item description 25 GB (SAN) template blockDevices device 5 diskImage capacity 25 localDiskFlag 0 itemPrice hourlyRecurringFee .017 recurringFee 12 item description 30 GB (SAN) template blockDevices device 5 diskImage capacity 30 localDiskFlag 0 itemPrice hourlyRecurringFee .019 recurringFee 14 item description 40 GB (SAN) template blockDevices device 5 diskImage capacity 40 localDiskFlag 0 itemPrice hourlyRecurringFee .021 recurringFee 16 item description 50 GB (SAN) template blockDevices device 5 diskImage capacity 50 localDiskFlag 0 itemPrice hourlyRecurringFee .023 recurringFee 17 item description 75 GB (SAN) template blockDevices device 5 diskImage capacity 75 localDiskFlag 0 itemPrice hourlyRecurringFee .025 recurringFee 18 item description 100 GB (SAN) template blockDevices device 5 diskImage capacity 100 localDiskFlag 0 itemPrice hourlyRecurringFee .028 recurringFee 19 item description 125 GB (SAN) template blockDevices device 5 diskImage capacity 125 localDiskFlag 0 itemPrice hourlyRecurringFee .03 recurringFee 20 item description 150 GB (SAN) template blockDevices device 5 diskImage capacity 150 localDiskFlag 0 itemPrice hourlyRecurringFee .035 recurringFee 21 item description 175 GB (SAN) template blockDevices device 5 diskImage capacity 175 localDiskFlag 0 itemPrice hourlyRecurringFee .04 recurringFee 22 item description 200 GB (SAN) template blockDevices device 5 diskImage capacity 200 localDiskFlag 0 itemPrice hourlyRecurringFee .05 recurringFee 25 item description 250 GB (SAN) template blockDevices device 5 diskImage capacity 250 localDiskFlag 0 itemPrice hourlyRecurringFee .06 recurringFee 32.5 item description 300 GB (SAN) template blockDevices device 5 diskImage capacity 300 localDiskFlag 0 itemPrice hourlyRecurringFee .07 recurringFee 40 item description 350 GB (SAN) template blockDevices device 5 diskImage capacity 350 localDiskFlag 0 itemPrice hourlyRecurringFee .08 recurringFee 45 item description 400 GB (SAN) template blockDevices device 5 diskImage capacity 400 localDiskFlag 0 itemPrice hourlyRecurringFee .1 recurringFee 50 item description 500 GB (SAN) template blockDevices device 5 diskImage capacity 500 localDiskFlag 0 itemPrice hourlyRecurringFee .15 recurringFee 75 item description 750 GB (SAN) template blockDevices device 5 diskImage capacity 750 localDiskFlag 0 itemPrice hourlyRecurringFee .2 recurringFee 100 item description 1,000 GB (SAN) template blockDevices device 5 diskImage capacity 1000 localDiskFlag 0 itemPrice hourlyRecurringFee .25 recurringFee 150 item description 1,500 GB (SAN) template blockDevices device 5 diskImage capacity 1500 localDiskFlag 0 itemPrice hourlyRecurringFee .3 recurringFee 200 item description 2,000 GB (SAN) template blockDevices device 5 diskImage capacity 2000 localDiskFlag 0 itemPrice hourlyRecurringFee 0 recurringFee 0 item description 25 GB (LOCAL) template blockDevices device 0 diskImage capacity 25 localDiskFlag 1 itemPrice hourlyRecurringFee .01 recurringFee 7 item description 100 GB (LOCAL) template blockDevices device 0 diskImage capacity 100 localDiskFlag 1 itemPrice hourlyRecurringFee .005 recurringFee 3.25 item description 25 GB (LOCAL) template blockDevices device 2 diskImage capacity 25 localDiskFlag 1 itemPrice hourlyRecurringFee .01 recurringFee 7 item description 100 GB (LOCAL) template blockDevices device 2 diskImage capacity 100 localDiskFlag 1 itemPrice hourlyRecurringFee .015 recurringFee 9 item description 150 GB (LOCAL) template blockDevices device 2 diskImage capacity 150 localDiskFlag 1 itemPrice hourlyRecurringFee .02 recurringFee 14 item description 200 GB (LOCAL) template blockDevices device 2 diskImage capacity 200 localDiskFlag 1 itemPrice hourlyRecurringFee .03 recurringFee 21 item description 300 GB (LOCAL) template blockDevices device 2 diskImage capacity 300 localDiskFlag 1 datacenters template datacenter name ams01 template datacenter name dal05 template datacenter name dal06 template datacenter name sea01 template datacenter name sjc01 template datacenter name sng01 template datacenter name wdc01 memory itemPrice hourlyRecurringFee .03 recurringFee 21 item description 1 GB template maxMemory 1024 itemPrice hourlyRecurringFee .06 recurringFee 42 item description 2 GB template maxMemory 2048 itemPrice hourlyRecurringFee .085 recurringFee 59.5 item description 3 GB template maxMemory 3072 itemPrice hourlyRecurringFee .11 recurringFee 77 item description 4 GB template maxMemory 4096 itemPrice hourlyRecurringFee .14 recurringFee 98 item description 5 GB template maxMemory 5120 itemPrice hourlyRecurringFee .165 recurringFee 115.5 item description 6 GB template maxMemory 6144 itemPrice hourlyRecurringFee .195 recurringFee 136.5 item description 7 GB template maxMemory 7168 itemPrice hourlyRecurringFee .215 recurringFee 150.5 item description 8 GB template maxMemory 8192 itemPrice hourlyRecurringFee .245 recurringFee 171.5 item description 9 GB template maxMemory 9216 itemPrice hourlyRecurringFee .265 recurringFee 185.5 item description 10 GB template maxMemory 10240 itemPrice hourlyRecurringFee .29 recurringFee 203 item description 11 GB template maxMemory 11264 itemPrice hourlyRecurringFee .31 recurringFee 217 item description 12 GB template maxMemory 12288 itemPrice hourlyRecurringFee .33 recurringFee 231 item description 13 GB template maxMemory 13312 itemPrice hourlyRecurringFee .345 recurringFee 241.5 item description 14 GB template maxMemory 14336 itemPrice hourlyRecurringFee .36 recurringFee 252 item description 15 GB template maxMemory 15360 itemPrice hourlyRecurringFee .375 recurringFee 262.5 item description 16 GB template maxMemory 16384 itemPrice hourlyRecurringFee .76 recurringFee 525 item description 32 GB template maxMemory 32768 itemPrice hourlyRecurringFee 3.5 recurringFee 2500 item description 48 GB template maxMemory 49152 networkComponents itemPrice hourlyRecurringFee 0 recurringFee 0 item description 10 Mbps Public & Private Networks template networkComponents maxSpeed 10 itemPrice hourlyRecurringFee 0 recurringFee 0 item description 100 Mbps Private Network template networkComponents maxSpeed 100 itemPrice hourlyRecurringFee .04 recurringFee 20 item description 1 Gbps Public & Private Networks template networkComponents maxSpeed 1000 operatingSystems itemPrice hourlyRecurringFee 0 recurringFee 0 item description CentOS 6.0 - Minimal Install (64 bit) template operatingSystemReferenceCode CENTOS_6_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description CentOS 6.0 - Minimal Install (32 bit) template operatingSystemReferenceCode CENTOS_6_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description CentOS 5 - Minimal Install (64 bit) template operatingSystemReferenceCode CENTOS_5_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description CentOS 5 - Minimal Install (32 bit) template operatingSystemReferenceCode CENTOS_5_32 itemPrice recurringFee 12 item description CloudLinux 6 (64 bit) template operatingSystemReferenceCode CLOUDLINUX_6_64 itemPrice recurringFee 12 item description CloudLinux 6 (32 bit) template operatingSystemReferenceCode CLOUDLINUX_6_32 itemPrice recurringFee 12 item description CloudLinux 5 (64 bit) template operatingSystemReferenceCode CLOUDLINUX_5_64 itemPrice recurringFee 12 item description CloudLinux 5 (32 bit) template operatingSystemReferenceCode CLOUDLINUX_5_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Debian GNU/Linux 7.0 Wheezy/Stable - Minimal Install (64 bit) template operatingSystemReferenceCode DEBIAN_7_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Debian GNU/Linux 7.0 Wheezy/Stable - Minimal Install (32 bit) template operatingSystemReferenceCode DEBIAN_7_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Debian GNU/Linux 6.0 Squeeze/Stable - Minimal Install (64 bit) template operatingSystemReferenceCode DEBIAN_6_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Debian GNU/Linux 6.0 Squeeze/Stable - Minimal Install (32 bit) template operatingSystemReferenceCode DEBIAN_6_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (64 bit) template operatingSystemReferenceCode DEBIAN_5_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (32 bit) template operatingSystemReferenceCode DEBIAN_5_32 itemPrice hourlyRecurringFee .08 recurringFee 45 item description Red Hat Enterprise Linux 6 - Minimal Install (64 bit) (1 - 4 Core) template operatingSystemReferenceCode REDHAT_6_64 itemPrice hourlyRecurringFee .12 recurringFee 100 item description Red Hat Enterprise Linux 6 - Minimal Install (64 bit) (5 - 100 Core) id -3839 softwareDescriptionId upgradeItemId softwareDescription controlPanel 0 id 795 longDescription Redhat / EL / 6.0-64 Minimal for CCI manufacturer Redhat name EL operatingSystem 1 referenceCode REDHAT_6_64 upgradeSoftwareDescriptionId upgradeSwDescId version 6.0-64 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root template operatingSystemReferenceCode REDHAT_6_64 itemPrice hourlyRecurringFee .08 recurringFee 45 item description Red Hat Enterprise Linux 6 - Minimal Install (32 bit) (1 - 4 Core) template operatingSystemReferenceCode REDHAT_6_32 itemPrice hourlyRecurringFee .12 recurringFee 100 item description Red Hat Enterprise Linux 6 - Minimal Install (32 bit) (5 - 100 Core) id -3837 softwareDescriptionId upgradeItemId softwareDescription controlPanel 0 id 796 longDescription Redhat / EL / 6.0-32 Minimal for CCI manufacturer Redhat name EL operatingSystem 1 referenceCode REDHAT_6_32 upgradeSoftwareDescriptionId upgradeSwDescId version 6.0-32 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root template operatingSystemReferenceCode REDHAT_6_32 itemPrice hourlyRecurringFee .08 recurringFee 45 item description Red Hat Enterprise Linux 5 - Minimal Install (64 bit) (1 - 4 Core) template operatingSystemReferenceCode REDHAT_5_64 itemPrice hourlyRecurringFee .12 recurringFee 100 item description Red Hat Enterprise Linux 5 - Minimal Install (64 bit) (5 - 100 Core) id -880 softwareDescriptionId upgradeItemId softwareDescription controlPanel 0 id 664 longDescription Redhat / EL / 5.5-64 Minimal for CCI manufacturer Redhat name EL operatingSystem 1 referenceCode REDHAT_5_64 upgradeSoftwareDescriptionId upgradeSwDescId version 5.5-64 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root template operatingSystemReferenceCode REDHAT_5_64 itemPrice hourlyRecurringFee .08 recurringFee 45 item description Red Hat Enterprise Linux 5 - Minimal Install (32 bit) (1 - 4 Core) template operatingSystemReferenceCode REDHAT_5_32 itemPrice hourlyRecurringFee .12 recurringFee 100 item description Red Hat Enterprise Linux 5 - Minimal Install (32 bit) (5 - 100 Core) id -879 softwareDescriptionId upgradeItemId softwareDescription controlPanel 0 id 662 longDescription Redhat / EL / 5.5-32 Minimal for CCI manufacturer Redhat name EL operatingSystem 1 referenceCode REDHAT_5_32 upgradeSoftwareDescriptionId 927 upgradeSwDescId 927 version 5.5-32 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root template operatingSystemReferenceCode REDHAT_5_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Ubuntu Linux 12.04 LTS Precise Pangolin - Minimal Install (64 bit) template operatingSystemReferenceCode UBUNTU_12_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Ubuntu Linux 12.04 LTS Precise Pangolin - Minimal Install (32 bit) template operatingSystemReferenceCode UBUNTU_12_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (64 bit) template operatingSystemReferenceCode UBUNTU_10_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Ubuntu Linux 10.04 LTS Lucid Lynx - Minimal Install (32 bit) template operatingSystemReferenceCode UBUNTU_10_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit) template operatingSystemReferenceCode UBUNTU_8_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (32 bit) template operatingSystemReferenceCode UBUNTU_8_32 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Vyatta 6.6 Community Edition (64 bit) template operatingSystemReferenceCode VYATTACE_6.6_64 itemPrice hourlyRecurringFee 0 recurringFee 0 item description Vyatta 6.5 Community Edition (64 bit) template operatingSystemReferenceCode VYATTACE_6.5_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2012 Standard Edition (64 bit) template operatingSystemReferenceCode WIN_2012-STD_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2012 Datacenter Edition (64bit) template operatingSystemReferenceCode WIN_2012-DC_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2008 Standard Edition SP2 (64bit) template operatingSystemReferenceCode WIN_2008-STD-SP2_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2008 Standard Edition SP2 (32bit) template operatingSystemReferenceCode WIN_2008-STD-SP2_32 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2008 Standard SP1 with R2 (64 bit) template operatingSystemReferenceCode WIN_2008-STD-R2-SP1_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2008 R2 Standard Edition (64bit) template operatingSystemReferenceCode WIN_2008-STD-R2_64 itemPrice hourlyRecurringFee .1 recurringFee 50 item description Windows Server 2008 Enterprise Edition SP2 (64bit) template operatingSystemReferenceCode WIN_2008-ENT-SP2_64 itemPrice hourlyRecurringFee .1 recurringFee 50 item description Windows Server 2008 Enterprise Edition SP2 (32bit) template operatingSystemReferenceCode WIN_2008-ENT-SP2_32 itemPrice hourlyRecurringFee .1 recurringFee 50 item description Windows Server 2008 R2 Enterprise Edition (64bit) template operatingSystemReferenceCode WIN_2008-ENT-R2_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2008 Datacenter Edition SP2 (64bit) template operatingSystemReferenceCode WIN_2008-DC-SP2_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2008 R2 Datacenter Edition (64bit) template operatingSystemReferenceCode WIN_2008-DC-R2_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2003 Standard SP2 with R2 (64 bit) template operatingSystemReferenceCode WIN_2003-STD-SP2-5_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2003 Standard SP2 with R2 (32 bit) template operatingSystemReferenceCode WIN_2003-STD-SP2-5_32 itemPrice hourlyRecurringFee .05 recurringFee 50 item description Windows Server 2003 Enterprise SP2 with R2 (64 bit) template operatingSystemReferenceCode WIN_2003-ENT-SP2-5_64 itemPrice hourlyRecurringFee .05 recurringFee 50 item description Windows Server 2003 Enterprise SP2 with R2 (32 bit) template operatingSystemReferenceCode WIN_2003-ENT-SP2-5_32 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2003 Datacenter SP2 with R2 (64 bit) template operatingSystemReferenceCode WIN_2003-DC-SP2-1_64 itemPrice hourlyRecurringFee .05 recurringFee 20 item description Windows Server 2003 Datacenter SP2 with R2 (32 bit) template operatingSystemReferenceCode WIN_2003-DC-SP2-1_32 processors itemPrice hourlyRecurringFee .07 recurringFee 29 item description 1 x 2.0 GHz Core template startCpus 1 itemPrice hourlyRecurringFee .14 recurringFee 78 item description 2 x 2.0 GHz Cores template startCpus 2 itemPrice hourlyRecurringFee .205 recurringFee 123.5 item description 3 x 2.0 GHz Cores template startCpus 3 itemPrice hourlyRecurringFee .265 recurringFee 165.5 item description 4 x 2.0 GHz Cores template startCpus 4 itemPrice hourlyRecurringFee .325 recurringFee 207.5 item description 5 x 2.0 GHz Cores template startCpus 5 itemPrice hourlyRecurringFee .39 recurringFee 253 item description 6 x 2.0 GHz Cores template startCpus 6 itemPrice hourlyRecurringFee .445 recurringFee 291.5 item description 7 x 2.0 GHz Cores template startCpus 7 itemPrice hourlyRecurringFee .495 recurringFee 326.5 item description 8 x 2.0 GHz Cores template startCpus 8 itemPrice hourlyRecurringFee .54 recurringFee 358 item description 9 x 2.0 GHz Cores template startCpus 9 itemPrice hourlyRecurringFee .59 recurringFee 393 item description 10 x 2.0 GHz Cores template startCpus 10 itemPrice hourlyRecurringFee .635 recurringFee 424.5 item description 11 x 2.0 GHz Cores template startCpus 11 itemPrice hourlyRecurringFee .66 recurringFee 442 item description 12 x 2.0 GHz Cores template startCpus 12 itemPrice hourlyRecurringFee .695 recurringFee 466.5 item description 13 x 2.0 GHz Cores template startCpus 13 itemPrice hourlyRecurringFee .72 recurringFee 484 item description 14 x 2.0 GHz Cores template startCpus 14 itemPrice hourlyRecurringFee .74 recurringFee 498 item description 15 x 2.0 GHz Cores template startCpus 15 itemPrice hourlyRecurringFee .75 recurringFee 505 item description 16 x 2.0 GHz Cores template startCpus 16 itemPrice hourlyRecurringFee .22 recurringFee 159 item description Private 1 x 2.0 GHz Core template dedicatedAccountHostOnlyFlag 1 startCpus 1 itemPrice hourlyRecurringFee .3 recurringFee 199 item description Private 2 x 2.0 GHz Cores template dedicatedAccountHostOnlyFlag 1 startCpus 2 itemPrice hourlyRecurringFee .44 recurringFee 299 item description Private 4 x 2.0 GHz Cores template dedicatedAccountHostOnlyFlag 1 startCpus 4 itemPrice hourlyRecurringFee .58 recurringFee 399 item description Private 8 x 2.0 GHz Cores template dedicatedAccountHostOnlyFlag 1 startCpus 8 ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject0000664000175000017500000002560113535474530034016 0ustar kamikami00000000000000 accountId 282402 createDate 2013-11-12T19:33:57+01:00 dedicatedAccountHostOnlyFlag 0 domain example.com fullyQualifiedDomainName libcloud-testing.example.com hostname libcloud-testing id 2905761 lastPowerStateId lastVerifiedDate maxCpu 1 maxCpuUnits CORE maxMemory 2048 metricPollDate modifyDate 2013-11-12T19:36:55+01:00 startCpus 1 statusId 1001 uuid cbc33604-afd0-4820-57c3-6c68ae7c5fe0 billingItem allowCancellationFlag 1 cancellationDate categoryCode guest_core createDate 2013-11-12T19:33:59+01:00 currentHourlyCharge .056 cycleStartDate 2013-11-12T19:39:03+01:00 description 1 x 2.0 GHz Core domainName example.com hostName libcloud-testing hourlyRecurringFee .056 hoursUsed 1 id 16538495 laborFee 0 laborFeeTaxRate .21 lastBillDate 2013-11-12T19:39:03+01:00 modifyDate 2013-11-12T19:39:03+01:00 nextBillDate 2013-11-28T07:00:00+01:00 oneTimeFee 0 oneTimeFeeTaxRate .21 orderItemId 22774406 parentId recurringFee .056 recurringFeeTaxRate .21 recurringMonths 1 serviceProviderId 1 setupFee 0 setupFeeTaxRate .21 resourceTableId 2905761 globalIdentifier 633fd9e3-4cf7-4c78-b746-c2b76e2c8b88 managedResourceFlag 0 operatingSystem hardwareId id 2211183 manufacturerLicenseInstance passwords createDate 2013-11-12T19:34:16+01:00 id 1867597 modifyDate 2013-11-12T19:34:16+01:00 password LTSp4cpJ port softwareId 2211183 username root softwareLicense id 1523 softwareDescriptionId 1163 softwareDescription controlPanel 0 id 1163 longDescription Debian / Debian / 7.0.0-64 Minimal for CCI manufacturer Debian name Debian operatingSystem 1 referenceCode DEBIAN_7_64 upgradeSoftwareDescriptionId upgradeSwDescId version 7.0.0-64 Minimal for CCI virtualLicense 0 virtualizationPlatform 0 requiredUser root powerState keyName RUNNING name Running primaryBackendIpAddress 10.55.62.124 primaryIpAddress 50.97.215.202 provisionDate 2013-11-12T19:39:03+01:00 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/0000775000175000017500000000000013600223624024516 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_catalogItem_5.xml0000664000175000017500000000154313535474530031420 0ustar kamikami00000000000000 0 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_login.xml0000664000175000017500000000046213535474530030052 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_org_240.xml0000664000175000017500000000140513535474530030114 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_task_10496.xml0000664000175000017500000000123013535474530030441 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_task_11001.xml0000664000175000017500000000122713535474530030426 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031.xml0000664000175000017500000003604213535474530030443 0ustar kamikami00000000000000 10.112.78.69 The kind of installed guest operating system Red Hat Enterprise Linux 5 (32-bit) Virtual Hardware Virtual Hardware Family 0 testerpart2 vmx-07
hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 1 3 2 count
byte * 2^20 Memory Size 512MB of memory 2 4 512 byte * 2^20
0
SCSI Controller SCSI Controller 0 3 lsilogic 6
0 Hard Disk 1 10485760 9 3 17 10485760 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_action_deploy.xml0000664000175000017500000000116413535474530033351 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_get.xml0000664000175000017500000003604213535474530031302 0ustar kamikami00000000000000 10.112.78.69 The kind of installed guest operating system Red Hat Enterprise Linux 5 (32-bit) Virtual Hardware Virtual Hardware Family 0 testerpart2 vmx-07
hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 1 3 2 count
byte * 2^20 Memory Size 512MB of memory 2 4 512 byte * 2^20
0
SCSI Controller SCSI Controller 0 3 lsilogic 6
0 Hard Disk 1 10485760 9 3 17 10485760 ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_powerOn.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_powe0000664000175000017500000000116413535474530033444 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_poweroff.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_powe0000664000175000017500000000116313535474530033443 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_reset.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vapp_14031_power_action_rese0000664000175000017500000000116413535474530033430 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224.xml0000664000175000017500000000224513535474530030106 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_action_instantiateVAppTemplate.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_action_instantiateVA0000664000175000017500000000067713535474530033505 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/terremark/api_v0_8_vdc_224_catalog.xml0000664000175000017500000000101413535474530031571 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/0000775000175000017500000000000013600223624024175 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_plan.json0000664000175000017500000000174513535474530027336 0ustar kamikami00000000000000{ "plans" : { "plan" : [ { "core_number" : 1, "memory_amount" : 1024, "name" : "1xCPU-1GB", "public_traffic_out" : 2048, "storage_size" : 30, "storage_tier" : "maxiops" }, { "core_number" : 2, "memory_amount" : 2048, "name" : "2xCPU-2GB", "public_traffic_out" : 3072, "storage_size" : 50, "storage_tier" : "maxiops" }, { "core_number" : 4, "memory_amount" : 4096, "name" : "4xCPU-4GB", "public_traffic_out" : 4096, "storage_size" : 100, "storage_tier" : "maxiops" }, { "core_number" : 6, "memory_amount" : 8192, "name" : "6xCPU-8GB", "public_traffic_out" : 8192, "storage_size" : 200, "storage_tier" : "maxiops" } ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_price.json0000664000175000017500000004460513535474530027510 0ustar kamikami00000000000000{ "prices" : { "zone" : [ { "firewall" : { "amount" : 1, "price" : 0.56 }, "io_request_backup" : { "amount" : 1000000, "price" : 0 }, "io_request_maxiops" : { "amount" : 1000000, "price" : 0 }, "ipv4_address" : { "amount" : 1, "price" : 0.336 }, "ipv6_address" : { "amount" : 1, "price" : 0 }, "name" : "de-fra1", "public_ipv4_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv4_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "public_ipv6_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv6_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "server_core" : { "amount" : 1, "price" : 1.12 }, "server_memory" : { "amount" : 256, "price" : 0.14 }, "server_plan_12xCPU-32GB" : { "amount" : 1, "price" : 47.619 }, "server_plan_16xCPU-48GB" : { "amount" : 1, "price" : 71.4286 }, "server_plan_1xCPU-1GB" : { "amount" : 1, "price" : 1.488 }, "server_plan_20xCPU-64GB" : { "amount" : 1, "price" : 95.2381 }, "server_plan_2xCPU-2GB" : { "amount" : 1, "price" : 2.976 }, "server_plan_4xCPU-4GB" : { "amount" : 1, "price" : 5.952 }, "server_plan_6xCPU-8GB" : { "amount" : 1, "price" : 11.905 }, "server_plan_8xCPU-16GB" : { "amount" : 1, "price" : 23.8095 }, "storage_backup" : { "amount" : 1, "price" : 0.0078 }, "storage_maxiops" : { "amount" : 1, "price" : 0.031 }, "storage_template" : { "amount" : 1, "price" : 0.031 } }, { "firewall" : { "amount" : 1, "price" : 0.56 }, "io_request_backup" : { "amount" : 1000000, "price" : 0 }, "io_request_hdd" : { "amount" : 1000000, "price" : 0 }, "io_request_maxiops" : { "amount" : 1000000, "price" : 0 }, "ipv4_address" : { "amount" : 1, "price" : 0.336 }, "ipv6_address" : { "amount" : 1, "price" : 0 }, "name" : "fi-dev2", "public_ipv4_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv4_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "public_ipv6_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv6_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "server_core" : { "amount" : 1, "price" : 1.24 }, "server_memory" : { "amount" : 256, "price" : 0.34 }, "server_plan_12xCPU-32GB" : { "amount" : 1, "price" : 71.4286 }, "server_plan_16xCPU-48GB" : { "amount" : 1, "price" : 107.1429 }, "server_plan_1xCPU-1GB" : { "amount" : 1, "price" : 2.232 }, "server_plan_20xCPU-64GB" : { "amount" : 1, "price" : 142.8571 }, "server_plan_2xCPU-2GB" : { "amount" : 1, "price" : 4.464 }, "server_plan_4xCPU-4GB" : { "amount" : 1, "price" : 8.928 }, "server_plan_6xCPU-8GB" : { "amount" : 1, "price" : 17.857 }, "server_plan_8xCPU-16GB" : { "amount" : 1, "price" : 35.7143 }, "storage_backup" : { "amount" : 1, "price" : 0.0078 }, "storage_hdd" : { "amount" : 1, "price" : 0.0145 }, "storage_maxiops" : { "amount" : 1, "price" : 0.031 }, "storage_template" : { "amount" : 1, "price" : 0.031 } }, { "firewall" : { "amount" : 1, "price" : 0.56 }, "io_request_backup" : { "amount" : 1000000, "price" : 0 }, "io_request_hdd" : { "amount" : 1000000, "price" : 0 }, "io_request_maxiops" : { "amount" : 1000000, "price" : 0 }, "io_request_ssd" : { "amount" : 1000000, "price" : 0 }, "ipv4_address" : { "amount" : 1, "price" : 0.336 }, "ipv6_address" : { "amount" : 1, "price" : 0 }, "name" : "fi-hel1", "public_ipv4_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv4_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "public_ipv6_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv6_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "server_core" : { "amount" : 1, "price" : 1.24 }, "server_memory" : { "amount" : 256, "price" : 0.34 }, "server_plan_12xCPU-32GB" : { "amount" : 1, "price" : 71.4286 }, "server_plan_16xCPU-48GB" : { "amount" : 1, "price" : 107.1429 }, "server_plan_1xCPU-1GB" : { "amount" : 1, "price" : 2.232 }, "server_plan_20xCPU-64GB" : { "amount" : 1, "price" : 142.8571 }, "server_plan_2xCPU-2GB" : { "amount" : 1, "price" : 4.464 }, "server_plan_4xCPU-4GB" : { "amount" : 1, "price" : 8.928 }, "server_plan_6xCPU-8GB" : { "amount" : 1, "price" : 17.857 }, "server_plan_8xCPU-16GB" : { "amount" : 1, "price" : 35.7143 }, "storage_backup" : { "amount" : 1, "price" : 0.0078 }, "storage_hdd" : { "amount" : 1, "price" : 0.0145 }, "storage_maxiops" : { "amount" : 1, "price" : 0.031 }, "storage_ssd" : { "amount" : 1, "price" : 0.056 }, "storage_template" : { "amount" : 1, "price" : 0.031 } }, { "firewall" : { "amount" : 1, "price" : 0.56 }, "io_request_backup" : { "amount" : 1000000, "price" : 0 }, "io_request_maxiops" : { "amount" : 1000000, "price" : 0 }, "ipv4_address" : { "amount" : 1, "price" : 0.336 }, "ipv6_address" : { "amount" : 1, "price" : 0 }, "name" : "nl-ams1", "public_ipv4_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv4_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "public_ipv6_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv6_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "server_core" : { "amount" : 1, "price" : 1.12 }, "server_memory" : { "amount" : 256, "price" : 0.14 }, "server_plan_12xCPU-32GB" : { "amount" : 1, "price" : 47.619 }, "server_plan_16xCPU-48GB" : { "amount" : 1, "price" : 71.4286 }, "server_plan_1xCPU-1GB" : { "amount" : 1, "price" : 1.488 }, "server_plan_20xCPU-64GB" : { "amount" : 1, "price" : 95.2381 }, "server_plan_2xCPU-2GB" : { "amount" : 1, "price" : 2.976 }, "server_plan_4xCPU-4GB" : { "amount" : 1, "price" : 5.952 }, "server_plan_6xCPU-8GB" : { "amount" : 1, "price" : 11.905 }, "server_plan_8xCPU-16GB" : { "amount" : 1, "price" : 23.8095 }, "storage_backup" : { "amount" : 1, "price" : 0.0078 }, "storage_maxiops" : { "amount" : 1, "price" : 0.031 }, "storage_template" : { "amount" : 1, "price" : 0.031 } }, { "firewall" : { "amount" : 1, "price" : 0.56 }, "io_request_backup" : { "amount" : 1000000, "price" : 0 }, "io_request_maxiops" : { "amount" : 1000000, "price" : 0 }, "ipv4_address" : { "amount" : 1, "price" : 0.336 }, "ipv6_address" : { "amount" : 1, "price" : 0 }, "name" : "sg-sin1", "public_ipv4_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv4_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "public_ipv6_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv6_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "server_core" : { "amount" : 1, "price" : 1.12 }, "server_memory" : { "amount" : 256, "price" : 0.14 }, "server_plan_12xCPU-32GB" : { "amount" : 1, "price" : 47.619 }, "server_plan_16xCPU-48GB" : { "amount" : 1, "price" : 71.4286 }, "server_plan_1xCPU-1GB" : { "amount" : 1, "price" : 1.488 }, "server_plan_20xCPU-64GB" : { "amount" : 1, "price" : 95.2381 }, "server_plan_2xCPU-2GB" : { "amount" : 1, "price" : 2.976 }, "server_plan_4xCPU-4GB" : { "amount" : 1, "price" : 5.952 }, "server_plan_6xCPU-8GB" : { "amount" : 1, "price" : 11.905 }, "server_plan_8xCPU-16GB" : { "amount" : 1, "price" : 23.8095 }, "storage_backup" : { "amount" : 1, "price" : 0.0078 }, "storage_maxiops" : { "amount" : 1, "price" : 0.031 }, "storage_template" : { "amount" : 1, "price" : 0.031 } }, { "firewall" : { "amount" : 1, "price" : 0.56 }, "io_request_backup" : { "amount" : 1000000, "price" : 0 }, "io_request_hdd" : { "amount" : 1000000, "price" : 0 }, "io_request_maxiops" : { "amount" : 1000000, "price" : 0 }, "io_request_ssd" : { "amount" : 1000000, "price" : 0 }, "ipv4_address" : { "amount" : 1, "price" : 0.336 }, "ipv6_address" : { "amount" : 1, "price" : 0 }, "name" : "uk-lon1", "public_ipv4_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv4_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "public_ipv6_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv6_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "server_core" : { "amount" : 1, "price" : 1.12 }, "server_memory" : { "amount" : 256, "price" : 0.14 }, "server_plan_12xCPU-32GB" : { "amount" : 1, "price" : 47.619 }, "server_plan_16xCPU-48GB" : { "amount" : 1, "price" : 71.4286 }, "server_plan_1xCPU-1GB" : { "amount" : 1, "price" : 1.488 }, "server_plan_20xCPU-64GB" : { "amount" : 1, "price" : 95.2381 }, "server_plan_2xCPU-2GB" : { "amount" : 1, "price" : 2.976 }, "server_plan_4xCPU-4GB" : { "amount" : 1, "price" : 5.952 }, "server_plan_6xCPU-8GB" : { "amount" : 1, "price" : 11.905 }, "server_plan_8xCPU-16GB" : { "amount" : 1, "price" : 23.8095 }, "storage_backup" : { "amount" : 1, "price" : 0.0078 }, "storage_hdd" : { "amount" : 1, "price" : 0.0078 }, "storage_maxiops" : { "amount" : 1, "price" : 0.031 }, "storage_ssd" : { "amount" : 1, "price" : 0.031 }, "storage_template" : { "amount" : 1, "price" : 0.031 } }, { "firewall" : { "amount" : 1, "price" : 0.56 }, "io_request_backup" : { "amount" : 1000000, "price" : 0 }, "io_request_maxiops" : { "amount" : 1000000, "price" : 0 }, "ipv4_address" : { "amount" : 1, "price" : 0.336 }, "ipv6_address" : { "amount" : 1, "price" : 0 }, "name" : "us-chi1", "public_ipv4_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv4_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "public_ipv6_bandwidth_in" : { "amount" : 1, "price" : 0 }, "public_ipv6_bandwidth_out" : { "amount" : 1, "price" : 5.6 }, "server_core" : { "amount" : 1, "price" : 1.12 }, "server_memory" : { "amount" : 256, "price" : 0.14 }, "server_plan_12xCPU-32GB" : { "amount" : 1, "price" : 47.619 }, "server_plan_16xCPU-48GB" : { "amount" : 1, "price" : 71.4286 }, "server_plan_1xCPU-1GB" : { "amount" : 1, "price" : 1.488 }, "server_plan_20xCPU-64GB" : { "amount" : 1, "price" : 95.2381 }, "server_plan_2xCPU-2GB" : { "amount" : 1, "price" : 2.976 }, "server_plan_4xCPU-4GB" : { "amount" : 1, "price" : 5.952 }, "server_plan_6xCPU-8GB" : { "amount" : 1, "price" : 11.905 }, "server_plan_8xCPU-16GB" : { "amount" : 1, "price" : 23.8095 }, "storage_backup" : { "amount" : 1, "price" : 0.0078 }, "storage_maxiops" : { "amount" : 1, "price" : 0.031 }, "storage_template" : { "amount" : 1, "price" : 0.031 } } ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server.json0000664000175000017500000000104713535474530027705 0ustar kamikami00000000000000{ "servers" : { "server" : [ { "core_number" : "1", "hostname" : "localhost", "license" : 0, "memory_amount" : "1024", "plan" : "1xCPU-1GB", "plan_ipv4_bytes" : "12267", "plan_ipv6_bytes" : "4644", "state" : "started", "tags" : { "tag" : [] }, "title" : "test_server", "uuid" : "00f8c525-7e62-4108-8115-3958df5b43dc", "zone" : "fi-hel1" } ] } }././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00893c98-5d5a-4363-b177-0000664000175000017500000000303413535474530031706 0ustar kamikami00000000000000{ "server" : { "boot_order" : "cdrom,disk", "core_number" : "1", "firewall" : "off", "host" : 4297867907, "hostname" : "localhost", "ip_addresses" : { "ip_address" : [ { "access" : "private", "address" : "10.2.1.244", "family" : "IPv4" }, { "access" : "public", "address" : "2a04:3541:1000:500:7cae:1dff:fead:5bde", "family" : "IPv6" }, { "access" : "public", "address" : "83.136.254.34", "family" : "IPv4", "part_of_plan" : "yes" } ] }, "license" : 0, "memory_amount" : "1024", "nic_model" : "virtio", "plan" : "1xCPU-1GB", "plan_ipv4_bytes" : "0", "plan_ipv6_bytes" : "0", "state" : "stopped", "storage_devices" : { "storage_device" : [ { "address" : "virtio:0", "part_of_plan" : "yes", "storage" : "01839922-a675-4214-b10e-a4cf7953992f", "storage_size" : 30, "storage_title" : "localhost-disk0", "type" : "disk" } ] }, "tags" : { "tag" : [] }, "timezone" : "UTC", "title" : "test", "uuid" : "00893c98-5d5a-4363-b177-88df518a2b60", "video_model" : "cirrus", "vnc" : "off", "vnc_password" : "Hf7qpJs8", "zone" : "uk-lon1" } } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-0000664000175000017500000000302113535474530031607 0ustar kamikami00000000000000{ "server" : { "boot_order" : "disk", "core_number" : "1", "firewall" : "off", "host" : 4964762243, "hostname" : "localhost", "ip_addresses" : { "ip_address" : [ { "access" : "private", "address" : "10.1.7.68", "family" : "IPv4" }, { "access" : "public", "address" : "2a04:3540:1000:310:7cae:1dff:fead:19dc", "family" : "IPv6" }, { "access" : "public", "address" : "94.237.37.249", "family" : "IPv4", "part_of_plan" : "yes" } ] }, "license" : 0, "memory_amount" : "1024", "nic_model" : "virtio", "plan" : "1xCPU-1GB", "plan_ipv4_bytes" : "8242", "plan_ipv6_bytes" : "3440", "state" : "started", "storage_devices" : { "storage_device" : [ { "address" : "virtio:0", "storage" : "01e5411f-37c9-4b8e-b0bb-4cad5119b3ea", "storage_size" : 10, "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)", "type" : "disk" } ] }, "tags" : { "tag" : [] }, "timezone" : "UTC", "title" : "test_server", "uuid" : "00f8c525-7e62-4108-8115-3958df5b43dc", "video_model" : "cirrus", "vnc" : "off", "vnc_password" : "r362XMmV", "zone" : "fi-hel1" } }././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_00f8c525-7e62-4108-8115-0000664000175000017500000000302313535474530031611 0ustar kamikami00000000000000{ "server" : { "boot_order" : "disk", "core_number" : "1", "firewall" : "off", "host" : 4964762243, "hostname" : "localhost", "ip_addresses" : { "ip_address" : [ { "access" : "private", "address" : "10.1.7.68", "family" : "IPv4" }, { "access" : "public", "address" : "2a04:3540:1000:310:7cae:1dff:fead:19dc", "family" : "IPv6" }, { "access" : "public", "address" : "94.237.37.249", "family" : "IPv4", "part_of_plan" : "yes" } ] }, "license" : 0, "memory_amount" : "1024", "nic_model" : "virtio", "plan" : "1xCPU-1GB", "plan_ipv4_bytes" : "218066", "plan_ipv6_bytes" : "6450", "state" : "started", "storage_devices" : { "storage_device" : [ { "address" : "virtio:0", "storage" : "01e5411f-37c9-4b8e-b0bb-4cad5119b3ea", "storage_size" : 10, "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)", "type" : "disk" } ] }, "tags" : { "tag" : [] }, "timezone" : "UTC", "title" : "test_server", "uuid" : "00f8c525-7e62-4108-8115-3958df5b43dc", "video_model" : "cirrus", "vnc" : "off", "vnc_password" : "r362XMmV", "zone" : "fi-hel1" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_cdrom.json0000664000175000017500000000350013535474530032110 0ustar kamikami00000000000000{ "server" : { "boot_order" : "disk", "core_number" : "1", "firewall" : "off", "hostname" : "localhost", "ip_addresses" : { "ip_address" : [ { "access" : "private", "address" : "10.1.2.26", "family" : "IPv4" }, { "access" : "public", "address" : "2a04:3540:1000:310:7cae:1dff:fead:5683", "family" : "IPv6" }, { "access" : "public", "address" : "94.237.37.215", "family" : "IPv4", "part_of_plan" : "yes" } ] }, "license" : 0, "memory_amount" : "1024", "nic_model" : "virtio", "plan" : "1xCPU-1GB", "plan_ipv4_bytes" : "0", "plan_ipv6_bytes" : "0", "progress" : "0", "state" : "maintenance", "storage_devices" : { "storage_device" : [ { "address" : "virtio:0", "part_of_plan" : "yes", "storage" : "01898fe2-9909-471e-b33c-59d7896b48f5", "storage_size" : 30, "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus), 64-bit", "type" : "disk" }, { "address" : "ide:0:0", "storage" : "01000000-0000-4000-8000-000030040101", "storage_size" : 1, "storage_title" : "Ubuntu Server 14.04 LTS", "type" : "cdrom" } ] }, "tags" : { "tag" : [] }, "timezone" : "UTC", "title" : "test_server", "uuid" : "00c68ee6-e6e1-4d5f-a213-4a1e063a3cbd", "video_model" : "cirrus", "vnc" : "off", "vnc_password" : "5C4TVPf8", "zone" : "fi-hel1" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_server_from_template.json0000664000175000017500000000311313535474530032617 0ustar kamikami00000000000000{ "server" : { "boot_order" : "disk", "core_number" : "1", "firewall" : "off", "hostname" : "localhost", "ip_addresses" : { "ip_address" : [ { "access" : "private", "address" : "10.1.3.163", "family" : "IPv4" }, { "access" : "public", "address" : "2a04:3540:1000:310:7cae:1dff:fead:3332", "family" : "IPv6" }, { "access" : "public", "address" : "94.237.37.216", "family" : "IPv4", "part_of_plan" : "yes" } ] }, "license" : 0, "memory_amount" : "1024", "nic_model" : "virtio", "password" : "777gznbm", "plan" : "1xCPU-1GB", "plan_ipv4_bytes" : "0", "plan_ipv6_bytes" : "0", "progress" : "0", "state" : "maintenance", "storage_devices" : { "storage_device" : [ { "address" : "virtio:0", "storage" : "018e2c82-1c16-46b9-8b7d-aeaf8d8309a9", "storage_size" : 10, "storage_title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)", "type" : "disk" } ] }, "tags" : { "tag" : [] }, "timezone" : "UTC", "title" : "test_server", "username" : "mlackman", "uuid" : "00814aac-240f-4f08-9139-9697c9ffc0b7", "video_model" : "cirrus", "vnc" : "off", "vnc_password" : "G4FvMjvg", "zone" : "fi-hel1" } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_cdrom.json0000664000175000017500000003076513535474530031240 0ustar kamikami00000000000000{ "storages" : { "storage" : [ { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Standard (CD 1)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Standard (CD 2)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010010102" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Standard (CD 1)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010010201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Standard (CD 2)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010010202" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Enterprise (CD 1)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010020101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Enterprise (CD 2)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010020102" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Enterprise (CD 1)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010020201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Enterprise (CD 2)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010020202" }, { "access" : "public", "license" : 0, "size" : 3, "state" : "online", "title" : "Windows Server 2008 R2 Datacenter", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010030101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Datacenter", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010040101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Windows Server 2003 R2 Datacenter", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010040201" }, { "access" : "public", "license" : 0, "size" : 4, "state" : "online", "title" : "Windows Server 2012", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000010050101" }, { "access" : "public", "license" : 0, "size" : 5, "state" : "online", "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (DVD)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (netinst)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020010201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (netinst)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020010301" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (live)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020010401" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "Debian GNU/Linux 6.0.1 (Squeeze) (live)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020010501" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Debian GNU/Linux 7.8 (Wheezy)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020020201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Debian GNU/Linux 8.6.0 (Jessie)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020030101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Debian GNU/Linux 9.0.0 (Stretch) Installation CD", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000020040101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Ubuntu Server 10.04", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000030010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Ubuntu Server 10.04", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000030010201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Ubuntu Server 11.04", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000030020101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Ubuntu Server 11.04", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000030020201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Ubuntu Server 12.04", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000030030101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Ubuntu Server 14.04 LTS", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000030040101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Ubuntu Server 16.04 LTS (Xenial Xerus), 64-bit", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000030060101" }, { "access" : "public", "license" : 0, "size" : 4, "state" : "online", "title" : "Fedora 16 (DVD)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000040010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Fedora 16 (live)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000040010201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Fedora 19", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000040020101" }, { "access" : "public", "license" : 0, "size" : 4, "state" : "online", "title" : "CentOS 6.0 (DVD 1)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000050010101" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "CentOS 6.0 (DVD 2)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000050010102" }, { "access" : "public", "license" : 0, "size" : 4, "state" : "online", "title" : "CentOS 6.8 (DVD 1)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000050010103" }, { "access" : "public", "license" : 0, "size" : 3, "state" : "online", "title" : "CentOS 6.8 (DVD 2)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000050010104" }, { "access" : "public", "license" : 0, "size" : 4, "state" : "online", "title" : "CentOS 6.8 (DVD 1)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000050010105" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "CentOS 6.8 (DVD 2)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000050010106" }, { "access" : "public", "license" : 0, "size" : 5, "state" : "online", "title" : "CentOS 7.3-1611 DVD", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000050010301" }, { "access" : "public", "license" : 0, "size" : 4, "state" : "online", "title" : "Knoppix 6.4.4", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000060010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Arch Linux 2010.05", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000070010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "CoreOS 607.0.0", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000080010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "CoreOS 845.0.0", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000080010201" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "CoreOS Alpha (1032.1.0)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000080010501" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "CoreOS Stable (1068.8.0)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000080020101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "Gentoo Linux Minimal Installation CD (64bit)", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000090010101" }, { "access" : "public", "license" : 0, "size" : 1, "state" : "online", "title" : "FreeBSD 11.0-RELEASE amd64 Installation CD", "type" : "cdrom", "uuid" : "01000000-0000-4000-8000-000100010101" } ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_storage_template.json0000664000175000017500000000666213535474530031746 0ustar kamikami00000000000000{ "storages" : { "storage" : [ { "access" : "public", "license" : 3.36, "size" : 20, "state" : "online", "title" : "Windows Server 2012 R2 Datacenter", "type" : "template", "uuid" : "01000000-0000-4000-8000-000010050200" }, { "access" : "public", "license" : 0.694, "size" : 20, "state" : "online", "title" : "Windows Server 2012 R2 Standard", "type" : "template", "uuid" : "01000000-0000-4000-8000-000010050300" }, { "access" : "public", "license" : 3.36, "size" : 20, "state" : "online", "title" : "Windows Server 2016 Datacenter", "type" : "template", "uuid" : "01000000-0000-4000-8000-000010060200" }, { "access" : "public", "license" : 0.694, "size" : 20, "state" : "online", "title" : "Windows Server 2016 Standard", "type" : "template", "uuid" : "01000000-0000-4000-8000-000010060300" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "Debian GNU/Linux 7.8 (Wheezy)", "type" : "template", "uuid" : "01000000-0000-4000-8000-000020020100" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "Debian GNU/Linux 8.7 (Jessie)", "type" : "template", "uuid" : "01000000-0000-4000-8000-000020030100" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "Ubuntu Server 12.04 LTS (Precise Pangolin)", "type" : "template", "uuid" : "01000000-0000-4000-8000-000030030200" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "Ubuntu Server 14.04 LTS (Trusty Tahr)", "type" : "template", "uuid" : "01000000-0000-4000-8000-000030040200" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "Ubuntu Server 16.04 LTS (Xenial Xerus)", "type" : "template", "uuid" : "01000000-0000-4000-8000-000030060200" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "CentOS 6.9", "type" : "template", "uuid" : "01000000-0000-4000-8000-000050010200" }, { "access" : "public", "license" : 0, "size" : 2, "state" : "online", "title" : "CentOS 7.0", "type" : "template", "uuid" : "01000000-0000-4000-8000-000050010300" }, { "access" : "public", "license" : 0, "size" : 5, "state" : "online", "title" : "CoreOS Stable 1068.8.0", "type" : "template", "uuid" : "01000000-0000-4000-8000-000080010200" } ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_zone.json0000664000175000017500000000115113535474530027346 0ustar kamikami00000000000000{ "zones" : { "zone" : [ { "description" : "Frankfurt #1", "id" : "de-fra1" }, { "description" : "Helsinki #1", "id" : "fi-hel1" }, { "description" : "Amsterdam #1", "id" : "nl-ams1" }, { "description" : "Singapore #1", "id" : "sg-sin1" }, { "description" : "London #1", "id" : "uk-lon1" }, { "description" : "Chicago #1", "id" : "us-chi1" } ] } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/upcloud/api_1_2_zone_failed_auth.json0000664000175000017500000000023413535474530031674 0ustar kamikami00000000000000{ "error" : { "error_code" : "AUTHENTICATION_FAILED", "error_message" : "Authentication failed using the given username and password." } }apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/0000775000175000017500000000000013600223624023306 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/XMLRPCaddRequest.xml0000664000175000017500000000057513535474530027101 0ustar kamikami00000000000000 requestid 51 status success apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/XMLRPCendRequest.xml0000664000175000017500000000042113535474530027105 0ustar kamikami00000000000000 status success apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/XMLRPCextendRequest.xml0000664000175000017500000000042113535474530027626 0ustar kamikami00000000000000 status success apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/XMLRPCgetImages.xml0000664000175000017500000000213213535474530026674 0ustar kamikami00000000000000 id 8 name CentOS 5 (EC2) id 5 name CentOS 5.4 Base (32 bit VM) id 6 name WinXP Base (32 bit VM) apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestConnectData.xml0000664000175000017500000000113513535474530031225 0ustar kamikami00000000000000 status ready serverIP 152.46.20.67 user admin password ehkNGW apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestIds.xml0000664000175000017500000000230213535474530027556 0ustar kamikami00000000000000 status success requests requestid 51 imageid 5 imagename CentOS 5.4 Base (32 bit VM) start 1334150100 end 1334168100 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/XMLRPCgetRequestStatus.xml0000664000175000017500000000041713535474530030327 0ustar kamikami00000000000000 status ready apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Account_getVirtualGuests.xml0000664000175000017500000006144313535474530033450 0ustar kamikami00000000000000 privateNetworkOnlyFlag 0 id 1832 accountId 11111 statusId 1001 uuid eaa9aaa2-8e2e-d6e0-ce11-6f01e765779c hostname test1 domain libcloud.org maxCpu 2 maxCpuUnits CORE maxMemory 2048 startCpus 2 createDate 2009-09-04T14:49:45-05:00 modifyDate 2010-04-22T13:08:47-05:00 metricPollDate 2010-04-22T13:08:00-05:00 dedicatedAccountHostOnlyFlag 0 powerState name Running keyName RUNNING softwareComponents id 191115 hardwareId manufacturerLicenseInstance passwords id 166980 softwareId 191115 username root password TEST createDate 2009-09-04T14:49:51-05:00 modifyDate 2009-09-04T14:49:51-05:00 port primaryIpAddress 67.254.254.254 primaryBackendIpAddress 10.254.254.254 privateNetworkOnlyFlag 0 id 13402 accountId 11111 statusId 1001 uuid 9e9e9e99-4ed9-4645-19f3-55ee4e404d56 hostname test2 domain libcloud.org maxCpu 1 maxCpuUnits CORE maxMemory 1024 startCpus 1 createDate 2010-03-23T17:06:13-05:00 modifyDate 2010-04-22T13:08:43-05:00 metricPollDate 2010-04-22T13:08:00-05:00 dedicatedAccountHostOnlyFlag 0 powerState name Running keyName RUNNING softwareComponents id 257314 hardwareId manufacturerLicenseInstance passwords id 235268 softwareId 257314 username root password TEST createDate 2010-03-23T17:06:17-05:00 modifyDate 2010-03-23T17:06:17-05:00 port primaryIpAddress 174.254.254.254 primaryBackendIpAddress 10.254.254.254 privateNetworkOnlyFlag 0 id 19293 accountId 11111 statusId 1001 uuid 9f99e19b-2c61-9cd5-2081-67b57fd7977b hostname test3 domain libcloud.org maxCpu 2 maxCpuUnits CORE maxMemory 1024 startCpus 2 createDate 2010-04-22T12:38:53-05:00 modifyDate 2010-04-22T13:08:01-05:00 metricPollDate 2010-04-22T13:08:00-05:00 dedicatedAccountHostOnlyFlag 1 powerState name Running keyName RUNNING softwareComponents id 277185 hardwareId manufacturerLicenseInstance passwords id 250826 softwareId 277185 username root password TEST createDate 2010-04-22T12:38:57-05:00 modifyDate 2010-04-22T12:38:57-05:00 port primaryIpAddress 174.254.254.254 primaryBackendIpAddress 10.254.254.254 privateNetworkOnlyFlag 0 id 19288 accountId 11111 statusId 1001 uuid 999f77d9-679b-c47d-136d-04cd302384ec hostname test4 domain libcloud.org maxCpu 2 maxCpuUnits CORE maxMemory 1024 startCpus 2 createDate 2010-04-22T12:15:24-05:00 modifyDate 2010-04-22T13:08:31-05:00 metricPollDate 2010-04-22T13:08:00-05:00 dedicatedAccountHostOnlyFlag 1 powerState name Running keyName RUNNING softwareComponents id 277171 hardwareId manufacturerLicenseInstance passwords id 250815 softwareId 277171 username root password TEST createDate 2010-04-22T12:15:26-05:00 modifyDate 2010-04-22T12:15:26-05:00 port primaryIpAddress 174.254.254.254 primaryBackendIpAddress 10.254.254.254 privateNetworkOnlyFlag 0 id 19284 accountId 11111 statusId 1001 uuid f3c73738-7731-1372-f3c3-e6808082f824 hostname test5 domain libcloud.org maxCpu 2 maxCpuUnits CORE maxMemory 1024 startCpus 2 createDate 2010-04-22T12:11:23-05:00 modifyDate 2010-04-22T13:08:31-05:00 metricPollDate 2010-04-22T13:08:00-05:00 dedicatedAccountHostOnlyFlag 1 powerState name Running keyName RUNNING softwareComponents id 277167 hardwareId manufacturerLicenseInstance passwords id 250811 softwareId 277167 username root password TEST createDate 2010-04-22T12:11:27-05:00 modifyDate 2010-04-22T12:11:27-05:00 port primaryIpAddress 174.254.254.254 primaryBackendIpAddress 10.254.254.254 ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Location_Datacenter_getDatacenters.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcl/v3_SoftLayer_Location_Datacenter_getDatacen0000664000175000017500000000334313535474530033670 0ustar kamikami00000000000000 id 2 name dal00 longName Corporate HQ id 3 name dal01 longName Dallas id 18171 name sea01 longName Seattle id 37473 name wdc01 longName Washington, DC apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/0000775000175000017500000000000013600223624024462 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_admin_group_b8202c48_7151_4e61_90000664000175000017500000000236013535474530032356 0ustar kamikami00000000000000 \CF\CB\AD\5D\1D\34\09\4D\A4\77\8D\A3\CA\99\75\FB ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_catalogItem_3132e037_759b_4627_9056_ca66466fa607.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_catalogItem_3132e037_759b_4627_90000664000175000017500000000223713535474530032235 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_catalog_cddb3cb2_3394_4b14_b831_0000664000175000017500000000213013535474530032415 0ustar kamikami00000000000000 false ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_network_dca8b667_6c8f_4c3e_be57_0000664000175000017500000000471713535474530032704 0ustar kamikami00000000000000 true 65.41.64.1 255.255.252.0 65.41.42.113 65.41.42.114 vm.netsuite.com 65.41.65.1 65.41.65.64 65.41.65.70 65.41.65.88 65.41.65.90 65.41.66.6 65.41.66.8 65.41.66.67 65.41.66.69 65.41.66.108 65.41.66.110 65.41.66.227 65.41.66.229 65.41.67.254 bridged false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_org.xml0000664000175000017500000000066613535474530026647 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_org_96726c78_4ae3_402f_b08b_7a780000664000175000017500000000321013535474530032063 0ustar kamikami00000000000000 MyOrg Product Development apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_query_group.xml0000664000175000017500000000202013535474530030423 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_query_user.xml0000664000175000017500000000226613535474530030261 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_query_vm.xml0000664000175000017500000000276613577507766027750 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_sessions.xml0000664000175000017500000000140713535474530027720 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_2518935e_b315_4d8e_9e99_9275f751877c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_2518935e_b315_4d8e_9e99_9270000664000175000017500000000272713535474530032046 0ustar kamikami00000000000000
././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_b034df55_fe81_4798_bc81_1f00000664000175000017500000000210213535474530032223 0ustar kamikami00000000000000 100 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_deploy.xml0000664000175000017500000000216513535474530030372 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_fab4b26f_4f2e_4d49_ad01_ae9324bbfe48.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_fab4b26f_4f2e_4d49_ad01_ae90000664000175000017500000000272313535474530032522 0ustar kamikami00000000000000
././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_fe75d3af_f5a3_44a5_b016_ae0bdadfc32b.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_fe75d3af_f5a3_44a5_b016_ae00000664000175000017500000000274013535474530032432 0ustar kamikami00000000000000
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy.xml0000664000175000017500000000220013535474530030723 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy_error.xml0000664000175000017500000000347313535474530032151 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_task_undeploy_power_off.xml0000664000175000017500000000220013577507766033007 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_undeployTest.xml0000664000175000017500000005772713535474530031557 0ustar kamikami00000000000000 Lease settings section 0 0 VApp startup section The list of logical networks The configuration parameters for logical networks true 65.41.64.1 255.255.252.0 65.41.42.113 65.41.42.114 vm.myorg.com 65.41.67.1 65.41.67.254 bridged false false 3600 7200 65.41.64.2 65.41.67.0 true drop false true Allow all outgoing traffic allow true -1 Any -1 Any out false true ipTranslation allowTraffic automatic ScrumVM_Master 0 false false false Virtual hardware requirements Virtual Hardware Family 0 mgalet-test2 vmx-07 00:50:56:01:00:99 0 true vCloud - Default PCNet32 ethernet adapter Network adapter 0 1 PCNet32 10 0 SCSI Controller SCSI Controller 0 2 lsilogic 6 0 Hard disk Hard disk 1 2000 2 17 0 IDE Controller IDE Controller 0 3 5 0 false CD/DVD Drive CD/DVD Drive 1 3002 3 15 0 false Floppy Drive Floppy Drive 1 8000 14 hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 4 0 3 2 0 byte * 2^20 Memory Size 4096 MB of memory 5 0 4 4096 0 Specifies the operating system installed Red Hat Enterprise Linux 5 (64-bit) Specifies the available VM network connections 0 0 65.41.67.2 true 00:50:56:01:00:99 POOL Specifies Guest OS Customization Settings true false dd75d1d3-5b7b-48f0-aff3-69622ab7e045 false false true true sN#9QH9# false mgalet-test2 Specifies Runtime info ScrumVM_Master ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000006022713535474530032553 0ustar kamikami00000000000000 Lease settings section 0 0 VApp startup section The list of logical networks The configuration parameters for logical networks true 65.41.64.1 255.255.252.0 65.41.42.113 65.41.42.114 vm.myorg.com 65.41.67.1 65.41.67.254 bridged false false 3600 7200 65.41.64.2 65.41.67.0 true drop false true Allow all outgoing traffic allow true -1 Any -1 Any out false true ipTranslation allowTraffic automatic ScrumVM_Master 0 false true false Virtual hardware requirements Virtual Hardware Family 0 mgalet-test2 vmx-07 00:50:56:01:00:99 0 true vCloud - Default PCNet32 ethernet adapter Network adapter 0 1 PCNet32 10 0 SCSI Controller SCSI Controller 0 2 lsilogic 6 0 Hard disk Hard disk 1 2000 2 17 0 IDE Controller IDE Controller 0 3 5 0 false CD/DVD Drive CD/DVD Drive 1 3002 3 15 0 false Floppy Drive Floppy Drive 1 8000 14 hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 4 0 3 2 0 byte * 2^20 Memory Size 4096 MB of memory 5 0 4 4096 0 Specifies the operating system installed Red Hat Enterprise Linux 5 (64-bit) Specifies the available VM network connections 0 0 65.41.67.2 true 00:50:56:01:00:99 POOL Specifies Guest OS Customization Settings true false dd75d1d3-5b7b-48f0-aff3-69622ab7e045 false false true true sN#9QH9# false mgalet-test2 Specifies Runtime info ScrumVM_Master VMware ESXi 5.0.0 VMware, Inc. en ././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000000117513535474530032550 0ustar kamikami00000000000000 true ReadOnly FullControl ././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000000230213535474530032541 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_powerOn.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000000224213535474530032544 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000021200000000000011210 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_reset.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000000220413535474530032542 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000006007213577507766032567 0ustar kamikami00000000000000 Lease settings section 0 0 VApp startup section The list of logical networks The configuration parameters for logical networks true 65.41.64.1 255.255.252.0 65.41.42.113 65.41.42.114 vm.myorg.com 65.41.67.1 65.41.67.254 bridged false false 3600 7200 65.41.64.2 65.41.67.0 true drop false true Allow all outgoing traffic allow true -1 Any -1 Any out false true ipTranslation allowTraffic automatic ScrumVM_Master 0 false true false Virtual hardware requirements Virtual Hardware Family 0 mgalet-test2 vmx-07 00:50:56:01:00:99 0 true vCloud - Default PCNet32 ethernet adapter Network adapter 0 1 PCNet32 10 0 SCSI Controller SCSI Controller 0 2 lsilogic 6 0 Hard disk Hard disk 1 2000 2 17 0 IDE Controller IDE Controller 0 3 5 0 false CD/DVD Drive CD/DVD Drive 1 3002 3 15 0 false Floppy Drive Floppy Drive 1 8000 14 hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 4 0 3 2 0 byte * 2^20 Memory Size 4096 MB of memory 5 0 4 4096 0 Specifies the operating system installed Red Hat Enterprise Linux 5 (64-bit) Specifies the available VM network connections 0 0 192.168.0.100 192.168.0.103 true 00:50:56:01:00:d9 POOL Specifies Guest OS Customization Settings true false dd75d1d3-5b7b-48f0-aff3-69622ab7e045 false false true true sN#9QH9# false mgalet-test2 Specifies Runtime info ScrumVM_Master VMware ESXi 5.0.0 VMware, Inc. en ././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_create_snapshot.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000000272313535474530032550 0ustar kamikami00000000000000
././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_remove_snapshots.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000000272713535474530032554 0ustar kamikami00000000000000
././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_revert_snapshot.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000000274013535474530032547 0ustar kamikami00000000000000
././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000005653313577507766032576 0ustar kamikami00000000000000 Lease settings section 0 0 VApp startup section The list of logical networks The configuration parameters for logical networks true 65.41.64.1 255.255.252.0 65.41.42.113 65.41.42.114 vm.myorg.com 65.41.67.1 65.41.67.254 bridged false false 3600 7200 65.41.64.2 65.41.67.0 true drop false true Allow all outgoing traffic allow true -1 Any -1 Any out false true ipTranslation allowTraffic automatic ScrumVM_Master 0 false true false Virtual hardware requirements Virtual Hardware Family 0 mgalet-test2 vmx-07 00:50:56:01:00:99 0 true vCloud - Default PCNet32 ethernet adapter Network adapter 0 1 PCNet32 10 0 SCSI Controller SCSI Controller 0 2 lsilogic 6 0 Hard disk Hard disk 1 2000 2 17 0 IDE Controller IDE Controller 0 3 5 0 false CD/DVD Drive CD/DVD Drive 1 3002 3 15 0 false Floppy Drive Floppy Drive 1 8000 14 hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 4 0 3 2 0 byte * 2^20 Memory Size 4096 MB of memory 5 0 4 4096 0 Specifies the available VM network connections 0 0 192.168.0.100 192.168.0.103 true 00:50:56:01:00:d9 POOL Specifies Guest OS Customization Settings true false dd75d1d3-5b7b-48f0-aff3-69622ab7e045 false false true true sN#9QH9# false mgalet-test2 Specifies Runtime info ScrumVM_Master VMware ESXi 5.0.0 VMware, Inc. en ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6d.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_8c57a5b6_e61b_48ca_8a70000664000175000017500000005705313577507766032574 0ustar kamikami00000000000000 Test Description Lease settings section 86400 172800 2019-10-07T14:06:29.980725 2019-10-08T14:06:29.980725 VApp startup section The list of logical networks The configuration parameters for logical networks true 65.41.64.1 255.255.252.0 65.41.42.113 65.41.42.114 vm.myorg.com 65.41.67.1 65.41.67.254 bridged false false 3600 7200 65.41.64.2 65.41.67.0 true drop false true Allow all outgoing traffic allow true -1 Any -1 Any out false true ipTranslation allowTraffic automatic ScrumVM_Master 0 false true false Virtual hardware requirements Virtual Hardware Family 0 mgalet-test2 vmx-07 00:50:56:01:00:99 0 true vCloud - Default PCNet32 ethernet adapter Network adapter 0 1 PCNet32 10 0 SCSI Controller SCSI Controller 0 2 lsilogic 6 0 Hard disk Hard disk 1 2000 2 17 0 IDE Controller IDE Controller 0 3 5 0 false CD/DVD Drive CD/DVD Drive 1 3002 3 15 0 false Floppy Drive Floppy Drive 1 8000 14 hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 4 0 3 2 0 byte * 2^20 Memory Size 4096 MB of memory 5 0 4 4096 0 Specifies the available VM network connections 0 0 192.168.0.100 192.168.0.103 true 00:50:56:01:00:d9 POOL Specifies Guest OS Customization Settings true false dd75d1d3-5b7b-48f0-aff3-69622ab7e045 false false true true sN#9QH9# false mgalet-test2 Specifies Runtime info ScrumVM_Master VMware ESXi 5.0.0 VMware, Inc. en ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_access_to_resource_forbidden.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vapp_access_to_resource_for0000664000175000017500000000065513535474530034013 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vApp_vm_test.xml0000664000175000017500000004523513535474530030530 0ustar kamikami00000000000000 Virtual hardware requirements Virtual Hardware Family 0 ScrumVM_Master vmx-07 00:50:56:01:00:d9 0 true vCloud - Default PCNet32 ethernet adapter Network adapter 0 1 PCNet32 10 0 SCSI Controller SCSI Controller 0 2 lsilogic 6 0 Hard disk Hard disk 1 2000 2 17 1 Hard disk Hard disk 2 2001 2 17 2 Hard disk Hard disk 3 2002 2 17 3 Hard disk Hard disk 4 2003 2 17 0 IDE Controller IDE Controller 0 3 5 0 false CD/DVD Drive CD/DVD Drive 1 3002 3 15 0 false Floppy Drive Floppy Drive 1 8000 14 hertz * 10^6 Number of Virtual CPUs 2 virtual CPU(s) 4 0 3 2 0 byte * 2^20 Memory Size 4096 MB of memory 5 0 4 4096 0 Specifies the operating system installed Red Hat Enterprise Linux 5 (64-bit) Specifies the available VM network connections 0 0 65.33.65.9 true 00:50:56:01:00:d9 POOL Specifies Guest OS Customization Settings true false cbfe57d5-7362-482b-b313-e5b5bcff3309 false false true true jW!4$$2i false #/bin/sh /usr/local/sbin/ns-guest-customization.sh "$@" ScrumVMMast-001 Specifies Runtime info ScrumVM_Master VMware ESXi 5.0.0 VMware, Inc. en apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_get_metadata.xml0000664000175000017500000000261613535474530031522 0ustar kamikami00000000000000 owners msamia@netsuite.com apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vapp_post_metadata.xml0000664000175000017500000000225313535474530031725 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_93560000664000175000017500000001022613535474530031774 0ustar kamikami00000000000000 AllocationPool MB 5120000 5120000 1984512 0 MHz 130000 160000 0 0 MB 527360 527360 130752 0 vmx-04 vmx-07 vmx-08 0 1024 150 true ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_93560000664000175000017500000000421113535474530031771 0ustar kamikami00000000000000 testing instance 1 false ././@LongLink0000000000000000000000000000022000000000000011207 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_3d9ae28c_1de9_4307_8107_93560000664000175000017500000000516213535474530031777 0ustar kamikami00000000000000 testing instance 1 false apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/api_vdc_brokenVdc.xml0000664000175000017500000000774213535474530030633 0ustar kamikami00000000000000 AllocationPool MB 5120000 5120000 1984512 0 MHz 130000 160000 0 0 MB 527360 527360 130752 0 vmx-04 vmx-07 vmx-08 0 1024 150 true ././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_dd75d1d3_5b7b_48f0_a0000664000175000017500000000220613535474530032677 0ustar kamikami00000000000000 Specifies Guest OS Customization Settings true false 9e8837e6-5c4c-4112-bf01-5498616d865f false false true true aabbccddee false VMMast-001 ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_cpu.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardware0000664000175000017500000000236613535474530034012 0ustar kamikami00000000000000 hertz * 10^6 Number of Virtual CPUs 1 virtual CPU(s) 4 0 3 1 0 ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_disks.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardware0000664000175000017500000000634213535474530034010 0ustar kamikami00000000000000 0 SCSI Controller SCSI Controller 0 2 lsilogic 6 0 Hard disk Hard disk 1 2000 2 17 1 Hard disk Hard disk 2 2001 2 17 2 Hard disk Hard disk 3 2002 2 17 3 Hard disk Hard disk 4 2003 2 17 0 IDE Controller IDE Controller 0 3 5 ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardwareSection_memory.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/get_api_vApp_vm_test_virtualHardware0000664000175000017500000000236413535474530034010 0ustar kamikami00000000000000 byte * 2^20 Memory Size 4096 MB of memory 5 0 4 4096 0 ././@LongLink0000000000000000000000000000022300000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_dd75d1d3_5b7b_48f0_a0000664000175000017500000000226513535474530032735 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_cpu.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardware0000664000175000017500000000223613535474530034037 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_disks.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardware0000664000175000017500000000223613535474530034037 0ustar kamikami00000000000000 ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardwareSection_memory.xmlapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vcloud_1_5/put_api_vApp_vm_test_virtualHardware0000664000175000017500000000223613535474530034037 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/0000775000175000017500000000000013600223624023657 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/create_node.xml0000664000175000017500000000021113535474530026656 0ustar kamikami00000000000000 1234 1235386846 QUEUED apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/failure.xml0000664000175000017500000000002313535474530026036 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/images.xml0000664000175000017500000000115113535474530025657 0ustar kamikami00000000000000 32 Linux 2.6.18 CentOS 5.1 root ext3 880 Base install of CentOS 5.1 i386. apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/locations.xml0000664000175000017500000000044513535474530026412 0ustar kamikami00000000000000 Amsterdam New York apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/nodes.xml0000664000175000017500000000204213535474530025522 0ustar kamikami00000000000000 Z100.12 Virtual Server Voxrox Intel Platform LGA7 - XO / 12th Floor Private cage primary Row Z Rack 100 12 172.x.x.x user root
zz.zz.us.voxel.net
55555 user
Voxel TruManaged Server Configuration 1
...
apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/success.xml0000664000175000017500000000002113535474530026055 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/compute/fixtures/voxel/unauthorized.xml0000664000175000017500000000073213535474530027137 0ustar kamikami00000000000000 voxel.devices.list 2010-02-10T23:39:25.808107+0000 authshouldfail ae069bb835e998622caaddaeff8c98e0 YOUR_SECRETtimestamp2010-02-10T23:39:25.808107+0000methodvoxel.devices.listkeyauthshouldfail apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vpsnet/0000775000175000017500000000000013600223624024041 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vpsnet/_available_clouds_api10json_templates.jsonapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vpsnet/_available_clouds_api10json_templates.js0000664000175000017500000001102113535474530033777 0ustar kamikami00000000000000[{"cloud":{"system_templates":[{"id":9,"label":"Ubuntu 8.04 x64"},{"id":10,"label":"CentOS 5.2 x64"},{"id":11,"label":"Gentoo 2008.0 x64"},{"id":18,"label":"Ubuntu 8.04 x64 LAMP"},{"id":19,"label":"Ubuntu 8.04 x64 MySQL"},{"id":20,"label":"Ubuntu 8.04 x64 Postfix"},{"id":21,"label":"Ubuntu 8.04 x64 Apache"},{"id":22,"label":"CentOS 5.2 x64 MySQL"},{"id":23,"label":"CentOS 5.2 x64 LAMP"},{"id":24,"label":"CentOS 5.2 x64 HAProxy"},{"id":25,"label":"CentOS 5.2 x64 Postfix"},{"id":26,"label":"CentOS 5.2 x64 Varnish"},{"id":27,"label":"CentOS 5.2 x64 Shoutcast"},{"id":28,"label":"CentOS 5.2 x64 Apache"},{"id":40,"label":"cPanel"},{"id":42,"label":"Debian 5.0 (Lenny) x64"},{"id":58,"label":"Django on Ubuntu 8.04 (x86)"},{"id":59,"label":"Drupal 5 on Ubuntu 8.04 (x86)"},{"id":60,"label":"Drupal 6 on Ubuntu 8.04 (x86)"},{"id":61,"label":"Google App Engine on Ubuntu 8.04 (x86)"},{"id":62,"label":"LAMP on Ubuntu 8.04 (x86)"},{"id":63,"label":"LAPP on Ubuntu 8.04 (x86)"},{"id":64,"label":"MediaWiki on Ubuntu 8.04 (x86)"},{"id":65,"label":"MySQL on Ubuntu 8.04 (x86)"},{"id":66,"label":"phpBB on Ubuntu 8.04 (x86)"},{"id":67,"label":"PostgreSQL on Ubuntu 8.04 (x86)"},{"id":68,"label":"Rails on Ubuntu 8.04 (x86)"},{"id":69,"label":"Tomcat on Ubuntu 8.04 (x86)"},{"id":70,"label":"Wordpress on Ubuntu 8.04 (x86)"},{"id":71,"label":"Joomla on Ubuntu 8.04 (x86)"},{"id":72,"label":"Ubuntu 8.04 Default Install (turnkey)"},{"id":128,"label":"CentOS Optimised"},{"id":129,"label":"Optimised CentOS + Apache + MySQL + PHP"},{"id":130,"label":"Optimised CentOS + Apache + MySQL + Ruby"},{"id":131,"label":"Optimised CentOS + Apache + MySQL + Ruby + PHP"},{"id":132,"label":"Debian Optimised"},{"id":133,"label":"Optimised Debian + Apache + MySQL + PHP"},{"id":134,"label":"Optimised Debian + NGINX + MySQL + PHP"},{"id":135,"label":"Optimised Debian + Lighttpd + MySQL + PHP"},{"id":136,"label":"Optimised Debian + Apache + MySQL + Ruby + PHP"},{"id":137,"label":"Optimised Debian + Apache + MySQL + Ruby"},{"id":138,"label":"Optimised Debian + NGINX + MySQL + Ruby + PHP"},{"id":139,"label":"Optimised Debian + NGINX + MySQL + Ruby"},{"id":140,"label":"Optimised Debian + Apache + MySQL + PHP + Magento"},{"id":141,"label":"Optimised Debian + NGINX + MySQL + PHP + Magento"},{"id":142,"label":"Optimised Debian + Lighttpd + MySQL + PHP + Wordpress"}],"id":2,"label":"USA VPS Cloud"}},{"cloud":{"system_templates":[{"id":15,"label":"Ubuntu 8.04 x64"},{"id":16,"label":"CentOS 5.2 x64"},{"id":17,"label":"Gentoo 2008.0 x64"},{"id":29,"label":"Ubuntu 8.04 x64 LAMP"},{"id":30,"label":"Ubuntu 8.04 x64 MySQL"},{"id":31,"label":"Ubuntu 8.04 x64 Postfix"},{"id":32,"label":"Ubuntu 8.04 x64 Apache"},{"id":33,"label":"CentOS 5.2 x64 MySQL"},{"id":34,"label":"CentOS 5.2 x64 LAMP"},{"id":35,"label":"CentOS 5.2 x64 HAProxy"},{"id":36,"label":"CentOS 5.2 x64 Postfix"},{"id":37,"label":"CentOS 5.2 x64 Varnish"},{"id":38,"label":"CentOS 5.2 x64 Shoutcast"},{"id":39,"label":"CentOS 5.2 x64 Apache"},{"id":41,"label":"cPanel"},{"id":43,"label":"Debian 5.0 (Lenny) x64"},{"id":44,"label":"Django on Ubuntu 8.04 (x86)"},{"id":45,"label":"Drupal 5 on Ubuntu 8.04 (x86)"},{"id":46,"label":"Drupal 6 on Ubuntu 8.04 (x86)"},{"id":47,"label":"Google App Engine on Ubuntu 8.04 (x86)"},{"id":48,"label":"LAMP on Ubuntu 8.04 (x86)"},{"id":49,"label":"LAPP on Ubuntu 8.04 (x86)"},{"id":50,"label":"MediaWiki on Ubuntu 8.04 (x86)"},{"id":51,"label":"MySQL on Ubuntu 8.04 (x86)"},{"id":52,"label":"phpBB on Ubuntu 8.04 (x86)"},{"id":53,"label":"PostgreSQL on Ubuntu 8.04 (x86)"},{"id":54,"label":"Rails on Ubuntu 8.04 (x86)"},{"id":55,"label":"Tomcat on Ubuntu 8.04 (x86)"},{"id":56,"label":"Wordpress on Ubuntu 8.04 (x86)"},{"id":57,"label":"Joomla on Ubuntu 8.04 (x86)"},{"id":73,"label":"Ubuntu 8.04 Default Install (turnkey)"},{"id":148,"label":"CentOS Optimised"},{"id":149,"label":"Optimised CentOS + Apache + MySQL + PHP"},{"id":150,"label":"Optimised CentOS + Apache + MySQL + Ruby"},{"id":151,"label":"Optimised CentOS + Apache + MySQL + Ruby + PHP"},{"id":152,"label":"Debian Optimised"},{"id":153,"label":"Optimised Debian + Apache + MySQL + PHP"},{"id":154,"label":"Optimised Debian + NGINX + MySQL + PHP"},{"id":155,"label":"Optimised Debian + Lighttpd + MySQL + PHP"},{"id":156,"label":"Optimised Debian + Apache + MySQL + Ruby + PHP"},{"id":157,"label":"Optimised Debian + Apache + MySQL + Ruby"},{"id":158,"label":"Optimised Debian + NGINX + MySQL + Ruby + PHP"},{"id":159,"label":"Optimised Debian + NGINX + MySQL + Ruby"},{"id":160,"label":"Optimised Debian + Lighttpd + MySQL + PHP + Wordpress"}],"id":3,"label":"UK VPS Cloud"}}] apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/0000775000175000017500000000000013600223624023676 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/create_key_pair.json0000664000175000017500000000004413535474530027730 0ustar kamikami00000000000000{ "SSHKEYID": "5806ab4970aba" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/create_node.json0000664000175000017500000000002313535474530027047 0ustar kamikami00000000000000{ "SUBID": "1" } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/error_rate_limit.txt0000664000175000017500000000013513535474530030013 0ustar kamikami00000000000000Rate limit reached - please try your request again later. Current rate limit: 2 requests/secapache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/list_images.json0000664000175000017500000000314013535474530027102 0ustar kamikami00000000000000{"127":{"OSID":127,"name":"CentOS 6 x64","arch":"x64","family":"centos","windows":false},"147":{"OSID":147,"name":"CentOS 6 i386","arch":"i386","family":"centos","windows":false},"162":{"OSID":162,"name":"CentOS 5 x64","arch":"x64","family":"centos","windows":false},"163":{"OSID":163,"name":"CentOS 5 i386","arch":"i386","family":"centos","windows":false},"167":{"OSID":167,"name":"CentOS 7 x64","arch":"x64","family":"centos","windows":false},"160":{"OSID":160,"name":"Ubuntu 14.04 x64","arch":"x64","family":"ubuntu","windows":false},"161":{"OSID":161,"name":"Ubuntu 14.04 i386","arch":"i386","family":"ubuntu","windows":false},"128":{"OSID":128,"name":"Ubuntu 12.04 x64","arch":"x64","family":"ubuntu","windows":false},"148":{"OSID":148,"name":"Ubuntu 12.04 i386","arch":"i386","family":"ubuntu","windows":false},"181":{"OSID":181,"name":"Ubuntu 14.10 x64","arch":"x64","family":"ubuntu","windows":false},"182":{"OSID":182,"name":"Ubuntu 14.10 i386","arch":"i386","family":"ubuntu","windows":false},"139":{"OSID":139,"name":"Debian 7 x64 (wheezy)","arch":"x64","family":"debian","windows":false},"152":{"OSID":152,"name":"Debian 7 i386 (wheezy)","arch":"i386","family":"debian","windows":false},"140":{"OSID":140,"name":"FreeBSD 10 x64","arch":"x64","family":"freebsd","windows":false},"124":{"OSID":124,"name":"Windows 2012 R2 x64","arch":"x64","family":"windows","windows":true},"159":{"OSID":159,"name":"Custom","arch":"x64","family":"iso","windows":false},"164":{"OSID":164,"name":"Snapshot","arch":"x64","family":"snapshot","windows":false},"180":{"OSID":180,"name":"Backup","arch":"x64","family":"backup","windows":false}}apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/list_key_pairs.json0000664000175000017500000000106413535474530027626 0ustar kamikami00000000000000{ "5806a8ef2a0c6": { "SSHKEYID": "5806a8ef2a0c6", "date_created": "2016-10-18 18:57:51", "name": "test-key-pair", "ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZYMivN4KqJZ3dNEWeH20PUeB2ZnZRkk91K5SgxWrEotgpX4pMVM/9oxkh4bKw5CBzT6KAOghzLcBViFpNVjDyyet9wwVcy6cjuUynx63UtbTLB+r4D+bD/+/9rQTeckvGYg9Y8xIKL/oaVeCcdBM8JhSQZbZ/aARi2K79FWGH61azAqc/JCHT63f3FhspjdVpcVoVOjsZG3WG6Vymys2cXH1PM5qMgBbmp+5LkSv0LvUULyxcrtKkUyntPr1BvIFSNbo2lhXLwnM4DXONP6U/yMFte+ZwiajF7pUCdB9HqvXVU+IfswYSDuhHzL9j8+ZLQ2enF/lkkYxpMHE2t215 tester@test" } } apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/list_locations.json0000664000175000017500000000230313535474530027630 0ustar kamikami00000000000000{"6":{"DCID":"6","name":"Atlanta","country":"US","continent":"North America","state":"GA"},"2":{"DCID":"2","name":"Chicago","country":"US","continent":"North America","state":"IL"},"3":{"DCID":"3","name":"Dallas","country":"US","continent":"North America","state":"TX"},"5":{"DCID":"5","name":"Los Angeles","country":"US","continent":"North America","state":"CA"},"39":{"DCID":"39","name":"Miami","country":"US","continent":"","state":"FL"},"1":{"DCID":"1","name":"New Jersey","country":"US","continent":"North America","state":"NJ"},"4":{"DCID":"4","name":"Seattle","country":"US","continent":"North America","state":"WA"},"12":{"DCID":"12","name":"Silicon Valley","country":"US","continent":"North America","state":"CA"},"7":{"DCID":"7","name":"Amsterdam","country":"NL","continent":"Europe","state":""},"25":{"DCID":"25","name":"Tokyo","country":"JP","continent":"Asia","state":""},"8":{"DCID":"8","name":"London","country":"GB","continent":"Europe","state":""},"24":{"DCID":"24","name":"France","country":"FR","continent":"Europe","state":""},"9":{"DCID":"9","name":"Frankfurt","country":"DE","continent":"Europe","state":""},"19":{"DCID":"19","name":"Australia","country":"AU","continent":"Australia","state":""}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/list_nodes.json0000664000175000017500000000343613535474530026755 0ustar kamikami00000000000000{"1":{"SUBID":"1","os":"Ubuntu 12.04 x64","ram":"1024 MB","disk":"Virtual 20 GB","main_ip":"108.61.206.153","vcpu_count":"1","location":"Los Angeles","DCID":"5","default_password":"twizewnatpom!7","date_created":"2014-03-21 12:46:35","pending_charges":"1.92","status":"active","cost_per_month":"7.00","current_bandwidth_gb":0.929,"allowed_bandwidth_gb":"2000","netmask_v4":"255.255.254.0","gateway_v4":"108.61.206.1","power_status":"running","VPSPLANID":"30","v6_network":"::","v6_main_ip":"","v6_network_size":"0","label":"","internal_ip":"","kvm_url":"https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=IF3C6VCEN5NFOZ3VMM3FOV3JJVXUQV3OHBWDG6TUKI3VST3JMFDXOOCMIE3HCTBWKVJXOZZYF5BVMZ3IM5XXGWRZIVZW4S2WKAVTSMTQHFCG4QTCNFUEKOCXKY3CW3LGNF4HIVTVJ5GXM4CJORTU6SKYOBDE6WJVMZ3E4ZSVOB2FQ4KYF5DXC5CTJI4FETDIGBITQQZPGFLXKTSRKRJS6ODOMFKDSNLLNVETONSNKA2XQ6CWLJMW6L2EGI2U6SDNN5FGUTJYNB3UC5DXN46Q","auto_backups":"no"},"2":{"SUBID":"2","os":"Ubuntu 14.04 x64","ram":"768 MB","disk":"Virtual 15 GB","main_ip":"104.207.153.143","vcpu_count":"1","location":"Los Angeles","DCID":"5","default_password":"cewxoaezap!0","date_created":"2014-11-08 14:12:13","pending_charges":"0.01","status":"active","cost_per_month":"5.00","current_bandwidth_gb":0,"allowed_bandwidth_gb":"1000","netmask_v4":"255.255.254.0","gateway_v4":"104.207.152.1","power_status":"running","VPSPLANID":"29","v6_network":"::","v6_main_ip":"","v6_network_size":"0","label":"vultr-test1","internal_ip":"","kvm_url":"https:\/\/my.vultr.com\/subs\/vps\/novnc\/api.php?data=NBUUYMTDI4VXGVZXOFBE6UBWKFLWE43MI5EFOR3MJNZW4NRXLFBHA33BHF3C63LSOJRXAU2PO5GHM5LPOFAW2MSDMFZWUMCNNJRG6TRWJREWYNBLG5VTG2DEGIYWITKIGV2FA3JTNJVEETLOGBHFG42XLEZHG22VFNWHE5RUKFIWU3DSOJCS6WDQGJRDIZRPIU2HILZTKB4E4MZSNZIFEQ3SOFSDANCBHBBEWRLVGZEUEVDSJVQVKOKZNQ4GKSRSIJEG62TWMREG6USNIE6Q","auto_backups":"no"}} apache-libcloud-2.8.0/libcloud/test/compute/fixtures/vultr/list_sizes.json0000664000175000017500000001041513535474530026775 0ustar kamikami00000000000000{"201":{"VPSPLANID":"201","name":"1024 MB RAM,25 GB SSD,1.00 TB BW","vcpu_count":"1","ram":"1024","disk":"25","bandwidth":"1.00","bandwidth_gb":"1024","price_per_month":"5.00","plan_type":"SSD","windows":false,"available_locations":[1,2,3,4,5,6,7,8,9,12,19,24,25,39,40]},"202":{"VPSPLANID":"202","name":"2048 MB RAM,40 GB SSD,2.00 TB BW","vcpu_count":"1","ram":"2048","disk":"40","bandwidth":"2.00","bandwidth_gb":"2048","price_per_month":"10.00","plan_type":"SSD","windows":false,"available_locations":[1,2,3,4,5,6,7,8,9,12,19,24,25,39,40]},"203":{"VPSPLANID":"203","name":"4096 MB RAM,60 GB SSD,3.00 TB BW","vcpu_count":"2","ram":"4096","disk":"60","bandwidth":"3.00","bandwidth_gb":"3072","price_per_month":"20.00","plan_type":"SSD","windows":false,"available_locations":[1,2,3,4,5,6,7,8,9,12,19,24,25,39,40]},"204":{"VPSPLANID":"204","name":"8192 MB RAM,100 GB SSD,4.00 TB BW","vcpu_count":"4","ram":"8192","disk":"100","bandwidth":"4.00","bandwidth_gb":"4096","price_per_month":"40.00","plan_type":"SSD","windows":false,"available_locations":[1,2,3,4,5,6,7,8,9,12,19,24,25,39,40]},"205":{"VPSPLANID":"205","name":"16384 MB RAM,200 GB SSD,5.00 TB BW","vcpu_count":"6","ram":"16384","disk":"200","bandwidth":"5.00","bandwidth_gb":"5120","price_per_month":"80.00","plan_type":"SSD","windows":false,"available_locations":[1,2,3,4,5,6,8,9,12,19,24,25,39,40]},"206":{"VPSPLANID":"206","name":"32768 MB RAM,300 GB SSD,6.00 TB BW","vcpu_count":"8","ram":"32768","disk":"300","bandwidth":"6.00","bandwidth_gb":"6144","price_per_month":"160.00","plan_type":"SSD","windows":false,"available_locations":[1,2,3,4,5,6,8,9,12,19,24,25,39,40]},"207":{"VPSPLANID":"207","name":"65536 MB RAM,400 GB SSD,10.00 TB BW","vcpu_count":"16","ram":"65536","disk":"400","bandwidth":"10.00","bandwidth_gb":"10240","price_per_month":"320.00","plan_type":"SSD","windows":false,"available_locations":[2,3,4,6,8,9,12,19,24,39,40]},"208":{"VPSPLANID":"208","name":"98304 MB RAM,800 GB SSD,15.00 TB BW","vcpu_count":"24","ram":"98304","disk":"800","bandwidth":"15.00","bandwidth_gb":"15360","price_per_month":"640.00","plan_type":"SSD","windows":false,"available_locations":[2,3,4,6,9,12,19,39]},"87":{"VPSPLANID":"87","name":"512 MB RAM,125 GB SATA,1.00 TB BW","vcpu_count":"1","ram":"512","disk":"125","bandwidth":"1.00","bandwidth_gb":"1024","price_per_month":"5.00","plan_type":"SATA","windows":false,"available_locations":[5,7]},"88":{"VPSPLANID":"88","name":"1024 MB RAM,250 GB SATA,2.00 TB BW","vcpu_count":"1","ram":"1024","disk":"250","bandwidth":"2.00","bandwidth_gb":"2048","price_per_month":"10.00","plan_type":"SATA","windows":false,"available_locations":[]},"89":{"VPSPLANID":"89","name":"2048 MB RAM,500 GB SATA,3.00 TB BW","vcpu_count":"1","ram":"2048","disk":"500","bandwidth":"3.00","bandwidth_gb":"3072","price_per_month":"20.00","plan_type":"SATA","windows":false,"available_locations":[]},"90":{"VPSPLANID":"90","name":"3072 MB RAM,750 GB SATA,4.00 TB BW","vcpu_count":"2","ram":"3072","disk":"750","bandwidth":"4.00","bandwidth_gb":"4096","price_per_month":"30.00","plan_type":"SATA","windows":false,"available_locations":[]},"91":{"VPSPLANID":"91","name":"4096 MB RAM,1000 GB SATA,5.00 TB BW","vcpu_count":"2","ram":"4096","disk":"1000","bandwidth":"5.00","bandwidth_gb":"5120","price_per_month":"40.00","plan_type":"SATA","windows":false,"available_locations":[]},"115":{"VPSPLANID":"115","name":"8192 MB RAM,110 GB SSD,10.00 TB BW","vcpu_count":"2","ram":"8192","disk":"110","bandwidth":"10.00","bandwidth_gb":"10240","price_per_month":"60.00","plan_type":"DEDICATED","windows":false,"available_locations":[1,2,25]},"116":{"VPSPLANID":"116","name":"16384 MB RAM,110 GB SSD,20.00 TB BW","vcpu_count":"4","ram":"16384","disk":"110","bandwidth":"20.00","bandwidth_gb":"20480","price_per_month":"120.00","plan_type":"DEDICATED","windows":false,"available_locations":[2]},"117":{"VPSPLANID":"117","name":"24576 MB RAM,110 GB SSD,30.00 TB BW","vcpu_count":"6","ram":"24576","disk":"110","bandwidth":"30.00","bandwidth_gb":"30720","price_per_month":"180.00","plan_type":"DEDICATED","windows":false,"available_locations":[2]},"118":{"VPSPLANID":"118","name":"32768 MB RAM,110 GB SSD,40.00 TB BW","vcpu_count":"8","ram":"32768","disk":"110","bandwidth":"40.00","bandwidth_gb":"40960","price_per_month":"240.00","plan_type":"DEDICATED","windows":false,"available_locations":[2]}}apache-libcloud-2.8.0/libcloud/test/compute/test_abiquo.py0000664000175000017500000005066713577507766023611 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Abiquo Test Suite """ import sys from libcloud.utils.py3 import ET from libcloud.utils.py3 import httplib from libcloud.compute.drivers.abiquo import AbiquoNodeDriver from libcloud.common.abiquo import ForbiddenError, get_href from libcloud.common.types import InvalidCredsError, LibcloudError from libcloud.compute.base import NodeLocation, NodeImage from libcloud.test.compute import TestCaseMixin from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import ComputeFileFixtures class AbiquoNodeDriverTest(TestCaseMixin, unittest.TestCase): """ Abiquo Node Driver test suite """ @classmethod def setUpClass(cls): """ Set up the driver with the main user """ AbiquoNodeDriver.connectionCls.conn_class = AbiquoMockHttp cls.driver = AbiquoNodeDriver('son', 'goku', 'http://dummy.host.com/api') def test_unauthorized_controlled(self): """ Test the Unauthorized Exception is Controlled. Test, through the 'login' method, that a '401 Unauthorized' raises a 'InvalidCredsError' instead of the 'MalformedUrlException' """ self.assertRaises(InvalidCredsError, AbiquoNodeDriver, 'son', 'goten', 'http://dummy.host.com/api') def test_forbidden_controlled(self): """ Test the Forbidden Exception is Controlled. Test, through the 'list_images' method, that a '403 Forbidden' raises an 'ForbidenError' instead of the 'MalformedUrlException' """ AbiquoNodeDriver.connectionCls.conn_class = AbiquoMockHttp conn = AbiquoNodeDriver('son', 'gohan', 'http://dummy.host.com/api') self.assertRaises(ForbiddenError, conn.list_images) def test_handle_other_errors_such_as_not_found(self): """ Test common 'logical' exceptions are controlled. Test that common exception (normally 404-Not Found and 409-Conflict), that return an XMLResponse with the explanation of the errors are controlled. """ self.driver = AbiquoNodeDriver('go', 'trunks', 'http://dummy.host.com/api') self.assertRaises(LibcloudError, self.driver.list_images) def test_ex_create_and_delete_empty_group(self): """ Test the creation and deletion of an empty group. """ group = self.driver.ex_create_group('libcloud_test_group') group.destroy() def test_create_node_no_image_raise_exception(self): """ Test 'create_node' without image. Test the 'create_node' function without 'image' parameter raises an Exception """ self.assertRaises(TypeError, self.driver.create_node) def test_list_locations_response(self): if not self.should_list_locations: return None locations = self.driver.list_locations() self.assertTrue(isinstance(locations, list)) def test_create_node_specify_location(self): """ Test you can create a node specifying the location. """ image = self.driver.list_images()[0] location = self.driver.list_locations()[0] self.driver.create_node(image=image, location=location) def test_create_node_specify_wrong_location(self): """ Test you can not create a node with wrong location. """ image = self.driver.list_images()[0] location = NodeLocation(435, 'fake-location', 'Spain', self.driver) self.assertRaises(LibcloudError, self.driver.create_node, image=image, location=location) def test_create_node_specify_wrong_image(self): """ Test image compatibility. Some locations only can handle a group of images, not all of them. Test you can not create a node with incompatible image-location. """ # Create fake NodeImage image = NodeImage(3234, 'dummy-image', self.driver) location = self.driver.list_locations()[0] # With this image, it should raise an Exception self.assertRaises(LibcloudError, self.driver.create_node, image=image, location=location) def test_create_node_specify_group_name(self): """ Test 'create_node' into a concrete group. """ image = self.driver.list_images()[0] self.driver.create_node(image=image, ex_group_name='new_group_name') def test_create_group_location_does_not_exist(self): """ Test 'create_node' with an unexistent location. Defines a 'fake' location and tries to create a node into it. """ location = NodeLocation(435, 'fake-location', 'Spain', self.driver) # With this location, it should raise an Exception self.assertRaises(LibcloudError, self.driver.ex_create_group, name='new_group_name', location=location) def test_destroy_node_response(self): """ 'destroy_node' basic test. Override the destroy to return a different node available to be undeployed. (by default it returns an already undeployed node, for test creation). """ self.driver = AbiquoNodeDriver('go', 'trunks', 'http://dummy.host.com/api') node = self.driver.list_nodes()[0] ret = self.driver.destroy_node(node) self.assertTrue(ret) def test_destroy_node_response_failed(self): """ 'destroy_node' asynchronous error. Test that the driver handles correctly when, for some reason, the 'destroy' job fails. """ self.driver = AbiquoNodeDriver('muten', 'roshi', 'http://dummy.host.com/api') node = self.driver.list_nodes()[0] ret = self.driver.destroy_node(node) self.assertFalse(ret) def test_destroy_node_allocation_state(self): """ Test the 'destroy_node' invalid state. Try to destroy a node when the node is not running. """ self.driver = AbiquoNodeDriver('ve', 'geta', 'http://dummy.host.com/api') # Override the destroy to return a different node available to be # undeployed node = self.driver.list_nodes()[0] # The mock class with the user:password 've:geta' returns a node that # is in 'ALLOCATION' state and hence, the 'destroy_node' method should # raise a LibcloudError self.assertRaises(LibcloudError, self.driver.destroy_node, node) def test_destroy_not_deployed_group(self): """ Test 'ex_destroy_group' when group is not deployed. """ location = self.driver.list_locations()[0] group = self.driver.ex_list_groups(location)[1] self.assertTrue(group.destroy()) def test_destroy_deployed_group(self): """ Test 'ex_destroy_group' when there are machines running. """ location = self.driver.list_locations()[0] group = self.driver.ex_list_groups(location)[0] self.assertTrue(group.destroy()) def test_destroy_deployed_group_failed(self): """ Test 'ex_destroy_group' fails. Test driver handles correctly when, for some reason, the asynchronous job fails. """ self.driver = AbiquoNodeDriver('muten', 'roshi', 'http://dummy.host.com/api') location = self.driver.list_locations()[0] group = self.driver.ex_list_groups(location)[0] self.assertFalse(group.destroy()) def test_destroy_group_invalid_state(self): """ Test 'ex_destroy_group' invalid state. Test the Driver raises an exception when the group is in invalid temporal state. """ self.driver = AbiquoNodeDriver('ve', 'geta', 'http://dummy.host.com/api') location = self.driver.list_locations()[0] group = self.driver.ex_list_groups(location)[1] self.assertRaises(LibcloudError, group.destroy) def test_run_node(self): """ Test 'ex_run_node' feature. """ node = self.driver.list_nodes()[0] # Node is by default in NodeState.TERMINATED and AbiquoState == # 'NOT_ALLOCATED' # so it is available to be runned self.driver.ex_run_node(node) def test_run_node_invalid_state(self): """ Test 'ex_run_node' invalid state. Test the Driver raises an exception when try to run a node that is in invalid state to run. """ self.driver = AbiquoNodeDriver('go', 'trunks', 'http://dummy.host.com/api') node = self.driver.list_nodes()[0] # Node is by default in AbiquoState = 'ON' for user 'go:trunks' # so is not available to be runned self.assertRaises(LibcloudError, self.driver.ex_run_node, node) def test_run_node_failed(self): """ Test 'ex_run_node' fails. Test driver handles correctly when, for some reason, the asynchronous job fails. """ self.driver = AbiquoNodeDriver('ten', 'shin', 'http://dummy.host.com/api') node = self.driver.list_nodes()[0] # Node is in the correct state, but it fails because of the # async task and it raises the error. self.assertRaises(LibcloudError, self.driver.ex_run_node, node) def test_get_href(self): xml = ''' ''' elem = ET.XML(xml) href = get_href(element=elem, rel='edit1') self.assertEqual(href, '/admin/datacenters/2') href = get_href(element=elem, rel='edit2') self.assertEqual(href, '/admin/datacenters/3') href = get_href(element=elem, rel='edit3') self.assertEqual(href, '/admin/enterprises/1234') class AbiquoMockHttp(MockHttp): """ Mock the functionallity of the remote Abiquo API. """ fixtures = ComputeFileFixtures('abiquo') fixture_tag = 'default' def _api_login(self, method, url, body, headers): if headers['Authorization'] == 'Basic c29uOmdvdGVu': expected_response = self.fixtures.load('unauthorized_user.html') expected_status = httplib.UNAUTHORIZED else: expected_response = self.fixtures.load('login.xml') expected_status = httplib.OK return (expected_status, expected_response, {}, '') def _api_cloud_virtualdatacenters(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('vdcs.xml'), {}, '') def _api_cloud_virtualdatacenters_4(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('vdc_4.xml'), {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances(self, method, url, body, headers): if method == 'POST': vapp_name = ET.XML(body).findtext('name') if vapp_name == 'libcloud_test_group': # we come from 'test_ex_create_and_delete_empty_group(self):' # method and so, we return the 'ok' return response = self.fixtures.load('vdc_4_vapp_creation_ok.xml') return (httplib.OK, response, {}, '') elif vapp_name == 'new_group_name': # we come from 'test_ex_create_and_delete_empty_group(self):' # method and so, we return the 'ok' return response = self.fixtures.load('vdc_4_vapp_creation_ok.xml') return (httplib.OK, response, {}, '') else: # It will be a 'GET'; return (httplib.OK, self.fixtures.load('vdc_4_vapps.xml'), {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_5(self, method, url, body, headers): if method == 'GET': if headers['Authorization'] == 'Basic dmU6Z2V0YQ==': # Try to destroy a group with 'needs_sync' state response = self.fixtures.load('vdc_4_vapp_5_needs_sync.xml') else: # Try to destroy a group with 'undeployed' state response = self.fixtures.load('vdc_4_vapp_5.xml') return (httplib.OK, response, {}, '') else: # it will be a 'DELETE' return (httplib.NO_CONTENT, '', {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6(self, method, url, body, headers): if method == 'GET': # deployed vapp response = self.fixtures.load('vdc_4_vapp_6.xml') return (httplib.OK, response, {}, '') else: # it will be a 'DELETE' return (httplib.NO_CONTENT, '', {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_tasks_1da8c8b6_86f6_49ef_9d29_57dcc73b875a(self, method, url, body, headers): if headers['Authorization'] == 'Basic bXV0ZW46cm9zaGk=': # User 'muten:roshi' failed task response = self.fixtures.load( 'vdc_4_vapp_6_undeploy_task_failed.xml') else: response = self.fixtures.load('vdc_4_vapp_6_undeploy_task.xml') return (httplib.OK, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_5_virtualmachines( self, method, url, body, headers): # This virtual app never have virtual machines if method == 'GET': response = self.fixtures.load('vdc_4_vapp_5_vms.xml') return (httplib.OK, response, {}, '') elif method == 'POST': # it must be a POST response = self.fixtures.load('vdc_4_vapp_6_vm_creation_ok.xml') return (httplib.CREATED, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines( self, method, url, body, headers): # Default-created virtual app virtual machines' if method == 'GET': if headers['Authorization'] == 'Basic dmU6Z2V0YQ==': response = self.fixtures.load('vdc_4_vapp_6_vms_allocated.xml') else: response = self.fixtures.load('vdc_4_vapp_6_vms.xml') return (httplib.OK, response, {}, '') else: # it must be a POST response = self.fixtures.load('vdc_4_vapp_6_vm_creation_ok.xml') return (httplib.CREATED, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3(self, method, url, body, headers): if (headers['Authorization'] == 'Basic Z286dHJ1bmtz' or headers['Authorization'] == 'Basic bXV0ZW46cm9zaGk='): # Undeploy node response = self.fixtures.load("vdc_4_vapp_6_vm_3_deployed.xml") elif headers['Authorization'] == 'Basic dmU6Z2V0YQ==': # Try to undeploy a node with 'allocation' state response = self.fixtures.load('vdc_4_vapp_6_vm_3_allocated.xml') else: # Get node response = self.fixtures.load('vdc_4_vapp_6_vm_3.xml') return (httplib.OK, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_action_deploy(self, method, url, body, headers): response = self.fixtures.load('vdc_4_vapp_6_vm_3_deploy.xml') return (httplib.CREATED, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_tasks_b44fe278_6b0f_4dfb_be81_7c03006a93cb(self, method, url, body, headers): if headers['Authorization'] == 'Basic dGVuOnNoaW4=': # User 'ten:shin' failed task response = self.fixtures.load( 'vdc_4_vapp_6_vm_3_deploy_task_failed.xml') else: response = self.fixtures.load('vdc_4_vapp_6_vm_3_deploy_task.xml') return (httplib.OK, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_action_undeploy( self, method, url, body, headers): response = self.fixtures.load('vdc_4_vapp_6_undeploy.xml') return (httplib.OK, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_action_reset(self, method, url, body, headers): response = self.fixtures.load('vdc_4_vapp_6_vm_3_reset.xml') return (httplib.CREATED, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_tasks_a8c9818e_f389_45b7_be2c_3db3a9689940(self, method, url, body, headers): if headers['Authorization'] == 'Basic bXV0ZW46cm9zaGk=': # User 'muten:roshi' failed task response = self.fixtures.load( 'vdc_4_vapp_6_undeploy_task_failed.xml') else: response = self.fixtures.load('vdc_4_vapp_6_vm_3_reset_task.xml') return (httplib.OK, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_action_undeploy(self, method, url, body, headers): response = self.fixtures.load('vdc_4_vapp_6_vm_3_undeploy.xml') return (httplib.CREATED, response, {}, '') def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_network_nics(self, method, url, body, headers): response = self.fixtures.load('vdc_4_vapp_6_vm_3_nics.xml') return (httplib.OK, response, {}, '') def _api_admin_datacenters(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('dcs.xml'), {}, '') def _api_admin_enterprises_1(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('ent_1.xml'), {}, '') def _api_admin_enterprises_1_datacenterrepositories(self, method, url, body, headers): # When the user is the common one for all the tests ('son, 'goku') # it creates this basic auth and we return the datacenters value if headers['Authorization'] == 'Basic Z286dHJ1bmtz': expected_response = self.fixtures.load("not_found_error.xml") return (httplib.NOT_FOUND, expected_response, {}, '') elif headers['Authorization'] != 'Basic c29uOmdvaGFu': return (httplib.OK, self.fixtures.load('ent_1_dcreps.xml'), {}, '') else: # son:gohan user: forbidden error expected_response = self.fixtures.load("privilege_errors.html") return (httplib.FORBIDDEN, expected_response, {}, '') def _api_admin_enterprises_1_datacenterrepositories_2(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('ent_1_dcrep_2.xml'), {}, '') def _api_admin_enterprises_1_datacenterrepositories_2_virtualmachinetemplates(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('ent_1_dcrep_2_templates.xml'), {}, '') def _api_admin_enterprises_1_datacenterrepositories_2_virtualmachinetemplates_11(self, method, url, body, headers): return ( httplib.OK, self.fixtures.load('ent_1_dcrep_2_template_11.xml'), {}, '') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_auroracompute.py0000664000175000017500000000421513535474530025165 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.compute.drivers.auroracompute import AuroraComputeNodeDriver from libcloud.compute.drivers.auroracompute import AuroraComputeRegion from libcloud.test.compute.test_cloudstack import CloudStackCommonTestCase from libcloud.test import unittest class AuroraComputeNodeDriverTestCase(CloudStackCommonTestCase, unittest.TestCase): driver_klass = AuroraComputeNodeDriver def test_api_host(self): driver = self.driver_klass('invalid', 'invalid') self.assertEqual(driver.host, 'api.auroracompute.eu') def test_without_region(self): driver = self.driver_klass('invalid', 'invalid') self.assertEqual(driver.path, '/ams') def test_with_ams_region(self): driver = self.driver_klass('invalid', 'invalid', region=AuroraComputeRegion.AMS) self.assertEqual(driver.path, '/ams') def test_with_miami_region(self): driver = self.driver_klass('invalid', 'invalid', region=AuroraComputeRegion.MIA) self.assertEqual(driver.path, '/mia') def test_with_tokyo_region(self): driver = self.driver_klass('invalid', 'invalid', region=AuroraComputeRegion.TYO) self.assertEqual(driver.path, '/tyo') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_azure.py0000664000175000017500000005330513535474530023431 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.import libcloud import os import sys import libcloud.security from libcloud.common.types import LibcloudError from libcloud.compute.base import NodeAuthPassword, NodeImage, NodeSize from libcloud.test import unittest from libcloud.test import LibcloudTestCase from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.utils.py3 import httplib from libcloud.compute.base import Node, NodeState from libcloud.compute.types import Provider from libcloud.compute.providers import get_driver class AzureNodeDriverTests(LibcloudTestCase): # required otherwise we get client side SSL verification libcloud.security.VERIFY_SSL_CERT = False SUBSCRIPTION_ID = '3761b98b-673d-526c-8d55-fee918758e6e' KEY_FILE = os.path.join(os.path.dirname(__file__), 'fixtures/azure/libcloud.pem') # empty file is fine def setUp(self): Azure = get_driver(Provider.AZURE) Azure.connectionCls.conn_class = AzureMockHttp self.driver = Azure(self.SUBSCRIPTION_ID, self.KEY_FILE) def test_locations_returned_successfully(self): locations = self.driver.list_locations() self.assertEqual(len(locations), 7) location_names_result = list(a.name for a in locations) location_names_expected = [ 'East Asia', 'Southeast Asia', 'North Europe', 'West Europe', 'East US', 'North Central US', 'West US' ] self.assertListEqual(location_names_result, location_names_expected) matched_location = next( location for location in locations if location.name == 'Southeast Asia' ) services_result = matched_location.available_services services_expected = [ 'Compute', 'Storage', 'PersistentVMRole', 'HighMemory' ] self.assertListEqual(services_result, services_expected) vm_role_sizes_result = matched_location.virtual_machine_role_sizes vm_role_sizes_expected = [ 'A5', 'A6', 'A7', 'Basic_A0', 'Basic_A1', 'Basic_A2', 'Basic_A3', 'Basic_A4', 'ExtraLarge', 'ExtraSmall', 'Large', 'Medium', 'Small' ] self.assertListEqual(vm_role_sizes_result, vm_role_sizes_expected) def test_images_returned_successfully(self): images = self.driver.list_images() # There should be 215 standard OSImages and one VMImage returned self.assertEqual(len(images), 216) def test_images_returned_successfully_filter_by_location(self): images = self.driver.list_images(location="West US") self.assertEqual(len(images), 207) def test_list_nodes_returned_successfully(self): vmimages = self.driver.list_nodes( ex_cloud_service_name="dcoddkinztest01" ) self.assertEqual(len(vmimages), 2) img0 = vmimages[0] self.assertEqual(img0.id, "dc03") self.assertEqual(img0.name, "dc03") self.assertListEqual(img0.public_ips, ["191.235.135.62"]) self.assertListEqual(img0.private_ips, ["100.92.66.69"]) self.assertIsNone(img0.size) self.assertEqual(img0.state, NodeState.RUNNING) self.assertTrue(isinstance(img0.extra, dict)) extra = img0.extra self.assertEqual(extra["instance_size"], 'Small') self.assertEqual(extra["power_state"], 'Started') self.assertEqual(extra["ssh_port"], '22') def test_list_nodes_returned_no_deployments(self): nodes = self.driver.list_nodes( ex_cloud_service_name="dcoddkinztest03" ) self.assertEqual(nodes, []) def test_list_nodes_returned_no_cloud_service(self): with self.assertRaises(LibcloudError): self.driver.list_nodes(ex_cloud_service_name="dcoddkinztest04") def test_restart_node_success(self): node = Node( id="dc03", name="dc03", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) result = self.driver.reboot_node( node=node, ex_cloud_service_name="dcoddkinztest01", ex_deployment_slot="Production" ) self.assertTrue(result) # simulating attempting to reboot a node that is already rebooting def test_restart_node_fail_no_deployment(self): node = Node( id="dc03", name="dc03", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) with self.assertRaises(LibcloudError): self.driver.reboot_node( node=node, ex_cloud_service_name="dcoddkinztest02", ex_deployment_slot="Production" ) def test_restart_node_fail_no_cloud_service(self): node = Node( id="dc03", name="dc03", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) with self.assertRaises(LibcloudError): self.driver.reboot_node( node=node, ex_cloud_service_name="dcoddkinztest03", ex_deployment_slot="Production" ) def test_restart_node_fail_node_not_found(self): node = Node( id="dc13", name="dc13", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) result = self.driver.reboot_node( node=node, ex_cloud_service_name="dcoddkinztest01", ex_deployment_slot="Production" ) self.assertFalse(result) def test_destroy_node_success_single_node_in_cloud_service(self): node = Node( id="oddkinz1", name="oddkinz1", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) result = self.driver.destroy_node( node=node, ex_cloud_service_name="oddkinz1", ex_deployment_slot="Production" ) self.assertTrue(result) def test_destroy_node_success_multiple_nodes_in_cloud_service(self): node = Node( id="oddkinz1", name="oddkinz1", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) result = self.driver.destroy_node( node=node, ex_cloud_service_name="oddkinz2", ex_deployment_slot="Production" ) self.assertTrue(result) def test_destroy_node_fail_node_does_not_exist(self): node = Node( id="oddkinz2", name="oddkinz2", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) with self.assertRaises(LibcloudError): self.driver.destroy_node( node=node, ex_cloud_service_name="oddkinz2", ex_deployment_slot="Production" ) def test_destroy_node_success_cloud_service_not_found(self): node = Node( id="cloudredis", name="cloudredis", state=NodeState.RUNNING, public_ips=[], private_ips=[], driver=self.driver ) with self.assertRaises(LibcloudError): self.driver.destroy_node( node=node, ex_cloud_service_name="oddkinz5", ex_deployment_slot="Production" ) def test_ex_create_cloud_service(self): result = self.driver.ex_create_cloud_service(name="testdc123", location="North Europe") self.assertTrue(result) def test_ex_create_cloud_service_service_exists(self): with self.assertRaises(LibcloudError): self.driver.ex_create_cloud_service( name="testdc1234", location="North Europe" ) def test_ex_destroy_cloud_service(self): result = self.driver.ex_destroy_cloud_service(name="testdc123") self.assertTrue(result) def test_ex_destroy_cloud_service_service_does_not_exist(self): with self.assertRaises(LibcloudError): self.driver.ex_destroy_cloud_service(name="testdc1234") def test_ex_create_storage_service(self): result = self.driver.ex_create_storage_service(name="testdss123", location="East US") self.assertTrue(result) def test_ex_create_storage_service_service_exists(self): with self.assertRaises(LibcloudError): self.driver.ex_create_storage_service( name="dss123", location="East US" ) def test_ex_destroy_storage_service(self): result = self.driver.ex_destroy_storage_service(name="testdss123") self.assertTrue(result) def test_ex_destroy_storage_service_service_does_not_exist(self): with self.assertRaises(LibcloudError): self.driver.ex_destroy_storage_service(name="dss123") def test_create_node_and_deployment_one_node(self): kwargs = { "ex_storage_service_name": "mtlytics", "ex_deployment_name": "dcoddkinztest02", "ex_deployment_slot": "Production", "ex_admin_user_id": "azurecoder" } auth = NodeAuthPassword("Pa55w0rd", False) kwargs["auth"] = auth kwargs["name"] = "dcoddkinztest03" kwargs["size"] = NodeSize( id="ExtraSmall", name="ExtraSmall", ram=1024, disk="30gb", bandwidth=0, price=0, driver=self.driver ) kwargs["image"] = NodeImage( id="5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415", name="FakeImage", driver=self.driver, extra={ 'vm_image': False } ) result = self.driver.create_node( ex_cloud_service_name="testdcabc", **kwargs ) self.assertIsNotNone(result) def test_create_node_and_deployment_second_node(self): kwargs = { "ex_storage_service_name": "mtlytics", "ex_deployment_name": "dcoddkinztest02", "ex_deployment_slot": "Production", "ex_admin_user_id": "azurecoder" } auth = NodeAuthPassword("Pa55w0rd", False) kwargs["auth"] = auth kwargs["size"] = NodeSize( id="ExtraSmall", name="ExtraSmall", ram=1024, disk="30gb", bandwidth=0, price=0, driver=self.driver ) kwargs["image"] = NodeImage( id="5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-65-20140415", name="FakeImage", driver=self.driver, extra={ 'vm_image': False } ) kwargs["name"] = "dcoddkinztest03" result = self.driver.create_node( ex_cloud_service_name="testdcabc2", **kwargs ) self.assertIsNotNone(result) class AzureMockHttp(MockHttp): fixtures = ComputeFileFixtures('azure') def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz1_deploymentslots_Production(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz1_deploymentslots_Production.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz1_deployments_dc01(self, method, url, body, headers): return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz2_deploymentslots_Production(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz2_deploymentslots_Production.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz2_deployments_dc03_roles_oddkinz1(self, method, url, body, headers): return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz2_deployments_dc03_roles_oddkinz2(self, method, url, body, headers): return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz5_deploymentslots_Production(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz5_deploymentslots_Production.xml') return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deploymentslots_Production(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deploymentslots_Production.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deployments_dc03_roleinstances_dc03(self, method, url, body, headers): headers["x-ms-request-id"] = "acc33f6756cda6fd96826394fce4c9f3" return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest02_deploymentslots_Production(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest02_deploymentslots_Production.xml') return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03_deploymentslots_Production(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03_deploymentslots_Production.xml') return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deployments_dc03_roleinstances_dc13(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01_deployments_dc03_roleinstances_dc13.xml') return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest01.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest03.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest04(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_dcoddkinztest04.xml') return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_images(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_images.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_vmimages(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_vmimages.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_locations(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_locations.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices(self, method, url, body, headers): # request url is the same irrespective of serviceName, only way to differentiate if "testdc123" in body: return (httplib.CREATED, body, headers, httplib.responses[httplib.CREATED]) elif "testdc1234" in body: return (httplib.CONFLICT, body, headers, httplib.responses[httplib.CONFLICT]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdc123(self, method, url, body, headers): return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_storageservices(self, method, url, body, headers): # request url is the same irrespective of serviceName, only way to differentiate if "testdss123" in body: return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) elif "dss123" in body: return (httplib.CONFLICT, body, headers, httplib.responses[httplib.CONFLICT]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_storageservices_testdss123(self, method, url, body, headers): return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_storageservices_dss123(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_storageservices_dss123.xml') return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdc1234(self, method, url, body, headers): return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc_deployments(self, method, url, body, headers): headers["x-ms-request-id"] = "acc33f6756cda6fd96826394fce4c9f3" return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deploymentslots_Production(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deploymentslots_Production.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deployments_dcoddkinztest02_roles(self, method, url, body, headers): headers["x-ms-request-id"] = "acc33f6756cda6fd96826394fce4c9f3" return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _3761b98b_673d_526c_8d55_fee918758e6e_operations_acc33f6756cda6fd96826394fce4c9f3(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_3761b98b_673d_526c_8d55_fee918758e6e_operations_acc33f6756cda6fd96826394fce4c9f3.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_azure_arm.py0000664000175000017500000007074313576514553024302 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.import libcloud import json import sys import functools from datetime import datetime import mock from libcloud.common.exceptions import BaseHTTPError from libcloud.common.types import LibcloudError from libcloud.compute.base import (NodeLocation, NodeSize, VolumeSnapshot, StorageVolume) from libcloud.compute.drivers.azure_arm import AzureImage, NodeAuthPassword from libcloud.compute.providers import get_driver from libcloud.compute.types import (NodeState, Provider, StorageVolumeState, VolumeSnapshotState) from libcloud.test import LibcloudTestCase, MockHttp from libcloud.test import unittest from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.utils.iso8601 import UTC from libcloud.utils.py3 import httplib class AzureNodeDriverTests(LibcloudTestCase): TENANT_ID = '77777777-7777-7777-7777-777777777777' SUBSCRIPTION_ID = '99999999' APPLICATION_ID = '55555555-5555-5555-5555-555555555555' APPLICATION_PASS = 'p4ssw0rd' def setUp(self): Azure = get_driver(Provider.AZURE_ARM) Azure.connectionCls.conn_class = AzureMockHttp self.driver = Azure(self.TENANT_ID, self.SUBSCRIPTION_ID, self.APPLICATION_ID, self.APPLICATION_PASS) def tearDown(self): AzureMockHttp.responses = [] def test_get_image(self): # Default storage suffix image = self.driver.get_image(image_id='http://www.example.com/foo/image_name') self.assertEqual(image.id, 'https://www.blob.core.windows.net/foo/image_name') self.assertEqual(image.name, 'image_name') # Custom storage suffix self.driver.connection.storage_suffix = '.core.chinacloudapi.cn' image = self.driver.get_image(image_id='http://www.example.com/foo/image_name') self.assertEqual(image.id, 'https://www.blob.core.chinacloudapi.cn/foo/image_name') self.assertEqual(image.name, 'image_name') def test_locations_returned_successfully(self): locations = self.driver.list_locations() self.assertEqual([l.name for l in locations], ["East US", "East US 2", "West US", "Central US", "South Central US", "North Europe", "West Europe", "East Asia", "Southeast Asia", "Japan East", "Japan West"]) def test_sizes_returned_successfully(self): location = self.driver.list_locations()[0] sizes = self.driver.list_sizes(location=location) self.assertEqual([l.name for l in sizes], ["Standard_A0", "Standard_A1", "Standard_A2"]) def test_ex_get_ratecard(self): ratecard = self.driver.ex_get_ratecard('0026P') self.assertEqual(set(ratecard.keys()), {'Currency', 'Locale', 'IsTaxIncluded', 'OfferTerms', 'Meters'}) def test_create_node(self): location = NodeLocation('any_location', '', '', self.driver) size = NodeSize('any_size', '', 0, 0, 0, 0, driver=self.driver) image = AzureImage('1', '1', 'ubuntu', 'pub', location.id, self.driver) auth = NodeAuthPassword('any_password') node = self.driver.create_node( 'test-node-1', size, image, auth, location=location, ex_resource_group='000000', ex_storage_account='000000', ex_user_name='any_user', ex_network='000000', ex_subnet='000000', ex_use_managed_disks=True ) hardware_profile = node.extra['properties']['hardwareProfile'] os_profile = node.extra['properties']['osProfile'] storage_profile = node.extra['properties']['storageProfile'] self.assertEqual(node.name, 'test-node-1') self.assertEqual(node.state, NodeState.UPDATING) self.assertEqual(node.private_ips, ['10.0.0.1']) self.assertEqual(node.public_ips, []) self.assertEqual(node.extra['location'], location.id) self.assertEqual(hardware_profile['vmSize'], size.id) self.assertEqual(os_profile['adminUsername'], 'any_user') self.assertEqual(os_profile['adminPassword'], 'any_password') self.assertTrue('managedDisk' in storage_profile['osDisk']) self.assertTrue('diskSizeGB' not in storage_profile['osDisk']) self.assertTrue(storage_profile['imageReference'], { 'publisher': image.publisher, 'offer': image.offer, 'sku': image.sku, 'version': image.version }) def test_create_node_ex_disk_size(self): location = NodeLocation('any_location', '', '', self.driver) size = NodeSize('any_size', '', 0, 0, 0, 0, driver=self.driver) image = AzureImage('1', '1', 'ubuntu', 'pub', location.id, self.driver) auth = NodeAuthPassword('any_password') node = self.driver.create_node( 'test-node-1', size, image, auth, location=location, ex_resource_group='000000', ex_storage_account='000000', ex_user_name='any_user', ex_network='000000', ex_subnet='000000', ex_disk_size=100, ex_use_managed_disks=True ) hardware_profile = node.extra['properties']['hardwareProfile'] os_profile = node.extra['properties']['osProfile'] storage_profile = node.extra['properties']['storageProfile'] self.assertEqual(node.name, 'test-node-1') self.assertEqual(node.state, NodeState.UPDATING) self.assertEqual(node.private_ips, ['10.0.0.1']) self.assertEqual(node.public_ips, []) self.assertEqual(node.extra['location'], location.id) self.assertEqual(hardware_profile['vmSize'], size.id) self.assertEqual(os_profile['adminUsername'], 'any_user') self.assertEqual(os_profile['adminPassword'], 'any_password') self.assertTrue('managedDisk' in storage_profile['osDisk']) self.assertEqual(storage_profile['osDisk']['diskSizeGB'], 100) self.assertTrue(storage_profile['imageReference'], { 'publisher': image.publisher, 'offer': image.offer, 'sku': image.sku, 'version': image.version }) @mock.patch('time.sleep', return_value=None) def test_destroy_node(self, time_sleep_mock): def error(e, **kwargs): raise e(**kwargs) node = self.driver.list_nodes()[0] AzureMockHttp.responses = [ # OK to the DELETE request lambda f: (httplib.OK, None, {}, 'OK'), # 404 means node is gone lambda f: error(BaseHTTPError, code=404, message='Not found'), ] ret = self.driver.destroy_node(node) self.assertTrue(ret) def test_destroy_node__node_not_found(self): """ This simulates the case when destroy_node is being called for the 2nd time because some related resource failed to clean up, so the DELETE operation on the node will return 204 (because it was already deleted) but the method should return success. """ def error(e, **kwargs): raise e(**kwargs) node = self.driver.list_nodes()[0] AzureMockHttp.responses = [ # 204 (No content) to the DELETE request on a deleted/non-existent node lambda f: error(BaseHTTPError, code=204, message='No content'), ] ret = self.driver.destroy_node(node) self.assertTrue(ret) @mock.patch('time.sleep', return_value=None) def test_destroy_node__retry(self, time_sleep_mock): def error(e, **kwargs): raise e(**kwargs) node = self.driver.list_nodes()[0] AzureMockHttp.responses = [ # 202 - The delete will happen asynchronously lambda f: error(BaseHTTPError, code=202, message='Deleting'), # 200 means the node is still here - Try 1 lambda f: (httplib.OK, None, {}, 'OK'), # 200 means the node is still here - Try 2 lambda f: (httplib.OK, None, {}, 'OK'), # 200 means the node is still here - Try 3 lambda f: (httplib.OK, None, {}, 'OK'), # 404 means node is gone - 4th retry: success! lambda f: error(BaseHTTPError, code=404, message='Not found'), ] ret = self.driver.destroy_node(node) self.assertTrue(ret) self.assertEqual(4, time_sleep_mock.call_count) # Retries @mock.patch('time.sleep', return_value=None) def test_destroy_node__destroy_nic_retries(self, time_sleep_mock): def error(e, **kwargs): raise e(**kwargs) node = self.driver.list_nodes()[0] err = BaseHTTPError(code=400, message='[NicInUse] Cannot destroy') with mock.patch.object(self.driver, 'ex_destroy_nic') as m: m.side_effect = [err] * 5 + [True] # 5 errors before a success ret = self.driver.destroy_node(node) self.assertTrue(ret) self.assertEqual(6, m.call_count) # 6th call was a success m.side_effect = [err] * 10 + [True] # 10 errors before a success with self.assertRaises(BaseHTTPError): self.driver.destroy_node(node) self.assertEqual(10, m.call_count) # try 10 times & fail @mock.patch('time.sleep', return_value=None) def test_destroy_node__async(self, time_sleep_mock): def error(e, **kwargs): raise e(**kwargs) node = self.driver.list_nodes()[0] AzureMockHttp.responses = [ # 202 - The delete will happen asynchronously lambda f: error(BaseHTTPError, code=202, message='Deleting'), # 404 means node is gone lambda f: error(BaseHTTPError, code=404, message='Not found'), ] ret = self.driver.destroy_node(node) self.assertTrue(ret) @mock.patch('time.sleep', return_value=None) def test_destroy_node__nic_not_cleaned_up(self, time_sleep_mock): def error(e, **kwargs): raise e(**kwargs) node = self.driver.list_nodes()[0] AzureMockHttp.responses = [ # OK to the DELETE request lambda f: (httplib.OK, None, {}, 'OK'), # 404 means node is gone lambda f: error(BaseHTTPError, code=404, message='Not found'), # 500 - transient error when trying to clean up the NIC lambda f: error(BaseHTTPError, code=500, message="Cloud weather"), ] with self.assertRaises(BaseHTTPError): self.driver.destroy_node(node) def test_destroy_node__failed(self): def error(e, **kwargs): raise e(**kwargs) node = self.driver.list_nodes()[0] AzureMockHttp.responses = [ # 403 - There was some problem with your request lambda f: error(BaseHTTPError, code=403, message='Forbidden'), ] with self.assertRaises(BaseHTTPError): self.driver.destroy_node(node) @mock.patch('libcloud.compute.drivers.azure_arm.AzureNodeDriver' '._fetch_power_state', return_value=NodeState.UPDATING) def test_list_nodes(self, fps_mock): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].name, 'test-node-1') self.assertEqual(nodes[0].state, NodeState.UPDATING) self.assertEqual(nodes[0].private_ips, ['10.0.0.1']) self.assertEqual(nodes[0].public_ips, []) fps_mock.assert_called() @mock.patch('libcloud.compute.drivers.azure_arm.AzureNodeDriver' '._fetch_power_state', return_value=NodeState.UPDATING) def test_list_nodes__no_fetch_power_state(self, fps_mock): nodes = self.driver.list_nodes(ex_fetch_power_state=False) self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].name, 'test-node-1') self.assertNotEqual(nodes[0].state, NodeState.UPDATING) self.assertEqual(nodes[0].private_ips, ['10.0.0.1']) self.assertEqual(nodes[0].public_ips, []) fps_mock.assert_not_called() def test_create_volume(self): location = self.driver.list_locations()[-1] volume = self.driver.create_volume( 2, 'test-disk-1', location, ex_resource_group='000000', ex_tags={'description': 'MyVolume'} ) self.assertEqual(volume.size, 2) self.assertEqual(volume.name, 'test-disk-1') self.assertEqual(volume.extra['name'], 'test-disk-1') self.assertEqual(volume.extra['tags'], {'description': 'MyVolume'}) self.assertEqual(volume.extra['location'], location.id) self.assertEqual( volume.extra['properties']['creationData']['createOption'], 'Empty') self.assertEqual( volume.extra['properties']['provisioningState'], 'Succeeded') self.assertEqual( volume.extra['properties']['diskState'], 'Attached') self.assertEqual(volume.state, StorageVolumeState.INUSE) def test_create_volume__with_snapshot(self): location = self.driver.list_locations()[0] snap_id = ( '/subscriptions/99999999-9999-9999-9999-999999999999' '/resourceGroups/000000/providers/Microsoft.Compute' '/snapshots/test-snap-1' ) snapshot = VolumeSnapshot(id=snap_id, size=2, driver=self.driver) volume = self.driver.create_volume( 2, 'test-disk-1', location, snapshot=snapshot, ex_resource_group='000000', ex_tags={'description': 'MyVolume'} ) self.assertEqual( volume.extra['properties']['creationData']['createOption'], 'Copy') self.assertEqual( volume.extra['properties']['creationData']['sourceUri'], snap_id) def test_create_volume__required_kw(self): location = self.driver.list_locations()[0] fn = functools.partial(self.driver.create_volume, 2, 'test-disk-1') self.assertRaises(ValueError, fn) self.assertRaises(ValueError, fn, location=location) self.assertRaises(ValueError, fn, ex_resource_group='000000') ret_value = fn(ex_resource_group='000000', location=location) self.assertTrue(isinstance(ret_value, StorageVolume)) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 3) self.assertEqual(volumes[0].name, 'test-disk-1') self.assertEqual(volumes[0].size, 31) self.assertEqual( volumes[0].extra['properties']['provisioningState'], 'Succeeded') self.assertEqual( volumes[0].extra['properties']['diskState'], 'Attached') self.assertEqual(volumes[0].state, StorageVolumeState.INUSE) self.assertEqual(volumes[1].name, 'test-disk-2') self.assertEqual(volumes[1].size, 31) self.assertEqual( volumes[1].extra['properties']['provisioningState'], 'Updating') self.assertEqual( volumes[1].extra['properties']['diskState'], 'Unattached') self.assertEqual(volumes[1].state, StorageVolumeState.UPDATING) self.assertEqual(volumes[2].name, 'test-disk-3') self.assertEqual(volumes[2].size, 10) self.assertEqual( volumes[2].extra['properties']['provisioningState'], 'Succeeded') self.assertEqual( volumes[2].extra['properties']['diskState'], 'Unattached') self.assertEqual(StorageVolumeState.AVAILABLE, volumes[2].state) def test_list_volumes__with_resource_group(self): volumes = self.driver.list_volumes(ex_resource_group='111111') self.assertEqual(len(volumes), 1) self.assertEqual(volumes[0].name, 'test-disk-3') self.assertEqual(volumes[0].size, 10) self.assertEqual( volumes[0].extra['properties']['provisioningState'], 'Succeeded') self.assertEqual( volumes[0].extra['properties']['diskState'], 'Unattached') self.assertEqual(volumes[0].state, StorageVolumeState.AVAILABLE) def test_attach_volume(self): volumes = self.driver.list_volumes() node = self.driver.list_nodes()[0] self.driver.attach_volume(node, volumes[0], ex_lun=0) self.driver.attach_volume(node, volumes[1], ex_lun=15) self.driver.attach_volume(node, volumes[2]) data_disks = node.extra['properties']['storageProfile']['dataDisks'] luns = [disk['lun'] for disk in data_disks] self.assertTrue(len(data_disks), len(volumes)) self.assertTrue(set(luns), {0, 1, 15}) volumes = self.driver.list_volumes() node = self.driver.list_nodes()[0] for count in range(64): self.driver.attach_volume(node, volumes[0]) data_disks = node.extra['properties']['storageProfile']['dataDisks'] luns = [disk['lun'] for disk in data_disks] self.assertTrue(len(data_disks), 64) self.assertTrue(set(luns), set(range(64))) def test_resize_volume(self): volume = self.driver.list_volumes()[0] original_size = volume.size volume = self.driver.ex_resize_volume( volume, volume.size + 8, '000000' ) new_size = volume.size self.assertEqual(new_size, original_size + 8) def test_detach_volume(self): volumes = self.driver.list_volumes() node = self.driver.list_nodes()[0] for volume in volumes: self.driver.attach_volume(node, volume) data_disks = node.extra['properties']['storageProfile']['dataDisks'] self.assertEqual(len(data_disks), len(volumes)) for volume in volumes: self.driver.detach_volume(volume, ex_node=node) data_disks = node.extra['properties']['storageProfile']['dataDisks'] self.assertEqual(len(data_disks), 0) def test_destroy_volume(self): volume = self.driver.list_volumes()[0] ret_value = self.driver.destroy_volume(volume) self.assertTrue(ret_value) def test_create_volume_snapshot(self): location = self.driver.list_locations()[-1] volume = self.driver.list_volumes()[0] snap = self.driver.create_volume_snapshot( volume, 'test-snap-1', location=location, ex_resource_group='000000' ) self.assertEqual(snap.name, 'test-snap-1') self.assertEqual(snap.extra['name'], 'test-snap-1') self.assertEqual(snap.size, 1) self.assertEqual(snap.extra['source_id'], volume.id) self.assertEqual(snap.state, VolumeSnapshotState.CREATING) self.assertEqual(snap.extra['location'], location.id) self.assertEqual( snap.extra['properties']['provisioningState'], 'Creating') self.assertEqual( snap.extra['properties']['diskState'], 'Unattached') # 2017-03-09T14:28:27.8655868+00:00" self.assertEqual( datetime(2017, 3, 9, 14, 28, 27, 865586, tzinfo=UTC), snap.created) def test_create_volume_snapshot__required_kw(self): location = self.driver.list_locations()[0] volume = self.driver.list_volumes()[0] fn = functools.partial(self.driver.create_volume_snapshot, volume) self.assertRaises(ValueError, fn) self.assertRaises(ValueError, fn, name='test-snap-1') self.assertRaises(ValueError, fn, location=location) self.assertRaises(ValueError, fn, ex_resource_group='000000') ret_value = fn( name='test-snap-1', ex_resource_group='000000', location=location ) self.assertTrue(isinstance(ret_value, VolumeSnapshot)) def test_list_snapshots(self): snaps = self.driver.list_snapshots() self.assertEqual(len(snaps), 4) self.assertEqual(snaps[0].name, 'test-snap-1') self.assertEqual(snaps[0].extra['name'], 'test-snap-1') self.assertEqual(snaps[0].state, VolumeSnapshotState.CREATING) self.assertEqual( snaps[0].extra['source_id'], '/subscriptions/99999999-9999-9999-9999-999999999999' '/resourceGroups/000000/providers/Microsoft.Compute' '/disks/test-disk-1') self.assertEqual(snaps[0].size, 1) self.assertEqual(snaps[0].extra['tags']['test_snap'], 'test') self.assertTrue(isinstance(snaps[3].created, datetime)) self.assertEqual(snaps[3].name, 'test-snap-4') self.assertEqual(snaps[3].extra['name'], 'test-snap-4') self.assertEqual(snaps[3].state, VolumeSnapshotState.ERROR) self.assertEqual( snaps[3].extra['source_id'], '/subscriptions/99999999-9999-9999-9999-999999999999' '/resourceGroups/111111/providers/Microsoft.Compute' '/disks/test-disk-4') self.assertEqual(snaps[3].size, 2) self.assertTrue(isinstance(snaps[3].created, datetime)) def test_list_snapshots_in_resource_group(self): snaps = self.driver.list_snapshots(ex_resource_group='111111') self.assertEqual(len(snaps), 2) self.assertEqual(snaps[0].name, 'test-snap-3') self.assertEqual(snaps[0].extra['name'], 'test-snap-3') self.assertEqual(snaps[0].state, VolumeSnapshotState.ERROR) self.assertEqual( snaps[0].extra['source_id'], '/subscriptions/99999999-9999-9999-9999-999999999999' '/resourceGroups/111111/providers/Microsoft.Compute' '/disks/test-disk-3') self.assertEqual(snaps[0].size, 2) self.assertTrue(isinstance(snaps[0].created, datetime)) def test_list_volume_snapshots(self): volume = self.driver.list_volumes()[0] self.assertTrue(volume.name == 'test-disk-1') snapshots = self.driver.list_volume_snapshots(volume) self.assertEqual(len(snapshots), 1) self.assertEqual(snapshots[0].name, 'test-snap-1') self.assertEqual(volume.id, snapshots[0].extra['source_id']) def test_destroy_volume_snapshot(self): snapshot = self.driver.list_snapshots()[0] res_value = snapshot.destroy() self.assertTrue(res_value) def test_delete_public_ip(self): location = self.driver.list_locations()[0] public_ip = self.driver.ex_create_public_ip(name='test_public_ip', resource_group='REVIZOR', location=location) res_value = self.driver.ex_delete_public_ip(public_ip) self.assertTrue(res_value) def test_update_network_profile(self): nics = self.driver.ex_list_nics() node = self.driver.list_nodes()[0] network_profile = node.extra['properties']['networkProfile'] primary_nic_exists = False num_nics_before = len(network_profile["networkInterfaces"]) for nic in network_profile["networkInterfaces"]: if "properties" in nic and nic["properties"]["primary"]: primary_nic_exists = True if not primary_nic_exists: network_profile["networkInterfaces"][0]["properties"] = { "primary": True} network_profile["networkInterfaces"].append({"id": nics[0].id}) self.driver.ex_update_network_profile_of_node( node, network_profile) network_profile = node.extra['properties']['networkProfile'] num_nics_after = len(network_profile["networkInterfaces"]) self.assertEqual(num_nics_after, num_nics_before + 1) def test_update_nic_properties(self): nics = self.driver.ex_list_nics() nic_to_update = nics[0] nic_properties = nic_to_update.extra ip_configs = nic_properties['ipConfigurations'] ip_configs[0]['properties']['primary'] = True updated_nic = self.driver.ex_update_nic_properties( nic_to_update, resource_group='REVIZOR', properties=nic_properties) self.assertTrue( updated_nic.extra['ipConfigurations'][0]['properties']['primary']) def test_check_ip_address_availability(self): networks = self.driver.ex_list_networks() result = self.driver.ex_check_ip_address_availability( 'REVIZOR', networks[0], '0.0.0.0') self.assertFalse(result['available']) def test_get_instance_vhd(self): with mock.patch.object(self.driver, '_ex_delete_old_vhd'): # Default storage suffix vhd_url = self.driver._get_instance_vhd(name='test1', ex_resource_group='000000', ex_storage_account='sga1') self.assertEqual(vhd_url, 'https://sga1.blob.core.windows.net/vhds/test1-os_0.vhd') # Custom storage suffix self.driver.connection.storage_suffix = '.core.chinacloudapi.cn' vhd_url = self.driver._get_instance_vhd(name='test1', ex_resource_group='000000', ex_storage_account='sga1') self.assertEqual(vhd_url, 'https://sga1.blob.core.chinacloudapi.cn/vhds/test1-os_0.vhd') def test_get_instance_vhd__retries_ten_times(self): with mock.patch.object(self.driver, '_ex_delete_old_vhd') as m: # 10 retries are OK m.side_effect = [False] * 9 + [True] vhd_url = self.driver._get_instance_vhd(name='test1', ex_resource_group='000000', ex_storage_account='sga1') self.assertEqual(vhd_url, 'https://sga1.blob.core.windows.net/vhds/test1-os_9.vhd') # Fail on the 11th m.side_effect = [False] * 10 + [True] with self.assertRaises(LibcloudError): self.driver._get_instance_vhd(name='test1', ex_resource_group='000000', ex_storage_account='sga1') class AzureMockHttp(MockHttp): fixtures = ComputeFileFixtures('azure_arm') # List of callables to be run in order as responses. Fixture # passed as argument. responses = [] def _update(self, fixture, body): for key, value in body.items(): if isinstance(value, dict): fixture[key] = self._update(fixture.get(key, {}), value) else: fixture[key] = body[key] return fixture def __getattr__(self, n): def fn(method, url, body, headers): # Note: We use shorter fixture name so we don't exceed 143 # character limit for file names file_name = n.replace('99999999_9999_9999_9999_999999999999', AzureNodeDriverTests.SUBSCRIPTION_ID) fixture = self.fixtures.load(file_name + ".json") if method in ('POST', 'PUT'): try: body = json.loads(body) fixture_tmp = json.loads(fixture) fixture_tmp = self._update(fixture_tmp, body) fixture = json.dumps(fixture_tmp) except ValueError: pass if (not n.endswith('_oauth2_token')) and len(self.responses) > 0: f = self.responses.pop(0) return f(fixture) else: return (httplib.OK, fixture, headers, httplib.responses[httplib.OK]) return fn if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_base.py0000664000175000017500000000775113535474530023221 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.common.base import Connection, ConnectionKey, ConnectionUserAndKey from libcloud.common.types import LibcloudError from libcloud.compute.base import Node, NodeSize, NodeImage, NodeDriver, StorageVolume from libcloud.compute.base import NodeAuthSSHKey, NodeAuthPassword from libcloud.compute.types import StorageVolumeState class FakeDriver(object): type = 0 class BaseTests(unittest.TestCase): def test_base_node(self): Node(id=0, name=0, state=0, public_ips=0, private_ips=0, driver=FakeDriver()) def test_base_node_size(self): NodeSize(id=0, name=0, ram=0, disk=0, bandwidth=0, price=0, driver=FakeDriver()) def test_base_node_image(self): NodeImage(id=0, name=0, driver=FakeDriver()) def test_base_storage_volume(self): StorageVolume(id="0", name="0", size=10, driver=FakeDriver(), state=StorageVolumeState.AVAILABLE) def test_base_node_driver(self): NodeDriver('foo') def test_base_connection_key(self): ConnectionKey('foo') def test_base_connection_userkey(self): ConnectionUserAndKey('foo', 'bar') def test_base_connection_timeout(self): Connection(timeout=10) class TestValidateAuth(unittest.TestCase): def test_get_auth_ssh(self): n = NodeDriver('foo') n.features = {'create_node': ['ssh_key']} auth = NodeAuthSSHKey('pubkey...') self.assertEqual(auth, n._get_and_check_auth(auth)) def test_get_auth_ssh_but_given_password(self): n = NodeDriver('foo') n.features = {'create_node': ['ssh_key']} auth = NodeAuthPassword('password') self.assertRaises(LibcloudError, n._get_and_check_auth, auth) def test_get_auth_password(self): n = NodeDriver('foo') n.features = {'create_node': ['password']} auth = NodeAuthPassword('password') self.assertEqual(auth, n._get_and_check_auth(auth)) def test_get_auth_password_but_given_ssh_key(self): n = NodeDriver('foo') n.features = {'create_node': ['password']} auth = NodeAuthSSHKey('publickey') self.assertRaises(LibcloudError, n._get_and_check_auth, auth) def test_get_auth_default_ssh_key(self): n = NodeDriver('foo') n.features = {'create_node': ['ssh_key']} self.assertEqual(None, n._get_and_check_auth(None)) def test_get_auth_default_password(self): n = NodeDriver('foo') n.features = {'create_node': ['password']} auth = n._get_and_check_auth(None) self.assertTrue(isinstance(auth, NodeAuthPassword)) def test_get_auth_default_no_feature(self): n = NodeDriver('foo') self.assertEqual(None, n._get_and_check_auth(None)) def test_get_auth_generates_password_but_given_nonsense(self): n = NodeDriver('foo') n.features = {'create_node': ['generates_password']} auth = "nonsense" self.assertRaises(LibcloudError, n._get_and_check_auth, auth) def test_get_auth_no_features_but_given_nonsense(self): n = NodeDriver('foo') auth = "nonsense" self.assertRaises(LibcloudError, n._get_and_check_auth, auth) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_bluebox.py0000664000175000017500000001106613535474530023741 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.bluebox import BlueboxNodeDriver as Bluebox from libcloud.compute.base import Node, NodeAuthPassword from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import BLUEBOX_PARAMS class BlueboxTest(unittest.TestCase): def setUp(self): Bluebox.connectionCls.conn_class = BlueboxMockHttp self.driver = Bluebox(*BLUEBOX_PARAMS) def test_create_node(self): node = self.driver.create_node( name='foo', size=self.driver.list_sizes()[0], image=self.driver.list_images()[0], auth=NodeAuthPassword("test123") ) self.assertTrue(isinstance(node, Node)) self.assertEqual(node.state, NodeState.PENDING) self.assertEqual(node.name, 'foo.apitest.blueboxgrid.com') def test_list_nodes(self): node = self.driver.list_nodes()[0] self.assertEqual(node.name, 'foo.apitest.blueboxgrid.com') self.assertEqual(node.state, NodeState.RUNNING) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 4) ids = [s.id for s in sizes] for size in sizes: self.assertTrue(size.price > 0) self.assertTrue('94fd37a7-2606-47f7-84d5-9000deda52ae' in ids) self.assertTrue('b412f354-5056-4bf0-a42f-6ddd998aa092' in ids) self.assertTrue('0cd183d3-0287-4b1a-8288-b3ea8302ed58' in ids) self.assertTrue('b9b87a5b-2885-4a2e-b434-44a163ca6251' in ids) def test_list_images(self): images = self.driver.list_images() image = images[0] self.assertEqual(len(images), 10) self.assertEqual(image.name, 'CentOS 5 (Latest Release)') self.assertEqual(image.id, 'c66b8145-f768-45ef-9878-395bf8b1b7ff') def test_reboot_node(self): node = self.driver.list_nodes()[0] ret = self.driver.reboot_node(node) self.assertTrue(ret) def test_destroy_node(self): node = self.driver.list_nodes()[0] ret = self.driver.destroy_node(node) self.assertTrue(ret) class BlueboxMockHttp(MockHttp): fixtures = ComputeFileFixtures('bluebox') def _api_blocks_json(self, method, url, body, headers): if method == "POST": body = self.fixtures.load('api_blocks_json_post.json') else: body = self.fixtures.load('api_blocks_json.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_block_products_json(self, method, url, body, headers): body = self.fixtures.load('api_block_products_json.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_block_templates_json(self, method, url, body, headers): body = self.fixtures.load('api_block_templates_json.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json') else: body = self.fixtures.load( 'api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json(self, method, url, body, headers): body = self.fixtures.load( 'api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_brightbox.py0000664000175000017500000003662413535474530024300 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest import base64 try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.common.types import InvalidCredsError from libcloud.compute.drivers.brightbox import BrightboxNodeDriver from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import BRIGHTBOX_PARAMS USER_DATA = '#!/bin/sh\ntest_script.sh\n' class BrightboxTest(unittest.TestCase, TestCaseMixin): def setUp(self): BrightboxNodeDriver.connectionCls.conn_class = BrightboxMockHttp BrightboxMockHttp.type = None BrightboxNodeDriver.connectionCls.token = 'test' self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS) def test_authentication(self): BrightboxMockHttp.type = 'INVALID_CLIENT' self.assertRaises(InvalidCredsError, self.driver.list_nodes) BrightboxMockHttp.type = 'UNAUTHORIZED_CLIENT' self.assertRaises(InvalidCredsError, self.driver.list_nodes) def test_invalid_api_version(self): kwargs = {'api_version': '2.0'} self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS, **kwargs) self.assertRaises(Exception, self.driver.list_locations) def test_other_host(self): kwargs = {'host': 'api.gbt.brightbox.com'} self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS, **kwargs) locations = self.driver.list_locations() self.assertEqual(len(locations), 0) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) self.assertEqual(len(nodes[0].public_ips), 1) self.assertEqual(len(nodes[1].public_ips), 1) self.assertEqual(len(nodes[0].private_ips), 1) self.assertEqual(len(nodes[1].private_ips), 1) self.assertTrue('109.107.35.16' in nodes[0].public_ips) self.assertTrue('10.74.210.210' in nodes[0].private_ips) self.assertTrue('10.240.228.234' in nodes[1].private_ips) self.assertTrue( '2a02:1348:14c:393a:24:19ff:fef0:e4ea' in nodes[1].public_ips) self.assertEqual(nodes[0].state, NodeState.RUNNING) self.assertEqual(nodes[1].state, NodeState.RUNNING) def test_list_node_extras(self): nodes = self.driver.list_nodes() self.assertFalse(nodes[0].size is None) self.assertFalse(nodes[1].size is None) self.assertFalse(nodes[0].image is None) self.assertFalse(nodes[1].image is None) self.assertEqual(nodes[0].image.id, 'img-arm8f') self.assertEqual(nodes[0].size.id, 'typ-urtky') self.assertEqual(nodes[1].image.id, 'img-j93gd') self.assertEqual(nodes[1].size.id, 'typ-qdiwq') self.assertEqual(nodes[0].extra['fqdn'], 'srv-xvpn7.gb1.brightbox.com') self.assertEqual(nodes[1].extra['fqdn'], 'srv-742vn.gb1.brightbox.com') self.assertEqual(nodes[0].extra['hostname'], 'srv-xvpn7') self.assertEqual(nodes[1].extra['hostname'], 'srv-742vn') self.assertEqual(nodes[0].extra['status'], 'active') self.assertEqual(nodes[1].extra['status'], 'active') self.assertTrue('interfaces' in nodes[0].extra) self.assertTrue('zone' in nodes[0].extra) self.assertTrue('snapshots' in nodes[0].extra) self.assertTrue('server_groups' in nodes[0].extra) self.assertTrue('started_at' in nodes[0].extra) self.assertTrue('created_at' in nodes[0].extra) self.assertFalse('deleted_at' in nodes[0].extra) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 7) self.assertEqual(sizes[0].id, 'typ-4nssg') self.assertEqual(sizes[0].name, 'Brightbox Nano Instance') self.assertEqual(sizes[0].ram, 512) self.assertEqual(sizes[0].disk, 20480) self.assertEqual(sizes[0].bandwidth, 0) self.assertEqual(sizes[0].price, 0) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 3) self.assertEqual(images[0].id, 'img-99q79') self.assertEqual(images[0].name, 'CentOS 5.5 server') self.assertTrue('ancestor' in images[0].extra) self.assertFalse('licence_name' in images[0].extra) def test_list_images_extras(self): images = self.driver.list_images() extra = images[-1].extra self.assertEqual(extra['arch'], 'i686') self.assertFalse(extra['compatibility_mode']) self.assertEqual(extra['created_at'], '2012-01-22T05:36:24Z') self.assertTrue('description' in extra) self.assertEqual(extra['disk_size'], 671) self.assertFalse('min_ram' in extra) self.assertFalse(extra['official']) self.assertEqual(extra['owner'], 'acc-tqs4c') self.assertTrue(extra['public']) self.assertEqual(extra['source'], 'oneiric-i386-20178.gz') self.assertEqual(extra['source_type'], 'upload') self.assertEqual(extra['status'], 'deprecated') self.assertEqual(extra['username'], 'ubuntu') self.assertEqual(extra['virtual_size'], 1025) self.assertFalse('ancestor' in extra) self.assertFalse('licence_name' in extra) def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(locations[0].id, 'zon-6mxqw') self.assertEqual(locations[0].name, 'gb1-a') self.assertEqual(locations[1].id, 'zon-remk1') self.assertEqual(locations[1].name, 'gb1-b') def test_reboot_node_response(self): node = self.driver.list_nodes()[0] self.assertRaises(NotImplementedError, self.driver.reboot_node, [node]) def test_destroy_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.destroy_node(node)) def test_create_node(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node( name='Test Node', image=image, size=size) self.assertEqual('srv-p61uj', node.id) self.assertEqual('Test Node', node.name) self.assertEqual('gb1-a', node.extra['zone'].name) def test_create_node_in_location(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[1] node = self.driver.create_node( name='Test Node', image=image, size=size, location=location) self.assertEqual('srv-nnumd', node.id) self.assertEqual('Test Node', node.name) self.assertEqual('gb1-b', node.extra['zone'].name) def test_create_node_with_user_data(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node( name='Test Node', image=image, size=size, ex_userdata=USER_DATA) decoded = base64.b64decode(b(node.extra['user_data'])).decode('ascii') self.assertEqual('gb1-a', node.extra['zone'].name) self.assertEqual(USER_DATA, decoded) def test_create_node_with_a_server_group(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node( name='Test Node', image=image, size=size, ex_servergroup='grp-12345') self.assertEqual('gb1-a', node.extra['zone'].name) self.assertEqual(len(node.extra['server_groups']), 1) self.assertEqual(node.extra['server_groups'][0]['id'], 'grp-12345') def test_create_node_with_a_list_of_server_groups(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node( name='Test Node', image=image, size=size, ex_servergroup=['grp-12345', 'grp-67890']) self.assertEqual('gb1-a', node.extra['zone'].name) self.assertEqual(len(node.extra['server_groups']), 2) self.assertEqual(node.extra['server_groups'][0]['id'], 'grp-12345') self.assertEqual(node.extra['server_groups'][1]['id'], 'grp-67890') def test_list_cloud_ips(self): cip_list = self.driver.ex_list_cloud_ips() self.assertEqual(len(cip_list), 4) self.assertEqual(cip_list[2]['status'], 'mapped') cip_check = cip_list[0] self.assertEqual(cip_check['id'], 'cip-tlrp3') self.assertEqual(cip_check['public_ip'], '109.107.35.16') self.assertEqual( cip_check['reverse_dns'], 'cip-109-107-35-16.gb1.brightbox.com') self.assertEqual(cip_check['status'], 'unmapped') self.assertTrue(cip_check['server'] is None) self.assertTrue(cip_check['server_group'] is None) self.assertTrue(cip_check['interface'] is None) self.assertTrue(cip_check['load_balancer'] is None) def test_create_cloud_ip(self): cip = self.driver.ex_create_cloud_ip() self.assertEqual(cip['id'], 'cip-jsjc5') self.assertEqual( cip['reverse_dns'], 'cip-109-107-37-234.gb1.brightbox.com') def test_create_cloud_ip_with_dns(self): cip = self.driver.ex_create_cloud_ip('fred.co.uk') self.assertEqual(cip['id'], 'cip-jsjc5') self.assertEqual(cip['reverse_dns'], 'fred.co.uk') def test_map_cloud_ip(self): self.assertTrue(self.driver.ex_map_cloud_ip('cip-jsjc5', 'int-ztqbx')) def test_unmap_cloud_ip(self): self.assertTrue(self.driver.ex_unmap_cloud_ip('cip-jsjc5')) def test_update_cloud_ip(self): self.assertTrue( self.driver.ex_update_cloud_ip('cip-jsjc5', 'fred.co.uk')) def test_destroy_cloud_ip(self): self.assertTrue(self.driver.ex_destroy_cloud_ip('cip-jsjc5')) class BrightboxMockHttp(MockHttp): fixtures = ComputeFileFixtures('brightbox') def _token(self, method, url, body, headers): if method == 'POST': return self.test_response(httplib.OK, self.fixtures.load('token.json')) def _token_INVALID_CLIENT(self, method, url, body, headers): if method == 'POST': return self.test_response(httplib.BAD_REQUEST, '{"error":"invalid_client"}') def _token_UNAUTHORIZED_CLIENT(self, method, url, body, headers): if method == 'POST': return self.test_response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}') def _1_0_servers_INVALID_CLIENT(self, method, url, body, headers): return self.test_response(httplib.BAD_REQUEST, '{"error":"invalid_client"}') def _1_0_servers_UNAUTHORIZED_CLIENT(self, method, url, body, headers): return self.test_response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}') def _1_0_images(self, method, url, body, headers): if method == 'GET': return self.test_response(httplib.OK, self.fixtures.load('list_images.json')) def _1_0_servers(self, method, url, body, headers): if method == 'GET': return self.test_response(httplib.OK, self.fixtures.load('list_servers.json')) elif method == 'POST': body = json.loads(body) encoded = base64.b64encode(b(USER_DATA)).decode('ascii') if 'user_data' in body and body['user_data'] != encoded: data = '{"error_name":"dodgy user data", "errors": ["User data not encoded properly"]}' return self.test_response(httplib.BAD_REQUEST, data) if body.get('zone', '') == 'zon-remk1': node = json.loads( self.fixtures.load('create_server_gb1_b.json')) else: node = json.loads( self.fixtures.load('create_server_gb1_a.json')) node['name'] = body['name'] if 'server_groups' in body: node['server_groups'] = [{'id': x} for x in body['server_groups']] if 'user_data' in body: node['user_data'] = body['user_data'] return self.test_response(httplib.ACCEPTED, json.dumps(node)) def _1_0_servers_srv_xvpn7(self, method, url, body, headers): if method == 'DELETE': return self.test_response(httplib.ACCEPTED, '') def _1_0_server_types(self, method, url, body, headers): if method == 'GET': return self.test_response(httplib.OK, self.fixtures.load('list_server_types.json')) def _1_0_zones(self, method, url, body, headers): if method == 'GET': if headers['Host'] == 'api.gbt.brightbox.com': return self.test_response(httplib.OK, "{}") else: return self.test_response(httplib.OK, self.fixtures.load('list_zones.json')) def _2_0_zones(self, method, url, body, headers): data = '{"error_name":"unrecognised_endpoint", "errors": ["The request was for an unrecognised API endpoint"]}' return self.test_response(httplib.BAD_REQUEST, data) def _1_0_cloud_ips(self, method, url, body, headers): if method == 'GET': return self.test_response(httplib.OK, self.fixtures.load('list_cloud_ips.json')) elif method == 'POST': if body: body = json.loads(body) node = json.loads(self.fixtures.load('create_cloud_ip.json')) if 'reverse_dns' in body: node['reverse_dns'] = body['reverse_dns'] return self.test_response(httplib.ACCEPTED, json.dumps(node)) def _1_0_cloud_ips_cip_jsjc5(self, method, url, body, headers): if method == 'DELETE': return self.test_response(httplib.OK, '') elif method == 'PUT': body = json.loads(body) if body.get('reverse_dns', None) == 'fred.co.uk': return self.test_response(httplib.OK, '') else: return self.test_response(httplib.BAD_REQUEST, '{"error_name":"bad dns", "errors": ["Bad dns"]}') def _1_0_cloud_ips_cip_jsjc5_map(self, method, url, body, headers): if method == 'POST': body = json.loads(body) if 'destination' in body: return self.test_response(httplib.ACCEPTED, '') else: data = '{"error_name":"bad destination", "errors": ["Bad destination"]}' return self.test_response(httplib.BAD_REQUEST, data) def _1_0_cloud_ips_cip_jsjc5_unmap(self, method, url, body, headers): if method == 'POST': return self.test_response(httplib.ACCEPTED, '') def test_response(self, status, body): return (status, body, {'content-type': 'application/json'}, httplib.responses[status]) if __name__ == '__main__': sys.exit(unittest.main()) # vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 # filetype=python apache-libcloud-2.8.0/libcloud/test/compute/test_bsnl.py0000664000175000017500000000240313535474530023232 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest from libcloud.compute.drivers.bsnl import BSNLNodeDriver from libcloud.test.compute.test_dimensiondata_v2_3 import DimensionDataMockHttp, DimensionData_v2_3_Tests class BSNLTests(DimensionData_v2_3_Tests, unittest.TestCase): def setUp(self): BSNLNodeDriver.connectionCls.conn_class = DimensionDataMockHttp BSNLNodeDriver.connectionCls.active_api_version = '2.3' DimensionDataMockHttp.type = None self.driver = BSNLNodeDriver('user', 'password') apache-libcloud-2.8.0/libcloud/test/compute/test_cloudscale.py0000664000175000017500000001067413535474530024423 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest try: import simplejson as json except ImportError: import json # NOQA from libcloud.utils.py3 import httplib from libcloud.compute.drivers.cloudscale import CloudscaleNodeDriver from libcloud.test import LibcloudTestCase, MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import CLOUDSCALE_PARAMS class CloudscaleTests(LibcloudTestCase): def setUp(self): CloudscaleNodeDriver.connectionCls.conn_class = \ CloudscaleMockHttp self.driver = CloudscaleNodeDriver(*CLOUDSCALE_PARAMS) def test_list_images_success(self): images = self.driver.list_images() image, = images self.assertTrue(image.id is not None) self.assertTrue(image.name is not None) def test_list_sizes_success(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 2) size = sizes[0] self.assertTrue(size.id is not None) self.assertEqual(size.name, 'Flex-2') self.assertEqual(size.ram, 2048) size = sizes[1] self.assertTrue(size.id is not None) self.assertEqual(size.name, 'Flex-4') self.assertEqual(size.ram, 4096) def test_list_locations_not_existing(self): # assertRaises doesn't exist in Python 2.5?! try: self.driver.list_locations() except NotImplementedError: pass else: assert False, 'Did not raise the wished error.' def test_list_nodes_success(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].id, '47cec963-fcd2-482f-bdb6-24461b2d47b1') self.assertEqual( nodes[0].public_ips, ['185.98.122.176', '2a06:c01:1:1902::7ab0:176'] ) def test_reboot_node_success(self): node = self.driver.list_nodes()[0] result = self.driver.reboot_node(node) self.assertTrue(result) def test_create_node_success(self): test_size = self.driver.list_sizes()[0] test_image = self.driver.list_images()[0] created_node = self.driver.create_node('node-name', test_size, test_image) self.assertEqual(created_node.id, "47cec963-fcd2-482f-bdb6-24461b2d47b1") def test_destroy_node_success(self): node = self.driver.list_nodes()[0] result = self.driver.destroy_node(node) self.assertTrue(result) class CloudscaleMockHttp(MockHttp): fixtures = ComputeFileFixtures('cloudscale') def _v1_images(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_flavors(self, method, url, body, headers): body = self.fixtures.load('list_sizes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_servers(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('list_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load('create_node.json') response = httplib.responses[httplib.CREATED] return (httplib.CREATED, body, {}, response) def _v1_servers_47cec963_fcd2_482f_bdb6_24461b2d47b1(self, method, url, body, headers): assert method == 'DELETE' return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) def _v1_servers_47cec963_fcd2_482f_bdb6_24461b2d47b1_reboot(self, method, url, body, headers): return (httplib.OK, "", {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_cloudsigma_v1_0.py0000664000175000017500000002015213577507766025267 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.base import Node from libcloud.compute.drivers.cloudsigma import CloudSigmaNodeDriver from libcloud.compute.drivers.cloudsigma import CloudSigmaZrhNodeDriver from libcloud.utils.misc import str2dicts, str2list, dict2str from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures class CloudSigmaAPI10BaseTestCase(object): should_list_locations = False driver_klass = CloudSigmaZrhNodeDriver driver_kwargs = {} def setUp(self): self.driver_klass.connectionCls.conn_class = CloudSigmaHttp CloudSigmaHttp.type = None self.driver = self.driver_klass(*self.driver_args, **self.driver_kwargs) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertTrue(isinstance(nodes, list)) self.assertEqual(len(nodes), 1) node = nodes[0] self.assertEqual(node.public_ips[0], "1.2.3.4") self.assertEqual(node.extra['smp'], 1) self.assertEqual(node.extra['cpu'], 1100) self.assertEqual(node.extra['mem'], 640) def test_list_sizes(self): images = self.driver.list_sizes() self.assertEqual(len(images), 9) def test_list_images(self): sizes = self.driver.list_images() self.assertEqual(len(sizes), 10) def test_start_node(self): nodes = self.driver.list_nodes() node = nodes[0] self.assertTrue(self.driver.ex_start_node(node)) def test_shutdown_node(self): nodes = self.driver.list_nodes() node = nodes[0] self.assertTrue(self.driver.ex_stop_node(node)) self.assertTrue(self.driver.ex_shutdown_node(node)) def test_reboot_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.reboot_node(node)) def test_destroy_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.destroy_node(node)) self.driver.list_nodes() def test_create_node(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node( name="cloudsigma node", image=image, size=size) self.assertTrue(isinstance(node, Node)) def test_ex_static_ip_list(self): ips = self.driver.ex_static_ip_list() self.assertEqual(len(ips), 3) def test_ex_static_ip_create(self): result = self.driver.ex_static_ip_create() self.assertEqual(len(result), 2) self.assertEqual(len(list(result[0].keys())), 6) self.assertEqual(len(list(result[1].keys())), 6) def test_ex_static_ip_destroy(self): result = self.driver.ex_static_ip_destroy('1.2.3.4') self.assertTrue(result) def test_ex_drives_list(self): result = self.driver.ex_drives_list() self.assertEqual(len(result), 2) def test_ex_drive_destroy(self): result = self.driver.ex_drive_destroy( # @@TR: this should be soft-coded: 'd18119ce_7afa_474a_9242_e0384b160220') self.assertTrue(result) def test_ex_set_node_configuration(self): node = self.driver.list_nodes()[0] result = self.driver.ex_set_node_configuration(node, **{'smp': 2}) self.assertTrue(result) def test_str2dicts(self): string = 'mem 1024\ncpu 2200\n\nmem2048\\cpu 1100' result = str2dicts(string) self.assertEqual(len(result), 2) def test_str2list(self): string = 'ip 1.2.3.4\nip 1.2.3.5\nip 1.2.3.6' result = str2list(string) self.assertEqual(len(result), 3) self.assertEqual(result[0], '1.2.3.4') self.assertEqual(result[1], '1.2.3.5') self.assertEqual(result[2], '1.2.3.6') def test_dict2str(self): d = {'smp': 5, 'cpu': 2200, 'mem': 1024} result = dict2str(d) self.assertTrue(len(result) > 0) self.assertTrue(result.find('smp 5') >= 0) self.assertTrue(result.find('cpu 2200') >= 0) self.assertTrue(result.find('mem 1024') >= 0) class CloudSigmaAPI10DirectTestCase(CloudSigmaAPI10BaseTestCase, unittest.TestCase): driver_klass = CloudSigmaZrhNodeDriver driver_args = ('foo', 'bar') driver_kwargs = {} class CloudSigmaAPI10IndiretTestCase(CloudSigmaAPI10BaseTestCase, unittest.TestCase): driver_klass = CloudSigmaNodeDriver driver_args = ('foo', 'bar') driver_kwargs = {'api_version': '1.0'} class CloudSigmaHttp(MockHttp): fixtures = ComputeFileFixtures('cloudsigma') def _drives_standard_info(self, method, url, body, headers): body = self.fixtures.load('drives_standard_info.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_start( self, method, url, body, headers): return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_stop( self, method, url, body, headers): return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK]) def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_destroy( self, method, url, body, headers): return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _drives_d18119ce_7afa_474a_9242_e0384b160220_clone( self, method, url, body, headers): body = self.fixtures.load('drives_clone.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _drives_a814def5_1789_49a0_bf88_7abe7bb1682a_info( self, method, url, body, headers): body = self.fixtures.load('drives_single_info.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _drives_info(self, method, url, body, headers): body = self.fixtures.load('drives_info.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_create(self, method, url, body, headers): body = self.fixtures.load('servers_create.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_info(self, method, url, body, headers): body = self.fixtures.load('servers_info.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _resources_ip_list(self, method, url, body, headers): body = self.fixtures.load('resources_ip_list.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _resources_ip_create(self, method, url, body, headers): body = self.fixtures.load('resources_ip_create.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _resources_ip_1_2_3_4_destroy(self, method, url, body, headers): return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK]) def _drives_d18119ce_7afa_474a_9242_e0384b160220_destroy( self, method, url, body, headers): return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK]) def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_set( self, method, url, body, headers): body = self.fixtures.load('servers_set.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_cloudsigma_v2_0.py0000664000175000017500000006656713535474530025276 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys try: import simplejson as json except Exception: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import assertRaisesRegex from libcloud.common.types import InvalidCredsError from libcloud.compute.drivers.cloudsigma import CloudSigmaNodeDriver from libcloud.compute.drivers.cloudsigma import CloudSigma_2_0_NodeDriver from libcloud.compute.drivers.cloudsigma import CloudSigmaError from libcloud.compute.types import NodeState from libcloud.test import unittest from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures class CloudSigmaAPI20BaseTestCase(object): def setUp(self): self.driver_klass.connectionCls.conn_class = CloudSigmaMockHttp CloudSigmaMockHttp.type = None CloudSigmaMockHttp.use_param = 'do' self.driver = self.driver_klass(*self.driver_args, **self.driver_kwargs) self.driver.DRIVE_TRANSITION_SLEEP_INTERVAL = 0.1 self.driver.DRIVE_TRANSITION_TIMEOUT = 1 self.node = self.driver.list_nodes()[0] def test_invalid_api_versions(self): expected_msg = 'Unsupported API version: invalid' assertRaisesRegex(self, NotImplementedError, expected_msg, CloudSigmaNodeDriver, 'username', 'password', api_version='invalid') def test_invalid_credentials(self): CloudSigmaMockHttp.type = 'INVALID_CREDS' self.assertRaises(InvalidCredsError, self.driver.list_nodes) def test_invalid_region(self): expected_msg = 'Invalid region:' assertRaisesRegex(self, ValueError, expected_msg, CloudSigma_2_0_NodeDriver, 'foo', 'bar', region='invalid') def test_list_sizes(self): sizes = self.driver.list_sizes() size = sizes[0] self.assertEqual(size.id, 'micro-regular') def test_list_images(self): images = self.driver.list_images() image = images[0] self.assertEqual(image.name, 'ubuntu-10.04-toMP') self.assertEqual(image.extra['image_type'], 'preinst') self.assertEqual(image.extra['media'], 'disk') self.assertEqual(image.extra['os'], 'linux') def test_list_nodes(self): nodes = self.driver.list_nodes() node = nodes[0] self.assertEqual(len(nodes), 2) self.assertEqual(node.id, '9de75ed6-fd33-45e2-963f-d405f31fd911') self.assertEqual(node.name, 'test no drives') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['185.12.5.181', '178.22.68.55']) self.assertEqual(node.private_ips, []) def test_create_node(self): image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] metadata = {'foo': 'bar'} node = self.driver.create_node(name='test node', size=size, image=image, ex_metadata=metadata) self.assertEqual(node.name, 'test node') self.assertEqual(len(node.extra['nics']), 1) self.assertEqual(node.extra['nics'][0]['ip_v4_conf']['conf'], 'dhcp') def test_create_node_with_vlan(self): image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] vlan_uuid = '39ae851d-433f-4ac2-a803-ffa24cb1fa3e' node = self.driver.create_node(name='test node vlan', size=size, image=image, ex_vlan=vlan_uuid) self.assertEqual(node.name, 'test node vlan') self.assertEqual(len(node.extra['nics']), 2) self.assertEqual(node.extra['nics'][0]['ip_v4_conf']['conf'], 'dhcp') self.assertEqual(node.extra['nics'][1]['vlan']['uuid'], vlan_uuid) def test_destroy_node(self): status = self.driver.destroy_node(node=self.node) self.assertTrue(status) def test_ex_start_node(self): status = self.driver.ex_start_node(node=self.node) self.assertTrue(status) def test_ex_start_node_avoid_mode(self): CloudSigmaMockHttp.type = 'AVOID_MODE' ex_avoid = ['1', '2'] status = self.driver.ex_start_node(node=self.node, ex_avoid=ex_avoid) self.assertTrue(status) def test_ex_start_node_already_started(self): CloudSigmaMockHttp.type = 'ALREADY_STARTED' expected_msg = 'Cannot start guest in state "started". Guest should ' \ 'be in state "stopped' assertRaisesRegex(self, CloudSigmaError, expected_msg, self.driver.ex_start_node, node=self.node) def test_ex_stop_node(self): status = self.driver.ex_stop_node(node=self.node) self.assertTrue(status) def test_ex_stop_node_already_stopped(self): CloudSigmaMockHttp.type = 'ALREADY_STOPPED' expected_msg = 'Cannot stop guest in state "stopped"' assertRaisesRegex(self, CloudSigmaError, expected_msg, self.driver.ex_stop_node, node=self.node) def test_ex_clone_node(self): node_to_clone = self.driver.list_nodes()[0] cloned_node = self.driver.ex_clone_node(node=node_to_clone, name='test cloned node') self.assertEqual(cloned_node.name, 'test cloned node') def test_ex_open_vnc_tunnel(self): node = self.driver.list_nodes()[0] vnc_url = self.driver.ex_open_vnc_tunnel(node=node) self.assertEqual(vnc_url, 'vnc://direct.lvs.cloudsigma.com:41111') def test_ex_close_vnc_tunnel(self): node = self.driver.list_nodes()[0] status = self.driver.ex_close_vnc_tunnel(node=node) self.assertTrue(status) def test_ex_list_library_drives(self): drives = self.driver.ex_list_library_drives() drive = drives[0] self.assertEqual(drive.name, 'IPCop 2.0.2') self.assertEqual(drive.size, 1000000000) self.assertEqual(drive.media, 'cdrom') self.assertEqual(drive.status, 'unmounted') def test_ex_list_user_drives(self): drives = self.driver.ex_list_user_drives() drive = drives[0] self.assertEqual(drive.name, 'test node 2-drive') self.assertEqual(drive.size, 13958643712) self.assertEqual(drive.media, 'disk') self.assertEqual(drive.status, 'unmounted') def test_ex_create_drive(self): CloudSigmaMockHttp.type = 'CREATE' name = 'test drive 5' size = 2000 * 1024 * 1024 drive = self.driver.ex_create_drive(name=name, size=size, media='disk') self.assertEqual(drive.name, 'test drive 5') self.assertEqual(drive.media, 'disk') def test_ex_clone_drive(self): drive = self.driver.ex_list_user_drives()[0] cloned_drive = self.driver.ex_clone_drive(drive=drive, name='cloned drive') self.assertEqual(cloned_drive.name, 'cloned drive') def test_ex_resize_drive(self): drive = self.driver.ex_list_user_drives()[0] size = 1111 * 1024 * 1024 resized_drive = self.driver.ex_resize_drive(drive=drive, size=size) self.assertEqual(resized_drive.name, 'test drive 5') self.assertEqual(resized_drive.media, 'disk') self.assertEqual(resized_drive.size, size) def test_ex_list_firewall_policies(self): policies = self.driver.ex_list_firewall_policies() policy = policies[1] rule = policy.rules[0] self.assertEqual(policy.name, 'My awesome policy') self.assertEqual(rule.action, 'drop') self.assertEqual(rule.direction, 'out') self.assertEqual(rule.dst_ip, '23.0.0.0/32') self.assertEqual(rule.ip_proto, 'tcp') self.assertIsNone(rule.dst_port) self.assertIsNone(rule.src_ip) self.assertIsNone(rule.src_port) self.assertEqual(rule.comment, 'Drop traffic from the VM to IP address 23.0.0.0/32') def test_ex_create_firewall_policy_no_rules(self): CloudSigmaMockHttp.type = 'CREATE_NO_RULES' policy = self.driver.ex_create_firewall_policy(name='test policy 1') self.assertEqual(policy.name, 'test policy 1') self.assertEqual(policy.rules, []) def test_ex_create_firewall_policy_with_rules(self): CloudSigmaMockHttp.type = 'CREATE_WITH_RULES' rules = [ { 'action': 'accept', 'direction': 'out', 'ip_proto': 'tcp', 'src_ip': '127.0.0.1', 'dst_ip': '127.0.0.1' } ] policy = self.driver.ex_create_firewall_policy(name='test policy 2', rules=rules) rule = policy.rules[0] self.assertEqual(policy.name, 'test policy 2') self.assertEqual(len(policy.rules), 1) self.assertEqual(rule.action, 'accept') self.assertEqual(rule.direction, 'out') self.assertEqual(rule.ip_proto, 'tcp') def test_ex_attach_firewall_policy(self): policy = self.driver.ex_list_firewall_policies()[0] node = self.driver.list_nodes()[0] CloudSigmaMockHttp.type = 'ATTACH_POLICY' updated_node = self.driver.ex_attach_firewall_policy(policy=policy, node=node) nic = updated_node.extra['nics'][0] self.assertEqual(nic['firewall_policy']['uuid'], '461dfb8c-e641-43d7-a20e-32e2aa399086') def test_ex_attach_firewall_policy_inexistent_nic(self): policy = self.driver.ex_list_firewall_policies()[0] node = self.driver.list_nodes()[0] nic_mac = 'inexistent' expected_msg = 'Cannot find the NIC interface to attach a policy to' assertRaisesRegex(self, ValueError, expected_msg, self.driver.ex_attach_firewall_policy, policy=policy, node=node, nic_mac=nic_mac) def test_ex_delete_firewall_policy(self): policy = self.driver.ex_list_firewall_policies()[0] status = self.driver.ex_delete_firewall_policy(policy=policy) self.assertTrue(status) def test_ex_list_tags(self): tags = self.driver.ex_list_tags() tag = tags[0] self.assertEqual(tag.id, 'a010ec41-2ead-4630-a1d0-237fa77e4d4d') self.assertEqual(tag.name, 'test tag 2') def test_ex_get_tag(self): tag = self.driver.ex_get_tag(tag_id='a010ec41-2ead-4630-a1d0-237fa77e4d4d') self.assertEqual(tag.id, 'a010ec41-2ead-4630-a1d0-237fa77e4d4d') self.assertEqual(tag.name, 'test tag 2') def test_ex_create_tag(self): tag = self.driver.ex_create_tag(name='test tag 3') self.assertEqual(tag.name, 'test tag 3') def test_ex_create_tag_with_resources(self): CloudSigmaMockHttp.type = 'WITH_RESOURCES' resource_uuids = ['1'] tag = self.driver.ex_create_tag(name='test tag 3', resource_uuids=resource_uuids) self.assertEqual(tag.name, 'test tag 3') self.assertEqual(tag.resources, resource_uuids) def test_ex_tag_resource(self): node = self.driver.list_nodes()[0] tag = self.driver.ex_list_tags()[0] updated_tag = self.driver.ex_tag_resource(resource=node, tag=tag) self.assertEqual(updated_tag.name, 'test tag 3') def test_ex_tag_resources(self): nodes = self.driver.list_nodes() tag = self.driver.ex_list_tags()[0] updated_tag = self.driver.ex_tag_resources(resources=nodes, tag=tag) self.assertEqual(updated_tag.name, 'test tag 3') def test_ex_tag_resource_invalid_resource_object(self): tag = self.driver.ex_list_tags()[0] expected_msg = 'Resource doesn\'t have id attribute' assertRaisesRegex(self, ValueError, expected_msg, self.driver.ex_tag_resource, tag=tag, resource={}) def test_ex_delete_tag(self): tag = self.driver.ex_list_tags()[0] status = self.driver.ex_delete_tag(tag=tag) self.assertTrue(status) def test_ex_get_balance(self): balance = self.driver.ex_get_balance() self.assertEqual(balance['balance'], '10.00') self.assertEqual(balance['currency'], 'USD') def test_ex_get_pricing(self): pricing = self.driver.ex_get_pricing() self.assertTrue('current' in pricing) self.assertTrue('next' in pricing) self.assertTrue('objects' in pricing) def test_ex_get_usage(self): pricing = self.driver.ex_get_usage() self.assertTrue('balance' in pricing) self.assertTrue('usage' in pricing) def test_ex_list_subscriptions(self): subscriptions = self.driver.ex_list_subscriptions() self.assertEqual(len(subscriptions), 6) subscription = subscriptions[0] self.assertEqual(subscription.id, '7272') self.assertEqual(subscription.resource, 'vlan') self.assertEqual(subscription.amount, 1) self.assertEqual(subscription.period, '345 days, 0:00:00') self.assertEqual(subscription.status, 'active') self.assertEqual(subscription.price, '0E-20') subscription = subscriptions[-1] self.assertEqual(subscription.id, '5555') self.assertEqual(subscription.start_time, None) self.assertEqual(subscription.end_time, None) def test_ex_create_subscription(self): CloudSigmaMockHttp.type = 'CREATE_SUBSCRIPTION' subscription = self.driver.ex_create_subscription(amount=1, period='1 month', resource='vlan') self.assertEqual(subscription.amount, 1) self.assertEqual(subscription.period, '1 month') self.assertEqual(subscription.resource, 'vlan') self.assertEqual(subscription.price, '10.26666666666666666666666667') self.assertEqual(subscription.auto_renew, False) self.assertEqual(subscription.subscribed_object, '2494079f-8376-40bf-9b37-34d633b8a7b7') def test_ex_list_subscriptions_status_filterting(self): CloudSigmaMockHttp.type = 'STATUS_FILTER' self.driver.ex_list_subscriptions(status='active') def test_ex_list_subscriptions_resource_filterting(self): CloudSigmaMockHttp.type = 'RESOURCE_FILTER' resources = ['cpu', 'mem'] self.driver.ex_list_subscriptions(resources=resources) def test_ex_toggle_subscription_auto_renew(self): subscription = self.driver.ex_list_subscriptions()[0] status = self.driver.ex_toggle_subscription_auto_renew( subscription=subscription) self.assertTrue(status) def test_ex_list_capabilities(self): capabilities = self.driver.ex_list_capabilities() self.assertEqual(capabilities['servers']['cpu']['min'], 250) def test_ex_list_servers_availability_groups(self): groups = self.driver.ex_list_servers_availability_groups() self.assertEqual(len(groups), 3) self.assertEqual(len(groups[0]), 2) self.assertEqual(len(groups[2]), 1) def test_ex_list_drives_availability_groups(self): groups = self.driver.ex_list_drives_availability_groups() self.assertEqual(len(groups), 1) self.assertEqual(len(groups[0]), 11) def test_wait_for_drive_state_transition_timeout(self): drive = self.driver.ex_list_user_drives()[0] state = 'timeout' expected_msg = 'Timed out while waiting for drive transition' assertRaisesRegex(self, Exception, expected_msg, self.driver._wait_for_drive_state_transition, drive=drive, state=state, timeout=0.5) def test_wait_for_drive_state_transition_success(self): drive = self.driver.ex_list_user_drives()[0] state = 'unmounted' drive = self.driver._wait_for_drive_state_transition(drive=drive, state=state, timeout=0.5) self.assertEqual(drive.status, state) class CloudSigmaAPI20DirectTestCase(CloudSigmaAPI20BaseTestCase, unittest.TestCase): driver_klass = CloudSigma_2_0_NodeDriver driver_args = ('foo', 'bar') driver_kwargs = {} class CloudSigmaAPI20IndirectTestCase(CloudSigmaAPI20BaseTestCase, unittest.TestCase): driver_klass = CloudSigmaNodeDriver driver_args = ('foo', 'bar') driver_kwargs = {'api_version': '2.0'} class CloudSigmaMockHttp(MockHttp, unittest.TestCase): fixtures = ComputeFileFixtures('cloudsigma_2_0') def _api_2_0_servers_detail_INVALID_CREDS(self, method, url, body, headers): body = self.fixtures.load('libdrives.json') return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.UNAUTHORIZED]) def _api_2_0_libdrives(self, method, url, body, headers): body = self.fixtures.load('libdrives.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_servers_detail(self, method, url, body, headers): body = self.fixtures.load('servers_detail_mixed_state.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911(self, method, url, body, headers): body = '' return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _api_2_0_servers(self, method, url, body, headers): if method == 'POST': # create_node parsed = json.loads(body) if 'vlan' in parsed['name']: self.assertEqual(len(parsed['nics']), 2) body = self.fixtures.load('servers_create_with_vlan.json') else: body = self.fixtures.load('servers_create.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_start(self, method, url, body, headers): body = self.fixtures.load('start_success.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_AVOID_MODE_start(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, {'avoid': '1,2'}) body = self.fixtures.load('start_success.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_ALREADY_STARTED_start(self, method, url, body, headers): body = self.fixtures.load('start_already_started.json') return (httplib.FORBIDDEN, body, {}, httplib.responses[httplib.FORBIDDEN]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_stop(self, method, url, body, headers): body = self.fixtures.load('stop_success.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_ALREADY_STOPPED_stop(self, method, url, body, headers): body = self.fixtures.load('stop_already_stopped.json') return (httplib.FORBIDDEN, body, {}, httplib.responses[httplib.FORBIDDEN]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_clone(self, method, url, body, headers): body = self.fixtures.load('servers_clone.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_open_vnc(self, method, url, body, headers): body = self.fixtures.load('servers_open_vnc.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_action_close_vnc(self, method, url, body, headers): body = self.fixtures.load('servers_close_vnc.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_drives_detail(self, method, url, body, headers): body = self.fixtures.load('drives_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_drives_b02311e2_a83c_4c12_af10_b30d51c86913(self, method, url, body, headers): body = self.fixtures.load('drives_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809(self, method, url, body, headers): body = self.fixtures.load('drives_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_drives_CREATE(self, method, url, body, headers): body = self.fixtures.load('drives_create.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809_action_clone(self, method, url, body, headers): body = self.fixtures.load('drives_clone.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_drives_5236b9ee_f735_42fd_a236_17558f9e12d3_action_clone(self, method, url, body, headers): body = self.fixtures.load('drives_clone.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_drives_b02311e2_a83c_4c12_af10_b30d51c86913_action_resize(self, method, url, body, headers): body = self.fixtures.load('drives_resize.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_drives_9d1d2cf3_08c1_462f_8485_f4b073560809_action_resize(self, method, url, body, headers): body = self.fixtures.load('drives_resize.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _api_2_0_fwpolicies_detail(self, method, url, body, headers): body = self.fixtures.load('fwpolicies_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_fwpolicies_CREATE_NO_RULES(self, method, url, body, headers): body = self.fixtures.load('fwpolicies_create_no_rules.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _api_2_0_fwpolicies_CREATE_WITH_RULES(self, method, url, body, headers): body = self.fixtures.load('fwpolicies_create_with_rules.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _api_2_0_servers_9de75ed6_fd33_45e2_963f_d405f31fd911_ATTACH_POLICY(self, method, url, body, headers): body = self.fixtures.load('servers_attach_policy.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _api_2_0_fwpolicies_0e339282_0cb5_41ac_a9db_727fb62ff2dc(self, method, url, body, headers): if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _api_2_0_tags_detail(self, method, url, body, headers): body = self.fixtures.load('tags_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_tags(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('tags_create.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _api_2_0_tags_WITH_RESOURCES(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('tags_create_with_resources.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _api_2_0_tags_a010ec41_2ead_4630_a1d0_237fa77e4d4d(self, method, url, body, headers): if method == 'GET': # ex_get_tag body = self.fixtures.load('tags_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'PUT': # ex_tag_resource body = self.fixtures.load('tags_update.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'DELETE': # ex_delete_tag body = '' return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _api_2_0_balance(self, method, url, body, headers): body = self.fixtures.load('balance.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_pricing(self, method, url, body, headers): body = self.fixtures.load('pricing.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_currentusage(self, method, url, body, headers): body = self.fixtures.load('currentusage.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_subscriptions(self, method, url, body, headers): body = self.fixtures.load('subscriptions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_subscriptions_STATUS_FILTER(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, {'status': 'active'}) body = self.fixtures.load('subscriptions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_subscriptions_RESOURCE_FILTER(self, method, url, body, headers): expected_params = {'resource': 'cpu,mem', 'status': 'all'} self.assertUrlContainsQueryParams(url, expected_params) body = self.fixtures.load('subscriptions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_subscriptions_7272_action_auto_renew(self, method, url, body, headers): body = '' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_subscriptions_CREATE_SUBSCRIPTION(self, method, url, body, headers): body = self.fixtures.load('create_subscription.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_capabilities(self, method, url, body, headers): body = self.fixtures.load('capabilities.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_servers_availability_groups(self, method, url, body, headers): body = self.fixtures.load('servers_avail_groups.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_2_0_drives_availability_groups(self, method, url, body, headers): body = self.fixtures.load('drives_avail_groups.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_cloudstack.py0000664000175000017500000016006713535474530024443 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import os from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qsl try: import simplejson as json except ImportError: import json from libcloud.compute.base import NodeLocation, NodeSize, NodeImage from libcloud.common.types import ProviderError from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver, \ CloudStackAffinityGroupType from libcloud.compute.types import LibcloudError, Provider, InvalidCredsError from libcloud.compute.types import KeyPairDoesNotExistError from libcloud.compute.types import NodeState from libcloud.compute.providers import get_driver from libcloud.utils.py3 import assertRaisesRegex from libcloud.test import unittest from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures class CloudStackCommonTestCase(TestCaseMixin): driver_klass = CloudStackNodeDriver def setUp(self): self.driver_klass.connectionCls.conn_class = CloudStackMockHttp self.driver = self.driver_klass('apikey', 'secret', path='/test/path', host='api.dummy.com') self.driver.path = '/test/path' self.driver.type = -1 CloudStackMockHttp.type = None CloudStackMockHttp.fixture_tag = 'default' self.driver.connection.poll_interval = 0.0 def test_invalid_credentials(self): CloudStackMockHttp.type = 'invalid_credentials' driver = self.driver_klass('invalid', 'invalid', path='/test/path', host='api.dummy.com') self.assertRaises(InvalidCredsError, driver.list_nodes) def test_import_keypair_from_string_api_error(self): CloudStackMockHttp.type = 'api_error' name = 'test-pair' key_material = '' expected_msg = 'Public key is invalid' assertRaisesRegex(self, ProviderError, expected_msg, self.driver.import_key_pair_from_string, name=name, key_material=key_material) def test_create_node_immediate_failure(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] CloudStackMockHttp.fixture_tag = 'deployfail' self.assertRaises( Exception, self.driver.create_node, name='node-name', image=image, size=size) def test_create_node_delayed_failure(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] CloudStackMockHttp.fixture_tag = 'deployfail2' self.assertRaises( Exception, self.driver.create_node, name='node-name', image=image, size=size) def test_create_node_default_location_success(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] default_location = self.driver.list_locations()[0] node = self.driver.create_node(name='fred', image=image, size=size) self.assertEqual(node.name, 'fred') self.assertEqual(node.public_ips, []) self.assertEqual(node.private_ips, ['192.168.1.2']) self.assertEqual(node.extra['zone_id'], default_location.id) def test_create_node_ex_networks(self): CloudStackMockHttp.fixture_tag = 'deploynetworks' size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] networks = [nw for nw in self.driver.ex_list_networks() if str(nw.zoneid) == str(location.id)] node = self.driver.create_node(name='deploynetworks', location=location, image=image, size=size, networks=networks) self.assertEqual(node.name, 'deploynetworks') self.assertEqual(node.extra['size_id'], size.id) self.assertEqual(node.extra['zone_id'], location.id) self.assertEqual(node.extra['image_id'], image.id) self.assertEqual(len(node.private_ips), 2) def test_create_node_ex_ipaddress(self): CloudStackMockHttp.fixture_tag = 'deployip' size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] ipaddress = '10.1.0.128' networks = [nw for nw in self.driver.ex_list_networks() if str(nw.zoneid) == str(location.id)] node = self.driver.create_node(name='deployip', location=location, image=image, size=size, networks=networks, ex_ip_address=ipaddress) self.assertEqual(node.name, 'deployip') self.assertEqual(node.extra['size_id'], size.id) self.assertEqual(node.extra['zone_id'], location.id) self.assertEqual(node.extra['image_id'], image.id) self.assertEqual(node.private_ips[0], ipaddress) def test_create_node_ex_rootdisksize(self): CloudStackMockHttp.fixture_tag = 'rootdisksize' size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] volumes = self.driver.list_volumes() rootdisksize = '50' networks = [nw for nw in self.driver.ex_list_networks() if str(nw.zoneid) == str(location.id)] node = self.driver.create_node(name='rootdisksize', location=location, image=image, size=size, networks=networks, ex_rootdisksize=rootdisksize) self.assertEqual(node.name, 'rootdisksize') self.assertEqual(node.extra['size_id'], size.id) self.assertEqual(node.extra['zone_id'], location.id) self.assertEqual(node.extra['image_id'], image.id) self.assertEqual(1, len(volumes)) self.assertEqual('ROOT-69941', volumes[0].name) self.assertEqual(53687091200, volumes[0].size) def test_create_node_ex_start_vm_false(self): CloudStackMockHttp.fixture_tag = 'stoppedvm' size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] networks = [nw for nw in self.driver.ex_list_networks() if str(nw.zoneid) == str(location.id)] node = self.driver.create_node(name='stopped_vm', location=location, image=image, size=size, networks=networks, ex_start_vm=False) self.assertEqual(node.name, 'stopped_vm') self.assertEqual(node.extra['size_id'], size.id) self.assertEqual(node.extra['zone_id'], location.id) self.assertEqual(node.extra['image_id'], image.id) self.assertEqual(node.state, NodeState.STOPPED) def test_create_node_ex_security_groups(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] sg = [sg['name'] for sg in self.driver.ex_list_security_groups()] CloudStackMockHttp.fixture_tag = 'deploysecuritygroup' node = self.driver.create_node(name='test', location=location, image=image, size=size, ex_security_groups=sg) self.assertEqual(node.name, 'test') self.assertEqual(node.extra['security_group'], sg) self.assertEqual(node.id, 'fc4fd31a-16d3-49db-814a-56b39b9ef986') def test_create_node_ex_keyname(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] CloudStackMockHttp.fixture_tag = 'deploykeyname' node = self.driver.create_node(name='test', location=location, image=image, size=size, ex_keyname='foobar') self.assertEqual(node.name, 'test') self.assertEqual(node.extra['key_name'], 'foobar') def test_create_node_ex_userdata(self): self.driver.path = '/test/path/userdata' size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] CloudStackMockHttp.fixture_tag = 'deploykeyname' node = self.driver.create_node(name='test', location=location, image=image, size=size, ex_userdata='foobar') self.assertEqual(node.name, 'test') def test_create_node_project(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] project = self.driver.ex_list_projects()[0] CloudStackMockHttp.fixture_tag = 'deployproject' node = self.driver.create_node(name='test', location=location, image=image, size=size, project=project) self.assertEqual(node.name, 'TestNode') self.assertEqual(node.extra['project'], 'Test Project') def test_list_images_no_images_available(self): CloudStackMockHttp.fixture_tag = 'notemplates' images = self.driver.list_images() self.assertEqual(0, len(images)) def test_list_images(self): _, fixture = self.driver.connection.connection._load_fixture( 'listTemplates_default.json') templates = fixture['listtemplatesresponse']['template'] images = self.driver.list_images() for i, image in enumerate(images): # NodeImage expects id to be a string, # the CloudStack fixture has an int tid = str(templates[i]['id']) tname = templates[i]['name'] self.assertIsInstance(image.driver, CloudStackNodeDriver) self.assertEqual(image.id, tid) self.assertEqual(image.name, tname) def test_ex_list_disk_offerings(self): diskOfferings = self.driver.ex_list_disk_offerings() self.assertEqual(1, len(diskOfferings)) diskOffering, = diskOfferings self.assertEqual('Disk offer 1', diskOffering.name) self.assertEqual(10, diskOffering.size) def test_ex_list_networks(self): _, fixture = self.driver.connection.connection._load_fixture( 'listNetworks_default.json') fixture_networks = fixture['listnetworksresponse']['network'] networks = self.driver.ex_list_networks() for i, network in enumerate(networks): self.assertEqual(network.id, fixture_networks[i]['id']) self.assertEqual( network.displaytext, fixture_networks[i]['displaytext']) self.assertEqual(network.name, fixture_networks[i]['name']) self.assertEqual( network.networkofferingid, fixture_networks[i]['networkofferingid']) self.assertEqual(network.zoneid, fixture_networks[i]['zoneid']) def test_ex_list_network_offerings(self): _, fixture = self.driver.connection.connection._load_fixture( 'listNetworkOfferings_default.json') fixture_networkoffers = \ fixture['listnetworkofferingsresponse']['networkoffering'] networkoffers = self.driver.ex_list_network_offerings() for i, networkoffer in enumerate(networkoffers): self.assertEqual(networkoffer.id, fixture_networkoffers[i]['id']) self.assertEqual(networkoffer.name, fixture_networkoffers[i]['name']) self.assertEqual(networkoffer.display_text, fixture_networkoffers[i]['displaytext']) self.assertEqual(networkoffer.for_vpc, fixture_networkoffers[i]['forvpc']) self.assertEqual(networkoffer.guest_ip_type, fixture_networkoffers[i]['guestiptype']) self.assertEqual(networkoffer.service_offering_id, fixture_networkoffers[i]['serviceofferingid']) def test_ex_create_network(self): _, fixture = self.driver.connection.connection._load_fixture( 'createNetwork_default.json') fixture_network = fixture['createnetworkresponse']['network'] netoffer = self.driver.ex_list_network_offerings()[0] location = self.driver.list_locations()[0] network = self.driver.ex_create_network(display_text='test', name='test', network_offering=netoffer, location=location, gateway='10.1.1.1', netmask='255.255.255.0', network_domain='cloud.local', vpc_id="2", project_id="2") self.assertEqual(network.name, fixture_network['name']) self.assertEqual(network.displaytext, fixture_network['displaytext']) self.assertEqual(network.id, fixture_network['id']) self.assertEqual(network.extra['gateway'], fixture_network['gateway']) self.assertEqual(network.extra['netmask'], fixture_network['netmask']) self.assertEqual(network.networkofferingid, fixture_network['networkofferingid']) self.assertEqual(network.extra['vpc_id'], fixture_network['vpcid']) self.assertEqual(network.extra['project_id'], fixture_network['projectid']) def test_ex_delete_network(self): network = self.driver.ex_list_networks()[0] result = self.driver.ex_delete_network(network=network) self.assertTrue(result) def test_ex_list_nics(self): _, fixture = self.driver.connection.connection._load_fixture( 'listNics_default.json') fixture_nic = fixture['listnicsresponse']['nic'] vm = self.driver.list_nodes()[0] nics = self.driver.ex_list_nics(vm) for i, nic in enumerate(nics): self.assertEqual(nic.id, fixture_nic[i]['id']) self.assertEqual(nic.network_id, fixture_nic[i]['networkid']) self.assertEqual(nic.net_mask, fixture_nic[i]['netmask']) self.assertEqual(nic.gateway, fixture_nic[i]['gateway']) self.assertEqual(nic.ip_address, fixture_nic[i]['ipaddress']) self.assertEqual(nic.is_default, fixture_nic[i]['isdefault']) self.assertEqual(nic.mac_address, fixture_nic[i]['macaddress']) def test_ex_add_nic_to_node(self): vm = self.driver.list_nodes()[0] network = self.driver.ex_list_networks()[0] ip = "10.1.4.123" result = self.driver.ex_attach_nic_to_node(node=vm, network=network, ip_address=ip) self.assertTrue(result) def test_ex_remove_nic_from_node(self): vm = self.driver.list_nodes()[0] nic = self.driver.ex_list_nics(node=vm)[0] result = self.driver.ex_detach_nic_from_node(node=vm, nic=nic) self.assertTrue(result) def test_ex_list_vpc_offerings(self): _, fixture = self.driver.connection.connection._load_fixture( 'listVPCOfferings_default.json') fixture_vpcoffers = \ fixture['listvpcofferingsresponse']['vpcoffering'] vpcoffers = self.driver.ex_list_vpc_offerings() for i, vpcoffer in enumerate(vpcoffers): self.assertEqual(vpcoffer.id, fixture_vpcoffers[i]['id']) self.assertEqual(vpcoffer.name, fixture_vpcoffers[i]['name']) self.assertEqual(vpcoffer.display_text, fixture_vpcoffers[i]['displaytext']) def test_ex_list_vpcs(self): _, fixture = self.driver.connection.connection._load_fixture( 'listVPCs_default.json') fixture_vpcs = fixture['listvpcsresponse']['vpc'] vpcs = self.driver.ex_list_vpcs() for i, vpc in enumerate(vpcs): self.assertEqual(vpc.id, fixture_vpcs[i]['id']) self.assertEqual(vpc.display_text, fixture_vpcs[i]['displaytext']) self.assertEqual(vpc.name, fixture_vpcs[i]['name']) self.assertEqual(vpc.vpc_offering_id, fixture_vpcs[i]['vpcofferingid']) self.assertEqual(vpc.zone_id, fixture_vpcs[i]['zoneid']) def test_ex_list_routers(self): _, fixture = self.driver.connection.connection._load_fixture( 'listRouters_default.json') fixture_routers = fixture['listroutersresponse']['router'] routers = self.driver.ex_list_routers() for i, router in enumerate(routers): self.assertEqual(router.id, fixture_routers[i]['id']) self.assertEqual(router.name, fixture_routers[i]['name']) self.assertEqual(router.state, fixture_routers[i]['state']) self.assertEqual(router.public_ip, fixture_routers[i]['publicip']) self.assertEqual(router.vpc_id, fixture_routers[i]['vpcid']) def test_ex_create_vpc(self): _, fixture = self.driver.connection.connection._load_fixture( 'createVPC_default.json') fixture_vpc = fixture['createvpcresponse'] vpcoffer = self.driver.ex_list_vpc_offerings()[0] vpc = self.driver.ex_create_vpc(cidr='10.1.1.0/16', display_text='cloud.local', name='cloud.local', vpc_offering=vpcoffer, zone_id="2") self.assertEqual(vpc.id, fixture_vpc['id']) def test_ex_delete_vpc(self): vpc = self.driver.ex_list_vpcs()[0] result = self.driver.ex_delete_vpc(vpc=vpc) self.assertTrue(result) def test_ex_create_network_acllist(self): _, fixture = self.driver.connection.connection._load_fixture( 'createNetworkACLList_default.json') fixture_network_acllist = fixture['createnetworkacllistresponse'] vpc = self.driver.ex_list_vpcs()[0] network_acllist = self.driver.ex_create_network_acllist( name='test_acllist', vpc_id=vpc.id, description='test description') self.assertEqual(network_acllist.id, fixture_network_acllist['id']) def test_ex_list_network_acllist(self): _, fixture = self.driver.connection.connection._load_fixture( 'listNetworkACLLists_default.json') fixture_acllist = \ fixture['listnetworkacllistsresponse']['networkacllist'] acllist = self.driver.ex_list_network_acllists() for i, acllist in enumerate(acllist): self.assertEqual(acllist.id, fixture_acllist[i]['id']) self.assertEqual(acllist.name, fixture_acllist[i]['name']) self.assertEqual(acllist.description, fixture_acllist[i]['description']) def test_ex_create_network_acl(self): _, fixture = self.driver.connection.connection._load_fixture( 'createNetworkACL_default.json') fixture_network_acllist = fixture['createnetworkaclresponse'] acllist = self.driver.ex_list_network_acllists()[0] network_acl = self.driver.ex_create_network_acl( protocol='test_acllist', acl_id=acllist.id, cidr_list='', start_port='80', end_port='80') self.assertEqual(network_acl.id, fixture_network_acllist['id']) def test_ex_list_projects(self): _, fixture = self.driver.connection.connection._load_fixture( 'listProjects_default.json') fixture_projects = fixture['listprojectsresponse']['project'] projects = self.driver.ex_list_projects() for i, project in enumerate(projects): self.assertEqual(project.id, fixture_projects[i]['id']) self.assertEqual( project.display_text, fixture_projects[i]['displaytext']) self.assertEqual(project.name, fixture_projects[i]['name']) self.assertEqual( project.extra['domainid'], fixture_projects[i]['domainid']) self.assertEqual( project.extra['cpulimit'], fixture_projects[i]['cpulimit']) # Note -1 represents unlimited self.assertEqual(project.extra['networklimit'], -1) def test_create_volume(self): volumeName = 'vol-0' location = self.driver.list_locations()[0] volume = self.driver.create_volume(10, volumeName, location) self.assertEqual(volumeName, volume.name) self.assertEqual(10, volume.size) def test_create_volume_no_noncustomized_offering_with_size(self): """If the sizes of disk offerings are not configurable and there are no disk offerings with the requested size, an exception should be thrown.""" location = self.driver.list_locations()[0] self.assertRaises( LibcloudError, self.driver.create_volume, 'vol-0', location, 11) def test_create_volume_with_custom_disk_size_offering(self): CloudStackMockHttp.fixture_tag = 'withcustomdisksize' volumeName = 'vol-0' location = self.driver.list_locations()[0] volume = self.driver.create_volume(10, volumeName, location) self.assertEqual(volumeName, volume.name) def test_create_volume_no_matching_volume_type(self): """If the ex_disk_type does not exit, then an exception should be thrown.""" location = self.driver.list_locations()[0] self.assertRaises( LibcloudError, self.driver.create_volume, 'vol-0', location, 11, ex_volume_type='FooVolumeType') def test_create_volume_with_defined_volume_type(self): CloudStackMockHttp.fixture_tag = 'withvolumetype' volumeName = 'vol-0' volLocation = self.driver.list_locations()[0] diskOffering = self.driver.ex_list_disk_offerings()[0] volumeType = diskOffering.name volume = self.driver.create_volume(10, volumeName, location=volLocation, ex_volume_type=volumeType) self.assertEqual(volumeName, volume.name) def test_attach_volume(self): node = self.driver.list_nodes()[0] volumeName = 'vol-0' location = self.driver.list_locations()[0] volume = self.driver.create_volume(10, volumeName, location) attachReturnVal = self.driver.attach_volume(volume, node) self.assertTrue(attachReturnVal) def test_detach_volume(self): volumeName = 'gre-test-volume' location = self.driver.list_locations()[0] volume = self.driver.create_volume(10, volumeName, location) res = self.driver.detach_volume(volume) self.assertTrue(res) def test_destroy_volume(self): volumeName = 'gre-test-volume' location = self.driver.list_locations()[0] volume = self.driver.create_volume(10, volumeName, location) res = self.driver.destroy_volume(volume) self.assertTrue(res) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(1, len(volumes)) self.assertEqual('ROOT-69942', volumes[0].name) def test_ex_get_volume(self): volume = self.driver.ex_get_volume(2600) self.assertEqual('ROOT-69942', volume.name) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(2, len(nodes)) self.assertEqual('test', nodes[0].name) self.assertEqual('2600', nodes[0].id) self.assertEqual(0, len(nodes[0].private_ips)) self.assertEqual([], nodes[0].extra['security_group']) self.assertEqual(None, nodes[0].extra['key_name']) self.assertEqual(1, len(nodes[0].public_ips)) self.assertEqual('1.1.1.116', nodes[0].public_ips[0]) self.assertEqual(1, len(nodes[0].extra['ip_addresses'])) self.assertEqual(34000, nodes[0].extra['ip_addresses'][0].id) self.assertEqual(1, len(nodes[0].extra['ip_forwarding_rules'])) self.assertEqual('772fd410-6649-43ed-befa-77be986b8906', nodes[0].extra['ip_forwarding_rules'][0].id) self.assertEqual(1, len(nodes[0].extra['port_forwarding_rules'])) self.assertEqual('bc7ea3ee-a2c3-4b86-a53f-01bdaa1b2e32', nodes[0].extra['port_forwarding_rules'][0].id) self.assertEqual({"testkey": "testvalue", "foo": "bar"}, nodes[0].extra['tags']) def test_list_nodes_location_filter(self): def list_nodes_mock(self, **kwargs): self.assertTrue('zoneid' in kwargs) self.assertEqual('1', kwargs.get('zoneid')) body, obj = self._load_fixture('listVirtualMachines_default.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) CloudStackMockHttp._cmd_listVirtualMachines = list_nodes_mock try: location = NodeLocation(1, 'Sydney', 'Unknown', self.driver) self.driver.list_nodes(location=location) finally: del CloudStackMockHttp._cmd_listVirtualMachines def test_list_nodes_noipaddress_filter(self): def list_nodes_mock(self, **kwargs): body, obj = self._load_fixture('listVirtualMachines_noipaddress.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) CloudStackMockHttp._cmd_listVirtualMachines = list_nodes_mock try: self.driver.list_nodes() finally: del CloudStackMockHttp._cmd_listVirtualMachines def test_ex_get_node(self): node = self.driver.ex_get_node(2600) self.assertEqual('test', node.name) self.assertEqual('2600', node.id) self.assertEqual([], node.extra['security_group']) self.assertEqual(None, node.extra['key_name']) self.assertEqual(1, len(node.public_ips)) self.assertEqual('1.1.1.116', node.public_ips[0]) self.assertEqual(1, len(node.extra['ip_addresses'])) self.assertEqual(34000, node.extra['ip_addresses'][0].id) def test_ex_get_node_doesnt_exist(self): self.assertRaises(Exception, self.driver.ex_get_node(26), node_id=26) def test_list_locations(self): location = self.driver.list_locations()[0] self.assertEqual('1', location.id) self.assertEqual('Sydney', location.name) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual('Compute Micro PRD', sizes[0].name) self.assertEqual('105', sizes[0].id) self.assertEqual(384, sizes[0].ram) self.assertEqual('Compute Large PRD', sizes[2].name) self.assertEqual('69', sizes[2].id) self.assertEqual(6964, sizes[2].ram) def test_ex_start_node(self): node = self.driver.list_nodes()[0] res = node.ex_start() self.assertEqual('Starting', res) def test_ex_stop_node(self): node = self.driver.list_nodes()[0] res = node.ex_stop() self.assertEqual('Stopped', res) def test_destroy_node(self): node = self.driver.list_nodes()[0] res = node.destroy() self.assertTrue(res) def test_expunge_node(self): node = self.driver.list_nodes()[0] res = self.driver.destroy_node(node, ex_expunge=True) self.assertTrue(res) def test_reboot_node(self): node = self.driver.list_nodes()[0] res = node.reboot() self.assertTrue(res) def test_list_key_pairs(self): keypairs = self.driver.list_key_pairs() fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \ '00:00:00:00:00' self.assertEqual(keypairs[0].name, 'cs-keypair') self.assertEqual(keypairs[0].fingerprint, fingerprint) # Test old and deprecated way keypairs = self.driver.ex_list_keypairs() self.assertEqual(keypairs[0]['name'], 'cs-keypair') self.assertEqual(keypairs[0]['fingerprint'], fingerprint) def test_list_key_pairs_no_keypair_key(self): CloudStackMockHttp.fixture_tag = 'no_keys' keypairs = self.driver.list_key_pairs() self.assertEqual(keypairs, []) def test_get_key_pair(self): CloudStackMockHttp.fixture_tag = 'get_one' key_pair = self.driver.get_key_pair(name='cs-keypair') self.assertEqual(key_pair.name, 'cs-keypair') def test_get_key_pair_doesnt_exist(self): CloudStackMockHttp.fixture_tag = 'get_one_doesnt_exist' self.assertRaises(KeyPairDoesNotExistError, self.driver.get_key_pair, name='does-not-exist') def test_create_keypair(self): key_pair = self.driver.create_key_pair(name='test-keypair') self.assertEqual(key_pair.name, 'test-keypair') self.assertTrue(key_pair.fingerprint is not None) self.assertTrue(key_pair.private_key is not None) # Test old and deprecated way res = self.driver.ex_create_keypair(name='test-keypair') self.assertEqual(res['name'], 'test-keypair') self.assertTrue(res['fingerprint'] is not None) self.assertTrue(res['privateKey'] is not None) def test_import_keypair_from_file(self): fingerprint = 'c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15' path = os.path.join(os.path.dirname(__file__), 'fixtures', 'cloudstack', 'dummy_rsa.pub') key_pair = self.driver.import_key_pair_from_file('foobar', path) self.assertEqual(key_pair.name, 'foobar') self.assertEqual(key_pair.fingerprint, fingerprint) # Test old and deprecated way res = self.driver.ex_import_keypair('foobar', path) self.assertEqual(res['keyName'], 'foobar') self.assertEqual(res['keyFingerprint'], fingerprint) def test_ex_import_keypair_from_string(self): fingerprint = 'c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15' path = os.path.join(os.path.dirname(__file__), 'fixtures', 'cloudstack', 'dummy_rsa.pub') fh = open(path) key_material = fh.read() fh.close() key_pair = self.driver.import_key_pair_from_string('foobar', key_material=key_material) self.assertEqual(key_pair.name, 'foobar') self.assertEqual(key_pair.fingerprint, fingerprint) # Test old and deprecated way res = self.driver.ex_import_keypair_from_string('foobar', key_material=key_material) self.assertEqual(res['keyName'], 'foobar') self.assertEqual(res['keyFingerprint'], fingerprint) def test_delete_key_pair(self): key_pair = self.driver.list_key_pairs()[0] res = self.driver.delete_key_pair(key_pair=key_pair) self.assertTrue(res) # Test old and deprecated way res = self.driver.ex_delete_keypair(keypair='cs-keypair') self.assertTrue(res) def test_ex_list_security_groups(self): groups = self.driver.ex_list_security_groups() self.assertEqual(2, len(groups)) self.assertEqual(groups[0]['name'], 'default') self.assertEqual(groups[1]['name'], 'mongodb') def test_ex_list_security_groups_no_securitygroup_key(self): CloudStackMockHttp.fixture_tag = 'no_groups' groups = self.driver.ex_list_security_groups() self.assertEqual(groups, []) def test_ex_create_security_group(self): group = self.driver.ex_create_security_group(name='MySG') self.assertEqual(group['name'], 'MySG') def test_ex_delete_security_group(self): res = self.driver.ex_delete_security_group(name='MySG') self.assertTrue(res) def test_ex_authorize_security_group_ingress(self): res = self.driver.ex_authorize_security_group_ingress('test_sg', 'udp', '0.0.0.0/0', '0', '65535') self.assertEqual(res.get('name'), 'test_sg') self.assertTrue('ingressrule' in res) rules = res['ingressrule'] self.assertEqual(len(rules), 1) rule = rules[0] self.assertEqual(rule['cidr'], '0.0.0.0/0') self.assertEqual(rule['endport'], 65535) self.assertEqual(rule['protocol'], 'udp') self.assertEqual(rule['startport'], 0) def test_ex_create_affinity_group(self): res = self.driver.ex_create_affinity_group('MyAG2', CloudStackAffinityGroupType('MyAGType')) self.assertEqual(res.name, 'MyAG2') self.assertIsInstance(res.type, CloudStackAffinityGroupType) self.assertEqual(res.type.type, 'MyAGType') def test_ex_create_affinity_group_already_exists(self): self.assertRaises(LibcloudError, self.driver.ex_create_affinity_group, 'MyAG', CloudStackAffinityGroupType('MyAGType')) def test_delete_ex_affinity_group(self): afg = self.driver.ex_create_affinity_group('MyAG3', CloudStackAffinityGroupType('MyAGType')) res = self.driver.ex_delete_affinity_group(afg) self.assertTrue(res) def test_ex_update_node_affinity_group(self): affinity_group_list = self.driver.ex_list_affinity_groups() nodes = self.driver.list_nodes() node = self.driver.ex_update_node_affinity_group(nodes[0], affinity_group_list) self.assertEqual(node.extra['affinity_group'][0], affinity_group_list[0].id) def test_ex_list_affinity_groups(self): res = self.driver.ex_list_affinity_groups() self.assertEqual(len(res), 1) self.assertEqual(res[0].id, '11112') self.assertEqual(res[0].name, 'MyAG') self.assertIsInstance(res[0].type, CloudStackAffinityGroupType) self.assertEqual(res[0].type.type, 'MyAGType') def test_ex_list_affinity_group_types(self): res = self.driver.ex_list_affinity_group_types() self.assertEqual(len(res), 1) self.assertIsInstance(res[0], CloudStackAffinityGroupType) self.assertEqual(res[0].type, 'MyAGType') def test_ex_list_public_ips(self): ips = self.driver.ex_list_public_ips() self.assertEqual(ips[0].address, '1.1.1.116') self.assertEqual(ips[0].virtualmachine_id, '2600') def test_ex_allocate_public_ip(self): addr = self.driver.ex_allocate_public_ip() self.assertEqual(addr.address, '7.5.6.1') self.assertEqual(addr.id, '10987171-8cc9-4d0a-b98f-1698c09ddd2d') def test_ex_release_public_ip(self): addresses = self.driver.ex_list_public_ips() res = self.driver.ex_release_public_ip(addresses[0]) self.assertTrue(res) def test_ex_create_port_forwarding_rule(self): node = self.driver.list_nodes()[0] address = self.driver.ex_list_public_ips()[0] private_port = 33 private_end_port = 34 public_port = 33 public_end_port = 34 openfirewall = True protocol = 'TCP' rule = self.driver.ex_create_port_forwarding_rule(node, address, private_port, public_port, protocol, public_end_port, private_end_port, openfirewall) self.assertEqual(rule.address, address) self.assertEqual(rule.protocol, protocol) self.assertEqual(rule.public_port, public_port) self.assertEqual(rule.public_end_port, public_end_port) self.assertEqual(rule.private_port, private_port) self.assertEqual(rule.private_end_port, private_end_port) def test_ex_list_firewall_rules(self): rules = self.driver.ex_list_firewall_rules() self.assertEqual(len(rules), 1) rule = rules[0] self.assertEqual(rule.address.address, '1.1.1.116') self.assertEqual(rule.protocol, 'tcp') self.assertEqual(rule.cidr_list, '192.168.0.0/16') self.assertIsNone(rule.icmp_code) self.assertIsNone(rule.icmp_type) self.assertEqual(rule.start_port, '33') self.assertEqual(rule.end_port, '34') def test_ex_list_firewall_rules_icmp(self): CloudStackMockHttp.fixture_tag = 'firewallicmp' rules = self.driver.ex_list_firewall_rules() self.assertEqual(len(rules), 1) rule = rules[0] self.assertEqual(rule.address.address, '1.1.1.116') self.assertEqual(rule.protocol, 'icmp') self.assertEqual(rule.cidr_list, '192.168.0.0/16') self.assertEqual(rule.icmp_code, 0) self.assertEqual(rule.icmp_type, 8) self.assertIsNone(rule.start_port) self.assertIsNone(rule.end_port) def test_ex_delete_firewall_rule(self): rules = self.driver.ex_list_firewall_rules() res = self.driver.ex_delete_firewall_rule(rules[0]) self.assertTrue(res) def test_ex_create_firewall_rule(self): address = self.driver.ex_list_public_ips()[0] cidr_list = '192.168.0.0/16' protocol = 'TCP' start_port = 33 end_port = 34 rule = self.driver.ex_create_firewall_rule(address, cidr_list, protocol, start_port=start_port, end_port=end_port) self.assertEqual(rule.address, address) self.assertEqual(rule.protocol, protocol) self.assertIsNone(rule.icmp_code) self.assertIsNone(rule.icmp_type) self.assertEqual(rule.start_port, start_port) self.assertEqual(rule.end_port, end_port) def test_ex_create_firewall_rule_icmp(self): address = self.driver.ex_list_public_ips()[0] cidr_list = '192.168.0.0/16' protocol = 'icmp' icmp_code = 0 icmp_type = 8 rule = self.driver.ex_create_firewall_rule(address, cidr_list, protocol, icmp_code=icmp_code, icmp_type=icmp_type) self.assertEqual(rule.address, address) self.assertEqual(rule.protocol, protocol) self.assertEqual(rule.icmp_code, 0) self.assertEqual(rule.icmp_type, 8) self.assertIsNone(rule.start_port) self.assertIsNone(rule.end_port) def test_ex_list_egress_firewall_rules(self): rules = self.driver.ex_list_egress_firewall_rules() self.assertEqual(len(rules), 1) rule = rules[0] self.assertEqual(rule.network_id, '874be2ca-20a7-4360-80e9-7356c0018c0b') self.assertEqual(rule.cidr_list, '192.168.0.0/16') self.assertEqual(rule.protocol, 'tcp') self.assertIsNone(rule.icmp_code) self.assertIsNone(rule.icmp_type) self.assertEqual(rule.start_port, '80') self.assertEqual(rule.end_port, '80') def test_ex_delete_egress_firewall_rule(self): rules = self.driver.ex_list_egress_firewall_rules() res = self.driver.ex_delete_egress_firewall_rule(rules[0]) self.assertTrue(res) def test_ex_create_egress_firewall_rule(self): network_id = '874be2ca-20a7-4360-80e9-7356c0018c0b' cidr_list = '192.168.0.0/16' protocol = 'TCP' start_port = 33 end_port = 34 rule = self.driver.ex_create_egress_firewall_rule( network_id, cidr_list, protocol, start_port=start_port, end_port=end_port) self.assertEqual(rule.network_id, network_id) self.assertEqual(rule.cidr_list, cidr_list) self.assertEqual(rule.protocol, protocol) self.assertIsNone(rule.icmp_code) self.assertIsNone(rule.icmp_type) self.assertEqual(rule.start_port, start_port) self.assertEqual(rule.end_port, end_port) def test_ex_list_port_forwarding_rules(self): rules = self.driver.ex_list_port_forwarding_rules() self.assertEqual(len(rules), 1) rule = rules[0] self.assertTrue(rule.node) self.assertEqual(rule.protocol, 'tcp') self.assertEqual(rule.public_port, '33') self.assertEqual(rule.public_end_port, '34') self.assertEqual(rule.private_port, '33') self.assertEqual(rule.private_end_port, '34') self.assertEqual(rule.address.address, '1.1.1.116') def test_ex_delete_port_forwarding_rule(self): node = self.driver.list_nodes()[0] rule = self.driver.ex_list_port_forwarding_rules()[0] res = self.driver.ex_delete_port_forwarding_rule(node, rule) self.assertTrue(res) def test_node_ex_delete_port_forwarding_rule(self): node = self.driver.list_nodes()[0] self.assertEqual(len(node.extra['port_forwarding_rules']), 1) node.extra['port_forwarding_rules'][0].delete() self.assertEqual(len(node.extra['port_forwarding_rules']), 0) def test_node_ex_create_port_forwarding_rule(self): node = self.driver.list_nodes()[0] self.assertEqual(len(node.extra['port_forwarding_rules']), 1) address = self.driver.ex_list_public_ips()[0] private_port = 33 private_end_port = 34 public_port = 33 public_end_port = 34 openfirewall = True protocol = 'TCP' rule = node.ex_create_port_forwarding_rule(address, private_port, public_port, protocol, public_end_port, private_end_port, openfirewall) self.assertEqual(rule.address, address) self.assertEqual(rule.protocol, protocol) self.assertEqual(rule.public_port, public_port) self.assertEqual(rule.public_end_port, public_end_port) self.assertEqual(rule.private_port, private_port) self.assertEqual(rule.private_end_port, private_end_port) self.assertEqual(len(node.extra['port_forwarding_rules']), 2) def test_ex_list_ip_forwarding_rules(self): rules = self.driver.ex_list_ip_forwarding_rules() self.assertEqual(len(rules), 1) rule = rules[0] self.assertTrue(rule.node) self.assertEqual(rule.protocol, 'tcp') self.assertEqual(rule.start_port, 33) self.assertEqual(rule.end_port, 34) self.assertEqual(rule.address.address, '1.1.1.116') def test_ex_limits(self): limits = self.driver.ex_limits() self.assertEqual(limits['max_images'], 20) self.assertEqual(limits['max_networks'], 20) self.assertEqual(limits['max_public_ips'], -1) self.assertEqual(limits['max_vpc'], 20) self.assertEqual(limits['max_instances'], 20) self.assertEqual(limits['max_projects'], -1) self.assertEqual(limits['max_volumes'], 20) self.assertEqual(limits['max_snapshots'], 20) def test_ex_create_tags(self): node = self.driver.list_nodes()[0] tags = {'Region': 'Canada'} resp = self.driver.ex_create_tags([node.id], 'UserVm', tags) self.assertTrue(resp) def test_ex_delete_tags(self): node = self.driver.list_nodes()[0] tag_keys = ['Region'] resp = self.driver.ex_delete_tags([node.id], 'UserVm', tag_keys) self.assertTrue(resp) def test_list_snapshots(self): snapshots = self.driver.list_snapshots() self.assertEqual(len(snapshots), 3) snap = snapshots[0] self.assertEqual(snap.id, 188402) self.assertEqual(snap.extra['name'], "i-123-87654-VM_ROOT-12344_20140917105548") self.assertEqual(snap.extra['volume_id'], 89341) def test_create_volume_snapshot(self): volume = self.driver.list_volumes()[0] snapshot = self.driver.create_volume_snapshot(volume) self.assertEqual(snapshot.id, 190547) self.assertEqual(snapshot.extra['name'], "i-123-87654-VM_ROOT-23456_20140917105548") self.assertEqual(snapshot.extra['volume_id'], "fe1ada16-57a0-40ae-b577-01a153690fb4") def test_destroy_volume_snapshot(self): snapshot = self.driver.list_snapshots()[0] resp = self.driver.destroy_volume_snapshot(snapshot) self.assertTrue(resp) def test_ex_create_snapshot_template(self): snapshot = self.driver.list_snapshots()[0] template = self.driver.ex_create_snapshot_template(snapshot, "test-libcloud-template", 99) self.assertEqual(template.id, '10260') self.assertEqual(template.name, "test-libcloud-template") self.assertEqual(template.extra['displaytext'], "test-libcloud-template") self.assertEqual(template.extra['hypervisor'], "VMware") self.assertEqual(template.extra['os'], "Other Linux (64-bit)") def test_ex_list_os_types(self): os_types = self.driver.ex_list_os_types() self.assertEqual(len(os_types), 146) self.assertEqual(os_types[0]['id'], 69) self.assertEqual(os_types[0]['oscategoryid'], 7) self.assertEqual(os_types[0]['description'], "Asianux 3(32-bit)") def test_ex_list_vpn_gateways(self): vpn_gateways = self.driver.ex_list_vpn_gateways() self.assertEqual(len(vpn_gateways), 1) self.assertEqual(vpn_gateways[0].id, 'cffa0cab-d1da-42a7-92f6-41379267a29f') self.assertEqual(vpn_gateways[0].account, 'some_account') self.assertEqual(vpn_gateways[0].domain, 'some_domain') self.assertEqual(vpn_gateways[0].domain_id, '9b397dea-25ef-4c5d-b47d-627eaebe8ed8') self.assertEqual(vpn_gateways[0].public_ip, '1.2.3.4') self.assertEqual(vpn_gateways[0].vpc_id, '4d25e181-8850-4d52-8ecb-a6f35bbbabde') def test_ex_create_vpn_gateway(self): vpc = self.driver.ex_list_vpcs()[0] vpn_gateway = self.driver.ex_create_vpn_gateway(vpc) self.assertEqual(vpn_gateway.id, '5ef6794e-cec8-4018-9fef-c4dacbadee14') self.assertEqual(vpn_gateway.account, 'some_account') self.assertEqual(vpn_gateway.domain, 'some_domain') self.assertEqual(vpn_gateway.domain_id, '9b397dea-25ef-4c5d-b47d-627eaebe8ed8') self.assertEqual(vpn_gateway.public_ip, '2.3.4.5') self.assertEqual(vpn_gateway.vpc_id, vpc.id) def test_ex_delete_vpn_gateway(self): vpn_gateway = self.driver.ex_list_vpn_gateways()[0] self.assertTrue(vpn_gateway.delete()) def test_ex_list_vpn_customer_gateways(self): vpn_customer_gateways = self.driver.ex_list_vpn_customer_gateways() self.assertEqual(len(vpn_customer_gateways), 1) self.assertEqual(vpn_customer_gateways[0].id, 'ea67eaae-1c2a-4e65-b910-441e77f69bea') self.assertEqual(vpn_customer_gateways[0].cidr_list, '10.2.2.0/24') self.assertEqual(vpn_customer_gateways[0].esp_policy, '3des-md5') self.assertEqual(vpn_customer_gateways[0].gateway, '10.2.2.1') self.assertEqual(vpn_customer_gateways[0].ike_policy, '3des-md5') self.assertEqual(vpn_customer_gateways[0].ipsec_psk, 'some_psk') def test_ex_create_vpn_customer_gateway(self): vpn_customer_gateway = self.driver.ex_create_vpn_customer_gateway( cidr_list='10.0.0.0/24', esp_policy='3des-md5', gateway='10.0.0.1', ike_policy='3des-md5', ipsec_psk='ipsecpsk') self.assertEqual(vpn_customer_gateway.id, 'cef3c766-116a-4e83-9844-7d08ab7d3fd4') self.assertEqual(vpn_customer_gateway.esp_policy, '3des-md5') self.assertEqual(vpn_customer_gateway.gateway, '10.0.0.1') self.assertEqual(vpn_customer_gateway.ike_policy, '3des-md5') self.assertEqual(vpn_customer_gateway.ipsec_psk, 'ipsecpsk') def test_ex_ex_delete_vpn_customer_gateway(self): vpn_customer_gateway = self.driver.ex_list_vpn_customer_gateways()[0] self.assertTrue(vpn_customer_gateway.delete()) def test_ex_list_vpn_connections(self): vpn_connections = self.driver.ex_list_vpn_connections() self.assertEqual(len(vpn_connections), 1) self.assertEqual(vpn_connections[0].id, '8f482d9a-6cee-453b-9e78-b0e1338ffce9') self.assertEqual(vpn_connections[0].passive, False) self.assertEqual(vpn_connections[0].vpn_customer_gateway_id, 'ea67eaae-1c2a-4e65-b910-441e77f69bea') self.assertEqual(vpn_connections[0].vpn_gateway_id, 'cffa0cab-d1da-42a7-92f6-41379267a29f') self.assertEqual(vpn_connections[0].state, 'Connected') def test_ex_create_vpn_connection(self): vpn_customer_gateway = self.driver.ex_list_vpn_customer_gateways()[0] vpn_gateway = self.driver.ex_list_vpn_gateways()[0] vpn_connection = self.driver.ex_create_vpn_connection( vpn_customer_gateway, vpn_gateway) self.assertEqual(vpn_connection.id, 'f45c3af8-f909-4f16-9d40-ed4409c575f8') self.assertEqual(vpn_connection.passive, False) self.assertEqual(vpn_connection.vpn_customer_gateway_id, 'ea67eaae-1c2a-4e65-b910-441e77f69bea') self.assertEqual(vpn_connection.vpn_gateway_id, 'cffa0cab-d1da-42a7-92f6-41379267a29f') self.assertEqual(vpn_connection.state, 'Connected') def test_ex_delete_vpn_connection(self): vpn_connection = self.driver.ex_list_vpn_connections()[0] self.assertTrue(vpn_connection.delete()) class CloudStackTestCase(CloudStackCommonTestCase, unittest.TestCase): def test_driver_instantiation(self): urls = [ 'http://api.exoscale.ch/compute1', # http, default port 'https://api.exoscale.ch/compute2', # https, default port 'http://api.exoscale.ch:8888/compute3', # https, custom port 'https://api.exoscale.ch:8787/compute4', # https, custom port 'https://api.test.com/compute/endpoint' # https, default port ] expected_values = [ {'host': 'api.exoscale.ch', 'port': 80, 'path': '/compute1'}, {'host': 'api.exoscale.ch', 'port': 443, 'path': '/compute2'}, {'host': 'api.exoscale.ch', 'port': 8888, 'path': '/compute3'}, {'host': 'api.exoscale.ch', 'port': 8787, 'path': '/compute4'}, {'host': 'api.test.com', 'port': 443, 'path': '/compute/endpoint'} ] cls = get_driver(Provider.CLOUDSTACK) for url, expected in zip(urls, expected_values): driver = cls('key', 'secret', url=url) self.assertEqual(driver.host, expected['host']) self.assertEqual(driver.path, expected['path']) self.assertEqual(driver.connection.port, expected['port']) def test_user_must_provide_host_and_path_or_url(self): expected_msg = ('When instantiating CloudStack driver directly ' 'you also need to provide url or host and path ' 'argument') cls = get_driver(Provider.CLOUDSTACK) assertRaisesRegex(self, Exception, expected_msg, cls, 'key', 'secret') try: cls('key', 'secret', True, 'localhost', '/path') except Exception: self.fail('host and path provided but driver raised an exception') try: cls('key', 'secret', url='https://api.exoscale.ch/compute') except Exception: self.fail('url provided but driver raised an exception') def test_restore(self): template = NodeImage("aaa-bbb-ccc-ddd", "fake-img", None) node = self.driver.list_nodes()[0] res = node.ex_restore(template=template) self.assertEqual(res, template.id) def test_change_offerings(self): offering = NodeSize("eee-fff-ggg-hhh", "fake-size", 1, 4, 5, 0.1, None) node = self.driver.list_nodes()[0] res = node.ex_change_node_size(offering=offering) self.assertEqual(res, offering.id) class CloudStackMockHttp(MockHttp, unittest.TestCase): fixtures = ComputeFileFixtures('cloudstack') fixture_tag = 'default' def _load_fixture(self, fixture): body = self.fixtures.load(fixture) return body, json.loads(body) def _test_path_invalid_credentials(self, method, url, body, headers): body = '' return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.UNAUTHORIZED]) def _test_path_api_error(self, method, url, body, headers): body = self.fixtures.load('registerSSHKeyPair_error.json') return (431, body, {}, httplib.responses[httplib.OK]) def _test_path(self, method, url, body, headers): url = urlparse.urlparse(url) query = dict(parse_qsl(url.query)) self.assertTrue('apiKey' in query) self.assertTrue('command' in query) self.assertTrue('response' in query) self.assertTrue('signature' in query) self.assertTrue(query['response'] == 'json') del query['apiKey'] del query['response'] del query['signature'] command = query.pop('command') if hasattr(self, '_cmd_' + command): return getattr(self, '_cmd_' + command)(**query) else: fixture = command + '_' + self.fixture_tag + '.json' body, obj = self._load_fixture(fixture) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _test_path_userdata(self, method, url, body, headers): if 'deployVirtualMachine' in url: self.assertUrlContainsQueryParams(url, {'userdata': 'Zm9vYmFy'}) return self._test_path(method, url, body, headers) def _cmd_queryAsyncJobResult(self, jobid): fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json' body, obj = self._load_fixture(fixture) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_cloudwatt.py0000664000175000017500000000250513535474530024305 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest from libcloud.compute.drivers.cloudwatt import CloudwattNodeDriver from libcloud.test.compute.test_openstack import OpenStack_1_1_Tests class CloudwattNodeDriverTests(OpenStack_1_1_Tests, unittest.TestCase): driver_klass = CloudwattNodeDriver driver_type = CloudwattNodeDriver # These tests dont work because cloudwatt doesn't pass, # auth tokens- hide them from the base class def test_ex_force_auth_token_passed_to_connection(self): pass def test_auth_token_without_base_url_raises_exception(self): pass apache-libcloud-2.8.0/libcloud/test/compute/test_deployment.py0000664000175000017500000005617313577507766024507 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more§ # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import os import sys import time import unittest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import u from libcloud.utils.py3 import PY3 from libcloud.compute.deployment import MultiStepDeployment, Deployment from libcloud.compute.deployment import SSHKeyDeployment, ScriptDeployment from libcloud.compute.deployment import ScriptFileDeployment, FileDeployment from libcloud.compute.base import Node from libcloud.compute.base import NodeAuthPassword from libcloud.compute.types import NodeState, DeploymentError, LibcloudError from libcloud.compute.ssh import BaseSSHClient from libcloud.compute.drivers.rackspace import RackspaceFirstGenNodeDriver as Rackspace from libcloud.test import MockHttp, XML_HEADERS from libcloud.test.file_fixtures import ComputeFileFixtures from mock import Mock, patch from libcloud.test.secrets import RACKSPACE_PARAMS # Keyword arguments which are specific to deploy_node() method, but not # create_node() DEPLOY_NODE_KWARGS = ['deploy', 'ssh_username', 'ssh_alternate_usernames', 'ssh_port', 'ssh_timeout', 'ssh_key', 'timeout', 'max_tries', 'ssh_interface'] class MockDeployment(Deployment): def run(self, node, client): return node class MockClient(BaseSSHClient): def __init__(self, *args, **kwargs): self.stdout = '' self.stderr = '' self.exit_status = 0 def put(self, path, contents, chmod=755, mode='w'): return contents def run(self, name): return self.stdout, self.stderr, self.exit_status def delete(self, name): return True class DeploymentTests(unittest.TestCase): def setUp(self): Rackspace.connectionCls.conn_class = RackspaceMockHttp RackspaceMockHttp.type = None self.driver = Rackspace(*RACKSPACE_PARAMS) # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() self.driver.features = {'create_node': ['generates_password']} self.node = Node(id=12345, name='test', state=NodeState.RUNNING, public_ips=['1.2.3.4'], private_ips=['1.2.3.5'], driver=Rackspace) self.node2 = Node(id=123456, name='test', state=NodeState.RUNNING, public_ips=['1.2.3.4'], private_ips=['1.2.3.5'], driver=Rackspace) def test_multi_step_deployment(self): msd = MultiStepDeployment() self.assertEqual(len(msd.steps), 0) msd.add(MockDeployment()) self.assertEqual(len(msd.steps), 1) self.assertEqual(self.node, msd.run(node=self.node, client=None)) def test_ssh_key_deployment(self): sshd = SSHKeyDeployment(key='1234') self.assertEqual(self.node, sshd.run(node=self.node, client=MockClient(hostname='localhost'))) def test_file_deployment(self): # use this file (__file__) for obtaining permissions target = os.path.join('/tmp', os.path.basename(__file__)) fd = FileDeployment(__file__, target) self.assertEqual(target, fd.target) self.assertEqual(__file__, fd.source) self.assertEqual(self.node, fd.run( node=self.node, client=MockClient(hostname='localhost'))) def test_script_deployment(self): sd1 = ScriptDeployment(script='foobar', delete=True) sd2 = ScriptDeployment(script='foobar', delete=False) sd3 = ScriptDeployment( script='foobar', delete=False, name='foobarname') self.assertTrue(sd1.name.find('deployment') != '1') self.assertEqual(sd3.name, 'foobarname') self.assertEqual(self.node, sd1.run(node=self.node, client=MockClient(hostname='localhost'))) self.assertEqual(self.node, sd2.run(node=self.node, client=MockClient(hostname='localhost'))) def test_script_file_deployment(self): file_path = os.path.abspath(__file__) with open(file_path, 'rb') as fp: content = fp.read() if PY3: content = content.decode('utf-8') sfd1 = ScriptFileDeployment(script_file=file_path) self.assertEqual(sfd1.script, content) def test_script_deployment_relative_path(self): client = Mock() client.put.return_value = '/home/ubuntu/relative.sh' client.run.return_value = ('', '', 0) sd = ScriptDeployment(script='echo "foo"', name='relative.sh') sd.run(self.node, client) client.run.assert_called_once_with('/home/ubuntu/relative.sh') def test_script_deployment_absolute_path(self): client = Mock() client.put.return_value = '/home/ubuntu/relative.sh' client.run.return_value = ('', '', 0) sd = ScriptDeployment(script='echo "foo"', name='/root/relative.sh') sd.run(self.node, client) client.run.assert_called_once_with('/root/relative.sh') def test_script_deployment_with_arguments(self): client = Mock() client.put.return_value = '/home/ubuntu/relative.sh' client.run.return_value = ('', '', 0) args = ['arg1', 'arg2', '--option1=test'] sd = ScriptDeployment(script='echo "foo"', args=args, name='/root/relative.sh') sd.run(self.node, client) expected = '/root/relative.sh arg1 arg2 --option1=test' client.run.assert_called_once_with(expected) client.reset_mock() args = [] sd = ScriptDeployment(script='echo "foo"', args=args, name='/root/relative.sh') sd.run(self.node, client) expected = '/root/relative.sh' client.run.assert_called_once_with(expected) def test_script_file_deployment_with_arguments(self): file_path = os.path.abspath(__file__) client = Mock() client.put.return_value = '/home/ubuntu/relative.sh' client.run.return_value = ('', '', 0) args = ['arg1', 'arg2', '--option1=test', 'option2'] sfd = ScriptFileDeployment(script_file=file_path, args=args, name='/root/relative.sh') sfd.run(self.node, client) expected = '/root/relative.sh arg1 arg2 --option1=test option2' client.run.assert_called_once_with(expected) def test_script_deployment_and_sshkey_deployment_argument_types(self): class FileObject(object): def __init__(self, name): self.name = name def read(self): return 'bar' ScriptDeployment(script='foobar') ScriptDeployment(script=u('foobar')) ScriptDeployment(script=FileObject('test')) SSHKeyDeployment(key='foobar') SSHKeyDeployment(key=u('foobar')) SSHKeyDeployment(key=FileObject('test')) try: ScriptDeployment(script=[]) except TypeError: pass else: self.fail('TypeError was not thrown') try: SSHKeyDeployment(key={}) except TypeError: pass else: self.fail('TypeError was not thrown') def test_wait_until_running_running_instantly(self): node2, ips = self.driver.wait_until_running( nodes=[self.node], wait_period=0.1, timeout=0.5)[0] self.assertEqual(self.node.uuid, node2.uuid) self.assertEqual(['67.23.21.33'], ips) def test_wait_until_running_without_ip(self): RackspaceMockHttp.type = 'NO_IP' try: node2, ips = self.driver.wait_until_running( nodes=[self.node], wait_period=0.1, timeout=0.2)[0] except LibcloudError as e: self.assertTrue(e.value.find('Timed out after 0.2 second') != -1) else: self.fail('Exception was not thrown') def test_wait_until_running_with_only_ipv6(self): RackspaceMockHttp.type = 'IPV6' try: node2, ips = self.driver.wait_until_running( nodes=[self.node], wait_period=0.1, timeout=0.2)[0] except LibcloudError as e: self.assertTrue(e.value.find('Timed out after 0.2 second') != -1) else: self.fail('Exception was not thrown') def test_wait_until_running_with_ipv6_ok(self): RackspaceMockHttp.type = 'IPV6' node2, ips = self.driver.wait_until_running( nodes=[self.node], wait_period=1, force_ipv4=False, timeout=0.5)[0] self.assertEqual(self.node.uuid, node2.uuid) self.assertEqual(['2001:DB8::1'], ips) def test_wait_until_running_running_after_0_2_second(self): RackspaceMockHttp.type = '05_SECOND_DELAY' node2, ips = self.driver.wait_until_running( nodes=[self.node], wait_period=0.2, timeout=0.1)[0] self.assertEqual(self.node.uuid, node2.uuid) self.assertEqual(['67.23.21.33'], ips) def test_wait_until_running_running_after_0_2_second_private_ips(self): RackspaceMockHttp.type = '05_SECOND_DELAY' node2, ips = self.driver.wait_until_running( nodes=[self.node], wait_period=0.2, timeout=0.1, ssh_interface='private_ips')[0] self.assertEqual(self.node.uuid, node2.uuid) self.assertEqual(['10.176.168.218'], ips) def test_wait_until_running_invalid_ssh_interface_argument(self): try: self.driver.wait_until_running(nodes=[self.node], wait_period=1, ssh_interface='invalid') except ValueError: pass else: self.fail('Exception was not thrown') def test_wait_until_running_timeout(self): RackspaceMockHttp.type = 'TIMEOUT' try: self.driver.wait_until_running(nodes=[self.node], wait_period=0.1, timeout=0.2) except LibcloudError as e: self.assertTrue(e.value.find('Timed out') != -1) else: self.fail('Exception was not thrown') def test_wait_until_running_running_node_missing_from_list_nodes(self): RackspaceMockHttp.type = 'MISSING' try: self.driver.wait_until_running(nodes=[self.node], wait_period=0.1, timeout=0.2) except LibcloudError as e: self.assertTrue(e.value.find('Timed out after 0.2 second') != -1) else: self.fail('Exception was not thrown') def test_wait_until_running_running_multiple_nodes_have_same_uuid(self): RackspaceMockHttp.type = 'SAME_UUID' try: self.driver.wait_until_running(nodes=[self.node], wait_period=0.1, timeout=0.2) except LibcloudError as e: self.assertTrue( e.value.find('Unable to match specified uuids') != -1) else: self.fail('Exception was not thrown') def test_wait_until_running_running_wait_for_multiple_nodes(self): RackspaceMockHttp.type = 'MULTIPLE_NODES' nodes = self.driver.wait_until_running( nodes=[self.node, self.node2], wait_period=0.1, timeout=0.5) self.assertEqual(self.node.uuid, nodes[0][0].uuid) self.assertEqual(self.node2.uuid, nodes[1][0].uuid) self.assertEqual(['67.23.21.33'], nodes[0][1]) self.assertEqual(['67.23.21.34'], nodes[1][1]) def test_ssh_client_connect_success(self): mock_ssh_client = Mock() mock_ssh_client.return_value = None ssh_client = self.driver._ssh_client_connect( ssh_client=mock_ssh_client, timeout=0.5) self.assertEqual(mock_ssh_client, ssh_client) def test_ssh_client_connect_timeout(self): mock_ssh_client = Mock() mock_ssh_client.connect = Mock() mock_ssh_client.connect.side_effect = IOError('bam') try: self.driver._ssh_client_connect(ssh_client=mock_ssh_client, wait_period=0.1, timeout=0.2) except LibcloudError as e: self.assertTrue(e.value.find('Giving up') != -1) else: self.fail('Exception was not thrown') def test_run_deployment_script_success(self): task = Mock() ssh_client = Mock() ssh_client2 = self.driver._run_deployment_script(task=task, node=self.node, ssh_client=ssh_client, max_tries=2) self.assertTrue(isinstance(ssh_client2, Mock)) def test_run_deployment_script_exception(self): task = Mock() task.run = Mock() task.run.side_effect = Exception('bar') ssh_client = Mock() try: self.driver._run_deployment_script(task=task, node=self.node, ssh_client=ssh_client, max_tries=2) except LibcloudError as e: self.assertTrue(e.value.find('Failed after 2 tries') != -1) else: self.fail('Exception was not thrown') @patch('libcloud.compute.base.SSHClient') @patch('libcloud.compute.ssh') def test_deploy_node_success(self, mock_ssh_module, _): self.driver.create_node = Mock() self.driver.create_node.return_value = self.node mock_ssh_module.have_paramiko = True deploy = Mock() node = self.driver.deploy_node(deploy=deploy) self.assertEqual(self.node.id, node.id) @patch('libcloud.compute.base.SSHClient') @patch('libcloud.compute.ssh') def test_deploy_node_deploy_node_kwargs_except_auth_are_not_propagated_on(self, mock_ssh_module, _): # Verify that keyword arguments which are specific to deploy_node() # are not propagated to create_node() mock_ssh_module.have_paramiko = True self.driver.create_node = Mock() self.driver.create_node.return_value = self.node self.driver._connect_and_run_deployment_script = Mock() self.driver._wait_until_running = Mock() kwargs = {} for key in DEPLOY_NODE_KWARGS: kwargs[key] = key kwargs['ssh_interface'] = 'public_ips' kwargs['ssh_alternate_usernames'] = ['foo', 'bar'] kwargs['timeout'] = 10 auth = NodeAuthPassword('P@$$w0rd') node = self.driver.deploy_node(name='name', image='image', size='size', auth=auth, ex_foo='ex_foo', **kwargs) self.assertEqual(self.node.id, node.id) self.assertEqual(self.driver.create_node.call_count, 1) call_kwargs = self.driver.create_node.call_args_list[0][1] expected_call_kwargs = { 'name': 'name', 'image': 'image', 'size': 'size', 'auth': auth, 'ex_foo': 'ex_foo' } self.assertEqual(expected_call_kwargs, call_kwargs) # If driver throws an exception it should fall back to passing in all # the arguments global call_count call_count = 0 def create_node(name, image, size, ex_custom_arg_1, ex_custom_arg_2, ex_foo=None, auth=None, **kwargs): global call_count call_count += 1 if call_count == 1: msg = 'create_node() takes at least 5 arguments (7 given)' raise TypeError(msg) return self.node self.driver.create_node = create_node node = self.driver.deploy_node(name='name', image='image', size='size', auth=auth, ex_foo='ex_foo', ex_custom_arg_1='a', ex_custom_arg_2='b', **kwargs) self.assertEqual(self.node.id, node.id) self.assertEqual(call_count, 2) call_count = 0 def create_node(name, image, size, ex_custom_arg_1, ex_custom_arg_2, ex_foo=None, auth=None, **kwargs): global call_count call_count += 1 if call_count == 1: msg = 'create_node() missing 3 required positional arguments' raise TypeError(msg) return self.node self.driver.create_node = create_node node = self.driver.deploy_node(name='name', image='image', size='size', auth=auth, ex_foo='ex_foo', ex_custom_arg_1='a', ex_custom_arg_2='b', **kwargs) self.assertEqual(self.node.id, node.id) self.assertEqual(call_count, 2) @patch('libcloud.compute.base.SSHClient') @patch('libcloud.compute.ssh') def test_deploy_node_exception_run_deployment_script(self, mock_ssh_module, _): self.driver.create_node = Mock() self.driver.create_node.return_value = self.node mock_ssh_module.have_paramiko = True deploy = Mock() deploy.run = Mock() deploy.run.side_effect = Exception('foo') try: self.driver.deploy_node(deploy=deploy) except DeploymentError as e: self.assertTrue(e.node.id, self.node.id) else: self.fail('Exception was not thrown') @patch('libcloud.compute.base.SSHClient') @patch('libcloud.compute.ssh') def test_deploy_node_exception_ssh_client_connect(self, mock_ssh_module, ssh_client): self.driver.create_node = Mock() self.driver.create_node.return_value = self.node mock_ssh_module.have_paramiko = True deploy = Mock() ssh_client.side_effect = IOError('bar') try: self.driver.deploy_node(deploy=deploy) except DeploymentError as e: self.assertTrue(e.node.id, self.node.id) else: self.fail('Exception was not thrown') @patch('libcloud.compute.ssh') def test_deploy_node_depoy_node_not_implemented(self, mock_ssh_module): self.driver.features = {'create_node': []} mock_ssh_module.have_paramiko = True try: self.driver.deploy_node(deploy=Mock()) except NotImplementedError: pass else: self.fail('Exception was not thrown') self.driver.features = {} try: self.driver.deploy_node(deploy=Mock()) except NotImplementedError: pass else: self.fail('Exception was not thrown') @patch('libcloud.compute.base.SSHClient') @patch('libcloud.compute.ssh') def test_deploy_node_password_auth(self, mock_ssh_module, _): self.driver.features = {'create_node': ['password']} mock_ssh_module.have_paramiko = True self.driver.create_node = Mock() self.driver.create_node.return_value = self.node node = self.driver.deploy_node(deploy=Mock()) self.assertEqual(self.node.id, node.id) @patch('libcloud.compute.base.SSHClient') @patch('libcloud.compute.ssh') def test_exception_is_thrown_is_paramiko_is_not_available(self, mock_ssh_module, _): self.driver.features = {'create_node': ['password']} self.driver.create_node = Mock() self.driver.create_node.return_value = self.node mock_ssh_module.have_paramiko = False try: self.driver.deploy_node(deploy=Mock()) except RuntimeError as e: self.assertTrue(str(e).find('paramiko is not installed') != -1) else: self.fail('Exception was not thrown') mock_ssh_module.have_paramiko = True node = self.driver.deploy_node(deploy=Mock()) self.assertEqual(self.node.id, node.id) class RackspaceMockHttp(MockHttp): fixtures = ComputeFileFixtures('openstack') def _v2_0_tokens(self, method, url, body, headers): body = self.fixtures.load('_v2_0__auth_deployment.json') headers = { 'content-type': 'application/json' } return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail(self, method, url, body, headers): body = self.fixtures.load( 'v1_slug_servers_detail_deployment_success.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_05_SECOND_DELAY(self, method, url, body, headers): time.sleep(0.5) body = self.fixtures.load( 'v1_slug_servers_detail_deployment_success.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_TIMEOUT(self, method, url, body, headers): body = self.fixtures.load( 'v1_slug_servers_detail_deployment_pending.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_MISSING(self, method, url, body, headers): body = self.fixtures.load( 'v1_slug_servers_detail_deployment_missing.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_SAME_UUID(self, method, url, body, headers): body = self.fixtures.load( 'v1_slug_servers_detail_deployment_same_uuid.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_MULTIPLE_NODES(self, method, url, body, headers): body = self.fixtures.load( 'v1_slug_servers_detail_deployment_multiple_nodes.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_IPV6(self, method, url, body, headers): body = self.fixtures.load( 'v1_slug_servers_detail_deployment_ipv6.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_NO_IP(self, method, url, body, headers): body = self.fixtures.load( 'v1_slug_servers_detail_deployment_no_ip.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_digitalocean_v2.py0000664000175000017500000005704213570310635025331 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from datetime import datetime from libcloud.utils.iso8601 import UTC try: import simplejson as json except ImportError: import json # NOQA from libcloud.utils.py3 import httplib from libcloud.utils.py3 import assertRaisesRegex from libcloud.common.types import InvalidCredsError from libcloud.common.digitalocean import DigitalOcean_v1_Error from libcloud.compute.base import NodeImage from libcloud.compute.drivers.digitalocean import DigitalOceanNodeDriver from libcloud.test import LibcloudTestCase, MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import DIGITALOCEAN_v1_PARAMS from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS # class DigitalOceanTests(unittest.TestCase, TestCaseMixin): class DigitalOcean_v2_Tests(LibcloudTestCase): def setUp(self): DigitalOceanNodeDriver.connectionCls.conn_class = \ DigitalOceanMockHttp DigitalOceanMockHttp.type = None self.driver = DigitalOceanNodeDriver(*DIGITALOCEAN_v2_PARAMS) def test_v1_Error(self): self.assertRaises(DigitalOcean_v1_Error, DigitalOceanNodeDriver, *DIGITALOCEAN_v1_PARAMS, api_version='v1') def test_v2_uses_v1_key(self): self.assertRaises(InvalidCredsError, DigitalOceanNodeDriver, *DIGITALOCEAN_v1_PARAMS, api_version='v2') def test_authentication(self): DigitalOceanMockHttp.type = 'UNAUTHORIZED' self.assertRaises(InvalidCredsError, self.driver.list_nodes) def test_list_images_success(self): images = self.driver.list_images() self.assertTrue(len(images) >= 1) image = images[0] self.assertTrue(image.id is not None) self.assertTrue(image.name is not None) def test_list_sizes_success(self): sizes = self.driver.list_sizes() self.assertTrue(len(sizes) >= 1) size = sizes[0] self.assertTrue(size.id is not None) self.assertEqual(size.name, '512mb') self.assertEqual(size.ram, 512) size = sizes[1] self.assertTrue(size.id is not None) self.assertEqual(size.name, '1gb') self.assertEqual(size.ram, 1024) def test_list_locations_success(self): locations = self.driver.list_locations() self.assertTrue(len(locations) == 2) location = locations[0] self.assertEqual(location.id, 'nyc1') self.assertEqual(location.name, 'New York 1') locations = self.driver.list_locations(ex_available=True) self.assertTrue(len(locations) == 2) locations = self.driver.list_locations(ex_available=False) self.assertTrue(len(locations) == 3) def test_list_nodes_success(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].name, 'example.com') self.assertEqual(nodes[0].public_ips, ['104.236.32.182']) self.assertEqual(nodes[0].extra['image']['id'], 6918990) self.assertEqual(nodes[0].extra['size_slug'], '512mb') self.assertEqual(len(nodes[0].extra['tags']), 2) def test_list_nodes_fills_created_datetime(self): nodes = self.driver.list_nodes() self.assertEqual(nodes[0].created_at, datetime(2014, 11, 14, 16, 29, 21, tzinfo=UTC)) def test_create_node_invalid_size(self): image = NodeImage(id='invalid', name=None, driver=self.driver) size = self.driver.list_sizes()[0] location = self.driver.list_locations()[0] DigitalOceanMockHttp.type = 'INVALID_IMAGE' expected_msg = \ r'You specified an invalid image for Droplet creation. \(code: (404|HTTPStatus.NOT_FOUND)\)' assertRaisesRegex(self, Exception, expected_msg, self.driver.create_node, name='test', size=size, image=image, location=location) def test_reboot_node_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'REBOOT' result = self.driver.reboot_node(node) self.assertTrue(result) def test_create_image_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'SNAPSHOT' result = self.driver.create_image(node, 'My snapshot') self.assertTrue(result) def test_get_image_success(self): image = self.driver.get_image(12345) self.assertEqual(image.name, 'My snapshot') self.assertEqual(image.id, '12345') self.assertEqual(image.extra['distribution'], 'Ubuntu') def test_delete_image_success(self): image = self.driver.get_image(12345) DigitalOceanMockHttp.type = 'DESTROY' result = self.driver.delete_image(image) self.assertTrue(result) def test_ex_power_on_node_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'POWERON' result = self.driver.ex_power_on_node(node) self.assertTrue(result) def test_ex_shutdown_node_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'SHUTDOWN' result = self.driver.ex_shutdown_node(node) self.assertTrue(result) def test_ex_hard_reboot_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'POWERCYCLE' result = self.driver.ex_hard_reboot(node) self.assertTrue(result) def test_ex_rebuild_node_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'REBUILD' result = self.driver.ex_rebuild_node(node) self.assertTrue(result) def test_ex_resize_node_success(self): node = self.driver.list_nodes()[0] size = self.driver.list_sizes()[0] DigitalOceanMockHttp.type = 'RESIZE' result = self.driver.ex_resize_node(node, size) self.assertTrue(result) def test_destroy_node_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'DESTROY' result = self.driver.destroy_node(node) self.assertTrue(result) def test_ex_change_kernel_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'KERNELCHANGE' result = self.driver.ex_change_kernel(node, 7515) self.assertTrue(result) def test_ex_enable_ipv6_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'ENABLEIPV6' result = self.driver.ex_enable_ipv6(node) self.assertTrue(result) def test_ex_rename_node_success(self): node = self.driver.list_nodes()[0] DigitalOceanMockHttp.type = 'RENAME' result = self.driver.ex_rename_node(node, 'fedora helios') self.assertTrue(result) def test_list_key_pairs(self): keys = self.driver.list_key_pairs() self.assertEqual(len(keys), 1) self.assertEqual(keys[0].extra['id'], 7717) self.assertEqual(keys[0].name, 'test1') self.assertEqual(keys[0].public_key, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDGk5 example") def test_create_key_pair(self): DigitalOceanMockHttp.type = 'CREATE' key = self.driver.create_key_pair( name="test1", public_key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQsxRiUKn example" ) self.assertEqual(key.name, "test1") self.assertEqual(key.fingerprint, "f5:d1:78:ed:28:72:5f:e1:ac:94:fd:1f:e0:a3:48:6d") def test_delete_key_pair(self): key = self.driver.list_key_pairs()[0] result = self.driver.delete_key_pair(key) self.assertTrue(result) def test__paginated_request_single_page(self): nodes = self.driver._paginated_request('/v2/droplets', 'droplets') self.assertEqual(nodes[0]['name'], 'example.com') self.assertEqual(nodes[0]['image']['id'], 6918990) self.assertEqual(nodes[0]['size_slug'], '512mb') def test__paginated_request_two_pages(self): DigitalOceanMockHttp.type = 'PAGE_ONE' nodes = self.driver._paginated_request('/v2/droplets', 'droplets') self.assertEqual(len(nodes), 2) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 1) volume = volumes[0] self.assertEqual(volume.id, "62766883-2c28-11e6-b8e6-000f53306ae1") self.assertEqual(volume.name, "example") self.assertEqual(volume.size, 4) self.assertEqual(volume.driver, self.driver) def test_list_volumes_empty(self): DigitalOceanMockHttp.type = 'EMPTY' volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 0) def test_create_volume(self): nyc1 = [r for r in self.driver.list_locations() if r.id == 'nyc1'][0] DigitalOceanMockHttp.type = 'CREATE' volume = self.driver.create_volume(4, 'example', nyc1) self.assertEqual(volume.id, "62766883-2c28-11e6-b8e6-000f53306ae1") self.assertEqual(volume.name, "example") self.assertEqual(volume.size, 4) self.assertEqual(volume.driver, self.driver) def test_attach_volume(self): node = self.driver.list_nodes()[0] volume = self.driver.list_volumes()[0] DigitalOceanMockHttp.type = 'ATTACH' resp = self.driver.attach_volume(node, volume) self.assertTrue(resp) def test_detach_volume(self): volume = self.driver.list_volumes()[0] DigitalOceanMockHttp.type = 'DETACH' resp = self.driver.detach_volume(volume) self.assertTrue(resp) def test_destroy_volume(self): volume = self.driver.list_volumes()[0] DigitalOceanMockHttp.type = 'DESTROY' resp = self.driver.destroy_volume(volume) self.assertTrue(resp) def test_list_volume_snapshots(self): volume = self.driver.list_volumes()[0] snapshots = self.driver.list_volume_snapshots(volume) self.assertEqual(len(snapshots), 3) snapshot1, snapshot2, snapshot3 = snapshots self.assertEqual(snapshot1.id, "c0def940-9324-11e6-9a56-000f533176b1") self.assertEqual(snapshot2.id, "c2036724-9343-11e6-aef4-000f53315a41") self.assertEqual(snapshot3.id, "d347e033-9343-11e6-9a56-000f533176b1") def test_create_volume_snapshot(self): volume = self.driver.list_volumes()[0] DigitalOceanMockHttp.type = 'CREATE' snapshot = self.driver.create_volume_snapshot(volume, 'test-snapshot') self.assertEqual(snapshot.id, "c0def940-9324-11e6-9a56-000f533176b1") self.assertEqual(snapshot.name, 'test-snapshot') self.assertEqual(volume.driver, self.driver) def test_delete_volume_snapshot(self): volume = self.driver.list_volumes()[0] snapshot = self.driver.list_volume_snapshots(volume)[0] DigitalOceanMockHttp.type = 'DELETE' result = self.driver.delete_volume_snapshot(snapshot) self.assertTrue(result) def test_ex_get_node_details(self): node = self.driver.ex_get_node_details('3164444') self.assertEqual(node.name, 'example.com') self.assertEqual(node.public_ips, ['36.123.0.123']) self.assertEqual(node.extra['image']['id'], 12089443) self.assertEqual(node.extra['size_slug'], '8gb') self.assertEqual(len(node.extra['tags']), 2) def test_ex_create_floating_ip(self): nyc1 = [r for r in self.driver.list_locations() if r.id == 'nyc1'][0] floating_ip = self.driver.ex_create_floating_ip(nyc1) # Note that this is the ID. There is no real ID for a floating IP at # DigitalOcean, but the IP is unique so we can use that instead. self.assertEqual(floating_ip.id, '167.138.123.111') self.assertEqual(floating_ip.ip_address, '167.138.123.111') self.assertEqual(floating_ip.extra['region']['slug'], 'nyc1') # The newly created floating IP reserved to a region is not # associated with any droplet. See the DigitalOcean API docs # how to create a floating IP that is associated with an instance # from the start. This API call creates an unattached IP. self.assertIsNone(floating_ip.node_id) def test_ex_delete_floating_ip(self): nyc1 = [r for r in self.driver.list_locations() if r.id == 'nyc1'][0] floating_ip = self.driver.ex_create_floating_ip(nyc1) ret = self.driver.ex_delete_floating_ip(floating_ip) # The API returns 204 NO CONTENT if all is well. self.assertTrue(ret) def test_floating_ip_can_be_deleted_by_calling_delete_on_floating_ip_object(self): nyc1 = [r for r in self.driver.list_locations() if r.id == 'nyc1'][0] floating_ip = self.driver.ex_create_floating_ip(nyc1) ret = floating_ip.delete() self.assertTrue(ret) def test_list_floating_ips(self): floating_ips = self.driver.ex_list_floating_ips() self.assertEqual(len(floating_ips), 2, 'Wrong floating IPs count') floating_ip = floating_ips[0] self.assertEqual(floating_ip.id, '133.166.122.204') self.assertEqual(floating_ip.ip_address, '133.166.122.204') self.assertEqual(floating_ip.extra['region']['slug'], 'ams3') self.assertEqual(84155775, floating_ip.node_id) def test_get_floating_ip(self): floating_ip = self.driver.ex_get_floating_ip('133.166.122.204') self.assertEqual(floating_ip.id, '133.166.122.204') self.assertEqual(floating_ip.ip_address, '133.166.122.204') self.assertEqual(floating_ip.extra['region']['slug'], 'ams3') self.assertEqual(84155775, floating_ip.node_id) def test_ex_attach_floating_ip_to_node(self): node = self.driver.list_nodes()[0] floating_ip = self.driver.ex_get_floating_ip('133.166.122.204') ret = self.driver.ex_attach_floating_ip_to_node(node, floating_ip) self.assertTrue(ret) def test_ex_detach_floating_ip_from_node(self): node = self.driver.list_nodes()[0] floating_ip = self.driver.ex_get_floating_ip('154.138.103.175') ret = self.driver.ex_detach_floating_ip_from_node(node, floating_ip) self.assertTrue(ret) class DigitalOceanMockHttp(MockHttp): fixtures = ComputeFileFixtures('digitalocean_v2') def _v2_regions(self, method, url, body, headers): body = self.fixtures.load('list_locations.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_images(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_sizes(self, method, url, body, headers): body = self.fixtures.load('list_sizes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_droplets(self, method, url, body, headers): body = self.fixtures.load('list_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_droplets_3164444(self, method, url, body, headers): body = self.fixtures.load('list_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_droplets_INVALID_IMAGE(self, method, url, body, headers): body = self.fixtures.load('error_invalid_image.json') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) def _v2_droplets_3164444_actions_REBOOT(self, method, url, body, headers): # reboot_node body = self.fixtures.load('reboot_node.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_droplets_3164444_DESTROY(self, method, url, body, headers): # destroy_node return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _v2_droplets_3164444_actions_KERNELCHANGE(self, method, url, body, headers): # change_kernel body = self.fixtures.load('ex_change_kernel.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_droplets_3164444_actions_ENABLEIPV6(self, method, url, body, headers): # enable_ipv6 body = self.fixtures.load('ex_enable_ipv6.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_droplets_3164444_actions_RENAME(self, method, url, body, headers): # rename_node body = self.fixtures.load('ex_rename_node.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_droplets_3164444_actions_SNAPSHOT(self, method, url, body, headers): # create_image body = self.fixtures.load('create_image.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_images_12345(self, method, url, body, headers): # get_image body = self.fixtures.load('get_image.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_images_12345_DESTROY(self, method, url, body, headers): # delete_image return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _v2_droplets_3164444_actions_POWERON(self, method, url, body, headers): # ex_power_on_node body = self.fixtures.load('ex_power_on_node.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_droplets_3164444_actions_SHUTDOWN(self, method, url, body, headers): # ex_shutdown_node body = self.fixtures.load('ex_shutdown_node.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_droplets_3164444_actions_POWERCYCLE(self, method, url, body, headers): # ex_hard_reboot body = self.fixtures.load('ex_hard_reboot.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.OK]) def _v2_droplets_3164444_actions_REBUILD(self, method, url, body, headers): # ex_rebuild_node body = self.fixtures.load('ex_rebuild_node.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.OK]) def _v2_droplets_3164444_actions_RESIZE(self, method, url, body, headers): # ex_resize_node body = self.fixtures.load('ex_resize_node.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.OK]) def _v2_account_keys(self, method, url, body, headers): body = self.fixtures.load('list_key_pairs.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_account_keys_7717(self, method, url, body, headers): # destroy_ssh_key return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _v2_account_keys_CREATE(self, method, url, body, headers): # create_ssh_key body = self.fixtures.load('create_key_pair.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_droplets_UNAUTHORIZED(self, method, url, body, headers): body = self.fixtures.load('error.json') return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.UNAUTHORIZED]) def _v2_droplets_PAGE_ONE(self, method, url, body, headers): body = self.fixtures.load('list_nodes_page_1.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_volumes(self, method, url, body, headers): body = self.fixtures.load('list_volumes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_volumes_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_volumes_empty.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_volumes_CREATE(self, method, url, body, headers): body = self.fixtures.load('create_volume.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_volumes_actions_ATTACH(self, method, url, body, headers): body = self.fixtures.load('attach_volume.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _v2_volumes_DETACH(self, method, url, body, headers): body = self.fixtures.load('detach_volume.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_volumes_62766883_2c28_11e6_b8e6_000f53306ae1_DESTROY(self, method, url, body, headers): return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) def _v2_volumes_62766883_2c28_11e6_b8e6_000f53306ae1_snapshots_CREATE( self, method, url, body, headers): body = self.fixtures.load('create_volume_snapshot.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _v2_volumes_62766883_2c28_11e6_b8e6_000f53306ae1_snapshots( self, method, url, body, headers): body = self.fixtures.load('list_volume_snapshots.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_snapshots_c0def940_9324_11e6_9a56_000f533176b1_DELETE( self, method, url, body, headers): return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) def _v2_floating_ips(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('create_floating_ip.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'GET': body = self.fixtures.load('list_floating_ips.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_floating_ips_167_138_123_111(self, method, url, body, headers): if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) else: raise NotImplementedError() def _v2_floating_ips_133_166_122_204_actions(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('attach_floating_ip.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) else: raise NotImplementedError() def _v2_floating_ips_154_138_103_175_actions(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('detach_floating_ip.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) else: raise NotImplementedError() if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_dimensiondata_v2_3.py0000664000175000017500000046544513577507766026005 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from types import GeneratorType from libcloud.utils.py3 import httplib from libcloud.common.types import InvalidCredsError from libcloud.common.dimensiondata import DimensionDataAPIException, NetworkDomainServicePlan from libcloud.common.dimensiondata import DimensionDataServerCpuSpecification, DimensionDataServerDisk, DimensionDataServerVMWareTools from libcloud.common.dimensiondata import DimensionDataTag, DimensionDataTagKey from libcloud.common.dimensiondata import DimensionDataIpAddress, \ DimensionDataIpAddressList, DimensionDataChildIpAddressList, \ DimensionDataPortList, DimensionDataPort, DimensionDataChildPortList from libcloud.common.dimensiondata import TYPES_URN from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver as DimensionData from libcloud.compute.drivers.dimensiondata import DimensionDataNic from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation from libcloud.utils.py3 import ET from libcloud.test import MockHttp, unittest from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import DIMENSIONDATA_PARAMS from libcloud.utils.xml import fixxpath, findtext, findall class DimensionData_v2_3_Tests(unittest.TestCase, TestCaseMixin): def setUp(self): DimensionData.connectionCls.active_api_version = '2.3' DimensionData.connectionCls.conn_class = DimensionDataMockHttp DimensionDataMockHttp.type = None self.driver = DimensionData(*DIMENSIONDATA_PARAMS) def test_invalid_region(self): with self.assertRaises(ValueError): DimensionData(*DIMENSIONDATA_PARAMS, region='blah') def test_invalid_creds(self): DimensionDataMockHttp.type = 'UNAUTHORIZED' with self.assertRaises(InvalidCredsError): self.driver.list_nodes() def test_get_account_details(self): DimensionDataMockHttp.type = None ret = self.driver.connection.get_account_details() self.assertEqual(ret.full_name, 'Test User') self.assertEqual(ret.first_name, 'Test') self.assertEqual(ret.email, 'test@example.com') def test_list_locations_response(self): DimensionDataMockHttp.type = None ret = self.driver.list_locations() self.assertEqual(len(ret), 5) first_loc = ret[0] self.assertEqual(first_loc.id, 'NA3') self.assertEqual(first_loc.name, 'US - West') self.assertEqual(first_loc.country, 'US') def test_list_nodes_response(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes() self.assertEqual(len(ret), 7) def test_node_extras(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes() self.assertTrue(isinstance(ret[0].extra['vmWareTools'], DimensionDataServerVMWareTools)) self.assertTrue(isinstance(ret[0].extra['cpu'], DimensionDataServerCpuSpecification)) self.assertTrue(isinstance(ret[0].extra['disks'], list)) self.assertTrue(isinstance(ret[0].extra['disks'][0], DimensionDataServerDisk)) self.assertEqual(ret[0].extra['disks'][0].size_gb, 10) self.assertTrue(isinstance(ret[1].extra['disks'], list)) self.assertTrue(isinstance(ret[1].extra['disks'][0], DimensionDataServerDisk)) self.assertEqual(ret[1].extra['disks'][0].size_gb, 10) def test_server_states(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes() self.assertTrue(ret[0].state == 'running') self.assertTrue(ret[1].state == 'starting') self.assertTrue(ret[2].state == 'stopping') self.assertTrue(ret[3].state == 'reconfiguring') self.assertTrue(ret[4].state == 'running') self.assertTrue(ret[5].state == 'terminated') self.assertTrue(ret[6].state == 'stopped') self.assertEqual(len(ret), 7) def test_list_nodes_response_PAGINATED(self): DimensionDataMockHttp.type = 'PAGINATED' ret = self.driver.list_nodes() self.assertEqual(len(ret), 9) def test_paginated_mcp2_call_EMPTY(self): # cache org self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'EMPTY' node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server') empty_node_list = [] for node_list in node_list_generator: empty_node_list.extend(node_list) self.assertTrue(len(empty_node_list) == 0) def test_paginated_mcp2_call_PAGED_THEN_EMPTY(self): # cache org self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'PAGED_THEN_EMPTY' node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server') final_node_list = [] for node_list in node_list_generator: final_node_list.extend(node_list) self.assertTrue(len(final_node_list) == 2) def test_paginated_mcp2_call_with_page_size(self): # cache org self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'PAGESIZE50' node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server', page_size=50) self.assertTrue(isinstance(node_list_generator, GeneratorType)) # We're making sure here the filters make it to the URL # See _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts def test_list_nodes_response_strings_ALLFILTERS(self): DimensionDataMockHttp.type = 'ALLFILTERS' ret = self.driver.list_nodes(ex_location='fake_loc', ex_name='fake_name', ex_ipv6='fake_ipv6', ex_ipv4='fake_ipv4', ex_vlan='fake_vlan', ex_image='fake_image', ex_deployed=True, ex_started=True, ex_state='fake_state', ex_network='fake_network', ex_network_domain='fake_network_domain') self.assertTrue(isinstance(ret, list)) self.assertEqual(len(ret), 7) node = ret[3] self.assertTrue(isinstance(node.extra['disks'], list)) self.assertTrue(isinstance(node.extra['disks'][0], DimensionDataServerDisk)) self.assertEqual(node.size.id, '1') self.assertEqual(node.image.id, '3ebf3c0f-90fe-4a8b-8585-6e65b316592c') self.assertEqual(node.image.name, 'WIN2008S/32') disk = node.extra['disks'][0] self.assertEqual(disk.id, "c2e1f199-116e-4dbc-9960-68720b832b0a") self.assertEqual(disk.scsi_id, 0) self.assertEqual(disk.size_gb, 50) self.assertEqual(disk.speed, "STANDARD") self.assertEqual(disk.state, "NORMAL") def test_list_nodes_response_LOCATION(self): DimensionDataMockHttp.type = None ret = self.driver.list_locations() first_loc = ret[0] ret = self.driver.list_nodes(ex_location=first_loc) for node in ret: self.assertEqual(node.extra['datacenterId'], 'NA3') def test_list_nodes_response_LOCATION_STR(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes(ex_location='NA3') for node in ret: self.assertEqual(node.extra['datacenterId'], 'NA3') def test_list_sizes_response(self): DimensionDataMockHttp.type = None ret = self.driver.list_sizes() self.assertEqual(len(ret), 1) size = ret[0] self.assertEqual(size.name, 'default') def test_reboot_node_response(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = node.reboot() self.assertTrue(ret is True) def test_reboot_node_response_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): node.reboot() def test_destroy_node_response(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = node.destroy() self.assertTrue(ret is True) def test_destroy_node_response_RESOURCE_BUSY(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): node.destroy() def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 3) self.assertEqual(images[0].name, 'RedHat 6 64-bit 2 CPU') self.assertEqual(images[0].id, 'c14b1a46-2428-44c1-9c1a-b20e6418d08c') self.assertEqual(images[0].extra['location'].id, 'NA9') self.assertEqual(images[0].extra['cpu'].cpu_count, 2) self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64') def test_clean_failed_deployment_response_with_node(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_clean_failed_deployment(node) self.assertTrue(ret is True) def test_clean_failed_deployment_response_with_node_id(self): node = 'e75ead52-692f-4314-8725-c8a4f4d13a87' ret = self.driver.ex_clean_failed_deployment(node) self.assertTrue(ret is True) def test_ex_list_customer_images(self): images = self.driver.ex_list_customer_images() self.assertEqual(len(images), 3) self.assertEqual(images[0].name, 'ImportedCustomerImage') self.assertEqual(images[0].id, '5234e5c7-01de-4411-8b6e-baeb8d91cf5d') self.assertEqual(images[0].extra['location'].id, 'NA9') self.assertEqual(images[0].extra['cpu'].cpu_count, 4) self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64') def test_create_mcp1_node_optional_param(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] network = self.driver.ex_list_networks()[0] cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4', cores_per_socket='2', performance='STANDARD') disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')] node = self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network=network, ex_is_started=False, ex_memory_gb=8, ex_disks=disks, ex_cpu_specification=cpu_spec, ex_primary_dns='10.0.0.5', ex_secondary_dns='10.0.0.6' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_mcp1_node_response_no_pass_random_gen(self): image = self.driver.list_images()[0] network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' in node.extra) def test_create_mcp1_node_response_no_pass_customer_windows(self): image = self.driver.ex_list_customer_images()[1] network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' in node.extra) def test_create_mcp1_node_response_no_pass_customer_windows_STR(self): image = self.driver.ex_list_customer_images()[1].id network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' in node.extra) def test_create_mcp1_node_response_no_pass_customer_linux(self): image = self.driver.ex_list_customer_images()[0] network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' not in node.extra) def test_create_mcp1_node_response_no_pass_customer_linux_STR(self): image = self.driver.ex_list_customer_images()[0].id network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' not in node.extra) def test_create_mcp1_node_response_STR(self): rootPw = 'pass123' image = self.driver.list_images()[0].id network = self.driver.ex_list_networks()[0].id node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_response_network_domain(self): rootPw = NodeAuthPassword('pass123') location = self.driver.ex_get_location_by_id('NA9') image = self.driver.list_images(location=location)[0] network_domain = self.driver.ex_list_network_domains(location=location)[0] vlan = self.driver.ex_list_vlans(location=location)[0] cpu = DimensionDataServerCpuSpecification( cpu_count=4, cores_per_socket=1, performance='HIGHPERFORMANCE' ) node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain=network_domain, ex_vlan=vlan, ex_is_started=False, ex_cpu_specification=cpu, ex_memory_gb=4) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_response_network_domain_STR(self): rootPw = NodeAuthPassword('pass123') location = self.driver.ex_get_location_by_id('NA9') image = self.driver.list_images(location=location)[0] network_domain = self.driver.ex_list_network_domains(location=location)[0].id vlan = self.driver.ex_list_vlans(location=location)[0].id cpu = DimensionDataServerCpuSpecification( cpu_count=4, cores_per_socket=1, performance='HIGHPERFORMANCE' ) node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain=network_domain, ex_vlan=vlan, ex_is_started=False, ex_cpu_specification=cpu, ex_memory_gb=4) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_mcp1_node_no_network(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(InvalidRequestError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network=None, ex_is_started=False) def test_create_node_mcp1_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network='fakenetwork', ex_primary_ipv4='10.0.0.1', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_mcp1_network(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network='fakenetwork', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_mcp2_vlan(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_vlan='fakevlan', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_mcp2_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_network_domain_no_vlan_or_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_is_started=False) def test_create_node_response(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_ms_time_zone(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan', ex_microsoft_time_zone='040' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_ambigious_mcps_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_network='fakenetwork', ex_primary_nic_vlan='fakevlan' ) def test_create_node_no_network_domain_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_primary_nic_vlan='fakevlan' ) def test_create_node_no_primary_nic_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain' ) def test_create_node_primary_vlan_nic(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan', ex_primary_nic_network_adapter='v1000' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_primary_ipv4(self): rootPw = 'pass123' image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_both_primary_nic_and_vlan_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_primary_nic_vlan='fakevlan' ) def test_create_node_cpu_specification(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4', cores_per_socket='2', performance='STANDARD') node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_cpu_specification=cpu_spec) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_memory(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_memory_gb=8) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_disks(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_disks=disks) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_disks_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] disks = 'blah' with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_disks=disks) def test_create_node_ipv4_gateway(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_ipv4_gateway='10.2.2.2') self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_network_domain_no_vlan_no_ipv4_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_is_started=False) def test_create_node_mcp2_additional_nics_legacy(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] additional_vlans = ['fakevlan1', 'fakevlan2'] additional_ipv4 = ['10.0.0.2', '10.0.0.3'] node = self.driver.create_node( name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_additional_nics_vlan=additional_vlans, ex_additional_nics_ipv4=additional_ipv4, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_bad_additional_nics_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_vlan='fake_vlan', ex_additional_nics_ipv4='badstring', ex_is_started=False) def test_create_node_additional_nics(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] nic1 = DimensionDataNic(vlan='fake_vlan', network_adapter_name='v1000') nic2 = DimensionDataNic(private_ip_v4='10.1.1.2', network_adapter_name='v1000') additional_nics = [nic1, nic2] node = self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_additional_nics_vlan_ipv4_coexist_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] nic1 = DimensionDataNic(private_ip_v4='10.1.1.1', vlan='fake_vlan', network_adapter_name='v1000') nic2 = DimensionDataNic(private_ip_v4='10.1.1.2', vlan='fake_vlan2', network_adapter_name='v1000') additional_nics = [nic1, nic2] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False ) def test_create_node_additional_nics_invalid_input_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] additional_nics = 'blah' with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False ) def test_create_node_additional_nics_vlan_ipv4_not_exist_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] nic1 = DimensionDataNic(network_adapter_name='v1000') nic2 = DimensionDataNic(network_adapter_name='v1000') additional_nics = [nic1, nic2] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False) def test_create_node_bad_additional_nics_vlan(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_vlan='fake_vlan', ex_additional_nics_vlan='badstring', ex_is_started=False) def test_create_node_mcp2_indicate_dns(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test node dns', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_primary_dns='8.8.8.8', ex_secondary_dns='8.8.4.4', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_ex_shutdown_graceful(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_shutdown_graceful(node) self.assertTrue(ret is True) def test_ex_shutdown_graceful_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): self.driver.ex_shutdown_graceful(node) def test_ex_start_node(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_start_node(node) self.assertTrue(ret is True) def test_ex_start_node_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): self.driver.ex_start_node(node) def test_ex_power_off(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_power_off(node) self.assertTrue(ret is True) def test_ex_update_vm_tools(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_update_vm_tools(node) self.assertTrue(ret is True) def test_ex_power_off_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state='STOPPING', public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): self.driver.ex_power_off(node) def test_ex_reset(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_reset(node) self.assertTrue(ret is True) def test_ex_attach_node_to_vlan(self): node = self.driver.ex_get_node_by_id('e75ead52-692f-4314-8725-c8a4f4d13a87') vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') ret = self.driver.ex_attach_node_to_vlan(node, vlan) self.assertTrue(ret is True) def test_ex_destroy_nic(self): node = self.driver.ex_destroy_nic('a202e51b-41c0-4cfc-add0-b1c62fc0ecf6') self.assertTrue(node) def test_list_networks(self): nets = self.driver.list_networks() self.assertEqual(nets[0].name, 'test-net1') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_create_network(self): location = self.driver.ex_get_location_by_id('NA9') net = self.driver.ex_create_network(location, "Test Network", "test") self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e") self.assertEqual(net.name, "Test Network") def test_ex_create_network_NO_DESCRIPTION(self): location = self.driver.ex_get_location_by_id('NA9') net = self.driver.ex_create_network(location, "Test Network") self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e") self.assertEqual(net.name, "Test Network") def test_ex_delete_network(self): net = self.driver.ex_list_networks()[0] result = self.driver.ex_delete_network(net) self.assertTrue(result) def test_ex_rename_network(self): net = self.driver.ex_list_networks()[0] result = self.driver.ex_rename_network(net, "barry") self.assertTrue(result) def test_ex_create_network_domain(self): location = self.driver.ex_get_location_by_id('NA9') plan = NetworkDomainServicePlan.ADVANCED net = self.driver.ex_create_network_domain(location=location, name='test', description='test', service_plan=plan) self.assertEqual(net.name, 'test') self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa') def test_ex_create_network_domain_NO_DESCRIPTION(self): location = self.driver.ex_get_location_by_id('NA9') plan = NetworkDomainServicePlan.ADVANCED net = self.driver.ex_create_network_domain(location=location, name='test', service_plan=plan) self.assertEqual(net.name, 'test') self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa') def test_ex_get_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') self.assertEqual(net.id, '8cdfd607-f429-4df6-9352-162cfc0891be') self.assertEqual(net.description, 'test2') self.assertEqual(net.name, 'test') def test_ex_update_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') net.name = 'new name' net2 = self.driver.ex_update_network_domain(net) self.assertEqual(net2.name, 'new name') def test_ex_delete_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') result = self.driver.ex_delete_network_domain(net) self.assertTrue(result) def test_ex_list_networks(self): nets = self.driver.ex_list_networks() self.assertEqual(nets[0].name, 'test-net1') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_list_network_domains(self): nets = self.driver.ex_list_network_domains() self.assertEqual(nets[0].name, 'Aurora') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_list_network_domains_ALLFILTERS(self): DimensionDataMockHttp.type = 'ALLFILTERS' nets = self.driver.ex_list_network_domains(location='fake_location', name='fake_name', service_plan='fake_plan', state='fake_state') self.assertEqual(nets[0].name, 'Aurora') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_list_vlans(self): vlans = self.driver.ex_list_vlans() self.assertEqual(vlans[0].name, "Primary") def test_ex_list_vlans_ALLFILTERS(self): DimensionDataMockHttp.type = 'ALLFILTERS' vlans = self.driver.ex_list_vlans(location='fake_location', network_domain='fake_network_domain', name='fake_name', ipv4_address='fake_ipv4', ipv6_address='fake_ipv6', state='fake_state') self.assertEqual(vlans[0].name, "Primary") def test_ex_create_vlan(self,): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') vlan = self.driver.ex_create_vlan(network_domain=net, name='test', private_ipv4_base_address='10.3.4.0', private_ipv4_prefix_size='24', description='test vlan') self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') def test_ex_create_vlan_NO_DESCRIPTION(self,): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') vlan = self.driver.ex_create_vlan(network_domain=net, name='test', private_ipv4_base_address='10.3.4.0', private_ipv4_prefix_size='24') self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') def test_ex_get_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') self.assertEqual(vlan.description, 'test2') self.assertEqual(vlan.status, 'NORMAL') self.assertEqual(vlan.name, 'Production VLAN') self.assertEqual(vlan.private_ipv4_range_address, '10.0.3.0') self.assertEqual(vlan.private_ipv4_range_size, 24) self.assertEqual(vlan.ipv6_range_size, 64) self.assertEqual(vlan.ipv6_range_address, '2607:f480:1111:1153:0:0:0:0') self.assertEqual(vlan.ipv4_gateway, '10.0.3.1') self.assertEqual(vlan.ipv6_gateway, '2607:f480:1111:1153:0:0:0:1') def test_ex_wait_for_state(self): self.driver.ex_wait_for_state('NORMAL', self.driver.ex_get_vlan, vlan_id='0e56433f-d808-4669-821d-812769517ff8', poll_interval=0.1) def test_ex_wait_for_state_NODE(self): self.driver.ex_wait_for_state('running', self.driver.ex_get_node_by_id, id='e75ead52-692f-4314-8725-c8a4f4d13a87', poll_interval=0.1) def test_ex_wait_for_state_FAIL(self): with self.assertRaises(DimensionDataAPIException) as context: self.driver.ex_wait_for_state('starting', self.driver.ex_get_node_by_id, id='e75ead52-692f-4314-8725-c8a4f4d13a87', poll_interval=0.1, timeout=0.1 ) self.assertEqual(context.exception.code, 'running') self.assertTrue('timed out' in context.exception.msg) def test_ex_update_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') vlan.name = 'new name' vlan2 = self.driver.ex_update_vlan(vlan) self.assertEqual(vlan2.name, 'new name') def test_ex_delete_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') result = self.driver.ex_delete_vlan(vlan) self.assertTrue(result) def test_ex_expand_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') vlan.private_ipv4_range_size = '23' vlan = self.driver.ex_expand_vlan(vlan) self.assertEqual(vlan.private_ipv4_range_size, '23') def test_ex_add_public_ip_block_to_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') block = self.driver.ex_add_public_ip_block_to_network_domain(net) self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') def test_ex_list_public_ip_blocks(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') blocks = self.driver.ex_list_public_ip_blocks(net) self.assertEqual(blocks[0].base_ip, '168.128.4.18') self.assertEqual(blocks[0].size, '2') self.assertEqual(blocks[0].id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') self.assertEqual(blocks[0].location.id, 'NA9') self.assertEqual(blocks[0].network_domain.id, net.id) def test_ex_get_public_ip_block(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') self.assertEqual(block.base_ip, '168.128.4.18') self.assertEqual(block.size, '2') self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') self.assertEqual(block.location.id, 'NA9') self.assertEqual(block.network_domain.id, net.id) def test_ex_delete_public_ip_block(self): block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') result = self.driver.ex_delete_public_ip_block(block) self.assertTrue(result) def test_ex_list_firewall_rules(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) self.assertEqual(rules[0].id, '756cba02-b0bc-48f4-aea5-9445870b6148') self.assertEqual(rules[0].network_domain.id, '8cdfd607-f429-4df6-9352-162cfc0891be') self.assertEqual(rules[0].name, 'CCDEFAULT.BlockOutboundMailIPv4') self.assertEqual(rules[0].action, 'DROP') self.assertEqual(rules[0].ip_version, 'IPV4') self.assertEqual(rules[0].protocol, 'TCP') self.assertEqual(rules[0].source.ip_address, 'ANY') self.assertTrue(rules[0].source.any_ip) self.assertTrue(rules[0].destination.any_ip) def test_ex_create_firewall_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) rule = self.driver.ex_create_firewall_rule(net, rules[0], 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_with_specific_source_ip(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) specific_source_ip_rule = list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_with_source_ip(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) specific_source_ip_rule = \ list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] specific_source_ip_rule.source.any_ip = False specific_source_ip_rule.source.ip_address = '10.0.0.1' specific_source_ip_rule.source.ip_prefix_size = '15' rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_with_any_ip(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) specific_source_ip_rule = \ list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] specific_source_ip_rule.source.any_ip = True rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_ip_prefix_size(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.address_list_id = None rule.source.any_ip = False rule.source.ip_address = '10.2.1.1' rule.source.ip_prefix_size = '10' rule.destination.address_list_id = None rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = '20' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_address_list(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.address_list_id = '12345' rule.destination.address_list_id = '12345' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_port_list(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.port_list_id = '12345' rule.destination.port_list_id = '12345' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_port(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.port_list_id = None rule.source.port_begin = '8000' rule.source.port_end = '8005' rule.destination.port_list_id = None rule.destination.port_begin = '7000' rule.destination.port_end = '7005' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_ALL_VALUES(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) for rule in rules: self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_WITH_POSITION_RULE(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', rules[-1]) self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_WITH_POSITION_RULE_STR(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', 'RULE_WITH_SOURCE_AND_DEST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_FAIL_POSITION(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) with self.assertRaises(ValueError): self.driver.ex_create_firewall_rule(net, rules[0], 'BEFORE') def test_ex_create_firewall_rule_FAIL_POSITION_WITH_RULE(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) with self.assertRaises(ValueError): self.driver.ex_create_firewall_rule(net, rules[0], 'LAST', 'RULE_WITH_SOURCE_AND_DEST') def test_ex_get_firewall_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_set_firewall_rule_state(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') result = self.driver.ex_set_firewall_rule_state(rule, False) self.assertTrue(result) def test_ex_delete_firewall_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') result = self.driver.ex_delete_firewall_rule(rule) self.assertTrue(result) def test_ex_edit_firewall_rule(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.any_ip = True result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_source_ipaddresslist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' rule.source.any_ip = False rule.source.ip_address = '10.0.0.1' rule.source.ip_prefix_size = 10 result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_ipaddresslist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = 10 result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_ipaddress(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.address_list_id = None rule.source.any_ip = False rule.source.ip_address = '10.0.0.1' rule.source.ip_prefix_size = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_source_ipaddress(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.address_list_id = None rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_with_relative_rule(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') placement_rule = self.driver.ex_list_firewall_rules( network_domain=net)[-1] result = self.driver.ex_edit_firewall_rule( rule=rule, position='BEFORE', relative_rule_for_position=placement_rule) self.assertTrue(result) def test_ex_edit_firewall_rule_with_relative_rule_by_name(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') placement_rule = self.driver.ex_list_firewall_rules( network_domain=net)[-1] result = self.driver.ex_edit_firewall_rule( rule=rule, position='BEFORE', relative_rule_for_position=placement_rule.name) self.assertTrue(result) def test_ex_edit_firewall_rule_source_portlist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_source_port(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.port_list_id = None rule.source.port_begin = '3' rule.source.port_end = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_portlist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_port(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.port_list_id = None rule.destination.port_begin = '3' rule.destination.port_end = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_invalid_position_fail(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') with self.assertRaises(ValueError): self.driver.ex_edit_firewall_rule(rule=rule, position='BEFORE') def test_ex_edit_firewall_rule_invalid_position_relative_rule_fail(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') relative_rule = self.driver.ex_list_firewall_rules( network_domain=net)[-1] with self.assertRaises(ValueError): self.driver.ex_edit_firewall_rule(rule=rule, position='FIRST', relative_rule_for_position=relative_rule) def test_ex_create_nat_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_create_nat_rule(net, '1.2.3.4', '4.3.2.1') self.assertEqual(rule.id, 'd31c2db0-be6b-4d50-8744-9a7a534b5fba') def test_ex_list_nat_rules(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_nat_rules(net) self.assertEqual(rules[0].id, '2187a636-7ebb-49a1-a2ff-5d617f496dce') self.assertEqual(rules[0].internal_ip, '10.0.0.15') self.assertEqual(rules[0].external_ip, '165.180.12.18') def test_ex_get_nat_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce') self.assertEqual(rule.id, '2187a636-7ebb-49a1-a2ff-5d617f496dce') self.assertEqual(rule.internal_ip, '10.0.0.16') self.assertEqual(rule.external_ip, '165.180.12.19') def test_ex_delete_nat_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce') result = self.driver.ex_delete_nat_rule(rule) self.assertTrue(result) def test_ex_enable_monitoring(self): node = self.driver.list_nodes()[0] result = self.driver.ex_enable_monitoring(node, "ADVANCED") self.assertTrue(result) def test_ex_disable_monitoring(self): node = self.driver.list_nodes()[0] result = self.driver.ex_disable_monitoring(node) self.assertTrue(result) def test_ex_change_monitoring_plan(self): node = self.driver.list_nodes()[0] result = self.driver.ex_update_monitoring_plan(node, "ESSENTIALS") self.assertTrue(result) def test_ex_add_storage_to_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_add_storage_to_node(node, 30, 'PERFORMANCE') self.assertTrue(result) def test_ex_remove_storage_from_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_remove_storage_from_node(node, 0) self.assertTrue(result) def test_ex_change_storage_speed(self): node = self.driver.list_nodes()[0] result = self.driver.ex_change_storage_speed(node, 1, 'PERFORMANCE') self.assertTrue(result) def test_ex_change_storage_size(self): node = self.driver.list_nodes()[0] result = self.driver.ex_change_storage_size(node, 1, 100) self.assertTrue(result) def test_ex_clone_node_to_image(self): node = self.driver.list_nodes()[0] result = self.driver.ex_clone_node_to_image(node, 'my image', 'a description') self.assertTrue(result) def test_ex_update_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_update_node(node, 'my new name', 'a description', 2, 4048) self.assertTrue(result) def test_ex_reconfigure_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_reconfigure_node(node, 4, 4, 1, 'HIGHPERFORMANCE') self.assertTrue(result) def test_ex_get_location_by_id(self): location = self.driver.ex_get_location_by_id('NA9') self.assertTrue(location.id, 'NA9') def test_ex_get_location_by_id_NO_LOCATION(self): location = self.driver.ex_get_location_by_id(None) self.assertIsNone(location) def test_ex_get_base_image_by_id(self): image_id = self.driver.list_images()[0].id image = self.driver.ex_get_base_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'UNIX') def test_ex_get_customer_image_by_id(self): image_id = self.driver.ex_list_customer_images()[1].id image = self.driver.ex_get_customer_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'WINDOWS') def test_ex_get_image_by_id_base_img(self): image_id = self.driver.list_images()[1].id image = self.driver.ex_get_base_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'WINDOWS') def test_ex_get_image_by_id_customer_img(self): image_id = self.driver.ex_list_customer_images()[0].id image = self.driver.ex_get_customer_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'UNIX') def test_ex_get_image_by_id_customer_FAIL(self): image_id = 'FAKE_IMAGE_ID' with self.assertRaises(DimensionDataAPIException): self.driver.ex_get_base_image_by_id(image_id) def test_ex_create_anti_affinity_rule(self): node_list = self.driver.list_nodes() success = self.driver.ex_create_anti_affinity_rule([node_list[0], node_list[1]]) self.assertTrue(success) def test_ex_create_anti_affinity_rule_TUPLE(self): node_list = self.driver.list_nodes() success = self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1])) self.assertTrue(success) def test_ex_create_anti_affinity_rule_TUPLE_STR(self): node_list = self.driver.list_nodes() success = self.driver.ex_create_anti_affinity_rule((node_list[0].id, node_list[1].id)) self.assertTrue(success) def test_ex_create_anti_affinity_rule_FAIL_STR(self): node_list = 'string' with self.assertRaises(TypeError): self.driver.ex_create_anti_affinity_rule(node_list) def test_ex_create_anti_affinity_rule_FAIL_EXISTING(self): node_list = self.driver.list_nodes() DimensionDataMockHttp.type = 'FAIL_EXISTING' with self.assertRaises(DimensionDataAPIException): self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1])) def test_ex_delete_anti_affinity_rule(self): net_domain = self.driver.ex_list_network_domains()[0] rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] success = self.driver.ex_delete_anti_affinity_rule(rule) self.assertTrue(success) def test_ex_delete_anti_affinity_rule_STR(self): net_domain = self.driver.ex_list_network_domains()[0] rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] success = self.driver.ex_delete_anti_affinity_rule(rule.id) self.assertTrue(success) def test_ex_delete_anti_affinity_rule_FAIL(self): net_domain = self.driver.ex_list_network_domains()[0] rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] DimensionDataMockHttp.type = 'FAIL' with self.assertRaises(DimensionDataAPIException): self.driver.ex_delete_anti_affinity_rule(rule) def test_ex_list_anti_affinity_rules_NETWORK_DOMAIN(self): net_domain = self.driver.ex_list_network_domains()[0] rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_NETWORK(self): network = self.driver.list_networks()[0] rules = self.driver.ex_list_anti_affinity_rules(network=network) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_NODE(self): node = self.driver.list_nodes()[0] rules = self.driver.ex_list_anti_affinity_rules(node=node) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_PAGINATED(self): net_domain = self.driver.ex_list_network_domains()[0] DimensionDataMockHttp.type = 'PAGINATED' rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 4) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_ALLFILTERS(self): net_domain = self.driver.ex_list_network_domains()[0] DimensionDataMockHttp.type = 'ALLFILTERS' rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain, filter_id='FAKE_ID', filter_state='FAKE_STATE') self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_BAD_ARGS(self): with self.assertRaises(ValueError): self.driver.ex_list_anti_affinity_rules(network='fake_network', network_domain='fake_network_domain') def test_ex_create_tag_key(self): success = self.driver.ex_create_tag_key('MyTestKey') self.assertTrue(success) def test_ex_create_tag_key_ALLPARAMS(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'ALLPARAMS' success = self.driver.ex_create_tag_key('MyTestKey', description="Test Key Desc.", value_required=False, display_on_report=False) self.assertTrue(success) def test_ex_create_tag_key_BADREQUEST(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'BADREQUEST' with self.assertRaises(DimensionDataAPIException): self.driver.ex_create_tag_key('MyTestKey') def test_ex_list_tag_keys(self): tag_keys = self.driver.ex_list_tag_keys() self.assertTrue(isinstance(tag_keys, list)) self.assertTrue(isinstance(tag_keys[0], DimensionDataTagKey)) self.assertTrue(isinstance(tag_keys[0].id, str)) def test_ex_list_tag_keys_ALLFILTERS(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'ALLFILTERS' self.driver.ex_list_tag_keys(id='fake_id', name='fake_name', value_required=False, display_on_report=False) def test_ex_get_tag_by_id(self): tag = self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075') self.assertTrue(isinstance(tag, DimensionDataTagKey)) def test_ex_get_tag_by_id_NOEXIST(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'NOEXIST' with self.assertRaises(DimensionDataAPIException): self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075') def test_ex_get_tag_by_name(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'SINGLE' tag = self.driver.ex_get_tag_key_by_name('LibcloudTest') self.assertTrue(isinstance(tag, DimensionDataTagKey)) def test_ex_get_tag_by_name_NOEXIST(self): with self.assertRaises(ValueError): self.driver.ex_get_tag_key_by_name('LibcloudTest') def test_ex_modify_tag_key_NAME(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NAME' success = self.driver.ex_modify_tag_key(tag_key, name='NewName') self.assertTrue(success) def test_ex_modify_tag_key_NOTNAME(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NOTNAME' success = self.driver.ex_modify_tag_key(tag_key, description='NewDesc', value_required=False, display_on_report=True) self.assertTrue(success) def test_ex_modify_tag_key_NOCHANGE(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NOCHANGE' with self.assertRaises(DimensionDataAPIException): self.driver.ex_modify_tag_key(tag_key) def test_ex_remove_tag_key(self): tag_key = self.driver.ex_list_tag_keys()[0] success = self.driver.ex_remove_tag_key(tag_key) self.assertTrue(success) def test_ex_remove_tag_key_NOEXIST(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NOEXIST' with self.assertRaises(DimensionDataAPIException): self.driver.ex_remove_tag_key(tag_key) def test_ex_apply_tag_to_asset(self): node = self.driver.list_nodes()[0] success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName', 'FakeValue') self.assertTrue(success) def test_ex_apply_tag_to_asset_NOVALUE(self): node = self.driver.list_nodes()[0] DimensionDataMockHttp.type = 'NOVALUE' success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName') self.assertTrue(success) def test_ex_apply_tag_to_asset_NOTAGKEY(self): node = self.driver.list_nodes()[0] DimensionDataMockHttp.type = 'NOTAGKEY' with self.assertRaises(DimensionDataAPIException): self.driver.ex_apply_tag_to_asset(node, 'TagKeyNam') def test_ex_apply_tag_to_asset_BADASSETTYPE(self): network = self.driver.list_networks()[0] DimensionDataMockHttp.type = 'NOTAGKEY' with self.assertRaises(TypeError): self.driver.ex_apply_tag_to_asset(network, 'TagKeyNam') def test_ex_remove_tag_from_asset(self): node = self.driver.list_nodes()[0] success = self.driver.ex_remove_tag_from_asset(node, 'TagKeyName') self.assertTrue(success) def test_ex_remove_tag_from_asset_NOTAG(self): node = self.driver.list_nodes()[0] DimensionDataMockHttp.type = 'NOTAG' with self.assertRaises(DimensionDataAPIException): self.driver.ex_remove_tag_from_asset(node, 'TagKeyNam') def test_ex_list_tags(self): tags = self.driver.ex_list_tags() self.assertTrue(isinstance(tags, list)) self.assertTrue(isinstance(tags[0], DimensionDataTag)) self.assertTrue(len(tags) == 3) def test_ex_list_tags_ALLPARAMS(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'ALLPARAMS' tags = self.driver.ex_list_tags(asset_id='fake_asset_id', asset_type='fake_asset_type', location='fake_location', tag_key_name='fake_tag_key_name', tag_key_id='fake_tag_key_id', value='fake_value', value_required=False, display_on_report=False) self.assertTrue(isinstance(tags, list)) self.assertTrue(isinstance(tags[0], DimensionDataTag)) self.assertTrue(len(tags) == 3) def test_priv_location_to_location_id(self): location = self.driver.ex_get_location_by_id('NA9') self.assertEqual( self.driver._location_to_location_id(location), 'NA9' ) def test_priv_location_to_location_id_STR(self): self.assertEqual( self.driver._location_to_location_id('NA9'), 'NA9' ) def test_priv_location_to_location_id_TYPEERROR(self): with self.assertRaises(TypeError): self.driver._location_to_location_id([1, 2, 3]) def test_priv_image_needs_auth_os_img(self): image = self.driver.list_images()[1] self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_os_img_STR(self): image = self.driver.list_images()[1].id self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_windows(self): image = self.driver.ex_list_customer_images()[1] self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_windows_STR(self): image = self.driver.ex_list_customer_images()[1].id self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_linux(self): image = self.driver.ex_list_customer_images()[0] self.assertTrue(not self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_linux_STR(self): image = self.driver.ex_list_customer_images()[0].id self.assertTrue(not self.driver._image_needs_auth(image)) def test_summary_usage_report(self): report = self.driver.ex_summary_usage_report('2016-06-01', '2016-06-30') report_content = report self.assertEqual(len(report_content), 13) self.assertEqual(len(report_content[0]), 6) def test_detailed_usage_report(self): report = self.driver.ex_detailed_usage_report('2016-06-01', '2016-06-30') report_content = report self.assertEqual(len(report_content), 42) self.assertEqual(len(report_content[0]), 4) def test_audit_log_report(self): report = self.driver.ex_audit_log_report('2016-06-01', '2016-06-30') report_content = report self.assertEqual(len(report_content), 25) self.assertEqual(report_content[2][2], 'OEC_SYSTEM') def test_ex_list_ip_address_list(self): net_domain = self.driver.ex_list_network_domains()[0] ip_list = self.driver.ex_list_ip_address_list( ex_network_domain=net_domain) self.assertTrue(isinstance(ip_list, list)) self.assertEqual(len(ip_list), 4) self.assertTrue(isinstance(ip_list[0].name, str)) self.assertTrue(isinstance(ip_list[0].description, str)) self.assertTrue(isinstance(ip_list[0].ip_version, str)) self.assertTrue(isinstance(ip_list[0].state, str)) self.assertTrue(isinstance(ip_list[0].create_time, str)) self.assertTrue(isinstance(ip_list[0].child_ip_address_lists, list)) self.assertEqual(len(ip_list[1].child_ip_address_lists), 1) self.assertTrue(isinstance(ip_list[1].child_ip_address_lists[0].name, str)) def test_ex_get_ip_address_list(self): net_domain = self.driver.ex_list_network_domains()[0] DimensionDataMockHttp.type = 'FILTERBYNAME' ip_list = self.driver.ex_get_ip_address_list( ex_network_domain=net_domain.id, ex_ip_address_list_name='Test_IP_Address_List_3') self.assertTrue(isinstance(ip_list, list)) self.assertEqual(len(ip_list), 1) self.assertTrue(isinstance(ip_list[0].name, str)) self.assertTrue(isinstance(ip_list[0].description, str)) self.assertTrue(isinstance(ip_list[0].ip_version, str)) self.assertTrue(isinstance(ip_list[0].state, str)) self.assertTrue(isinstance(ip_list[0].create_time, str)) ips = ip_list[0].ip_address_collection self.assertEqual(len(ips), 3) self.assertTrue(isinstance(ips[0].begin, str)) self.assertTrue(isinstance(ips[0].prefix_size, str)) self.assertTrue(isinstance(ips[2].end, str)) def test_ex_create_ip_address_list_FAIL(self): net_domain = self.driver.ex_list_network_domains()[0] with self.assertRaises(TypeError): self.driver.ex_create_ip_address_list( ex_network_domain=net_domain.id) def test_ex_create_ip_address_list(self): name = "Test_IP_Address_List_3" description = "Test Description" ip_version = "IPV4" child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41' child_ip_address_list = DimensionDataChildIpAddressList( id=child_ip_address_list_id, name="test_child_ip_addr_list") net_domain = self.driver.ex_list_network_domains()[0] ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100') ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106', end='190.2.2.108') ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0', prefix_size='24') ip_address_collection = [ip_address_1, ip_address_2, ip_address_3] # Create IP Address List success = self.driver.ex_create_ip_address_list( ex_network_domain=net_domain, name=name, ip_version=ip_version, description=description, ip_address_collection=ip_address_collection, child_ip_address_list=child_ip_address_list) self.assertTrue(success) def test_ex_create_ip_address_list_STR(self): name = "Test_IP_Address_List_3" description = "Test Description" ip_version = "IPV4" child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41' net_domain = self.driver.ex_list_network_domains()[0] ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100') ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106', end='190.2.2.108') ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0', prefix_size='24') ip_address_collection = [ip_address_1, ip_address_2, ip_address_3] # Create IP Address List success = self.driver.ex_create_ip_address_list( ex_network_domain=net_domain.id, name=name, ip_version=ip_version, description=description, ip_address_collection=ip_address_collection, child_ip_address_list=child_ip_address_list_id) self.assertTrue(success) def test_ex_edit_ip_address_list(self): ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111') ip_address_collection = [ip_address_1] child_ip_address_list = DimensionDataChildIpAddressList( id='2221ef78-4059-4bc1-b433-3f6ad698dc41', name="test_child_ip_address_list edited") ip_address_list = DimensionDataIpAddressList( id='1111ef78-4059-4bc1-b433-3f6ad698d111', name="test ip address list edited", ip_version="IPv4", description="test", ip_address_collection=ip_address_collection, child_ip_address_lists=child_ip_address_list, state="NORMAL", create_time='2015-09-29T02:49:45' ) success = self.driver.ex_edit_ip_address_list( ex_ip_address_list=ip_address_list, description="test ip address list", ip_address_collection=ip_address_collection, child_ip_address_lists=child_ip_address_list ) self.assertTrue(success) def test_ex_edit_ip_address_list_STR(self): ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111') ip_address_collection = [ip_address_1] child_ip_address_list = DimensionDataChildIpAddressList( id='2221ef78-4059-4bc1-b433-3f6ad698dc41', name="test_child_ip_address_list edited") success = self.driver.ex_edit_ip_address_list( ex_ip_address_list='84e34850-595d- 436e-a885-7cd37edb24a4', description="test ip address list", ip_address_collection=ip_address_collection, child_ip_address_lists=child_ip_address_list ) self.assertTrue(success) def test_ex_delete_ip_address_list(self): child_ip_address_list = DimensionDataChildIpAddressList( id='2221ef78-4059-4bc1-b433-3f6ad698dc41', name="test_child_ip_address_list edited") ip_address_list = DimensionDataIpAddressList( id='1111ef78-4059-4bc1-b433-3f6ad698d111', name="test ip address list edited", ip_version="IPv4", description="test", ip_address_collection=None, child_ip_address_lists=child_ip_address_list, state="NORMAL", create_time='2015-09-29T02:49:45' ) success = self.driver.ex_delete_ip_address_list( ex_ip_address_list=ip_address_list) self.assertTrue(success) def test_ex_delete_ip_address_list_STR(self): success = self.driver.ex_delete_ip_address_list( ex_ip_address_list='111ef78-4059-4bc1-b433-3f6ad698d111') self.assertTrue(success) def test_ex_list_portlist(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist( ex_network_domain=net_domain) self.assertTrue(isinstance(portlist, list)) self.assertEqual(len(portlist), 3) self.assertTrue(isinstance(portlist[0].name, str)) self.assertTrue(isinstance(portlist[0].description, str)) self.assertTrue(isinstance(portlist[0].state, str)) self.assertTrue(isinstance(portlist[0].port_collection, list)) self.assertTrue(isinstance(portlist[0].port_collection[0].begin, str)) self.assertTrue(isinstance(portlist[0].port_collection[0].end, str)) self.assertTrue(isinstance(portlist[0].child_portlist_list, list)) self.assertTrue(isinstance(portlist[0].child_portlist_list[0].id, str)) self.assertTrue(isinstance(portlist[0].child_portlist_list[0].name, str)) self.assertTrue(isinstance(portlist[0].create_time, str)) def test_ex_get_port_list(self): net_domain = self.driver.ex_list_network_domains()[0] portlist_id = self.driver.ex_list_portlist( ex_network_domain=net_domain)[0].id portlist = self.driver.ex_get_portlist( ex_portlist_id=portlist_id) self.assertTrue(isinstance(portlist, DimensionDataPortList)) self.assertTrue(isinstance(portlist.name, str)) self.assertTrue(isinstance(portlist.description, str)) self.assertTrue(isinstance(portlist.state, str)) self.assertTrue(isinstance(portlist.port_collection, list)) self.assertTrue(isinstance(portlist.port_collection[0].begin, str)) self.assertTrue(isinstance(portlist.port_collection[0].end, str)) self.assertTrue(isinstance(portlist.child_portlist_list, list)) self.assertTrue(isinstance(portlist.child_portlist_list[0].id, str)) self.assertTrue(isinstance(portlist.child_portlist_list[0].name, str)) self.assertTrue(isinstance(portlist.create_time, str)) def test_ex_get_portlist_STR(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist( ex_network_domain=net_domain)[0] port_list = self.driver.ex_get_portlist( ex_portlist_id=portlist.id) self.assertTrue(isinstance(port_list, DimensionDataPortList)) self.assertTrue(isinstance(port_list.name, str)) self.assertTrue(isinstance(port_list.description, str)) self.assertTrue(isinstance(port_list.state, str)) self.assertTrue(isinstance(port_list.port_collection, list)) self.assertTrue(isinstance(port_list.port_collection[0].begin, str)) self.assertTrue(isinstance(port_list.port_collection[0].end, str)) self.assertTrue(isinstance(port_list.child_portlist_list, list)) self.assertTrue(isinstance(port_list.child_portlist_list[0].id, str)) self.assertTrue(isinstance(port_list.child_portlist_list[0].name, str)) self.assertTrue(isinstance(port_list.create_time, str)) def test_ex_create_portlist_NOCHILDPORTLIST(self): name = "Test_Port_List" description = "Test Description" net_domain = self.driver.ex_list_network_domains()[0] port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] # Create IP Address List success = self.driver.ex_create_portlist( ex_network_domain=net_domain, name=name, description=description, port_collection=port_collection ) self.assertTrue(success) def test_ex_create_portlist(self): name = "Test_Port_List" description = "Test Description" net_domain = self.driver.ex_list_network_domains()[0] port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports = [child_port_1, child_port_2] # Create IP Address List success = self.driver.ex_create_portlist( ex_network_domain=net_domain, name=name, description=description, port_collection=port_collection, child_portlist_list=child_ports ) self.assertTrue(success) def test_ex_create_portlist_STR(self): name = "Test_Port_List" description = "Test Description" net_domain = self.driver.ex_list_network_domains()[0] port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports_ids = [child_port_1.id, child_port_2.id] # Create IP Address List success = self.driver.ex_create_portlist( ex_network_domain=net_domain.id, name=name, description=description, port_collection=port_collection, child_portlist_list=child_ports_ids ) self.assertTrue(success) def test_ex_edit_portlist(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist(net_domain)[0] description = "Test Description" port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports = [child_port_1.id, child_port_2.id] # Create IP Address List success = self.driver.ex_edit_portlist( ex_portlist=portlist, description=description, port_collection=port_collection, child_portlist_list=child_ports ) self.assertTrue(success) def test_ex_edit_portlist_STR(self): portlist_id = "484174a2-ae74-4658-9e56-50fc90e086cf" description = "Test Description" port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports_ids = [child_port_1.id, child_port_2.id] # Create IP Address List success = self.driver.ex_edit_portlist( ex_portlist=portlist_id, description=description, port_collection=port_collection, child_portlist_list=child_ports_ids ) self.assertTrue(success) def test_ex_delete_portlist(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist(net_domain)[0] success = self.driver.ex_delete_portlist( ex_portlist=portlist) self.assertTrue(success) def test_ex_delete_portlist_STR(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist(net_domain)[0] success = self.driver.ex_delete_portlist( ex_portlist=portlist.id) self.assertTrue(success) class InvalidRequestError(Exception): def __init__(self, tag): super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag) class DimensionDataMockHttp(MockHttp): fixtures = ComputeFileFixtures('dimensiondata') def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_report_usage(self, method, url, body, headers): body = self.fixtures.load( 'summary_usage_report.csv' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_report_usageDetailed(self, method, url, body, headers): body = self.fixtures.load( 'detailed_usage_report.csv' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_auditlog(self, method, url, body, headers): body = self.fixtures.load( 'audit_log.csv' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_PAGINATED(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_ALLFILTERS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_base_image(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_base_image.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_base_imageWithDiskSpeed(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_base_imageWithDiskSpeed.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11(self, method, url, body, headers): body = None action = url.split('?')[-1] if action == 'restart': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xml') elif action == 'shutdown': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xml') elif action == 'delete': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xml') elif action == 'start': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xml') elif action == 'poweroff': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_INPROGRESS(self, method, url, body, headers): body = None action = url.split('?')[-1] if action == 'restart': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xml') elif action == 'shutdown': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xml') elif action == 'delete': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xml') elif action == 'start': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xml') elif action == 'poweroff': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers): body = self.fixtures.load( '_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation(self, method, url, body, headers): if method == "POST": request = ET.fromstring(body) if request.tag != "{http://oec.api.opsource.net/schemas/network}NewNetworkWithLocation": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation_NA9(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_4bba37be_506f_11e3_b29c_001517c4643e(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_4bba37be_506f_11e3_b29c_001517c4643e.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSize(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSize.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSpeed(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSpeed.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1(self, method, url, body, headers): action = url.split('?')[-1] if action == 'delete': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_POST.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_FAIL_EXISTING(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_07e3621a_a920_4a9a_943c_d8021f27f418(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_07e3621a_a920_4a9a_943c_d8021f27f418_FAIL(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers): body = self.fixtures.load( 'server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_deleteServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_deleteServer_RESOURCEBUSY.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}rebootServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_rebootServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}rebootServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_rebootServer_RESOURCEBUSY.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers): if url.endswith('datacenterId=NA3'): body = self.fixtures.load( 'server_server_NA3.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGESIZE50(self, method, url, body, headers): if not url.endswith('pageSize=50'): raise ValueError("pageSize is not set as expected") body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_EMPTY(self, method, url, body, headers): body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGED_THEN_EMPTY(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( 'server_server_paginated.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATED(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( 'server_server_paginated.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATEDEMPTY(self, method, url, body, headers): body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_loc' elif key == 'networkId': assert value == 'fake_network' elif key == 'networkDomainId': assert value == 'fake_network_domain' elif key == 'vlanId': assert value == 'fake_vlan' elif key == 'ipv6': assert value == 'fake_ipv6' elif key == 'privateIpv4': assert value == 'fake_ipv4' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' elif key == 'started': assert value == 'True' elif key == 'deployed': assert value == 'True' elif key == 'sourceImageId': assert value == 'fake_image' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule(self, method, url, body, headers): body = self.fixtures.load( 'server_antiAffinityRule_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'id': assert value == 'FAKE_ID' elif key == 'state': assert value == 'FAKE_STATE' elif key == 'pageSize': assert value == '250' elif key == 'networkDomainId': pass else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'server_antiAffinityRule_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_PAGINATED(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_antiAffinityRule_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( 'server_antiAffinityRule_list_PAGINATED.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers): if url.endswith('id=NA9'): body = self.fixtures.load( 'infrastructure_datacenter_NA9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'infrastructure_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_ALLFILTERS(self, method, url, body, headers): if url.endswith('id=NA9'): body = self.fixtures.load( 'infrastructure_datacenter_NA9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'infrastructure_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_updateVmwareTools(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}updateVmwareTools": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_updateVmwareTools.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}startServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_startServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}startServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_startServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_shutdownServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_shutdownServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}resetServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_resetServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_powerOffServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_powerOffServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_11_INPROGRESS( self, method, url, body, headers): body = self.fixtures.load('server_GetServer.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_location' elif key == 'type': assert value == 'fake_plan' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'network_networkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan(self, method, url, body, headers): body = self.fixtures.load( 'network_vlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_location' elif key == 'networkDomainId': assert value == 'fake_network_domain' elif key == 'ipv6Address': assert value == 'fake_ipv6' elif key == 'privateIpv4Address': assert value == 'fake_ipv4' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'network_vlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployServer": raise InvalidRequestError(request.tag) # Make sure the we either have a network tag with an IP or networkId # Or Network info with a primary nic that has privateip or vlanid network = request.find(fixxpath('network', TYPES_URN)) network_info = request.find(fixxpath('networkInfo', TYPES_URN)) if network is not None: if network_info is not None: raise InvalidRequestError("Request has both MCP1 and MCP2 values") ipv4 = findtext(network, 'privateIpv4', TYPES_URN) networkId = findtext(network, 'networkId', TYPES_URN) if ipv4 is None and networkId is None: raise InvalidRequestError('Invalid request MCP1 requests need privateIpv4 or networkId') elif network_info is not None: if network is not None: raise InvalidRequestError("Request has both MCP1 and MCP2 values") primary_nic = network_info.find(fixxpath('primaryNic', TYPES_URN)) ipv4 = findtext(primary_nic, 'privateIpv4', TYPES_URN) vlanId = findtext(primary_nic, 'vlanId', TYPES_URN) if ipv4 is None and vlanId is None: raise InvalidRequestError('Invalid request MCP2 requests need privateIpv4 or vlanId') else: raise InvalidRequestError('Invalid request, does not have network or network_info in XML') body = self.fixtures.load( 'server_deployServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deployNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be_ALLFILTERS(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deployVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_0e56433f_d808_4669_821d_812769517ff8(self, method, url, body, headers): body = self.fixtures.load( 'network_vlan_0e56433f_d808_4669_821d_812769517ff8.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_expandVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}expandVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_expandVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_addPublicIpBlock(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}addPublicIpBlock": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_addPublicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_removePublicIpBlock(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removePublicIpBlock": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_removePublicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule(self, method, url, body, headers): body = self.fixtures.load( 'network_firewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_createFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c(self, method, url, body, headers): body = self.fixtures.load( 'network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createNatRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createNatRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_createNatRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule(self, method, url, body, headers): body = self.fixtures.load( 'network_natRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce(self, method, url, body, headers): body = self.fixtures.load( 'network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNatRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteNatRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteNatRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addNic(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}addNic": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_addNic.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeNic(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removeNic": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_removeNic.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_disableServerMonitoring(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}disableServerMonitoring": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_disableServerMonitoring.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_enableServerMonitoring(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}enableServerMonitoring": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_enableServerMonitoring.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeServerMonitoringPlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}changeServerMonitoringPlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_changeServerMonitoringPlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_FAKE_IMAGE_ID(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_FAKE_IMAGE_ID(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_reconfigureServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}reconfigureServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_reconfigureServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cleanServer(self, method, url, body, headers): body = self.fixtures.load( 'server_cleanServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addDisk(self, method, url, body, headers): body = self.fixtures.load( 'server_addDisk.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeDisk(self, method, url, body, headers): body = self.fixtures.load( 'server_removeDisk.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is not None: raise ValueError("Default description for a tag should be blank") if value_required is None or value_required != 'true': raise ValueError("Default valueRequired should be true") if display_on_report is None or display_on_report != 'true': raise ValueError("Default displayOnReport should be true") body = self.fixtures.load( 'tag_createTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_ALLPARAMS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is None: raise ValueError("Description should have a value") if value_required is None or value_required != 'false': raise ValueError("valueRequired should be false") if display_on_report is None or display_on_report != 'false': raise ValueError("displayOnReport should be false") body = self.fixtures.load( 'tag_createTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_BADREQUEST(self, method, url, body, headers): body = self.fixtures.load( 'tag_createTagKey_BADREQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_SINGLE(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_list_SINGLE.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'id': assert value == 'fake_id' elif key == 'name': assert value == 'fake_name' elif key == 'valueRequired': assert value == 'false' elif key == 'displayOnReport': assert value == 'false' elif key == 'pageSize': assert value == '250' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'tag_tagKey_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075_NOEXIST(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NAME(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is not None: raise ValueError("Description should be empty") if value_required is not None: raise ValueError("valueRequired should be empty") if display_on_report is not None: raise ValueError("displayOnReport should be empty") body = self.fixtures.load( 'tag_editTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOTNAME(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is not None: raise ValueError("Name should be empty") if description is None: raise ValueError("Description should not be empty") if value_required is None: raise ValueError("valueRequired should not be empty") if display_on_report is None: raise ValueError("displayOnReport should not be empty") body = self.fixtures.load( 'tag_editTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOCHANGE(self, method, url, body, headers): body = self.fixtures.load( 'tag_editTagKey_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteTagKey": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'tag_deleteTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey_NOEXIST(self, method, url, body, headers): body = self.fixtures.load( 'tag_deleteTagKey_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}applyTags": raise InvalidRequestError(request.tag) asset_type = findtext(request, 'assetType', TYPES_URN) asset_id = findtext(request, 'assetId', TYPES_URN) tag = request.find(fixxpath('tag', TYPES_URN)) tag_key_name = findtext(tag, 'tagKeyName', TYPES_URN) value = findtext(tag, 'value', TYPES_URN) if asset_type is None: raise ValueError("assetType should not be empty") if asset_id is None: raise ValueError("assetId should not be empty") if tag_key_name is None: raise ValueError("tagKeyName should not be empty") if value is None: raise ValueError("value should not be empty") body = self.fixtures.load( 'tag_applyTags.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOVALUE(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}applyTags": raise InvalidRequestError(request.tag) asset_type = findtext(request, 'assetType', TYPES_URN) asset_id = findtext(request, 'assetId', TYPES_URN) tag = request.find(fixxpath('tag', TYPES_URN)) tag_key_name = findtext(tag, 'tagKeyName', TYPES_URN) value = findtext(tag, 'value', TYPES_URN) if asset_type is None: raise ValueError("assetType should not be empty") if asset_id is None: raise ValueError("assetId should not be empty") if tag_key_name is None: raise ValueError("tagKeyName should not be empty") if value is not None: raise ValueError("value should be empty") body = self.fixtures.load( 'tag_applyTags.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOTAGKEY(self, method, url, body, headers): body = self.fixtures.load( 'tag_applyTags_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removeTags": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'tag_removeTag.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags_NOTAG(self, method, url, body, headers): body = self.fixtures.load( 'tag_removeTag_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag(self, method, url, body, headers): body = self.fixtures.load( 'tag_tag_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag_ALLPARAMS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'assetId': assert value == 'fake_asset_id' elif key == 'assetType': assert value == 'fake_asset_type' elif key == 'valueRequired': assert value == 'false' elif key == 'displayOnReport': assert value == 'false' elif key == 'pageSize': assert value == '250' elif key == 'datacenterId': assert value == 'fake_location' elif key == 'value': assert value == 'fake_value' elif key == 'tagKeyName': assert value == 'fake_tag_key_name' elif key == 'tagKeyId': assert value == 'fake_tag_key_id' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'tag_tag_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList( self, method, url, body, headers): body = self.fixtures.load('ip_address_lists.xml') return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList_FILTERBYNAME( self, method, url, body, headers): body = self.fixtures.load('ip_address_lists_FILTERBYNAME.xml') return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "createIpAddressList": raise InvalidRequestError(request.tag) net_domain = findtext(request, 'networkDomainId', TYPES_URN) if net_domain is None: raise ValueError("Network Domain should not be empty") name = findtext(request, 'name', TYPES_URN) if name is None: raise ValueError("Name should not be empty") ip_version = findtext(request, 'ipVersion', TYPES_URN) if ip_version is None: raise ValueError("IP Version should not be empty") ip_address_col_required = findall(request, 'ipAddress', TYPES_URN) child_ip_address_required = findall(request, 'childIpAddressListId', TYPES_URN) if 0 == len(ip_address_col_required) and \ 0 == len(child_ip_address_required): raise ValueError("At least one ipAddress element or " "one childIpAddressListId element must be " "provided.") if ip_address_col_required[0].get('begin') is None: raise ValueError("IP Address should not be empty") body = self.fixtures.load( 'ip_address_list_create.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "editIpAddressList": raise InvalidRequestError(request.tag) ip_address_list = request.get('id') if ip_address_list is None: raise ValueError("IpAddressList ID should not be empty") name = findtext(request, 'name', TYPES_URN) if name is not None: raise ValueError("Name should not exists in request") ip_version = findtext(request, 'ipVersion', TYPES_URN) if ip_version is not None: raise ValueError("IP Version should not exists in request") ip_address_col_required = findall(request, 'ipAddress', TYPES_URN) child_ip_address_required = findall(request, 'childIpAddressListId', TYPES_URN) if 0 == len(ip_address_col_required) and \ 0 == len(child_ip_address_required): raise ValueError("At least one ipAddress element or " "one childIpAddressListId element must be " "provided.") if ip_address_col_required[0].get('begin') is None: raise ValueError("IP Address should not be empty") body = self.fixtures.load( 'ip_address_list_edit.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "deleteIpAddressList": raise InvalidRequestError(request.tag) ip_address_list = request.get('id') if ip_address_list is None: raise ValueError("IpAddressList ID should not be empty") body = self.fixtures.load( 'ip_address_list_delete.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList( self, method, url, body, headers): body = self.fixtures.load( 'port_list_lists.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList_c8c92ea3_2da8_4d51_8153_f39bec794d69( self, method, url, body, headers): body = self.fixtures.load( 'port_list_get.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "createPortList": raise InvalidRequestError(request.tag) net_domain = findtext(request, 'networkDomainId', TYPES_URN) if net_domain is None: raise ValueError("Network Domain should not be empty") ports_required = findall(request, 'port', TYPES_URN) child_port_list_required = findall(request, 'childPortListId', TYPES_URN) if 0 == len(ports_required) and \ 0 == len(child_port_list_required): raise ValueError("At least one port element or one " "childPortListId element must be provided") if ports_required[0].get('begin') is None: raise ValueError("PORT begin value should not be empty") body = self.fixtures.load( 'port_list_create.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "editPortList": raise InvalidRequestError(request.tag) ports_required = findall(request, 'port', TYPES_URN) child_port_list_required = findall(request, 'childPortListId', TYPES_URN) if 0 == len(ports_required) and \ 0 == len(child_port_list_required): raise ValueError("At least one port element or one " "childPortListId element must be provided") if ports_required[0].get('begin') is None: raise ValueError("PORT begin value should not be empty") body = self.fixtures.load( 'port_list_edit.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deletePortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "deletePortList": raise InvalidRequestError(request.tag) port_list = request.get('id') if port_list is None: raise ValueError("Port List ID should not be empty") body = self.fixtures.load( 'ip_address_list_delete.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_dimensiondata_v2_4.py0000664000175000017500000047762513577507766026011 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from types import GeneratorType from libcloud.utils.py3 import httplib from libcloud.utils.py3 import ET from libcloud.common.types import InvalidCredsError from libcloud.common.dimensiondata import DimensionDataAPIException, NetworkDomainServicePlan from libcloud.common.dimensiondata import DimensionDataServerCpuSpecification, DimensionDataServerDisk, DimensionDataServerVMWareTools from libcloud.common.dimensiondata import DimensionDataTag, DimensionDataTagKey from libcloud.common.dimensiondata import DimensionDataIpAddress, \ DimensionDataIpAddressList, DimensionDataChildIpAddressList, \ DimensionDataPortList, DimensionDataPort, DimensionDataChildPortList from libcloud.common.dimensiondata import TYPES_URN from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver as DimensionData from libcloud.compute.drivers.dimensiondata import DimensionDataNic from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import DIMENSIONDATA_PARAMS from libcloud.utils.xml import fixxpath, findtext, findall class DimensionData_v2_4_Tests(unittest.TestCase): def setUp(self): DimensionData.connectionCls.active_api_version = '2.4' DimensionData.connectionCls.conn_class = DimensionDataMockHttp DimensionDataMockHttp.type = None self.driver = DimensionData(*DIMENSIONDATA_PARAMS) def test_invalid_region(self): with self.assertRaises(ValueError): DimensionData(*DIMENSIONDATA_PARAMS, region='blah') def test_invalid_creds(self): DimensionDataMockHttp.type = 'UNAUTHORIZED' with self.assertRaises(InvalidCredsError): self.driver.list_nodes() def test_get_account_details(self): DimensionDataMockHttp.type = None ret = self.driver.connection.get_account_details() self.assertEqual(ret.full_name, 'Test User') self.assertEqual(ret.first_name, 'Test') self.assertEqual(ret.email, 'test@example.com') def test_list_locations_response(self): DimensionDataMockHttp.type = None ret = self.driver.list_locations() self.assertEqual(len(ret), 5) first_loc = ret[0] self.assertEqual(first_loc.id, 'NA3') self.assertEqual(first_loc.name, 'US - West') self.assertEqual(first_loc.country, 'US') def test_list_nodes_response(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes() self.assertEqual(len(ret), 7) def test_node_extras(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes() self.assertTrue(isinstance(ret[0].extra['vmWareTools'], DimensionDataServerVMWareTools)) self.assertTrue(isinstance(ret[0].extra['cpu'], DimensionDataServerCpuSpecification)) self.assertTrue(isinstance(ret[0].extra['disks'], list)) self.assertTrue(isinstance(ret[0].extra['disks'][0], DimensionDataServerDisk)) self.assertEqual(ret[0].extra['disks'][0].size_gb, 10) self.assertTrue(isinstance(ret[1].extra['disks'], list)) self.assertTrue(isinstance(ret[1].extra['disks'][0], DimensionDataServerDisk)) self.assertEqual(ret[1].extra['disks'][0].size_gb, 10) def test_server_states(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes() self.assertTrue(ret[0].state == 'running') self.assertTrue(ret[1].state == 'starting') self.assertTrue(ret[2].state == 'stopping') self.assertTrue(ret[3].state == 'reconfiguring') self.assertTrue(ret[4].state == 'running') self.assertTrue(ret[5].state == 'terminated') self.assertTrue(ret[6].state == 'stopped') self.assertEqual(len(ret), 7) def test_list_nodes_response_PAGINATED(self): DimensionDataMockHttp.type = 'PAGINATED' ret = self.driver.list_nodes() self.assertEqual(len(ret), 9) def test_paginated_mcp2_call_EMPTY(self): # cache org self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'EMPTY' node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server') empty_node_list = [] for node_list in node_list_generator: empty_node_list.extend(node_list) self.assertTrue(len(empty_node_list) == 0) def test_paginated_mcp2_call_PAGED_THEN_EMPTY(self): # cache org self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'PAGED_THEN_EMPTY' node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server') final_node_list = [] for node_list in node_list_generator: final_node_list.extend(node_list) self.assertTrue(len(final_node_list) == 2) def test_paginated_mcp2_call_with_page_size(self): # cache org self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'PAGESIZE50' node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server', page_size=50) self.assertTrue(isinstance(node_list_generator, GeneratorType)) # We're making sure here the filters make it to the URL # See _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts def test_list_nodes_response_strings_ALLFILTERS(self): DimensionDataMockHttp.type = 'ALLFILTERS' ret = self.driver.list_nodes(ex_location='fake_loc', ex_name='fake_name', ex_ipv6='fake_ipv6', ex_ipv4='fake_ipv4', ex_vlan='fake_vlan', ex_image='fake_image', ex_deployed=True, ex_started=True, ex_state='fake_state', ex_network='fake_network', ex_network_domain='fake_network_domain') self.assertTrue(isinstance(ret, list)) self.assertEqual(len(ret), 7) node = ret[3] self.assertTrue(isinstance(node.extra['disks'], list)) self.assertTrue(isinstance(node.extra['disks'][0], DimensionDataServerDisk)) self.assertEqual(node.size.id, '1') self.assertEqual(node.image.id, '3ebf3c0f-90fe-4a8b-8585-6e65b316592c') self.assertEqual(node.image.name, 'WIN2008S/32') disk = node.extra['disks'][0] self.assertEqual(disk.id, "c2e1f199-116e-4dbc-9960-68720b832b0a") self.assertEqual(disk.scsi_id, 0) self.assertEqual(disk.size_gb, 50) self.assertEqual(disk.speed, "STANDARD") self.assertEqual(disk.state, "NORMAL") def test_list_nodes_response_LOCATION(self): DimensionDataMockHttp.type = None ret = self.driver.list_locations() first_loc = ret[0] ret = self.driver.list_nodes(ex_location=first_loc) for node in ret: self.assertEqual(node.extra['datacenterId'], 'NA3') def test_list_nodes_response_LOCATION_STR(self): DimensionDataMockHttp.type = None ret = self.driver.list_nodes(ex_location='NA3') for node in ret: self.assertEqual(node.extra['datacenterId'], 'NA3') def test_list_sizes_response(self): DimensionDataMockHttp.type = None ret = self.driver.list_sizes() self.assertEqual(len(ret), 1) size = ret[0] self.assertEqual(size.name, 'default') def test_reboot_node_response(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = node.reboot() self.assertTrue(ret is True) def test_reboot_node_response_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): node.reboot() def test_destroy_node_response(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = node.destroy() self.assertTrue(ret is True) def test_destroy_node_response_RESOURCE_BUSY(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): node.destroy() def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 3) self.assertEqual(images[0].name, 'RedHat 6 64-bit 2 CPU') self.assertEqual(images[0].id, 'c14b1a46-2428-44c1-9c1a-b20e6418d08c') self.assertEqual(images[0].extra['location'].id, 'NA9') self.assertEqual(images[0].extra['cpu'].cpu_count, 2) self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64') def test_clean_failed_deployment_response_with_node(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_clean_failed_deployment(node) self.assertTrue(ret is True) def test_clean_failed_deployment_response_with_node_id(self): node = 'e75ead52-692f-4314-8725-c8a4f4d13a87' ret = self.driver.ex_clean_failed_deployment(node) self.assertTrue(ret is True) def test_ex_list_customer_images(self): images = self.driver.ex_list_customer_images() self.assertEqual(len(images), 3) self.assertEqual(images[0].name, 'ImportedCustomerImage') self.assertEqual(images[0].id, '5234e5c7-01de-4411-8b6e-baeb8d91cf5d') self.assertEqual(images[0].extra['location'].id, 'NA9') self.assertEqual(images[0].extra['cpu'].cpu_count, 4) self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64') def test_create_mcp1_node_optional_param(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] network = self.driver.ex_list_networks()[0] cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4', cores_per_socket='2', performance='STANDARD') disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')] node = self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network=network, ex_is_started=False, ex_memory_gb=8, ex_disks=disks, ex_cpu_specification=cpu_spec, ex_primary_dns='10.0.0.5', ex_secondary_dns='10.0.0.6' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_mcp1_node_response_no_pass_random_gen(self): image = self.driver.list_images()[0] network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' in node.extra) def test_create_mcp1_node_response_no_pass_customer_windows(self): image = self.driver.ex_list_customer_images()[1] network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' in node.extra) def test_create_mcp1_node_response_no_pass_customer_windows_STR(self): image = self.driver.ex_list_customer_images()[1].id network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' in node.extra) def test_create_mcp1_node_response_no_pass_customer_linux(self): image = self.driver.ex_list_customer_images()[0] network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' not in node.extra) def test_create_mcp1_node_response_no_pass_customer_linux_STR(self): image = self.driver.ex_list_customer_images()[0].id network = self.driver.ex_list_networks()[0] node = self.driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') self.assertTrue('password' not in node.extra) def test_create_mcp1_node_response_STR(self): rootPw = 'pass123' image = self.driver.list_images()[0].id network = self.driver.ex_list_networks()[0].id node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network=network, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_response_network_domain(self): rootPw = NodeAuthPassword('pass123') location = self.driver.ex_get_location_by_id('NA9') image = self.driver.list_images(location=location)[0] network_domain = self.driver.ex_list_network_domains(location=location)[0] vlan = self.driver.ex_list_vlans(location=location)[0] cpu = DimensionDataServerCpuSpecification( cpu_count=4, cores_per_socket=1, performance='HIGHPERFORMANCE' ) node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain=network_domain, ex_vlan=vlan, ex_is_started=False, ex_cpu_specification=cpu, ex_memory_gb=4) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_response_network_domain_STR(self): rootPw = NodeAuthPassword('pass123') location = self.driver.ex_get_location_by_id('NA9') image = self.driver.list_images(location=location)[0] network_domain = self.driver.ex_list_network_domains(location=location)[0].id vlan = self.driver.ex_list_vlans(location=location)[0].id cpu = DimensionDataServerCpuSpecification( cpu_count=4, cores_per_socket=1, performance='HIGHPERFORMANCE' ) node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain=network_domain, ex_vlan=vlan, ex_is_started=False, ex_cpu_specification=cpu, ex_memory_gb=4) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_mcp1_node_no_network(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(InvalidRequestError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network=None, ex_is_started=False) def test_create_node_mcp1_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network='fakenetwork', ex_primary_ipv4='10.0.0.1', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_mcp1_network(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network='fakenetwork', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_mcp2_vlan(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_vlan='fakevlan', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_mcp2_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_network_domain_no_vlan_or_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_is_started=False) def test_create_node_response(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_ms_time_zone(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan', ex_microsoft_time_zone='040' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_ambigious_mcps_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_network='fakenetwork', ex_primary_nic_vlan='fakevlan' ) def test_create_node_no_network_domain_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_primary_nic_vlan='fakevlan' ) def test_create_node_no_primary_nic_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain' ) def test_create_node_primary_vlan_nic(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan', ex_primary_nic_network_adapter='v1000' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_primary_ipv4(self): rootPw = 'pass123' image = self.driver.list_images()[0] node = self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1' ) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_both_primary_nic_and_vlan_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_primary_nic_vlan='fakevlan' ) def test_create_node_cpu_specification(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4', cores_per_socket='2', performance='STANDARD') node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_cpu_specification=cpu_spec) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_memory(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_memory_gb=8) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_disks(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_disks=disks) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_disks_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] disks = 'blah' with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_disks=disks) def test_create_node_ipv4_gateway(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_ipv4_gateway='10.2.2.2') self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_network_domain_no_vlan_no_ipv4_fail(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_is_started=False) def test_create_node_mcp2_additional_nics_legacy(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] additional_vlans = ['fakevlan1', 'fakevlan2'] additional_ipv4 = ['10.0.0.2', '10.0.0.3'] node = self.driver.create_node( name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_additional_nics_vlan=additional_vlans, ex_additional_nics_ipv4=additional_ipv4, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_bad_additional_nics_ipv4(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_vlan='fake_vlan', ex_additional_nics_ipv4='badstring', ex_is_started=False) def test_create_node_additional_nics(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] nic1 = DimensionDataNic(vlan='fake_vlan', network_adapter_name='v1000') nic2 = DimensionDataNic(private_ip_v4='10.1.1.2', network_adapter_name='v1000') additional_nics = [nic1, nic2] node = self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_create_node_additional_nics_vlan_ipv4_coexist_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] nic1 = DimensionDataNic(private_ip_v4='10.1.1.1', vlan='fake_vlan', network_adapter_name='v1000') nic2 = DimensionDataNic(private_ip_v4='10.1.1.2', vlan='fake_vlan2', network_adapter_name='v1000') additional_nics = [nic1, nic2] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False ) def test_create_node_additional_nics_invalid_input_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] additional_nics = 'blah' with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False ) def test_create_node_additional_nics_vlan_ipv4_not_exist_fail(self): root_pw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] nic1 = DimensionDataNic(network_adapter_name='v1000') nic2 = DimensionDataNic(network_adapter_name='v1000') additional_nics = [nic1, nic2] with self.assertRaises(ValueError): self.driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False) def test_create_node_bad_additional_nics_vlan(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] with self.assertRaises(TypeError): self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_vlan='fake_vlan', ex_additional_nics_vlan='badstring', ex_is_started=False) def test_create_node_mcp2_indicate_dns(self): rootPw = NodeAuthPassword('pass123') image = self.driver.list_images()[0] node = self.driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test node dns', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_primary_dns='8.8.8.8', ex_secondary_dns='8.8.4.4', ex_is_started=False) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER') def test_ex_shutdown_graceful(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_shutdown_graceful(node) self.assertTrue(ret is True) def test_ex_shutdown_graceful_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): self.driver.ex_shutdown_graceful(node) def test_ex_start_node(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_start_node(node) self.assertTrue(ret is True) def test_ex_start_node_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): self.driver.ex_start_node(node) def test_ex_power_off(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_power_off(node) self.assertTrue(ret is True) def test_ex_update_vm_tools(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_update_vm_tools(node) self.assertTrue(ret is True) def test_ex_power_off_INPROGRESS(self): DimensionDataMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state='STOPPING', public_ips=None, private_ips=None, driver=self.driver) with self.assertRaises(DimensionDataAPIException): self.driver.ex_power_off(node) def test_ex_reset(self): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_reset(node) self.assertTrue(ret is True) def test_ex_attach_node_to_vlan(self): node = self.driver.ex_get_node_by_id('e75ead52-692f-4314-8725-c8a4f4d13a87') vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') ret = self.driver.ex_attach_node_to_vlan(node, vlan) self.assertTrue(ret is True) def test_ex_destroy_nic(self): node = self.driver.ex_destroy_nic('a202e51b-41c0-4cfc-add0-b1c62fc0ecf6') self.assertTrue(node) def test_list_networks(self): nets = self.driver.list_networks() self.assertEqual(nets[0].name, 'test-net1') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_create_network(self): location = self.driver.ex_get_location_by_id('NA9') net = self.driver.ex_create_network(location, "Test Network", "test") self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e") self.assertEqual(net.name, "Test Network") def test_ex_create_network_NO_DESCRIPTION(self): location = self.driver.ex_get_location_by_id('NA9') net = self.driver.ex_create_network(location, "Test Network") self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e") self.assertEqual(net.name, "Test Network") def test_ex_delete_network(self): net = self.driver.ex_list_networks()[0] result = self.driver.ex_delete_network(net) self.assertTrue(result) def test_ex_rename_network(self): net = self.driver.ex_list_networks()[0] result = self.driver.ex_rename_network(net, "barry") self.assertTrue(result) def test_ex_create_network_domain(self): location = self.driver.ex_get_location_by_id('NA9') plan = NetworkDomainServicePlan.ADVANCED net = self.driver.ex_create_network_domain(location=location, name='test', description='test', service_plan=plan) self.assertEqual(net.name, 'test') self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa') def test_ex_create_network_domain_NO_DESCRIPTION(self): location = self.driver.ex_get_location_by_id('NA9') plan = NetworkDomainServicePlan.ADVANCED net = self.driver.ex_create_network_domain(location=location, name='test', service_plan=plan) self.assertEqual(net.name, 'test') self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa') def test_ex_get_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') self.assertEqual(net.id, '8cdfd607-f429-4df6-9352-162cfc0891be') self.assertEqual(net.description, 'test2') self.assertEqual(net.name, 'test') def test_ex_update_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') net.name = 'new name' net2 = self.driver.ex_update_network_domain(net) self.assertEqual(net2.name, 'new name') def test_ex_delete_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') result = self.driver.ex_delete_network_domain(net) self.assertTrue(result) def test_ex_list_networks(self): nets = self.driver.ex_list_networks() self.assertEqual(nets[0].name, 'test-net1') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_list_network_domains(self): nets = self.driver.ex_list_network_domains() self.assertEqual(nets[0].name, 'Aurora') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_list_network_domains_ALLFILTERS(self): DimensionDataMockHttp.type = 'ALLFILTERS' nets = self.driver.ex_list_network_domains(location='fake_location', name='fake_name', service_plan='fake_plan', state='fake_state') self.assertEqual(nets[0].name, 'Aurora') self.assertTrue(isinstance(nets[0].location, NodeLocation)) def test_ex_list_vlans(self): vlans = self.driver.ex_list_vlans() self.assertEqual(vlans[0].name, "Primary") def test_ex_list_vlans_ALLFILTERS(self): DimensionDataMockHttp.type = 'ALLFILTERS' vlans = self.driver.ex_list_vlans(location='fake_location', network_domain='fake_network_domain', name='fake_name', ipv4_address='fake_ipv4', ipv6_address='fake_ipv6', state='fake_state') self.assertEqual(vlans[0].name, "Primary") def test_ex_create_vlan(self,): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') vlan = self.driver.ex_create_vlan(network_domain=net, name='test', private_ipv4_base_address='10.3.4.0', private_ipv4_prefix_size='24', description='test vlan') self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') def test_ex_create_vlan_NO_DESCRIPTION(self,): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') vlan = self.driver.ex_create_vlan(network_domain=net, name='test', private_ipv4_base_address='10.3.4.0', private_ipv4_prefix_size='24') self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') def test_ex_get_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8') self.assertEqual(vlan.description, 'test2') self.assertEqual(vlan.status, 'NORMAL') self.assertEqual(vlan.name, 'Production VLAN') self.assertEqual(vlan.private_ipv4_range_address, '10.0.3.0') self.assertEqual(vlan.private_ipv4_range_size, 24) self.assertEqual(vlan.ipv6_range_size, 64) self.assertEqual(vlan.ipv6_range_address, '2607:f480:1111:1153:0:0:0:0') self.assertEqual(vlan.ipv4_gateway, '10.0.3.1') self.assertEqual(vlan.ipv6_gateway, '2607:f480:1111:1153:0:0:0:1') def test_ex_wait_for_state(self): self.driver.ex_wait_for_state('NORMAL', self.driver.ex_get_vlan, vlan_id='0e56433f-d808-4669-821d-812769517ff8', poll_interval=0.1) def test_ex_wait_for_state_NODE(self): self.driver.ex_wait_for_state('running', self.driver.ex_get_node_by_id, id='e75ead52-692f-4314-8725-c8a4f4d13a87', poll_interval=0.1) def test_ex_wait_for_state_FAIL(self): with self.assertRaises(DimensionDataAPIException) as context: self.driver.ex_wait_for_state('starting', self.driver.ex_get_node_by_id, id='e75ead52-692f-4314-8725-c8a4f4d13a87', poll_interval=0.1, timeout=0.1 ) self.assertEqual(context.exception.code, 'running') self.assertTrue('timed out' in context.exception.msg) def test_ex_update_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') vlan.name = 'new name' vlan2 = self.driver.ex_update_vlan(vlan) self.assertEqual(vlan2.name, 'new name') def test_ex_delete_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') result = self.driver.ex_delete_vlan(vlan) self.assertTrue(result) def test_ex_expand_vlan(self): vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') vlan.private_ipv4_range_size = '23' vlan = self.driver.ex_expand_vlan(vlan) self.assertEqual(vlan.private_ipv4_range_size, '23') def test_ex_add_public_ip_block_to_network_domain(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') block = self.driver.ex_add_public_ip_block_to_network_domain(net) self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') def test_ex_list_public_ip_blocks(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') blocks = self.driver.ex_list_public_ip_blocks(net) self.assertEqual(blocks[0].base_ip, '168.128.4.18') self.assertEqual(blocks[0].size, '2') self.assertEqual(blocks[0].id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') self.assertEqual(blocks[0].location.id, 'NA9') self.assertEqual(blocks[0].network_domain.id, net.id) def test_ex_get_public_ip_block(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') self.assertEqual(block.base_ip, '168.128.4.18') self.assertEqual(block.size, '2') self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') self.assertEqual(block.location.id, 'NA9') self.assertEqual(block.network_domain.id, net.id) def test_ex_delete_public_ip_block(self): block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') result = self.driver.ex_delete_public_ip_block(block) self.assertTrue(result) def test_ex_list_firewall_rules(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) self.assertEqual(rules[0].id, '756cba02-b0bc-48f4-aea5-9445870b6148') self.assertEqual(rules[0].network_domain.id, '8cdfd607-f429-4df6-9352-162cfc0891be') self.assertEqual(rules[0].name, 'CCDEFAULT.BlockOutboundMailIPv4') self.assertEqual(rules[0].action, 'DROP') self.assertEqual(rules[0].ip_version, 'IPV4') self.assertEqual(rules[0].protocol, 'TCP') self.assertEqual(rules[0].source.ip_address, 'ANY') self.assertTrue(rules[0].source.any_ip) self.assertTrue(rules[0].destination.any_ip) def test_ex_create_firewall_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) rule = self.driver.ex_create_firewall_rule(net, rules[0], 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_with_specific_source_ip(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) specific_source_ip_rule = list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_with_source_ip(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) specific_source_ip_rule = \ list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] specific_source_ip_rule.source.any_ip = False specific_source_ip_rule.source.ip_address = '10.0.0.1' specific_source_ip_rule.source.ip_prefix_size = '15' rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_with_any_ip(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) specific_source_ip_rule = \ list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] specific_source_ip_rule.source.any_ip = True rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_ip_prefix_size(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.address_list_id = None rule.source.any_ip = False rule.source.ip_address = '10.2.1.1' rule.source.ip_prefix_size = '10' rule.destination.address_list_id = None rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = '20' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_address_list(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.address_list_id = '12345' rule.destination.address_list_id = '12345' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_port_list(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.port_list_id = '12345' rule.destination.port_list_id = '12345' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_port(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_list_firewall_rules(net)[0] rule.source.port_list_id = None rule.source.port_begin = '8000' rule.source.port_end = '8005' rule.destination.port_list_id = None rule.destination.port_begin = '7000' rule.destination.port_end = '7005' self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_ALL_VALUES(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) for rule in rules: self.driver.ex_create_firewall_rule(net, rule, 'LAST') def test_ex_create_firewall_rule_WITH_POSITION_RULE(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', rules[-1]) self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_WITH_POSITION_RULE_STR(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', 'RULE_WITH_SOURCE_AND_DEST') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_create_firewall_rule_FAIL_POSITION(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) with self.assertRaises(ValueError): self.driver.ex_create_firewall_rule(net, rules[0], 'BEFORE') def test_ex_create_firewall_rule_FAIL_POSITION_WITH_RULE(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_firewall_rules(net) with self.assertRaises(ValueError): self.driver.ex_create_firewall_rule(net, rules[0], 'LAST', 'RULE_WITH_SOURCE_AND_DEST') def test_ex_get_firewall_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') def test_ex_set_firewall_rule_state(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') result = self.driver.ex_set_firewall_rule_state(rule, False) self.assertTrue(result) def test_ex_delete_firewall_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') result = self.driver.ex_delete_firewall_rule(rule) self.assertTrue(result) def test_ex_edit_firewall_rule(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.any_ip = True result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_source_ipaddresslist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' rule.source.any_ip = False rule.source.ip_address = '10.0.0.1' rule.source.ip_prefix_size = 10 result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_ipaddresslist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = 10 result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_ipaddress(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.address_list_id = None rule.source.any_ip = False rule.source.ip_address = '10.0.0.1' rule.source.ip_prefix_size = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_source_ipaddress(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.address_list_id = None rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_with_relative_rule(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') placement_rule = self.driver.ex_list_firewall_rules( network_domain=net)[-1] result = self.driver.ex_edit_firewall_rule( rule=rule, position='BEFORE', relative_rule_for_position=placement_rule) self.assertTrue(result) def test_ex_edit_firewall_rule_with_relative_rule_by_name(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') placement_rule = self.driver.ex_list_firewall_rules( network_domain=net)[-1] result = self.driver.ex_edit_firewall_rule( rule=rule, position='BEFORE', relative_rule_for_position=placement_rule.name) self.assertTrue(result) def test_ex_edit_firewall_rule_source_portlist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_source_port(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.port_list_id = None rule.source.port_begin = '3' rule.source.port_end = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_portlist(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_destination_port(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.port_list_id = None rule.destination.port_begin = '3' rule.destination.port_end = '10' result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST') self.assertTrue(result) def test_ex_edit_firewall_rule_invalid_position_fail(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') with self.assertRaises(ValueError): self.driver.ex_edit_firewall_rule(rule=rule, position='BEFORE') def test_ex_edit_firewall_rule_invalid_position_relative_rule_fail(self): net = self.driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') relative_rule = self.driver.ex_list_firewall_rules( network_domain=net)[-1] with self.assertRaises(ValueError): self.driver.ex_edit_firewall_rule(rule=rule, position='FIRST', relative_rule_for_position=relative_rule) def test_ex_create_nat_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_create_nat_rule(net, '1.2.3.4', '4.3.2.1') self.assertEqual(rule.id, 'd31c2db0-be6b-4d50-8744-9a7a534b5fba') def test_ex_list_nat_rules(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = self.driver.ex_list_nat_rules(net) self.assertEqual(rules[0].id, '2187a636-7ebb-49a1-a2ff-5d617f496dce') self.assertEqual(rules[0].internal_ip, '10.0.0.15') self.assertEqual(rules[0].external_ip, '165.180.12.18') def test_ex_get_nat_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce') self.assertEqual(rule.id, '2187a636-7ebb-49a1-a2ff-5d617f496dce') self.assertEqual(rule.internal_ip, '10.0.0.16') self.assertEqual(rule.external_ip, '165.180.12.19') def test_ex_delete_nat_rule(self): net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce') result = self.driver.ex_delete_nat_rule(rule) self.assertTrue(result) def test_ex_enable_monitoring(self): node = self.driver.list_nodes()[0] result = self.driver.ex_enable_monitoring(node, "ADVANCED") self.assertTrue(result) def test_ex_disable_monitoring(self): node = self.driver.list_nodes()[0] result = self.driver.ex_disable_monitoring(node) self.assertTrue(result) def test_ex_change_monitoring_plan(self): node = self.driver.list_nodes()[0] result = self.driver.ex_update_monitoring_plan(node, "ESSENTIALS") self.assertTrue(result) def test_ex_add_storage_to_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_add_storage_to_node(node, 30, 'PERFORMANCE') self.assertTrue(result) def test_ex_remove_storage_from_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_remove_storage_from_node(node, 0) self.assertTrue(result) def test_ex_change_storage_speed(self): node = self.driver.list_nodes()[0] result = self.driver.ex_change_storage_speed(node, 1, 'PERFORMANCE') self.assertTrue(result) def test_ex_change_storage_size(self): node = self.driver.list_nodes()[0] result = self.driver.ex_change_storage_size(node, 1, 100) self.assertTrue(result) def test_ex_clone_node_to_image(self): node = self.driver.list_nodes()[0] result = self.driver.ex_clone_node_to_image(node, 'my image', 'a description') self.assertTrue(result) def test_ex_update_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_update_node(node, 'my new name', 'a description', 2, 4048) self.assertTrue(result) def test_ex_reconfigure_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_reconfigure_node(node, 4, 4, 1, 'HIGHPERFORMANCE') self.assertTrue(result) def test_ex_get_location_by_id(self): location = self.driver.ex_get_location_by_id('NA9') self.assertTrue(location.id, 'NA9') def test_ex_get_location_by_id_NO_LOCATION(self): location = self.driver.ex_get_location_by_id(None) self.assertIsNone(location) def test_ex_get_base_image_by_id(self): image_id = self.driver.list_images()[0].id image = self.driver.ex_get_base_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'UNIX') def test_ex_get_customer_image_by_id(self): image_id = self.driver.ex_list_customer_images()[1].id image = self.driver.ex_get_customer_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'WINDOWS') def test_ex_get_image_by_id_base_img(self): image_id = self.driver.list_images()[1].id image = self.driver.ex_get_base_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'WINDOWS') def test_ex_get_image_by_id_customer_img(self): image_id = self.driver.ex_list_customer_images()[0].id image = self.driver.ex_get_customer_image_by_id(image_id) self.assertEqual(image.extra['OS_type'], 'UNIX') def test_ex_get_image_by_id_customer_FAIL(self): image_id = 'FAKE_IMAGE_ID' with self.assertRaises(DimensionDataAPIException): self.driver.ex_get_base_image_by_id(image_id) def test_ex_create_anti_affinity_rule(self): node_list = self.driver.list_nodes() success = self.driver.ex_create_anti_affinity_rule([node_list[0], node_list[1]]) self.assertTrue(success) def test_ex_create_anti_affinity_rule_TUPLE(self): node_list = self.driver.list_nodes() success = self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1])) self.assertTrue(success) def test_ex_create_anti_affinity_rule_TUPLE_STR(self): node_list = self.driver.list_nodes() success = self.driver.ex_create_anti_affinity_rule((node_list[0].id, node_list[1].id)) self.assertTrue(success) def test_ex_create_anti_affinity_rule_FAIL_STR(self): node_list = 'string' with self.assertRaises(TypeError): self.driver.ex_create_anti_affinity_rule(node_list) def test_ex_create_anti_affinity_rule_FAIL_EXISTING(self): node_list = self.driver.list_nodes() DimensionDataMockHttp.type = 'FAIL_EXISTING' with self.assertRaises(DimensionDataAPIException): self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1])) def test_ex_delete_anti_affinity_rule(self): net_domain = self.driver.ex_list_network_domains()[0] rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] success = self.driver.ex_delete_anti_affinity_rule(rule) self.assertTrue(success) def test_ex_delete_anti_affinity_rule_STR(self): net_domain = self.driver.ex_list_network_domains()[0] rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] success = self.driver.ex_delete_anti_affinity_rule(rule.id) self.assertTrue(success) def test_ex_delete_anti_affinity_rule_FAIL(self): net_domain = self.driver.ex_list_network_domains()[0] rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] DimensionDataMockHttp.type = 'FAIL' with self.assertRaises(DimensionDataAPIException): self.driver.ex_delete_anti_affinity_rule(rule) def test_ex_list_anti_affinity_rules_NETWORK_DOMAIN(self): net_domain = self.driver.ex_list_network_domains()[0] rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_NETWORK(self): network = self.driver.list_networks()[0] rules = self.driver.ex_list_anti_affinity_rules(network=network) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_NODE(self): node = self.driver.list_nodes()[0] rules = self.driver.ex_list_anti_affinity_rules(node=node) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_PAGINATED(self): net_domain = self.driver.ex_list_network_domains()[0] DimensionDataMockHttp.type = 'PAGINATED' rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain) self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 4) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_ALLFILTERS(self): net_domain = self.driver.ex_list_network_domains()[0] DimensionDataMockHttp.type = 'ALLFILTERS' rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain, filter_id='FAKE_ID', filter_state='FAKE_STATE') self.assertTrue(isinstance(rules, list)) self.assertEqual(len(rules), 2) self.assertTrue(isinstance(rules[0].id, str)) self.assertTrue(isinstance(rules[0].node_list, list)) def test_ex_list_anti_affinity_rules_BAD_ARGS(self): with self.assertRaises(ValueError): self.driver.ex_list_anti_affinity_rules(network='fake_network', network_domain='fake_network_domain') def test_ex_create_tag_key(self): success = self.driver.ex_create_tag_key('MyTestKey') self.assertTrue(success) def test_ex_create_tag_key_ALLPARAMS(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'ALLPARAMS' success = self.driver.ex_create_tag_key('MyTestKey', description="Test Key Desc.", value_required=False, display_on_report=False) self.assertTrue(success) def test_ex_create_tag_key_BADREQUEST(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'BADREQUEST' with self.assertRaises(DimensionDataAPIException): self.driver.ex_create_tag_key('MyTestKey') def test_ex_list_tag_keys(self): tag_keys = self.driver.ex_list_tag_keys() self.assertTrue(isinstance(tag_keys, list)) self.assertTrue(isinstance(tag_keys[0], DimensionDataTagKey)) self.assertTrue(isinstance(tag_keys[0].id, str)) def test_ex_list_tag_keys_ALLFILTERS(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'ALLFILTERS' self.driver.ex_list_tag_keys(id='fake_id', name='fake_name', value_required=False, display_on_report=False) def test_ex_get_tag_by_id(self): tag = self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075') self.assertTrue(isinstance(tag, DimensionDataTagKey)) def test_ex_get_tag_by_id_NOEXIST(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'NOEXIST' with self.assertRaises(DimensionDataAPIException): self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075') def test_ex_get_tag_by_name(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'SINGLE' tag = self.driver.ex_get_tag_key_by_name('LibcloudTest') self.assertTrue(isinstance(tag, DimensionDataTagKey)) def test_ex_get_tag_by_name_NOEXIST(self): with self.assertRaises(ValueError): self.driver.ex_get_tag_key_by_name('LibcloudTest') def test_ex_modify_tag_key_NAME(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NAME' success = self.driver.ex_modify_tag_key(tag_key, name='NewName') self.assertTrue(success) def test_ex_modify_tag_key_NOTNAME(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NOTNAME' success = self.driver.ex_modify_tag_key(tag_key, description='NewDesc', value_required=False, display_on_report=True) self.assertTrue(success) def test_ex_modify_tag_key_NOCHANGE(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NOCHANGE' with self.assertRaises(DimensionDataAPIException): self.driver.ex_modify_tag_key(tag_key) def test_ex_remove_tag_key(self): tag_key = self.driver.ex_list_tag_keys()[0] success = self.driver.ex_remove_tag_key(tag_key) self.assertTrue(success) def test_ex_remove_tag_key_NOEXIST(self): tag_key = self.driver.ex_list_tag_keys()[0] DimensionDataMockHttp.type = 'NOEXIST' with self.assertRaises(DimensionDataAPIException): self.driver.ex_remove_tag_key(tag_key) def test_ex_apply_tag_to_asset(self): node = self.driver.list_nodes()[0] success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName', 'FakeValue') self.assertTrue(success) def test_ex_apply_tag_to_asset_NOVALUE(self): node = self.driver.list_nodes()[0] DimensionDataMockHttp.type = 'NOVALUE' success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName') self.assertTrue(success) def test_ex_apply_tag_to_asset_NOTAGKEY(self): node = self.driver.list_nodes()[0] DimensionDataMockHttp.type = 'NOTAGKEY' with self.assertRaises(DimensionDataAPIException): self.driver.ex_apply_tag_to_asset(node, 'TagKeyNam') def test_ex_apply_tag_to_asset_BADASSETTYPE(self): network = self.driver.list_networks()[0] DimensionDataMockHttp.type = 'NOTAGKEY' with self.assertRaises(TypeError): self.driver.ex_apply_tag_to_asset(network, 'TagKeyNam') def test_ex_remove_tag_from_asset(self): node = self.driver.list_nodes()[0] success = self.driver.ex_remove_tag_from_asset(node, 'TagKeyName') self.assertTrue(success) def test_ex_remove_tag_from_asset_NOTAG(self): node = self.driver.list_nodes()[0] DimensionDataMockHttp.type = 'NOTAG' with self.assertRaises(DimensionDataAPIException): self.driver.ex_remove_tag_from_asset(node, 'TagKeyNam') def test_ex_list_tags(self): tags = self.driver.ex_list_tags() self.assertTrue(isinstance(tags, list)) self.assertTrue(isinstance(tags[0], DimensionDataTag)) self.assertTrue(len(tags) == 3) def test_ex_list_tags_ALLPARAMS(self): self.driver.connection._get_orgId() DimensionDataMockHttp.type = 'ALLPARAMS' tags = self.driver.ex_list_tags(asset_id='fake_asset_id', asset_type='fake_asset_type', location='fake_location', tag_key_name='fake_tag_key_name', tag_key_id='fake_tag_key_id', value='fake_value', value_required=False, display_on_report=False) self.assertTrue(isinstance(tags, list)) self.assertTrue(isinstance(tags[0], DimensionDataTag)) self.assertTrue(len(tags) == 3) def test_priv_location_to_location_id(self): location = self.driver.ex_get_location_by_id('NA9') self.assertEqual( self.driver._location_to_location_id(location), 'NA9' ) def test_priv_location_to_location_id_STR(self): self.assertEqual( self.driver._location_to_location_id('NA9'), 'NA9' ) def test_priv_location_to_location_id_TYPEERROR(self): with self.assertRaises(TypeError): self.driver._location_to_location_id([1, 2, 3]) def test_priv_image_needs_auth_os_img(self): image = self.driver.list_images()[1] self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_os_img_STR(self): image = self.driver.list_images()[1].id self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_windows(self): image = self.driver.ex_list_customer_images()[1] self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_windows_STR(self): image = self.driver.ex_list_customer_images()[1].id self.assertTrue(self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_linux(self): image = self.driver.ex_list_customer_images()[0] self.assertTrue(not self.driver._image_needs_auth(image)) def test_priv_image_needs_auth_cust_img_linux_STR(self): image = self.driver.ex_list_customer_images()[0].id self.assertTrue(not self.driver._image_needs_auth(image)) def test_summary_usage_report(self): report = self.driver.ex_summary_usage_report('2016-06-01', '2016-06-30') report_content = report self.assertEqual(len(report_content), 13) self.assertEqual(len(report_content[0]), 6) def test_detailed_usage_report(self): report = self.driver.ex_detailed_usage_report('2016-06-01', '2016-06-30') report_content = report self.assertEqual(len(report_content), 42) self.assertEqual(len(report_content[0]), 4) def test_audit_log_report(self): report = self.driver.ex_audit_log_report('2016-06-01', '2016-06-30') report_content = report self.assertEqual(len(report_content), 25) self.assertEqual(report_content[2][2], 'OEC_SYSTEM') def test_ex_list_ip_address_list(self): net_domain = self.driver.ex_list_network_domains()[0] ip_list = self.driver.ex_list_ip_address_list( ex_network_domain=net_domain) self.assertTrue(isinstance(ip_list, list)) self.assertEqual(len(ip_list), 4) self.assertTrue(isinstance(ip_list[0].name, str)) self.assertTrue(isinstance(ip_list[0].description, str)) self.assertTrue(isinstance(ip_list[0].ip_version, str)) self.assertTrue(isinstance(ip_list[0].state, str)) self.assertTrue(isinstance(ip_list[0].create_time, str)) self.assertTrue(isinstance(ip_list[0].child_ip_address_lists, list)) self.assertEqual(len(ip_list[1].child_ip_address_lists), 1) self.assertTrue(isinstance(ip_list[1].child_ip_address_lists[0].name, str)) def test_ex_get_ip_address_list(self): net_domain = self.driver.ex_list_network_domains()[0] DimensionDataMockHttp.type = 'FILTERBYNAME' ip_list = self.driver.ex_get_ip_address_list( ex_network_domain=net_domain.id, ex_ip_address_list_name='Test_IP_Address_List_3') self.assertTrue(isinstance(ip_list, list)) self.assertEqual(len(ip_list), 1) self.assertTrue(isinstance(ip_list[0].name, str)) self.assertTrue(isinstance(ip_list[0].description, str)) self.assertTrue(isinstance(ip_list[0].ip_version, str)) self.assertTrue(isinstance(ip_list[0].state, str)) self.assertTrue(isinstance(ip_list[0].create_time, str)) ips = ip_list[0].ip_address_collection self.assertEqual(len(ips), 3) self.assertTrue(isinstance(ips[0].begin, str)) self.assertTrue(isinstance(ips[0].prefix_size, str)) self.assertTrue(isinstance(ips[2].end, str)) def test_ex_create_ip_address_list_FAIL(self): net_domain = self.driver.ex_list_network_domains()[0] with self.assertRaises(TypeError): self.driver.ex_create_ip_address_list( ex_network_domain=net_domain.id) def test_ex_create_ip_address_list(self): name = "Test_IP_Address_List_3" description = "Test Description" ip_version = "IPV4" child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41' child_ip_address_list = DimensionDataChildIpAddressList( id=child_ip_address_list_id, name="test_child_ip_addr_list") net_domain = self.driver.ex_list_network_domains()[0] ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100') ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106', end='190.2.2.108') ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0', prefix_size='24') ip_address_collection = [ip_address_1, ip_address_2, ip_address_3] # Create IP Address List success = self.driver.ex_create_ip_address_list( ex_network_domain=net_domain, name=name, ip_version=ip_version, description=description, ip_address_collection=ip_address_collection, child_ip_address_list=child_ip_address_list) self.assertTrue(success) def test_ex_create_ip_address_list_STR(self): name = "Test_IP_Address_List_3" description = "Test Description" ip_version = "IPV4" child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41' net_domain = self.driver.ex_list_network_domains()[0] ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100') ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106', end='190.2.2.108') ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0', prefix_size='24') ip_address_collection = [ip_address_1, ip_address_2, ip_address_3] # Create IP Address List success = self.driver.ex_create_ip_address_list( ex_network_domain=net_domain.id, name=name, ip_version=ip_version, description=description, ip_address_collection=ip_address_collection, child_ip_address_list=child_ip_address_list_id) self.assertTrue(success) def test_ex_edit_ip_address_list(self): ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111') ip_address_collection = [ip_address_1] child_ip_address_list = DimensionDataChildIpAddressList( id='2221ef78-4059-4bc1-b433-3f6ad698dc41', name="test_child_ip_address_list edited") ip_address_list = DimensionDataIpAddressList( id='1111ef78-4059-4bc1-b433-3f6ad698d111', name="test ip address list edited", ip_version="IPv4", description="test", ip_address_collection=ip_address_collection, child_ip_address_lists=child_ip_address_list, state="NORMAL", create_time='2015-09-29T02:49:45' ) success = self.driver.ex_edit_ip_address_list( ex_ip_address_list=ip_address_list, description="test ip address list", ip_address_collection=ip_address_collection, child_ip_address_lists=child_ip_address_list ) self.assertTrue(success) def test_ex_edit_ip_address_list_STR(self): ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111') ip_address_collection = [ip_address_1] child_ip_address_list = DimensionDataChildIpAddressList( id='2221ef78-4059-4bc1-b433-3f6ad698dc41', name="test_child_ip_address_list edited") success = self.driver.ex_edit_ip_address_list( ex_ip_address_list='84e34850-595d- 436e-a885-7cd37edb24a4', description="test ip address list", ip_address_collection=ip_address_collection, child_ip_address_lists=child_ip_address_list ) self.assertTrue(success) def test_ex_delete_ip_address_list(self): child_ip_address_list = DimensionDataChildIpAddressList( id='2221ef78-4059-4bc1-b433-3f6ad698dc41', name="test_child_ip_address_list edited") ip_address_list = DimensionDataIpAddressList( id='1111ef78-4059-4bc1-b433-3f6ad698d111', name="test ip address list edited", ip_version="IPv4", description="test", ip_address_collection=None, child_ip_address_lists=child_ip_address_list, state="NORMAL", create_time='2015-09-29T02:49:45' ) success = self.driver.ex_delete_ip_address_list( ex_ip_address_list=ip_address_list) self.assertTrue(success) def test_ex_delete_ip_address_list_STR(self): success = self.driver.ex_delete_ip_address_list( ex_ip_address_list='111ef78-4059-4bc1-b433-3f6ad698d111') self.assertTrue(success) def test_ex_list_portlist(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist( ex_network_domain=net_domain) self.assertTrue(isinstance(portlist, list)) self.assertEqual(len(portlist), 3) self.assertTrue(isinstance(portlist[0].name, str)) self.assertTrue(isinstance(portlist[0].description, str)) self.assertTrue(isinstance(portlist[0].state, str)) self.assertTrue(isinstance(portlist[0].port_collection, list)) self.assertTrue(isinstance(portlist[0].port_collection[0].begin, str)) self.assertTrue(isinstance(portlist[0].port_collection[0].end, str)) self.assertTrue(isinstance(portlist[0].child_portlist_list, list)) self.assertTrue(isinstance(portlist[0].child_portlist_list[0].id, str)) self.assertTrue(isinstance(portlist[0].child_portlist_list[0].name, str)) self.assertTrue(isinstance(portlist[0].create_time, str)) def test_ex_get_port_list(self): net_domain = self.driver.ex_list_network_domains()[0] portlist_id = self.driver.ex_list_portlist( ex_network_domain=net_domain)[0].id portlist = self.driver.ex_get_portlist( ex_portlist_id=portlist_id) self.assertTrue(isinstance(portlist, DimensionDataPortList)) self.assertTrue(isinstance(portlist.name, str)) self.assertTrue(isinstance(portlist.description, str)) self.assertTrue(isinstance(portlist.state, str)) self.assertTrue(isinstance(portlist.port_collection, list)) self.assertTrue(isinstance(portlist.port_collection[0].begin, str)) self.assertTrue(isinstance(portlist.port_collection[0].end, str)) self.assertTrue(isinstance(portlist.child_portlist_list, list)) self.assertTrue(isinstance(portlist.child_portlist_list[0].id, str)) self.assertTrue(isinstance(portlist.child_portlist_list[0].name, str)) self.assertTrue(isinstance(portlist.create_time, str)) def test_ex_get_portlist_STR(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist( ex_network_domain=net_domain)[0] port_list = self.driver.ex_get_portlist( ex_portlist_id=portlist.id) self.assertTrue(isinstance(port_list, DimensionDataPortList)) self.assertTrue(isinstance(port_list.name, str)) self.assertTrue(isinstance(port_list.description, str)) self.assertTrue(isinstance(port_list.state, str)) self.assertTrue(isinstance(port_list.port_collection, list)) self.assertTrue(isinstance(port_list.port_collection[0].begin, str)) self.assertTrue(isinstance(port_list.port_collection[0].end, str)) self.assertTrue(isinstance(port_list.child_portlist_list, list)) self.assertTrue(isinstance(port_list.child_portlist_list[0].id, str)) self.assertTrue(isinstance(port_list.child_portlist_list[0].name, str)) self.assertTrue(isinstance(port_list.create_time, str)) def test_ex_create_portlist_NOCHILDPORTLIST(self): name = "Test_Port_List" description = "Test Description" net_domain = self.driver.ex_list_network_domains()[0] port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] # Create IP Address List success = self.driver.ex_create_portlist( ex_network_domain=net_domain, name=name, description=description, port_collection=port_collection ) self.assertTrue(success) def test_ex_create_portlist(self): name = "Test_Port_List" description = "Test Description" net_domain = self.driver.ex_list_network_domains()[0] port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports = [child_port_1, child_port_2] # Create IP Address List success = self.driver.ex_create_portlist( ex_network_domain=net_domain, name=name, description=description, port_collection=port_collection, child_portlist_list=child_ports ) self.assertTrue(success) def test_ex_create_portlist_STR(self): name = "Test_Port_List" description = "Test Description" net_domain = self.driver.ex_list_network_domains()[0] port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports_ids = [child_port_1.id, child_port_2.id] # Create IP Address List success = self.driver.ex_create_portlist( ex_network_domain=net_domain.id, name=name, description=description, port_collection=port_collection, child_portlist_list=child_ports_ids ) self.assertTrue(success) def test_ex_edit_portlist(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist(net_domain)[0] description = "Test Description" port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports = [child_port_1.id, child_port_2.id] # Create IP Address List success = self.driver.ex_edit_portlist( ex_portlist=portlist, description=description, port_collection=port_collection, child_portlist_list=child_ports ) self.assertTrue(success) def test_ex_edit_portlist_STR(self): portlist_id = "484174a2-ae74-4658-9e56-50fc90e086cf" description = "Test Description" port_1 = DimensionDataPort(begin='8080') port_2 = DimensionDataIpAddress(begin='8899', end='9023') port_collection = [port_1, port_2] child_port_1 = DimensionDataChildPortList( id="333174a2-ae74-4658-9e56-50fc90e086cf", name='test port 1') child_port_2 = DimensionDataChildPortList( id="311174a2-ae74-4658-9e56-50fc90e04444", name='test port 2') child_ports_ids = [child_port_1.id, child_port_2.id] # Create IP Address List success = self.driver.ex_edit_portlist( ex_portlist=portlist_id, description=description, port_collection=port_collection, child_portlist_list=child_ports_ids ) self.assertTrue(success) def test_ex_delete_portlist(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist(net_domain)[0] success = self.driver.ex_delete_portlist( ex_portlist=portlist) self.assertTrue(success) def test_ex_delete_portlist_STR(self): net_domain = self.driver.ex_list_network_domains()[0] portlist = self.driver.ex_list_portlist(net_domain)[0] success = self.driver.ex_delete_portlist( ex_portlist=portlist.id) self.assertTrue(success) def test_import_image(self): tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None} success = self.driver.import_image( ovf_package_name='aTestGocToNGoc2_export2.mf', name='Libcloud NGOCImage_New 2', description='test', cluster_id='QA1_N2_VMWARE_1-01', is_guest_os_customization='false', tagkey_name_value_dictionaries=tag_dictionaries) self.assertTrue(success) def test_import_image_error_too_many_choice(self): tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None} with self.assertRaises(ValueError): self.driver.import_image( ovf_package_name='aTestGocToNGoc2_export2.mf', name='Libcloud NGOCImage_New 2', description='test', cluster_id='QA1_N2_VMWARE_1-01', datacenter_id='QA1_N1_VMWARE_1', is_guest_os_customization='false', tagkey_name_value_dictionaries=tag_dictionaries) def test_import_image_error_missing_choice(self): tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None} with self.assertRaises(ValueError): self.driver.import_image( ovf_package_name='aTestGocToNGoc2_export2.mf', name='Libcloud NGOCImage_New 2', description='test', cluster_id=None, datacenter_id=None, is_guest_os_customization='false', tagkey_name_value_dictionaries=tag_dictionaries) def test_exchange_nic_vlans(self): success = self.driver.ex_exchange_nic_vlans( nic_id_1='a4b4b42b-ccb5-416f-b052-ce7cb7fdff12', nic_id_2='b39d09b8-ea65-424a-8fa6-c6f5a98afc69') self.assertTrue(success) def test_change_nic_network_adapter(self): success = self.driver.ex_change_nic_network_adapter( nic_id='0c55c269-20a5-4fec-8054-22a245a48fe4', network_adapter_name='E1000') self.assertTrue(success) def test_ex_create_node_uncustomized_mcp2_using_vlan(self): # Get VLAN vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') # Create node using vlan instead of private IPv4 node = self.driver.ex_create_node_uncustomized( name='test_server_05', image='fake_customer_image', ex_network_domain='fakenetworkdomain', ex_is_started=False, ex_description=None, ex_cluster_id=None, ex_cpu_specification=None, ex_memory_gb=None, ex_primary_nic_private_ipv4=None, ex_primary_nic_vlan=vlan, ex_primary_nic_network_adapter=None, ex_additional_nics=None, ex_disks=None, ex_tagid_value_pairs=None, ex_tagname_value_pairs=None) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') def test_ex_create_node_uncustomized_mcp2_using_ipv4(self): node = self.driver.ex_create_node_uncustomized( name='test_server_05', image='fake_customer_image', ex_network_domain='fakenetworkdomain', ex_is_started=False, ex_description=None, ex_cluster_id=None, ex_cpu_specification=None, ex_memory_gb=None, ex_primary_nic_private_ipv4='10.0.0.1', ex_primary_nic_vlan=None, ex_primary_nic_network_adapter=None, ex_additional_nics=None, ex_disks=None, ex_tagid_value_pairs=None, ex_tagname_value_pairs=None) self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87') class InvalidRequestError(Exception): def __init__(self, tag): super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag) class DimensionDataMockHttp(MockHttp): fixtures = ComputeFileFixtures('dimensiondata') def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_report_usage(self, method, url, body, headers): body = self.fixtures.load( 'summary_usage_report.csv' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_report_usageDetailed(self, method, url, body, headers): body = self.fixtures.load( 'detailed_usage_report.csv' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_auditlog(self, method, url, body, headers): body = self.fixtures.load( 'audit_log.csv' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_PAGINATED(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_ALLFILTERS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_base_image(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_base_image.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_base_imageWithDiskSpeed(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_base_imageWithDiskSpeed.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployed.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_pendingDeploy.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11(self, method, url, body, headers): body = None action = url.split('?')[-1] if action == 'restart': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart.xml') elif action == 'shutdown': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown.xml') elif action == 'delete': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete.xml') elif action == 'start': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start.xml') elif action == 'poweroff': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_INPROGRESS(self, method, url, body, headers): body = None action = url.split('?')[-1] if action == 'restart': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_restart_INPROGRESS.xml') elif action == 'shutdown': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_shutdown_INPROGRESS.xml') elif action == 'delete': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_delete_INPROGRESS.xml') elif action == 'start': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_start_INPROGRESS.xml') elif action == 'poweroff': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_11_poweroff_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers): body = self.fixtures.load( '_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation(self, method, url, body, headers): if method == "POST": request = ET.fromstring(body) if request.tag != "{http://oec.api.opsource.net/schemas/network}NewNetworkWithLocation": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation_NA9(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_4bba37be_506f_11e3_b29c_001517c4643e(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_4bba37be_506f_11e3_b29c_001517c4643e.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSize(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSize.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSpeed(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1_changeSpeed.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1(self, method, url, body, headers): action = url.split('?')[-1] if action == 'delete': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_disk_1.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_POST.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_FAIL_EXISTING(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_07e3621a_a920_4a9a_943c_d8021f27f418(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_07e3621a_a920_4a9a_943c_d8021f27f418_FAIL(self, method, url, body, headers): body = self.fixtures.load( 'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers): body = self.fixtures.load( 'server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_deleteServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_deleteServer_RESOURCEBUSY.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}rebootServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_rebootServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}rebootServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_rebootServer_RESOURCEBUSY.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers): if url.endswith('datacenterId=NA3'): body = self.fixtures.load( '2.4/server_server_NA3.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( '2.4/server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGESIZE50(self, method, url, body, headers): if not url.endswith('pageSize=50'): raise ValueError("pageSize is not set as expected") body = self.fixtures.load( '2.4/server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_EMPTY(self, method, url, body, headers): body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGED_THEN_EMPTY(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( '2.4/server_server_paginated.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATED(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( '2.4/server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( '2.4/server_server_paginated.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATEDEMPTY(self, method, url, body, headers): body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_loc' elif key == 'networkId': assert value == 'fake_network' elif key == 'networkDomainId': assert value == 'fake_network_domain' elif key == 'vlanId': assert value == 'fake_vlan' elif key == 'ipv6': assert value == 'fake_ipv6' elif key == 'privateIpv4': assert value == 'fake_ipv4' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' elif key == 'started': assert value == 'True' elif key == 'deployed': assert value == 'True' elif key == 'sourceImageId': assert value == 'fake_image' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( '2.4/server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule(self, method, url, body, headers): body = self.fixtures.load( 'server_antiAffinityRule_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'id': assert value == 'FAKE_ID' elif key == 'state': assert value == 'FAKE_STATE' elif key == 'pageSize': assert value == '250' elif key == 'networkDomainId': pass else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'server_antiAffinityRule_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_PAGINATED(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_antiAffinityRule_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( 'server_antiAffinityRule_list_PAGINATED.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers): if url.endswith('id=NA9'): body = self.fixtures.load( 'infrastructure_datacenter_NA9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'infrastructure_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_ALLFILTERS(self, method, url, body, headers): if url.endswith('id=NA9'): body = self.fixtures.load( 'infrastructure_datacenter_NA9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'infrastructure_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_updateVmwareTools(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}updateVmwareTools": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_updateVmwareTools.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}startServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_startServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}startServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_startServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_shutdownServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_shutdownServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}resetServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_resetServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_powerOffServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_powerOffServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_11_INPROGRESS( self, method, url, body, headers): body = self.fixtures.load('2.4/server_GetServer.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_location' elif key == 'type': assert value == 'fake_plan' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'network_networkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan(self, method, url, body, headers): body = self.fixtures.load( 'network_vlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_location' elif key == 'networkDomainId': assert value == 'fake_network_domain' elif key == 'ipv6Address': assert value == 'fake_ipv6' elif key == 'privateIpv4Address': assert value == 'fake_ipv4' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'network_vlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployServer": raise InvalidRequestError(request.tag) # Make sure the we either have a network tag with an IP or networkId # Or Network info with a primary nic that has privateip or vlanid network = request.find(fixxpath('network', TYPES_URN)) network_info = request.find(fixxpath('networkInfo', TYPES_URN)) if network is not None: if network_info is not None: raise InvalidRequestError("Request has both MCP1 and MCP2 values") ipv4 = findtext(network, 'privateIpv4', TYPES_URN) networkId = findtext(network, 'networkId', TYPES_URN) if ipv4 is None and networkId is None: raise InvalidRequestError('Invalid request MCP1 requests need privateIpv4 or networkId') elif network_info is not None: if network is not None: raise InvalidRequestError("Request has both MCP1 and MCP2 values") primary_nic = network_info.find(fixxpath('primaryNic', TYPES_URN)) ipv4 = findtext(primary_nic, 'privateIpv4', TYPES_URN) vlanId = findtext(primary_nic, 'vlanId', TYPES_URN) if ipv4 is None and vlanId is None: raise InvalidRequestError('Invalid request MCP2 requests need privateIpv4 or vlanId') else: raise InvalidRequestError('Invalid request, does not have network or network_info in XML') body = self.fixtures.load( 'server_deployServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers): body = self.fixtures.load( '2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deployNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be_ALLFILTERS(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deployVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_0e56433f_d808_4669_821d_812769517ff8(self, method, url, body, headers): body = self.fixtures.load( 'network_vlan_0e56433f_d808_4669_821d_812769517ff8.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_expandVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}expandVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_expandVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_addPublicIpBlock(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}addPublicIpBlock": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_addPublicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_removePublicIpBlock(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removePublicIpBlock": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_removePublicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule(self, method, url, body, headers): body = self.fixtures.load( 'network_firewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_createFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c(self, method, url, body, headers): body = self.fixtures.load( 'network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createNatRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createNatRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_createNatRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule(self, method, url, body, headers): body = self.fixtures.load( 'network_natRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce(self, method, url, body, headers): body = self.fixtures.load( 'network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNatRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteNatRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteNatRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addNic(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}addNic": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_addNic.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeNic(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removeNic": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_removeNic.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_disableServerMonitoring(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}disableServerMonitoring": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_disableServerMonitoring.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_enableServerMonitoring(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}enableServerMonitoring": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_enableServerMonitoring.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeServerMonitoringPlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}changeServerMonitoringPlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_changeServerMonitoringPlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage(self, method, url, body, headers): body = self.fixtures.load( '2.4/image_osImage.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c(self, method, url, body, headers): body = self.fixtures.load( '2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a(self, method, url, body, headers): body = self.fixtures.load( '2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_FAKE_IMAGE_ID(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage(self, method, url, body, headers): body = self.fixtures.load( '2.4/image_customerImage.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers): body = self.fixtures.load( '2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers): body = self.fixtures.load( '2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_FAKE_IMAGE_ID(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_reconfigureServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}reconfigureServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_reconfigureServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cleanServer(self, method, url, body, headers): body = self.fixtures.load( 'server_cleanServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addDisk(self, method, url, body, headers): body = self.fixtures.load( 'server_addDisk.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeDisk(self, method, url, body, headers): body = self.fixtures.load( 'server_removeDisk.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is not None: raise ValueError("Default description for a tag should be blank") if value_required is None or value_required != 'true': raise ValueError("Default valueRequired should be true") if display_on_report is None or display_on_report != 'true': raise ValueError("Default displayOnReport should be true") body = self.fixtures.load( 'tag_createTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_ALLPARAMS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is None: raise ValueError("Description should have a value") if value_required is None or value_required != 'false': raise ValueError("valueRequired should be false") if display_on_report is None or display_on_report != 'false': raise ValueError("displayOnReport should be false") body = self.fixtures.load( 'tag_createTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_BADREQUEST(self, method, url, body, headers): body = self.fixtures.load( 'tag_createTagKey_BADREQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_SINGLE(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_list_SINGLE.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'id': assert value == 'fake_id' elif key == 'name': assert value == 'fake_name' elif key == 'valueRequired': assert value == 'false' elif key == 'displayOnReport': assert value == 'false' elif key == 'pageSize': assert value == '250' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'tag_tagKey_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075_NOEXIST(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NAME(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is not None: raise ValueError("Description should be empty") if value_required is not None: raise ValueError("valueRequired should be empty") if display_on_report is not None: raise ValueError("displayOnReport should be empty") body = self.fixtures.load( 'tag_editTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOTNAME(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is not None: raise ValueError("Name should be empty") if description is None: raise ValueError("Description should not be empty") if value_required is None: raise ValueError("valueRequired should not be empty") if display_on_report is None: raise ValueError("displayOnReport should not be empty") body = self.fixtures.load( 'tag_editTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOCHANGE(self, method, url, body, headers): body = self.fixtures.load( 'tag_editTagKey_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteTagKey": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'tag_deleteTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey_NOEXIST(self, method, url, body, headers): body = self.fixtures.load( 'tag_deleteTagKey_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}applyTags": raise InvalidRequestError(request.tag) asset_type = findtext(request, 'assetType', TYPES_URN) asset_id = findtext(request, 'assetId', TYPES_URN) tag = request.find(fixxpath('tag', TYPES_URN)) tag_key_name = findtext(tag, 'tagKeyName', TYPES_URN) value = findtext(tag, 'value', TYPES_URN) if asset_type is None: raise ValueError("assetType should not be empty") if asset_id is None: raise ValueError("assetId should not be empty") if tag_key_name is None: raise ValueError("tagKeyName should not be empty") if value is None: raise ValueError("value should not be empty") body = self.fixtures.load( 'tag_applyTags.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOVALUE(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}applyTags": raise InvalidRequestError(request.tag) asset_type = findtext(request, 'assetType', TYPES_URN) asset_id = findtext(request, 'assetId', TYPES_URN) tag = request.find(fixxpath('tag', TYPES_URN)) tag_key_name = findtext(tag, 'tagKeyName', TYPES_URN) value = findtext(tag, 'value', TYPES_URN) if asset_type is None: raise ValueError("assetType should not be empty") if asset_id is None: raise ValueError("assetId should not be empty") if tag_key_name is None: raise ValueError("tagKeyName should not be empty") if value is not None: raise ValueError("value should be empty") body = self.fixtures.load( 'tag_applyTags.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOTAGKEY(self, method, url, body, headers): body = self.fixtures.load( 'tag_applyTags_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removeTags": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'tag_removeTag.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags_NOTAG(self, method, url, body, headers): body = self.fixtures.load( 'tag_removeTag_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag(self, method, url, body, headers): body = self.fixtures.load( 'tag_tag_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag_ALLPARAMS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'assetId': assert value == 'fake_asset_id' elif key == 'assetType': assert value == 'fake_asset_type' elif key == 'valueRequired': assert value == 'false' elif key == 'displayOnReport': assert value == 'false' elif key == 'pageSize': assert value == '250' elif key == 'datacenterId': assert value == 'fake_location' elif key == 'value': assert value == 'fake_value' elif key == 'tagKeyName': assert value == 'fake_tag_key_name' elif key == 'tagKeyId': assert value == 'fake_tag_key_id' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'tag_tag_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList( self, method, url, body, headers): body = self.fixtures.load('ip_address_lists.xml') return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList_FILTERBYNAME( self, method, url, body, headers): body = self.fixtures.load('ip_address_lists_FILTERBYNAME.xml') return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "createIpAddressList": raise InvalidRequestError(request.tag) net_domain = findtext(request, 'networkDomainId', TYPES_URN) if net_domain is None: raise ValueError("Network Domain should not be empty") name = findtext(request, 'name', TYPES_URN) if name is None: raise ValueError("Name should not be empty") ip_version = findtext(request, 'ipVersion', TYPES_URN) if ip_version is None: raise ValueError("IP Version should not be empty") ip_address_col_required = findall(request, 'ipAddress', TYPES_URN) child_ip_address_required = findall(request, 'childIpAddressListId', TYPES_URN) if 0 == len(ip_address_col_required) and \ 0 == len(child_ip_address_required): raise ValueError("At least one ipAddress element or " "one childIpAddressListId element must be " "provided.") if ip_address_col_required[0].get('begin') is None: raise ValueError("IP Address should not be empty") body = self.fixtures.load( 'ip_address_list_create.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "editIpAddressList": raise InvalidRequestError(request.tag) ip_address_list = request.get('id') if ip_address_list is None: raise ValueError("IpAddressList ID should not be empty") name = findtext(request, 'name', TYPES_URN) if name is not None: raise ValueError("Name should not exists in request") ip_version = findtext(request, 'ipVersion', TYPES_URN) if ip_version is not None: raise ValueError("IP Version should not exists in request") ip_address_col_required = findall(request, 'ipAddress', TYPES_URN) child_ip_address_required = findall(request, 'childIpAddressListId', TYPES_URN) if 0 == len(ip_address_col_required) and \ 0 == len(child_ip_address_required): raise ValueError("At least one ipAddress element or " "one childIpAddressListId element must be " "provided.") if ip_address_col_required[0].get('begin') is None: raise ValueError("IP Address should not be empty") body = self.fixtures.load( 'ip_address_list_edit.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "deleteIpAddressList": raise InvalidRequestError(request.tag) ip_address_list = request.get('id') if ip_address_list is None: raise ValueError("IpAddressList ID should not be empty") body = self.fixtures.load( 'ip_address_list_delete.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList( self, method, url, body, headers): body = self.fixtures.load( 'port_list_lists.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList_c8c92ea3_2da8_4d51_8153_f39bec794d69( self, method, url, body, headers): body = self.fixtures.load( 'port_list_get.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "createPortList": raise InvalidRequestError(request.tag) net_domain = findtext(request, 'networkDomainId', TYPES_URN) if net_domain is None: raise ValueError("Network Domain should not be empty") ports_required = findall(request, 'port', TYPES_URN) child_port_list_required = findall(request, 'childPortListId', TYPES_URN) if 0 == len(ports_required) and \ 0 == len(child_port_list_required): raise ValueError("At least one port element or one " "childPortListId element must be provided") if ports_required[0].get('begin') is None: raise ValueError("PORT begin value should not be empty") body = self.fixtures.load( 'port_list_create.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "editPortList": raise InvalidRequestError(request.tag) ports_required = findall(request, 'port', TYPES_URN) child_port_list_required = findall(request, 'childPortListId', TYPES_URN) if 0 == len(ports_required) and \ 0 == len(child_port_list_required): raise ValueError("At least one port element or one " "childPortListId element must be provided") if ports_required[0].get('begin') is None: raise ValueError("PORT begin value should not be empty") body = self.fixtures.load( 'port_list_edit.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deletePortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "deletePortList": raise InvalidRequestError(request.tag) port_list = request.get('id') if port_list is None: raise ValueError("Port List ID should not be empty") body = self.fixtures.load( 'ip_address_list_delete.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cloneServer( self, method, url, body, headers): body = self.fixtures.load( '2.4/server_clone_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_importImage( self, method, url, body, headers): body = self.fixtures.load( '2.4/import_image_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_exchangeNicVlans( self, method, url, body, headers): body = self.fixtures.load( '2.4/exchange_nic_vlans_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeNetworkAdapter( self, method, url, body, headers): body = self.fixtures.load( '2.4/change_nic_networkadapter_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployUncustomizedServer( self, method, url, body, headers): body = self.fixtures.load( '2.4/deploy_customised_server.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_ec2.py0000664000175000017500000026116213577507766022774 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement from collections import OrderedDict import os import sys from datetime import datetime from libcloud.utils.iso8601 import UTC from libcloud.utils.py3 import httplib from libcloud.compute.drivers.ec2 import EC2NodeDriver from libcloud.compute.drivers.ec2 import EC2PlacementGroup from libcloud.compute.drivers.ec2 import NimbusNodeDriver, EucNodeDriver from libcloud.compute.drivers.ec2 import OutscaleSASNodeDriver from libcloud.compute.drivers.ec2 import IdempotentParamError from libcloud.compute.drivers.ec2 import REGION_DETAILS, VALID_EC2_REGIONS from libcloud.compute.drivers.ec2 import ExEC2AvailabilityZone from libcloud.compute.drivers.ec2 import EC2NetworkSubnet from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation from libcloud.compute.base import StorageVolume, VolumeSnapshot from libcloud.compute.types import KeyPairDoesNotExistError, StorageVolumeState, \ VolumeSnapshotState from libcloud.test import MockHttp, LibcloudTestCase from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test import unittest from libcloud.test.secrets import EC2_PARAMS null_fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \ '00:00:00:00:00' class BaseEC2Tests(LibcloudTestCase): def test_instantiate_driver_valid_regions(self): regions = REGION_DETAILS.keys() regions = [d for d in regions if d != 'nimbus' and d != 'cn-north-1'] region_endpoints = [ EC2NodeDriver(*EC2_PARAMS, **{'region': region}).connection.host for region in regions ] # Verify that each driver doesn't get the same API host endpoint self.assertEqual(len(region_endpoints), len(set(region_endpoints)), "Multiple Region Drivers were given the same API endpoint") def test_instantiate_driver_invalid_regions(self): for region in ['invalid', 'nimbus']: try: EC2NodeDriver(*EC2_PARAMS, **{'region': region}) except ValueError: pass else: self.fail('Invalid region, but exception was not thrown') def test_list_sizes_valid_regions(self): unsupported_regions = list() for region in VALID_EC2_REGIONS: no_pricing = region in ['cn-north-1'] driver = EC2NodeDriver(*EC2_PARAMS, **{'region': region}) try: sizes = driver.list_sizes() if no_pricing: self.assertTrue(all([s.price is None for s in sizes])) except Exception: unsupported_regions.append(region) if unsupported_regions: self.fail('Cannot list sizes from ec2 regions: %s' % unsupported_regions) class EC2Tests(LibcloudTestCase, TestCaseMixin): image_name = 'ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml' region = 'us-east-1' def setUp(self): EC2MockHttp.test = self EC2NodeDriver.connectionCls.conn_class = EC2MockHttp EC2MockHttp.use_param = 'Action' EC2MockHttp.type = None self.driver = EC2NodeDriver(*EC2_PARAMS, **{'region': self.region}) def test_instantiate_driver_with_token(self): token = 'temporary_credentials_token' driver = EC2NodeDriver(*EC2_PARAMS, **{'region': self.region, 'token': token}) self.assertTrue(hasattr(driver, 'token'), 'Driver has no attribute token') self.assertEqual(token, driver.token, "Driver token does not match with provided token") def test_driver_with_token_signature_version(self): token = 'temporary_credentials_token' driver = EC2NodeDriver(*EC2_PARAMS, **{'region': self.region, 'token': token}) kwargs = driver._ex_connection_class_kwargs() self.assertIn('signature_version', kwargs) self.assertEqual('4', kwargs['signature_version'], 'Signature version is not 4 with temporary credentials') def test_create_node(self): image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='foo', image=image, size=size) self.assertEqual(node.id, 'i-2ba64342') self.assertEqual(node.name, 'foo') self.assertEqual(node.extra['tags']['Name'], 'foo') self.assertEqual(len(node.extra['tags']), 1) def test_create_node_with_ex_mincount(self): image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='foo', image=image, size=size, ex_mincount=1, ex_maxcount=10) self.assertEqual(node.id, 'i-2ba64342') self.assertEqual(node.name, 'foo') self.assertEqual(node.extra['tags']['Name'], 'foo') self.assertEqual(len(node.extra['tags']), 1) def test_create_node_with_ex_assign_public_ip(self): # assertions are done in _create_ex_assign_public_ip_RunInstances EC2MockHttp.type = 'create_ex_assign_public_ip' image = NodeImage(id='ami-11111111', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) subnet = EC2NetworkSubnet('subnet-11111111', "test_subnet", "pending") self.driver.create_node( name='foo', image=image, size=size, ex_subnet=subnet, ex_security_group_ids=[ 'sg-11111111' ], ex_assign_public_ip=True, ) def test_create_node_with_ex_terminate_on_shutdown(self): EC2MockHttp.type = 'create_ex_terminate_on_shutdown' image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) # The important part about the test is asserted inside # EC2MockHttp._create_ex_terminate_on_shutdown self.driver.create_node(name='foo', image=image, size=size, ex_terminate_on_shutdown=True) def test_create_node_with_metadata(self): image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='foo', image=image, size=size, ex_metadata={'Bar': 'baz', 'Num': '42'}) self.assertEqual(node.name, 'foo') self.assertEqual(node.extra['tags']['Name'], 'foo') self.assertEqual(node.extra['tags']['Bar'], 'baz') self.assertEqual(node.extra['tags']['Num'], '42') self.assertEqual(len(node.extra['tags']), 3) def test_create_node_idempotent(self): EC2MockHttp.type = 'idempotent' image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) token = 'testclienttoken' node = self.driver.create_node(name='foo', image=image, size=size, ex_clienttoken=token) self.assertEqual(node.id, 'i-2ba64342') self.assertEqual(node.extra['client_token'], token) # from: http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/index.html?Run_Instance_Idempotency.html # If you repeat the request with the same client token, but change # another request parameter, Amazon EC2 returns an # IdempotentParameterMismatch error. # In our case, changing the parameter doesn't actually matter since we # are forcing the error response fixture. EC2MockHttp.type = 'idempotent_mismatch' idem_error = None # different count try: self.driver.create_node(name='foo', image=image, size=size, ex_mincount='2', ex_maxcount='2', ex_clienttoken=token) except IdempotentParamError as e: idem_error = e self.assertTrue(idem_error is not None) def test_create_node_no_availability_zone(self): image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='foo', image=image, size=size) location = NodeLocation(0, 'Amazon US N. Virginia', 'US', self.driver) self.assertEqual(node.id, 'i-2ba64342') node = self.driver.create_node(name='foo', image=image, size=size, location=location) self.assertEqual(node.id, 'i-2ba64342') self.assertEqual(node.name, 'foo') def test_list_nodes(self): node = self.driver.list_nodes()[0] public_ips = sorted(node.public_ips) self.assertEqual(node.id, 'i-4382922a') self.assertEqual(node.name, node.id) self.assertEqual(len(node.public_ips), 2) self.assertEqual(node.extra['launch_time'], '2013-12-02T11:58:11.000Z') self.assertEqual(node.created_at, datetime(2013, 12, 2, 11, 58, 11, tzinfo=UTC)) self.assertTrue('instance_type' in node.extra) self.assertEqual(node.extra['availability'], 'us-east-1d') self.assertEqual(node.extra['key_name'], 'fauxkey') self.assertEqual(node.extra['monitoring'], 'disabled') self.assertEqual(node.extra['image_id'], 'ami-3215fe5a') self.assertEqual(len(node.extra['groups']), 2) self.assertEqual(len(node.extra['block_device_mapping']), 1) self.assertEqual(node.extra['block_device_mapping'][0]['device_name'], '/dev/sda1') self.assertEqual(node.extra['block_device_mapping'][0]['ebs']['volume_id'], 'vol-5e312311') self.assertTrue(node.extra['block_device_mapping'][0]['ebs']['delete']) self.assertEqual(node.extra['block_device_mapping'][0]['ebs']['status'], 'attached') self.assertEqual(node.extra['block_device_mapping'][0]['ebs']['attach_time'], datetime(2013, 4, 9, 18, 1, 1, tzinfo=UTC)) self.assertEqual(public_ips[0], '1.2.3.4') nodes = self.driver.list_nodes(ex_node_ids=['i-4382922a', 'i-8474834a']) ret_node1 = nodes[0] ret_node2 = nodes[1] self.assertEqual(ret_node1.id, 'i-4382922a') self.assertEqual(ret_node2.id, 'i-8474834a') self.assertEqual(ret_node2.name, 'Test Server 2') self.assertEqual(ret_node2.extra['subnet_id'], 'subnet-5fd9d412') self.assertEqual(ret_node2.extra['vpc_id'], 'vpc-61dcd30e') self.assertEqual(ret_node2.extra['tags']['Group'], 'VPC Test') self.assertEqual(ret_node1.extra['launch_time'], '2013-12-02T11:58:11.000Z') self.assertEqual(ret_node1.created_at, datetime(2013, 12, 2, 11, 58, 11, tzinfo=UTC)) self.assertEqual(ret_node2.extra['launch_time'], '2013-12-02T15:58:29.000Z') self.assertEqual(ret_node2.created_at, datetime(2013, 12, 2, 15, 58, 29, tzinfo=UTC)) self.assertIn('instance_type', ret_node1.extra) self.assertIn('instance_type', ret_node2.extra) def test_ex_list_reserved_nodes(self): node = self.driver.ex_list_reserved_nodes()[0] self.assertEqual(node.id, '93bbbca2-c500-49d0-9ede-9d8737400498') self.assertEqual(node.state, 'active') self.assertEqual(node.extra['instance_type'], 't1.micro') self.assertEqual(node.extra['availability'], 'us-east-1b') self.assertEqual(node.extra['start'], '2013-06-18T12:07:53.161Z') self.assertEqual(node.extra['end'], '2014-06-18T12:07:53.161Z') self.assertEqual(node.extra['duration'], 31536000) self.assertEqual(node.extra['usage_price'], 0.012) self.assertEqual(node.extra['fixed_price'], 23.0) self.assertEqual(node.extra['instance_count'], 1) self.assertEqual(node.extra['description'], 'Linux/UNIX') self.assertEqual(node.extra['instance_tenancy'], 'default') self.assertEqual(node.extra['currency_code'], 'USD') self.assertEqual(node.extra['offering_type'], 'Light Utilization') def test_list_location(self): locations = self.driver.list_locations() self.assertTrue(len(locations) > 0) self.assertEqual(locations[0].name, 'eu-west-1a') self.assertTrue(locations[0].availability_zone is not None) self.assertTrue(isinstance(locations[0].availability_zone, ExEC2AvailabilityZone)) def test_list_security_groups(self): groups = self.driver.ex_list_security_groups() self.assertEqual(groups, ['WebServers', 'RangedPortsBySource']) def test_ex_delete_security_group_by_id(self): group_id = 'sg-443d0a12' retValue = self.driver.ex_delete_security_group_by_id(group_id) self.assertTrue(retValue) def test_delete_security_group_by_name(self): group_name = 'WebServers' retValue = self.driver.ex_delete_security_group_by_name(group_name) self.assertTrue(retValue) def test_ex_delete_security_group(self): name = 'WebServers' retValue = self.driver.ex_delete_security_group(name) self.assertTrue(retValue) def test_authorize_security_group(self): resp = self.driver.ex_authorize_security_group('TestGroup', '22', '22', '0.0.0.0/0') self.assertTrue(resp) def test_authorize_security_group_ingress(self): ranges = ['1.1.1.1/32', '2.2.2.2/32'] description = "automated authorised IP ingress test" resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges, description=description) self.assertTrue(resp) groups = [{'group_id': 'sg-949265ff'}] description = "automated authorised group ingress test" resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 23, group_pairs=groups, description=description) self.assertTrue(resp) def test_authorize_security_group_egress(self): ranges = ['1.1.1.1/32', '2.2.2.2/32'] resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges) self.assertTrue(resp) groups = [{'group_id': 'sg-949265ff'}] resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, group_pairs=groups) self.assertTrue(resp) def test_revoke_security_group_ingress(self): ranges = ['1.1.1.1/32', '2.2.2.2/32'] resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges) self.assertTrue(resp) groups = [{'group_id': 'sg-949265ff'}] resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, group_pairs=groups) self.assertTrue(resp) def test_revoke_security_group_egress(self): ranges = ['1.1.1.1/32', '2.2.2.2/32'] resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, cidr_ips=ranges) self.assertTrue(resp) groups = [{'group_id': 'sg-949265ff'}] resp = self.driver.ex_authorize_security_group_ingress('sg-42916629', 22, 22, group_pairs=groups) self.assertTrue(resp) def test_reboot_node(self): node = Node('i-4382922a', None, None, None, None, self.driver) ret = self.driver.reboot_node(node) self.assertTrue(ret) def test_ex_start_node(self): node = Node('i-4382922a', None, None, None, None, self.driver) ret = self.driver.ex_start_node(node) self.assertTrue(ret) def test_ex_stop_node(self): node = Node('i-4382922a', None, None, None, None, self.driver) ret = self.driver.ex_stop_node(node) self.assertTrue(ret) def test_ex_create_node_with_ex_blockdevicemappings(self): EC2MockHttp.type = 'create_ex_blockdevicemappings' image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) mappings = [ {'DeviceName': '/dev/sda1', 'Ebs.VolumeSize': 10}, {'DeviceName': '/dev/sdb', 'VirtualName': 'ephemeral0'}, {'DeviceName': '/dev/sdc', 'VirtualName': 'ephemeral1'} ] node = self.driver.create_node(name='foo', image=image, size=size, ex_blockdevicemappings=mappings) self.assertEqual(node.id, 'i-2ba64342') def test_ex_create_node_with_ex_blockdevicemappings_attribute_error(self): EC2MockHttp.type = 'create_ex_blockdevicemappings' image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) mappings = 'this should be a list' self.assertRaises(AttributeError, self.driver.create_node, name='foo', image=image, size=size, ex_blockdevicemappings=mappings) mappings = ['this should be a dict'] self.assertRaises(AttributeError, self.driver.create_node, name='foo', image=image, size=size, ex_blockdevicemappings=mappings) def test_destroy_node(self): node = Node('i-4382922a', None, None, None, None, self.driver) ret = self.driver.destroy_node(node) self.assertTrue(ret) def test_list_sizes(self): region_old = self.driver.region_name names = [ ('ec2_us_east', 'us-east-1'), ('ec2_us_west', 'us-west-1'), ('ec2_us_west', 'us-west-2'), ('ec2_eu_west', 'eu-west-1'), ('ec2_ap_southeast', 'ap-southeast-1'), ('ec2_ap_northeast', 'ap-northeast-1'), ('ec2_ap_southeast_2', 'ap-southeast-2'), ('ec2_ap_south_1', 'ap-south-1') ] for api_name, region_name in names: self.driver.api_name = api_name self.driver.region_name = region_name sizes = self.driver.list_sizes() self.assertNotEqual(len(sizes), 0) self.driver.region_name = region_old def test_ex_create_node_with_ex_iam_profile(self): iamProfile = { 'id': 'AIDGPMS9RO4H3FEXAMPLE', 'name': 'Foo', 'arn': 'arn:aws:iam:...' } image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) EC2MockHttp.type = None node1 = self.driver.create_node(name='foo', image=image, size=size) EC2MockHttp.type = 'ex_iam_profile' node2 = self.driver.create_node(name='bar', image=image, size=size, ex_iamprofile=iamProfile['name']) node3 = self.driver.create_node(name='bar', image=image, size=size, ex_iamprofile=iamProfile['arn']) self.assertFalse(node1.extra['iam_profile']) self.assertEqual(node2.extra['iam_profile'], iamProfile['id']) self.assertEqual(node3.extra['iam_profile'], iamProfile['id']) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 2) location = '123456788908/Test Image' self.assertEqual(images[0].id, 'ami-57ba933a') self.assertEqual(images[0].name, 'Test Image') self.assertEqual(images[0].extra['image_location'], location) self.assertEqual(images[0].extra['architecture'], 'x86_64') self.assertEqual(len(images[0].extra['block_device_mapping']), 2) ephemeral = images[0].extra['block_device_mapping'][1]['virtual_name'] self.assertEqual(ephemeral, 'ephemeral0') billing_product1 = images[0].extra['billing_products'][0] self.assertEqual(billing_product1, 'ab-5dh78019') location = '123456788908/Test Image 2' self.assertEqual(images[1].id, 'ami-85b2a8ae') self.assertEqual(images[1].name, 'Test Image 2') self.assertEqual(images[1].extra['image_location'], location) self.assertEqual(images[1].extra['architecture'], 'x86_64') size = images[1].extra['block_device_mapping'][0]['ebs']['volume_size'] billing_product2 = images[1].extra['billing_products'][0] self.assertEqual(billing_product2, 'as-6dr90319') self.assertEqual(size, 20) def test_list_images_with_image_ids(self): EC2MockHttp.type = 'ex_imageids' images = self.driver.list_images(ex_image_ids=['ami-57ba933a']) self.assertEqual(len(images), 1) self.assertEqual(images[0].name, 'Test Image') def test_list_images_with_executable_by(self): images = self.driver.list_images(ex_executableby='self') self.assertEqual(len(images), 2) def test_get_image(self): image = self.driver.get_image('ami-57ba933a') self.assertEqual(image.id, 'ami-57ba933a') self.assertEqual(image.name, 'Test Image') self.assertEqual(image.extra['architecture'], 'x86_64') self.assertEqual(len(image.extra['block_device_mapping']), 2) self.assertEqual(image.extra['billing_products'][0], 'ab-5dh78019') def test_copy_image(self): image = self.driver.list_images()[0] resp = self.driver.copy_image(image, 'us-east-1', name='Faux Image', description='Test Image Copy') self.assertEqual(resp.id, 'ami-4db38224') def test_create_image(self): node = self.driver.list_nodes()[0] mapping = [{'VirtualName': None, 'Ebs': {'VolumeSize': 10, 'VolumeType': 'standard', 'DeleteOnTermination': 'true'}, 'DeviceName': '/dev/sda1'}] resp = self.driver.create_image(node, 'New Image', description='New EBS Image', block_device_mapping=mapping) self.assertEqual(resp.id, 'ami-e9b38280') def test_create_image_no_mapping(self): node = self.driver.list_nodes()[0] resp = self.driver.create_image(node, 'New Image', description='New EBS Image') self.assertEqual(resp.id, 'ami-e9b38280') def delete_image(self): images = self.driver.list_images() image = images[0] resp = self.driver.delete_image(image) self.assertTrue(resp) def ex_register_image(self): mapping = [{'DeviceName': '/dev/sda1', 'Ebs': {'SnapshotId': 'snap-5ade3e4e'}}] image = self.driver.ex_register_image(name='Test Image', root_device_name='/dev/sda1', description='My Image', architecture='x86_64', block_device_mapping=mapping, ena_support=True, billing_products=['ab-5dh78019'], sriov_net_support='simple') self.assertEqual(image.id, 'ami-57c2fb3e') def test_ex_import_snapshot(self): disk_container = [{'Description': 'Dummy import snapshot task', 'Format': 'raw', 'UserBucket': {'S3Bucket': 'dummy-bucket', 'S3Key': 'dummy-key'}}] snap = self.driver.ex_import_snapshot(disk_container=disk_container) self.assertEqual(snap.id, 'snap-0ea83e8a87e138f39') def test_wait_for_import_snapshot_completion(self): snap = self.driver._wait_for_import_snapshot_completion( import_task_id='import-snap-fhdysyq6') self.assertEqual(snap.id, 'snap-0ea83e8a87e138f39') def test_timeout_wait_for_import_snapshot_completion(self): import_task_id = 'import-snap-fhdysyq6' EC2MockHttp.type = 'timeout' with self.assertRaises(Exception) as context: self.driver._wait_for_import_snapshot_completion( import_task_id=import_task_id, timeout=0.01, interval=0.001) self.assertEqual('Timeout while waiting for import task Id %s' % import_task_id, str(context.exception)) def test_ex_describe_import_snapshot_tasks(self): snap = self.driver.ex_describe_import_snapshot_tasks( import_task_id='import-snap-fh7y6i6w<') self.assertEqual(snap.snapshotId, 'snap-0ea83e8a87e138f39') self.assertEqual(snap.status, 'completed') def test_ex_list_availability_zones(self): availability_zones = self.driver.ex_list_availability_zones() availability_zone = availability_zones[0] self.assertTrue(len(availability_zones) > 0) self.assertEqual(availability_zone.name, 'eu-west-1a') self.assertEqual(availability_zone.zone_state, 'available') self.assertEqual(availability_zone.region_name, 'eu-west-1') def test_list_keypairs(self): keypairs = self.driver.list_key_pairs() self.assertEqual(len(keypairs), 1) self.assertEqual(keypairs[0].name, 'gsg-keypair') self.assertEqual(keypairs[0].fingerprint, null_fingerprint) # Test old deprecated method keypairs = self.driver.ex_list_keypairs() self.assertEqual(len(keypairs), 1) self.assertEqual(keypairs[0]['keyName'], 'gsg-keypair') self.assertEqual(keypairs[0]['keyFingerprint'], null_fingerprint) def test_get_key_pair(self): EC2MockHttp.type = 'get_one' key_pair = self.driver.get_key_pair(name='gsg-keypair') self.assertEqual(key_pair.name, 'gsg-keypair') def test_get_key_pair_does_not_exist(self): EC2MockHttp.type = 'doesnt_exist' self.assertRaises(KeyPairDoesNotExistError, self.driver.get_key_pair, name='test-key-pair') def test_create_key_pair(self): key_pair = self.driver.create_key_pair(name='test-keypair') fingerprint = ('1f:51:ae:28:bf:89:e9:d8:1f:25:5d' ':37:2d:7d:b8:ca:9f:f5:f1:6f') self.assertEqual(key_pair.name, 'my-key-pair') self.assertEqual(key_pair.fingerprint, fingerprint) self.assertTrue(key_pair.private_key is not None) # Test old and deprecated method key_pair = self.driver.ex_create_keypair(name='test-keypair') self.assertEqual(key_pair['keyFingerprint'], fingerprint) self.assertTrue(key_pair['keyMaterial'] is not None) def test_ex_describe_all_keypairs(self): keys = self.driver.ex_describe_all_keypairs() self.assertEqual(keys, ['gsg-keypair']) def test_list_key_pairs(self): keypair1 = self.driver.list_key_pairs()[0] self.assertEqual(keypair1.name, 'gsg-keypair') self.assertEqual(keypair1.fingerprint, null_fingerprint) # Test backward compatibility keypair2 = self.driver.ex_describe_keypairs('gsg-keypair') self.assertEqual(keypair2['keyName'], 'gsg-keypair') self.assertEqual(keypair2['keyFingerprint'], null_fingerprint) def test_delete_key_pair(self): keypair = self.driver.list_key_pairs()[0] success = self.driver.delete_key_pair(keypair) self.assertTrue(success) # Test old and deprecated method resp = self.driver.ex_delete_keypair('gsg-keypair') self.assertTrue(resp) def test_ex_describe_tags(self): node = Node('i-4382922a', None, None, None, None, self.driver) tags = self.driver.ex_describe_tags(resource=node) self.assertEqual(len(tags), 3) self.assertTrue('tag' in tags) self.assertTrue('owner' in tags) self.assertTrue('stack' in tags) def test_import_key_pair_from_string(self): path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa.pub') with open(path, 'r') as fp: key_material = fp.read() key = self.driver.import_key_pair_from_string(name='keypair', key_material=key_material) self.assertEqual(key.name, 'keypair') self.assertEqual(key.fingerprint, null_fingerprint) # Test old and deprecated method key = self.driver.ex_import_keypair_from_string('keypair', key_material) self.assertEqual(key['keyName'], 'keypair') self.assertEqual(key['keyFingerprint'], null_fingerprint) def test_import_key_pair_from_file(self): path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa.pub') key = self.driver.import_key_pair_from_file('keypair', path) self.assertEqual(key.name, 'keypair') self.assertEqual(key.fingerprint, null_fingerprint) # Test old and deprecated method key = self.driver.ex_import_keypair('keypair', path) self.assertEqual(key['keyName'], 'keypair') self.assertEqual(key['keyFingerprint'], null_fingerprint) def test_ex_create_tags(self): node = Node('i-4382922a', None, None, None, None, self.driver) self.driver.ex_create_tags(node, {'sample': 'tag'}) def test_ex_delete_tags(self): node = Node('i-4382922a', None, None, None, None, self.driver) self.driver.ex_delete_tags(node, {'sample': 'tag'}) def test_ex_delete_tags2(self): node = Node('i-4382922a', None, None, None, None, self.driver) self.driver.ex_create_tags(node, {'sample': 'another tag'}) self.driver.ex_delete_tags(node, {'sample': None}) def test_ex_describe_addresses_for_node(self): node1 = Node('i-4382922a', None, None, None, None, self.driver) ip_addresses1 = self.driver.ex_describe_addresses_for_node(node1) node2 = Node('i-4382922b', None, None, None, None, self.driver) ip_addresses2 = sorted( self.driver.ex_describe_addresses_for_node(node2)) node3 = Node('i-4382922g', None, None, None, None, self.driver) ip_addresses3 = sorted( self.driver.ex_describe_addresses_for_node(node3)) self.assertEqual(len(ip_addresses1), 1) self.assertEqual(ip_addresses1[0], '1.2.3.4') self.assertEqual(len(ip_addresses2), 2) self.assertEqual(ip_addresses2[0], '1.2.3.5') self.assertEqual(ip_addresses2[1], '1.2.3.6') self.assertEqual(len(ip_addresses3), 0) def test_ex_describe_addresses(self): node1 = Node('i-4382922a', None, None, None, None, self.driver) node2 = Node('i-4382922g', None, None, None, None, self.driver) nodes_elastic_ips1 = self.driver.ex_describe_addresses([node1]) nodes_elastic_ips2 = self.driver.ex_describe_addresses([node2]) self.assertEqual(len(nodes_elastic_ips1), 1) self.assertTrue(node1.id in nodes_elastic_ips1) self.assertEqual(nodes_elastic_ips1[node1.id], ['1.2.3.4']) self.assertEqual(len(nodes_elastic_ips2), 1) self.assertTrue(node2.id in nodes_elastic_ips2) self.assertEqual(nodes_elastic_ips2[node2.id], []) def test_ex_describe_all_addresses(self): EC2MockHttp.type = 'all_addresses' elastic_ips1 = self.driver.ex_describe_all_addresses() elastic_ips2 = self.driver.ex_describe_all_addresses( only_associated=True) self.assertEqual('1.2.3.7', elastic_ips1[3].ip) self.assertEqual('vpc', elastic_ips1[3].domain) self.assertEqual('eipalloc-992a5cf8', elastic_ips1[3].extra['allocation_id']) self.assertEqual(len(elastic_ips2), 2) self.assertEqual('1.2.3.5', elastic_ips2[1].ip) self.assertEqual('vpc', elastic_ips2[1].domain) def test_ex_allocate_address(self): elastic_ip = self.driver.ex_allocate_address() self.assertEqual('192.0.2.1', elastic_ip.ip) self.assertEqual('standard', elastic_ip.domain) EC2MockHttp.type = 'vpc' elastic_ip = self.driver.ex_allocate_address(domain='vpc') self.assertEqual('192.0.2.2', elastic_ip.ip) self.assertEqual('vpc', elastic_ip.domain) self.assertEqual('eipalloc-666d7f04', elastic_ip.extra['allocation_id']) def test_ex_release_address(self): EC2MockHttp.type = 'all_addresses' elastic_ips = self.driver.ex_describe_all_addresses() EC2MockHttp.type = '' ret = self.driver.ex_release_address(elastic_ips[2]) self.assertTrue(ret) ret = self.driver.ex_release_address(elastic_ips[0], domain='vpc') self.assertTrue(ret) self.assertRaises(AttributeError, self.driver.ex_release_address, elastic_ips[0], domain='bogus') def test_ex_associate_address_with_node(self): node = Node('i-4382922a', None, None, None, None, self.driver) EC2MockHttp.type = 'all_addresses' elastic_ips = self.driver.ex_describe_all_addresses() EC2MockHttp.type = '' ret1 = self.driver.ex_associate_address_with_node( node, elastic_ips[2]) ret2 = self.driver.ex_associate_addresses( node, elastic_ips[2]) self.assertEqual(None, ret1) self.assertEqual(None, ret2) EC2MockHttp.type = 'vpc' ret3 = self.driver.ex_associate_address_with_node( node, elastic_ips[3], domain='vpc') ret4 = self.driver.ex_associate_addresses( node, elastic_ips[3], domain='vpc') self.assertEqual('eipassoc-167a8073', ret3) self.assertEqual('eipassoc-167a8073', ret4) self.assertRaises(AttributeError, self.driver.ex_associate_address_with_node, node, elastic_ips[1], domain='bogus') def test_ex_disassociate_address(self): EC2MockHttp.type = 'all_addresses' elastic_ips = self.driver.ex_describe_all_addresses() EC2MockHttp.type = '' ret = self.driver.ex_disassociate_address(elastic_ips[2]) self.assertTrue(ret) # Test a VPC disassociation ret = self.driver.ex_disassociate_address(elastic_ips[1], domain='vpc') self.assertTrue(ret) self.assertRaises(AttributeError, self.driver.ex_disassociate_address, elastic_ips[1], domain='bogus') def test_ex_change_node_size_same_size(self): size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) node = Node('i-4382922a', None, None, None, None, self.driver, extra={'instancetype': 'm1.small'}) try: self.driver.ex_change_node_size(node=node, new_size=size) except ValueError: pass else: self.fail('Same size was passed, but an exception was not thrown') def test_ex_change_node_size(self): size = NodeSize('m1.large', 'Small Instance', None, None, None, None, driver=self.driver) node = Node('i-4382922a', None, None, None, None, self.driver, extra={'instancetype': 'm1.small'}) result = self.driver.ex_change_node_size(node=node, new_size=size) self.assertTrue(result) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 3) self.assertEqual('vol-10ae5e2b', volumes[0].id) self.assertEqual(1, volumes[0].size) self.assertEqual('available', volumes[0].extra['state']) self.assertEqual(StorageVolumeState.AVAILABLE, volumes[0].state) self.assertEqual('vol-v24bfh75', volumes[1].id) self.assertEqual(11, volumes[1].size) self.assertIsNone(volumes[1].extra['snapshot_id']) self.assertEqual('in-use', volumes[1].extra['state']) self.assertEqual(StorageVolumeState.INUSE, volumes[1].state) self.assertEqual('vol-b6c851ec', volumes[2].id) self.assertEqual(8, volumes[2].size) self.assertEqual('some-unknown-status', volumes[2].extra['state']) self.assertEqual('i-d334b4b3', volumes[2].extra['instance_id']) self.assertEqual('/dev/sda1', volumes[2].extra['device']) self.assertEqual('snap-30d37269', volumes[2].extra['snapshot_id']) self.assertEqual(StorageVolumeState.UNKNOWN, volumes[2].state) EC2MockHttp.type = 'filters_nodes' node = Node('i-d334b4b3', None, None, None, None, self.driver) self.driver.list_volumes(node=node) EC2MockHttp.type = 'filters_status' self.driver.list_volumes(ex_filters={'status': 'available'}) def test_create_volume(self): location = self.driver.list_locations()[0] vol = self.driver.create_volume(10, 'vol', location) self.assertEqual(10, vol.size) self.assertEqual('vol', vol.name) self.assertEqual('creating', vol.extra['state']) self.assertTrue(isinstance(vol.extra['create_time'], datetime)) self.assertEqual(False, vol.extra['encrypted']) def test_create_encrypted_volume(self): location = self.driver.list_locations()[0] vol = self.driver.create_volume( 10, 'vol', location, ex_encrypted=True, ex_kms_key_id='1234') self.assertEqual(10, vol.size) self.assertEqual('vol', vol.name) self.assertEqual('creating', vol.extra['state']) self.assertTrue(isinstance(vol.extra['create_time'], datetime)) self.assertEqual(True, vol.extra['encrypted']) def test_destroy_volume(self): vol = StorageVolume(id='vol-4282672b', name='test', state=StorageVolumeState.AVAILABLE, size=10, driver=self.driver) retValue = self.driver.destroy_volume(vol) self.assertTrue(retValue) def test_attach(self): vol = StorageVolume(id='vol-4282672b', name='test', size=10, state=StorageVolumeState.AVAILABLE, driver=self.driver) node = Node('i-4382922a', None, None, None, None, self.driver) retValue = self.driver.attach_volume(node, vol, '/dev/sdh') self.assertTrue(retValue) def test_detach(self): vol = StorageVolume(id='vol-4282672b', name='test', state=StorageVolumeState.INUSE, size=10, driver=self.driver) retValue = self.driver.detach_volume(vol) self.assertTrue(retValue) def test_create_volume_snapshot(self): vol = StorageVolume(id='vol-4282672b', name='test', state=StorageVolumeState.AVAILABLE, size=10, driver=self.driver) snap = self.driver.create_volume_snapshot( vol, 'Test snapshot') self.assertEqual('snap-a7cb2hd9', snap.id) self.assertEqual(vol.size, snap.size) self.assertEqual('Test snapshot', snap.extra['name']) self.assertEqual(vol.id, snap.extra['volume_id']) self.assertEqual('pending', snap.extra['state']) self.assertEqual(VolumeSnapshotState.CREATING, snap.state) # 2013-08-15T16:22:30.000Z self.assertEqual(datetime(2013, 8, 15, 16, 22, 30, tzinfo=UTC), snap.created) def test_create_volume_snapshot_with_tags(self): vol = StorageVolume(id='vol-4282672b', name='test', state=StorageVolumeState.AVAILABLE, size=10, driver=self.driver) snap = self.driver.create_volume_snapshot( vol, 'Test snapshot', ex_metadata={'my_tag': 'test'}) self.assertEqual('test', snap.extra['tags']['my_tag']) def test_list_snapshots(self): snaps = self.driver.list_snapshots() self.assertEqual(len(snaps), 3) self.assertEqual('snap-428abd35', snaps[0].id) self.assertEqual(VolumeSnapshotState.CREATING, snaps[0].state) self.assertEqual('vol-e020df80', snaps[0].extra['volume_id']) self.assertEqual(30, snaps[0].size) self.assertEqual('Daily Backup', snaps[0].extra['description']) self.assertEqual('snap-18349159', snaps[1].id) self.assertEqual('DB Backup 1', snaps[1].name) self.assertEqual(VolumeSnapshotState.AVAILABLE, snaps[1].state) self.assertEqual('vol-b5a2c1v9', snaps[1].extra['volume_id']) self.assertEqual(15, snaps[1].size) self.assertEqual('Weekly backup', snaps[1].extra['description']) self.assertEqual('DB Backup 1', snaps[1].extra['name']) def test_list_volume_snapshots(self): volume = self.driver.list_volumes()[0] assert volume.id == 'vol-10ae5e2b' snapshots = self.driver.list_volume_snapshots(volume) self.assertEqual(len(snapshots), 1) self.assertEqual(snapshots[0].id, 'snap-18349160') def test_destroy_snapshot(self): snap = VolumeSnapshot(id='snap-428abd35', size=10, driver=self.driver) resp = snap.destroy() self.assertTrue(resp) def test_ex_modify_image_attribute(self): images = self.driver.list_images() image = images[0] data = {'LaunchPermission.Add.1.Group': 'all'} resp = self.driver.ex_modify_image_attribute(image, data) self.assertTrue(resp) def test_ex_modify_snapshot_attribute(self): snap = VolumeSnapshot(id='snap-1234567890abcdef0', size=10, driver=self.driver) data = {'CreateVolumePermission.Add.1.Group': 'all'} resp = self.driver.ex_modify_snapshot_attribute(snap, data) self.assertTrue(resp) def test_create_node_ex_security_groups(self): EC2MockHttp.type = 'ex_security_groups' image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) security_groups = ['group1', 'group2'] # Old, deprecated argument name self.driver.create_node(name='foo', image=image, size=size, ex_securitygroup=security_groups) # New argument name self.driver.create_node(name='foo', image=image, size=size, ex_security_groups=security_groups) # Test old and new arguments are mutually exclusive self.assertRaises(ValueError, self.driver.create_node, name='foo', image=image, size=size, ex_securitygroup=security_groups, ex_security_groups=security_groups) def test_create_node_ex_security_group_ids(self): EC2MockHttp.type = 'ex_security_group_ids' image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) subnet = EC2NetworkSubnet(12345, "test_subnet", "pending") security_groups = ['sg-1aa11a1a', 'sg-2bb22b2b'] self.driver.create_node(name='foo', image=image, size=size, ex_security_group_ids=security_groups, ex_subnet=subnet) self.assertRaises(ValueError, self.driver.create_node, name='foo', image=image, size=size, ex_security_group_ids=security_groups) def test_ex_get_metadata_for_node(self): image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='foo', image=image, size=size, ex_metadata={'Bar': 'baz', 'Num': '42'}) metadata = self.driver.ex_get_metadata_for_node(node) self.assertEqual(metadata['Name'], 'foo') self.assertEqual(metadata['Bar'], 'baz') self.assertEqual(metadata['Num'], '42') self.assertEqual(len(metadata), 3) def test_ex_get_limits(self): limits = self.driver.ex_get_limits() expected = {'max-instances': 20, 'vpc-max-elastic-ips': 5, 'max-elastic-ips': 5} self.assertEqual(limits['resource'], expected) def test_ex_create_security_group(self): group = self.driver.ex_create_security_group("WebServers", "Rules to protect web nodes", "vpc-143cab4") self.assertEqual(group["group_id"], "sg-52e2f530") def test_ex_create_placement_groups(self): resp = self.driver.ex_create_placement_group("NewPG") self.assertTrue(resp) def test_ex_delete_placement_groups(self): pgs = self.driver.ex_list_placement_groups() pg = pgs[0] resp = self.driver.ex_delete_placement_group(pg.name) self.assertTrue(resp) def test_ex_list_placement_groups(self): pgs = self.driver.ex_list_placement_groups() self.assertEqual(len(pgs), 2) self.assertIsInstance(pgs[0], EC2PlacementGroup) def test_ex_list_networks(self): vpcs = self.driver.ex_list_networks() self.assertEqual(len(vpcs), 2) self.assertEqual('vpc-532335e1', vpcs[0].id) self.assertEqual('vpc-532335e1', vpcs[0].name) self.assertEqual('192.168.51.0/24', vpcs[0].cidr_block) self.assertEqual('available', vpcs[0].extra['state']) self.assertEqual('dopt-7eded312', vpcs[0].extra['dhcp_options_id']) self.assertEqual('vpc-62ded30e', vpcs[1].id) self.assertEqual('Test VPC', vpcs[1].name) self.assertEqual('192.168.52.0/24', vpcs[1].cidr_block) self.assertEqual('available', vpcs[1].extra['state']) self.assertEqual('dopt-7eded312', vpcs[1].extra['dhcp_options_id']) def test_ex_list_networks_network_ids(self): EC2MockHttp.type = 'network_ids' network_ids = ['vpc-532335e1'] # We assert in the mock http method self.driver.ex_list_networks(network_ids=network_ids) def test_ex_list_networks_filters(self): EC2MockHttp.type = 'filters' filters = OrderedDict([ ('dhcp-options-id', 'dopt-7eded312'), # matches two networks ('cidr', '192.168.51.0/24') # matches two networks ]) # We assert in the mock http method self.driver.ex_list_networks(filters=filters) def test_ex_create_network(self): vpc = self.driver.ex_create_network('192.168.55.0/24', name='Test VPC', instance_tenancy='default') self.assertEqual('vpc-ad3527cf', vpc.id) self.assertEqual('192.168.55.0/24', vpc.cidr_block) self.assertEqual('pending', vpc.extra['state']) def test_ex_delete_network(self): vpcs = self.driver.ex_list_networks() vpc = vpcs[0] resp = self.driver.ex_delete_network(vpc) self.assertTrue(resp) def test_ex_list_subnets(self): subnets = self.driver.ex_list_subnets() self.assertEqual(len(subnets), 2) self.assertEqual('subnet-ce0e7ce5', subnets[0].id) self.assertEqual('available', subnets[0].state) self.assertEqual(123, subnets[0].extra['available_ips']) self.assertEqual('subnet-ce0e7ce6', subnets[1].id) self.assertEqual('available', subnets[1].state) self.assertEqual(59, subnets[1].extra['available_ips']) def test_ex_create_subnet(self): subnet = self.driver.ex_create_subnet('vpc-532135d1', '192.168.51.128/26', 'us-east-1b', name='Test Subnet') self.assertEqual('subnet-ce0e7ce6', subnet.id) self.assertEqual('pending', subnet.state) self.assertEqual('vpc-532135d1', subnet.extra['vpc_id']) def test_ex_modify_subnet_attribute(self): subnet = self.driver.ex_list_subnets()[0] resp = self.driver.ex_modify_subnet_attribute(subnet, 'auto_public_ip', True) self.assertTrue(resp) resp = self.driver.ex_modify_subnet_attribute(subnet, 'auto_ipv6', False) self.assertTrue(resp) expected_msg = 'Unsupported attribute: invalid' self.assertRaisesRegexp(ValueError, expected_msg, self.driver.ex_modify_subnet_attribute, subnet, 'invalid', True) def test_ex_delete_subnet(self): subnet = self.driver.ex_list_subnets()[0] resp = self.driver.ex_delete_subnet(subnet=subnet) self.assertTrue(resp) def test_ex_get_console_output(self): node = self.driver.list_nodes()[0] resp = self.driver.ex_get_console_output(node) self.assertEqual('Test String', resp['output']) def test_ex_list_network_interfaces(self): interfaces = self.driver.ex_list_network_interfaces() self.assertEqual(len(interfaces), 2) self.assertEqual('eni-18e6c05e', interfaces[0].id) self.assertEqual('in-use', interfaces[0].state) self.assertEqual('0e:6e:df:72:78:af', interfaces[0].extra['mac_address']) self.assertEqual('eni-83e3c5c5', interfaces[1].id) self.assertEqual('in-use', interfaces[1].state) self.assertEqual('0e:93:0b:e9:e9:c4', interfaces[1].extra['mac_address']) def test_ex_create_network_interface(self): subnet = self.driver.ex_list_subnets()[0] interface = self.driver.ex_create_network_interface( subnet, name='Test Interface', description='My Test') self.assertEqual('eni-2b36086d', interface.id) self.assertEqual('pending', interface.state) self.assertEqual('0e:bd:49:3e:11:74', interface.extra['mac_address']) def test_ex_delete_network_interface(self): interface = self.driver.ex_list_network_interfaces()[0] resp = self.driver.ex_delete_network_interface(interface) self.assertTrue(resp) def test_ex_attach_network_interface_to_node(self): node = self.driver.list_nodes()[0] interface = self.driver.ex_list_network_interfaces()[0] resp = self.driver.ex_attach_network_interface_to_node(interface, node, 1) self.assertTrue(resp) def test_ex_detach_network_interface(self): resp = self.driver.ex_detach_network_interface('eni-attach-2b588b47') self.assertTrue(resp) def test_ex_list_internet_gateways(self): gateways = self.driver.ex_list_internet_gateways() self.assertEqual(len(gateways), 2) self.assertEqual('igw-84dd3ae1', gateways[0].id) self.assertEqual('igw-7fdae215', gateways[1].id) self.assertEqual('available', gateways[1].state) self.assertEqual('vpc-62cad41e', gateways[1].vpc_id) def test_ex_create_internet_gateway(self): gateway = self.driver.ex_create_internet_gateway() self.assertEqual('igw-13ac2b36', gateway.id) def test_ex_delete_internet_gateway(self): gateway = self.driver.ex_list_internet_gateways()[0] resp = self.driver.ex_delete_internet_gateway(gateway) self.assertTrue(resp) def test_ex_attach_internet_gateway(self): gateway = self.driver.ex_list_internet_gateways()[0] network = self.driver.ex_list_networks()[0] resp = self.driver.ex_attach_internet_gateway(gateway, network) self.assertTrue(resp) def test_ex_detach_internet_gateway(self): gateway = self.driver.ex_list_internet_gateways()[0] network = self.driver.ex_list_networks()[0] resp = self.driver.ex_detach_internet_gateway(gateway, network) self.assertTrue(resp) def test_ex_modify_volume(self): volume = self.driver.list_volumes()[0] assert volume.id == 'vol-10ae5e2b' params = {'VolumeType': 'io1', 'Size': 2, 'Iops': 1000} volume_modification = self.driver.ex_modify_volume(volume, params) self.assertIsNone(volume_modification.end_time) self.assertEqual('modifying', volume_modification.modification_state) self.assertEqual(300, volume_modification.original_iops) self.assertEqual(1, volume_modification.original_size) self.assertEqual('gp2', volume_modification.original_volume_type) self.assertEqual(0, volume_modification.progress) self.assertIsNone(volume_modification.status_message) self.assertEqual(1000, volume_modification.target_iops) self.assertEqual(2, volume_modification.target_size) self.assertEqual('io1', volume_modification.target_volume_type) self.assertEqual('vol-10ae5e2b', volume_modification.volume_id) def test_ex_describe_volumes_modifications(self): modifications = self.driver.ex_describe_volumes_modifications() self.assertEqual(len(modifications), 2) self.assertIsNone(modifications[0].end_time) self.assertEqual('optimizing', modifications[0].modification_state) self.assertEqual(100, modifications[0].original_iops) self.assertEqual(10, modifications[0].original_size) self.assertEqual('gp2', modifications[0].original_volume_type) self.assertEqual(3, modifications[0].progress) self.assertIsNone(modifications[0].status_message) self.assertEqual(10000, modifications[0].target_iops) self.assertEqual(2000, modifications[0].target_size) self.assertEqual('io1', modifications[0].target_volume_type) self.assertEqual('vol-06397e7a0eEXAMPLE', modifications[0].volume_id) self.assertEqual('completed', modifications[1].modification_state) self.assertEqual(100, modifications[1].original_iops) self.assertEqual(8, modifications[1].original_size) self.assertEqual('gp2', modifications[1].original_volume_type) self.assertEqual(100, modifications[1].progress) self.assertIsNone(modifications[1].status_message) self.assertEqual(10000, modifications[1].target_iops) self.assertEqual(200, modifications[1].target_size) self.assertEqual('io1', modifications[1].target_volume_type) self.assertEqual('vol-bEXAMPLE', modifications[1].volume_id) def test_params_is_not_simple_type_exception_is_thrown(self): params = { 'not': {'not': ['simple']} } expected_msg = 'dictionary contains an attribute "not" which value' self.assertRaisesRegexp(ValueError, expected_msg, self.driver.connection.request, '/', params=params) params = { 'invalid': [1, 2, 3] } expected_msg = 'dictionary contains an attribute "invalid" which value' self.assertRaisesRegexp(ValueError, expected_msg, self.driver.connection.request, '/', params=params) class EC2USWest1Tests(EC2Tests): region = 'us-west-1' class EC2USWest2Tests(EC2Tests): region = 'us-west-2' class EC2EUWestTests(EC2Tests): region = 'eu-west-1' class EC2APSE1Tests(EC2Tests): region = 'ap-southeast-1' class EC2APNETests(EC2Tests): region = 'ap-northeast-1' class EC2APSE2Tests(EC2Tests): region = 'ap-southeast-2' class EC2SAEastTests(EC2Tests): region = 'sa-east-1' class EC2MockHttp(MockHttp): fixtures = ComputeFileFixtures('ec2') def _DescribeInstances(self, method, url, body, headers): body = self.fixtures.load('describe_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeReservedInstances(self, method, url, body, headers): body = self.fixtures.load('describe_reserved_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeAvailabilityZones(self, method, url, body, headers): body = self.fixtures.load('describe_availability_zones.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _RebootInstances(self, method, url, body, headers): body = self.fixtures.load('reboot_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _StartInstances(self, method, url, body, headers): body = self.fixtures.load('start_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _StopInstances(self, method, url, body, headers): body = self.fixtures.load('stop_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeSecurityGroups(self, method, url, body, headers): body = self.fixtures.load('describe_security_groups.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteSecurityGroup(self, method, url, body, headers): body = self.fixtures.load('delete_security_group.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _AuthorizeSecurityGroupIngress(self, method, url, body, headers): body = self.fixtures.load('authorize_security_group_ingress.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeImages(self, method, url, body, headers): body = self.fixtures.load('describe_images.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _RegisterImages(self, method, url, body, headers): body = self.fixtures.load('register_image.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ImportSnapshot(self, method, url, body, headers): body = self.fixtures.load('import_snapshot.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeImportSnapshotTasks(self, method, url, body, headers): body = self.fixtures.load('describe_import_snapshot_tasks.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _timeout_DescribeImportSnapshotTasks(self, method, url, body, headers): body = self.fixtures.load('describe_import_snapshot_tasks_active.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ex_imageids_DescribeImages(self, method, url, body, headers): body = self.fixtures.load('describe_images_ex_imageids.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _RunInstances(self, method, url, body, headers): body = self.fixtures.load('run_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _create_ex_assign_public_ip_RunInstances(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, { 'NetworkInterface.1.AssociatePublicIpAddress': "true", 'NetworkInterface.1.DeleteOnTermination': "true", 'NetworkInterface.1.DeviceIndex': "0", 'NetworkInterface.1.SubnetId': "subnet-11111111", 'NetworkInterface.1.SecurityGroupId.1': "sg-11111111", }) body = self.fixtures.load('run_instances_with_subnet_and_security_group.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _create_ex_terminate_on_shutdown_RunInstances(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, { 'InstanceInitiatedShutdownBehavior': 'terminate' }) body = self.fixtures.load('run_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ex_security_groups_RunInstances(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, {'SecurityGroup.1': 'group1'}) self.assertUrlContainsQueryParams(url, {'SecurityGroup.2': 'group2'}) body = self.fixtures.load('run_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ex_security_group_ids_RunInstances(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, {'SecurityGroupId.1': 'sg-1aa11a1a'}) self.assertUrlContainsQueryParams(url, {'SecurityGroupId.2': 'sg-2bb22b2b'}) body = self.fixtures.load('run_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _create_ex_blockdevicemappings_RunInstances(self, method, url, body, headers): expected_params = { 'BlockDeviceMapping.1.DeviceName': '/dev/sda1', 'BlockDeviceMapping.1.Ebs.VolumeSize': '10', 'BlockDeviceMapping.2.DeviceName': '/dev/sdb', 'BlockDeviceMapping.2.VirtualName': 'ephemeral0', 'BlockDeviceMapping.3.DeviceName': '/dev/sdc', 'BlockDeviceMapping.3.VirtualName': 'ephemeral1' } self.assertUrlContainsQueryParams(url, expected_params) body = self.fixtures.load('run_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _idempotent_RunInstances(self, method, url, body, headers): body = self.fixtures.load('run_instances_idem.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _idempotent_mismatch_RunInstances(self, method, url, body, headers): body = self.fixtures.load('run_instances_idem_mismatch.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.BAD_REQUEST]) def _ex_iam_profile_RunInstances(self, method, url, body, headers): body = self.fixtures.load('run_instances_iam_profile.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _TerminateInstances(self, method, url, body, headers): body = self.fixtures.load('terminate_instances.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeKeyPairs(self, method, url, body, headers): body = self.fixtures.load('describe_key_pairs.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _get_one_DescribeKeyPairs(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, {'KeyName': 'gsg-keypair'}) body = self.fixtures.load('describe_key_pairs.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _doesnt_exist_DescribeKeyPairs(self, method, url, body, headers): body = self.fixtures.load('describe_key_pairs_doesnt_exist.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.BAD_REQUEST]) def _CreateKeyPair(self, method, url, body, headers): body = self.fixtures.load('create_key_pair.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ImportKeyPair(self, method, url, body, headers): body = self.fixtures.load('import_key_pair.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeTags(self, method, url, body, headers): body = self.fixtures.load('describe_tags.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateTags(self, method, url, body, headers): body = self.fixtures.load('create_tags.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteTags(self, method, url, body, headers): body = self.fixtures.load('delete_tags.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeAddresses(self, method, url, body, headers): body = self.fixtures.load('describe_addresses_multi.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _AllocateAddress(self, method, url, body, headers): body = self.fixtures.load('allocate_address.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _vpc_AllocateAddress(self, method, url, body, headers): body = self.fixtures.load('allocate_vpc_address.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _AssociateAddress(self, method, url, body, headers): body = self.fixtures.load('associate_address.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _vpc_AssociateAddress(self, method, url, body, headers): body = self.fixtures.load('associate_vpc_address.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DisassociateAddress(self, method, url, body, headers): body = self.fixtures.load('disassociate_address.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ReleaseAddress(self, method, url, body, headers): body = self.fixtures.load('release_address.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _all_addresses_DescribeAddresses(self, method, url, body, headers): body = self.fixtures.load('describe_addresses_all.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _WITH_TAGS_DescribeAddresses(self, method, url, body, headers): body = self.fixtures.load('describe_addresses_multi.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ModifyInstanceAttribute(self, method, url, body, headers): body = self.fixtures.load('modify_instance_attribute.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ModifySnapshotAttribute(self, method, url, body, headers): body = self.fixtures.load('modify_snapshot_attribute.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateVolume(self, method, url, body, headers): if 'KmsKeyId=' in url: assert 'Encrypted=1' in url, "If a KmsKeyId is specified, the " \ "Encrypted flag must also be set." if 'Encrypted=1' in url: body = self.fixtures.load('create_encrypted_volume.xml') else: body = self.fixtures.load('create_volume.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteVolume(self, method, url, body, headers): body = self.fixtures.load('delete_volume.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _AttachVolume(self, method, url, body, headers): body = self.fixtures.load('attach_volume.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DetachVolume(self, method, url, body, headers): body = self.fixtures.load('detach_volume.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeVolumes(self, method, url, body, headers): body = self.fixtures.load('describe_volumes.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _filters_nodes_DescribeVolumes(self, method, url, body, headers): expected_params = { 'Filter.1.Name': 'attachment.instance-id', 'Filter.1.Value.1': 'i-d334b4b3', } self.assertUrlContainsQueryParams(url, expected_params) body = self.fixtures.load('describe_volumes.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _filters_status_DescribeVolumes(self, method, url, body, headers): expected_params = { 'Filter.1.Name': 'status', 'Filter.1.Value.1': 'available' } self.assertUrlContainsQueryParams(url, expected_params) body = self.fixtures.load('describe_volumes.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateSnapshot(self, method, url, body, headers): body = self.fixtures.load('create_snapshot.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeSnapshots(self, method, url, body, headers): body = self.fixtures.load('describe_snapshots.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteSnapshot(self, method, url, body, headers): body = self.fixtures.load('delete_snapshot.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CopyImage(self, method, url, body, headers): body = self.fixtures.load('copy_image.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateImage(self, method, url, body, headers): body = self.fixtures.load('create_image.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeregisterImage(self, method, url, body, headers): body = self.fixtures.load('deregister_image.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteKeyPair(self, method, url, body, headers): self.assertUrlContainsQueryParams(url, {'KeyName': 'gsg-keypair'}) body = self.fixtures.load('delete_key_pair.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ModifyImageAttribute(self, method, url, body, headers): body = self.fixtures.load('modify_image_attribute.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeAccountAttributes(self, method, url, body, headers): body = self.fixtures.load('describe_account_attributes.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateSecurityGroup(self, method, url, body, headers): body = self.fixtures.load('create_security_group.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeVpcs(self, method, url, body, headers): body = self.fixtures.load('describe_vpcs.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _network_ids_DescribeVpcs(self, method, url, body, headers): expected_params = { 'VpcId.1': 'vpc-532335e1' } self.assertUrlContainsQueryParams(url, expected_params) body = self.fixtures.load('describe_vpcs.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _filters_DescribeVpcs(self, method, url, body, headers): expected_params = { 'Filter.1.Name': 'dhcp-options-id', 'Filter.1.Value.1': 'dopt-7eded312', 'Filter.2.Name': 'cidr', 'Filter.2.Value.1': '192.168.51.0/24' } self.assertUrlContainsQueryParams(url, expected_params) body = self.fixtures.load('describe_vpcs.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateVpc(self, method, url, body, headers): body = self.fixtures.load('create_vpc.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteVpc(self, method, url, body, headers): body = self.fixtures.load('delete_vpc.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeSubnets(self, method, url, body, headers): body = self.fixtures.load('describe_subnets.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateSubnet(self, method, url, body, headers): body = self.fixtures.load('create_subnet.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ModifySubnetAttribute(self, method, url, body, headers): body = self.fixtures.load('modify_subnet_attribute.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteSubnet(self, method, url, body, headers): body = self.fixtures.load('delete_subnet.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _GetConsoleOutput(self, method, url, body, headers): body = self.fixtures.load('get_console_output.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeNetworkInterfaces(self, method, url, body, headers): body = self.fixtures.load('describe_network_interfaces.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateNetworkInterface(self, method, url, body, headers): body = self.fixtures.load('create_network_interface.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteNetworkInterface(self, method, url, body, headers): body = self.fixtures.load('delete_network_interface.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _AttachNetworkInterface(self, method, url, body, headers): body = self.fixtures.load('attach_network_interface.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DetachNetworkInterface(self, method, url, body, headers): body = self.fixtures.load('detach_network_interface.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeInternetGateways(self, method, url, body, headers): body = self.fixtures.load('describe_internet_gateways.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateInternetGateway(self, method, url, body, headers): body = self.fixtures.load('create_internet_gateway.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteInternetGateway(self, method, url, body, headers): body = self.fixtures.load('delete_internet_gateway.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _AttachInternetGateway(self, method, url, body, headers): body = self.fixtures.load('attach_internet_gateway.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DetachInternetGateway(self, method, url, body, headers): body = self.fixtures.load('detach_internet_gateway.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreatePlacementGroup(self, method, url, body, headers): body = self.fixtures.load('create_placement_groups.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeletePlacementGroup(self, method, url, body, headers): body = self.fixtures.load('delete_placement_groups.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribePlacementGroups(self, method, url, body, headers): body = self.fixtures.load('describe_placement_groups.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ModifyVolume(self, method, url, body, headers): body = self.fixtures.load('modify_volume.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeVolumesModifications(self, method, url, body, headers): body = self.fixtures.load('describe_volumes_modifications.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class EucMockHttp(EC2MockHttp): fixtures = ComputeFileFixtures('ec2') def _services_Eucalyptus_DescribeInstances(self, method, url, body, headers): return self._DescribeInstances(method, url, body, headers) def _services_Eucalyptus_DescribeImages(self, method, url, body, headers): return self._DescribeImages(method, url, body, headers) def _services_Eucalyptus_DescribeAddresses(self, method, url, body, headers): return self._DescribeAddresses(method, url, body, headers) def _services_Eucalyptus_RebootInstances(self, method, url, body, headers): return self._RebootInstances(method, url, body, headers) def _services_Eucalyptus_TerminateInstances(self, method, url, body, headers): return self._TerminateInstances(method, url, body, headers) def _services_Eucalyptus_RunInstances(self, method, url, body, headers): return self._RunInstances(method, url, body, headers) def _services_Eucalyptus_DescribeInstanceTypes(self, method, url, body, headers): body = self.fixtures.load('describe_instance_types.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class NimbusTests(EC2Tests): def setUp(self): NimbusNodeDriver.connectionCls.conn_class = EC2MockHttp EC2MockHttp.use_param = 'Action' EC2MockHttp.type = None self.driver = NimbusNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1], host='some.nimbuscloud.com') def test_ex_describe_addresses_for_node(self): # overridden from EC2Tests -- Nimbus doesn't support elastic IPs. node = Node('i-4382922a', None, None, None, None, self.driver) ip_addresses = self.driver.ex_describe_addresses_for_node(node) self.assertEqual(len(ip_addresses), 0) def test_ex_describe_addresses(self): # overridden from EC2Tests -- Nimbus doesn't support elastic IPs. node = Node('i-4382922a', None, None, None, None, self.driver) nodes_elastic_ips = self.driver.ex_describe_addresses([node]) self.assertEqual(len(nodes_elastic_ips), 1) self.assertEqual(len(nodes_elastic_ips[node.id]), 0) def test_list_sizes(self): sizes = self.driver.list_sizes() ids = [s.id for s in sizes] self.assertTrue('m1.small' in ids) self.assertTrue('m1.large' in ids) self.assertTrue('m1.xlarge' in ids) def test_list_nodes(self): # overridden from EC2Tests -- Nimbus doesn't support elastic IPs. node = self.driver.list_nodes()[0] self.assertExecutedMethodCount(0) public_ips = node.public_ips self.assertEqual(node.id, 'i-4382922a') self.assertEqual(len(node.public_ips), 1) self.assertEqual(public_ips[0], '1.2.3.4') self.assertEqual(node.extra['tags'], {}) node = self.driver.list_nodes()[1] self.assertExecutedMethodCount(0) public_ips = node.public_ips self.assertEqual(node.id, 'i-8474834a') self.assertEqual(len(node.public_ips), 1) self.assertEqual(public_ips[0], '1.2.3.5') self.assertEqual(node.extra['tags'], {'Name': 'Test Server 2', 'Group': 'VPC Test'}) def test_ex_create_tags(self): # Nimbus doesn't support creating tags so this one should be a # passthrough node = self.driver.list_nodes()[0] self.driver.ex_create_tags(resource=node, tags={'foo': 'bar'}) self.assertExecutedMethodCount(0) def test_create_volume_snapshot_with_tags(self): vol = StorageVolume(id='vol-4282672b', name='test', state=StorageVolumeState.AVAILABLE, size=10, driver=self.driver) snap = self.driver.create_volume_snapshot( vol, 'Test snapshot', ex_metadata={'my_tag': 'test'}) self.assertDictEqual({}, snap.extra['tags']) class EucTests(LibcloudTestCase, TestCaseMixin): def setUp(self): EucNodeDriver.connectionCls.conn_class = EucMockHttp EC2MockHttp.use_param = 'Action' EC2MockHttp.type = None self.driver = EucNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1], host='some.eucalyptus.com', api_version='3.4.1') def test_list_locations_response(self): try: self.driver.list_locations() except Exception: pass else: self.fail('Exception was not thrown') def test_list_location(self): pass def test_list_sizes(self): sizes = self.driver.list_sizes() ids = [s.id for s in sizes] self.assertEqual(len(ids), 18) self.assertTrue('t1.micro' in ids) self.assertTrue('m1.medium' in ids) self.assertTrue('m3.xlarge' in ids) class OutscaleTests(EC2Tests): def setUp(self): OutscaleSASNodeDriver.connectionCls.conn_class = EC2MockHttp EC2MockHttp.use_param = 'Action' EC2MockHttp.type = None self.driver = OutscaleSASNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1], host='some.outscalecloud.com') def test_ex_create_network(self): # overridden from EC2Tests -- Outscale don't support instance_tenancy vpc = self.driver.ex_create_network('192.168.55.0/24', name='Test VPC') self.assertEqual('vpc-ad3527cf', vpc.id) self.assertEqual('192.168.55.0/24', vpc.cidr_block) self.assertEqual('pending', vpc.extra['state']) def test_ex_copy_image(self): # overridden from EC2Tests -- Outscale does not support copying images image = self.driver.list_images()[0] try: self.driver.ex_copy_image('us-east-1', image, name='Faux Image', description='Test Image Copy') except NotImplementedError: pass else: self.fail('Exception was not thrown') def test_ex_get_limits(self): # overridden from EC2Tests -- Outscale does not support getting limits try: self.driver.ex_get_limits() except NotImplementedError: pass else: self.fail('Exception was not thrown') def test_ex_create_network_interface(self): # overridden from EC2Tests -- Outscale don't allow creating interfaces subnet = self.driver.ex_list_subnets()[0] try: self.driver.ex_create_network_interface( subnet, name='Test Interface', description='My Test') except NotImplementedError: pass else: self.fail('Exception was not thrown') def test_ex_delete_network_interface(self): # overridden from EC2Tests -- Outscale don't allow deleting interfaces interface = self.driver.ex_list_network_interfaces()[0] try: self.driver.ex_delete_network_interface(interface) except NotImplementedError: pass else: self.fail('Exception was not thrown') def test_ex_attach_network_interface_to_node(self): # overridden from EC2Tests -- Outscale don't allow attaching interfaces node = self.driver.list_nodes()[0] interface = self.driver.ex_list_network_interfaces()[0] try: self.driver.ex_attach_network_interface_to_node(interface, node, 1) except NotImplementedError: pass else: self.fail('Exception was not thrown') def test_ex_detach_network_interface(self): # overridden from EC2Tests -- Outscale don't allow detaching interfaces try: self.driver.ex_detach_network_interface('eni-attach-2b588b47') except NotImplementedError: pass else: self.fail('Exception was not thrown') def test_list_sizes(self): sizes = self.driver.list_sizes() ids = [s.id for s in sizes] self.assertTrue('m1.small' in ids) self.assertTrue('m1.large' in ids) self.assertTrue('m1.xlarge' in ids) def test_ex_create_node_with_ex_iam_profile(self): image = NodeImage(id='ami-be3adfd7', name=self.image_name, driver=self.driver) size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver) self.assertRaises(NotImplementedError, self.driver.create_node, name='foo', image=image, size=size, ex_iamprofile='foo') class FCUMockHttp(EC2MockHttp): fixtures = ComputeFileFixtures('fcu') def _DescribeQuotas(self, method, url, body, headers): body = self.fixtures.load('ex_describe_quotas.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeProductTypes(self, method, url, body, headers): body = self.fixtures.load('ex_describe_product_types.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeInstanceTypes(self, method, url, body, headers): body = self.fixtures.load('ex_describe_instance_types.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _GetProductType(self, method, url, body, headers): body = self.fixtures.load('ex_get_product_type.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ModifyInstanceKeypair(self, method, url, body, headers): body = self.fixtures.load('ex_modify_instance_keypair.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class OutscaleFCUTests(LibcloudTestCase): def setUp(self): OutscaleSASNodeDriver.connectionCls.conn_class = FCUMockHttp EC2MockHttp.use_param = 'Action' EC2MockHttp.type = None self.driver = OutscaleSASNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1], host='some.fcucloud.com') def test_ex_describe_quotas(self): is_truncated, quota = self.driver.ex_describe_quotas() self.assertTrue(is_truncated == 'true') self.assertTrue('global' in quota.keys()) self.assertTrue('vpc-00000000' in quota.keys()) def test_ex_describe_product_types(self): product_types = self.driver.ex_describe_product_types() pt = {} for e in product_types: pt[e['productTypeId']] = e['description'] self.assertTrue('0001' in pt.keys()) self.assertTrue('MapR' in pt.values()) self.assertTrue(pt['0002'] == 'Windows') def test_ex_describe_instance_instance_types(self): instance_types = self.driver.ex_describe_instance_types() it = {} for e in instance_types: it[e['name']] = e['memory'] self.assertTrue('og4.4xlarge' in it.keys()) self.assertTrue('oc2.8xlarge' in it.keys()) self.assertTrue('68718428160' in it.values()) self.assertTrue(it['m3.large'] == '8050966528') def test_ex_get_product_type(self): product_type = self.driver.ex_get_product_type('ami-29ab9e54') self.assertTrue(product_type['productTypeId'] == '0002') self.assertTrue(product_type['description'] == 'Windows') def test_ex_modify_instance_keypair(self): r = self.driver.ex_modify_instance_keypair('i-57292bc5', 'key_name') self.assertTrue(r) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_ecp.py0000664000175000017500000001176713535474530023060 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.ecp import ECPNodeDriver from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import ECP_PARAMS class ECPTests(unittest.TestCase, TestCaseMixin): def setUp(self): ECPNodeDriver.connectionCls.conn_class = ECPMockHttp self.driver = ECPNodeDriver(*ECP_PARAMS, host='dummy') def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) node = nodes[0] self.assertEqual(node.id, '1') self.assertEqual(node.name, 'dummy-1') self.assertEqual(node.public_ips[0], "42.78.124.75") self.assertEqual(node.state, NodeState.RUNNING) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 3) size = sizes[0] self.assertEqual(size.id, '1') self.assertEqual(size.ram, 512) self.assertEqual(size.disk, 0) self.assertEqual(size.bandwidth, 0) self.assertEqual(size.price, 0) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 2) self.assertEqual( images[0].name, "centos54: AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2") self.assertEqual(images[0].id, "1") name = "centos54 two: AUTO import from /opt/enomalism2/repo/5d407a68-c76c-11de-86e5-000475cb7577.xvm2" self.assertEqual(images[1].name, name) self.assertEqual(images[1].id, "2") def test_reboot_node(self): # Raises exception on failure node = self.driver.list_nodes()[0] self.driver.reboot_node(node) def test_destroy_node(self): # Raises exception on failure node = self.driver.list_nodes()[0] self.driver.destroy_node(node) def test_create_node(self): # Raises exception on failure size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node( name="api.ivan.net.nz", image=image, size=size) self.assertEqual(node.name, "api.ivan.net.nz") self.assertEqual(node.id, "1234") class ECPMockHttp(MockHttp): fixtures = ComputeFileFixtures('ecp') def _modules_hosting(self, method, url, body, headers): headers = {} headers['set-cookie'] = 'vcloud-token=testtoken' body = 'Anything' return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _rest_hosting_vm_1(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('vm_1_get.json') if method == 'POST': if body.find('delete', 0): body = self.fixtures.load('vm_1_action_delete.json') if body.find('stop', 0): body = self.fixtures.load('vm_1_action_stop.json') if body.find('start', 0): body = self.fixtures.load('vm_1_action_start.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_hosting_vm(self, method, url, body, headers): if method == 'PUT': body = self.fixtures.load('vm_put.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_hosting_vm_list(self, method, url, body, headers): body = self.fixtures.load('vm_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_hosting_htemplate_list(self, method, url, body, headers): body = self.fixtures.load('htemplate_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_hosting_network_list(self, method, url, body, headers): body = self.fixtures.load('network_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_hosting_ptemplate_list(self, method, url, body, headers): body = self.fixtures.load('ptemplate_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_ecs.py0000664000175000017500000013523213535474530023055 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import unicode_literals import sys import unittest from libcloud.common.types import LibcloudError from libcloud.compute.base import Node, NodeAuthPassword, NodeImage, \ NodeLocation, NodeSize, StorageVolume, VolumeSnapshot from libcloud.compute.drivers.ecs import ECSDriver from libcloud.compute.types import NodeState, StorageVolumeState from libcloud.test import MockHttp, LibcloudTestCase from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import ECS_PARAMS from libcloud.utils.py3 import httplib class ECSDriverTestCase(LibcloudTestCase): region = 'cn-qingdao' zone = 'cn-qingdao-b' image_id = 'ubuntu1404_64_20G_aliaegis_20150325.vhd' def setUp(self): ECSMockHttp.test = self ECSDriver.connectionCls.conn_class = ECSMockHttp ECSMockHttp.use_param = 'Action' ECSMockHttp.type = None self.driver = ECSDriver(*ECS_PARAMS, region=self.region) self.fake_size = NodeSize('ecs.t1.small', 'ecs t1 small', None, None, None, None, self.driver) self.fake_image = NodeImage(self.image_id, name='ubuntu 14.04 64bit', driver=self.driver) self.fake_node = Node(id='fake-node1', name='fake-node', state=NodeState.RUNNING, public_ips=None, private_ips=None, driver=self.driver) self.fake_volume = StorageVolume(id='fake-volume1', name='fake-volume', size=self.fake_size, driver=self.driver) self.fake_snapshot = VolumeSnapshot(id='fake-snapshot1', driver=self.driver) self.fake_location = NodeLocation(id=self.region, name=self.region, country=None, driver=self.driver) self.fake_instance_id = 'fake_instance_id' self.fake_security_group_id = 'fake_security_group_id' def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertIsNotNone(nodes) self.assertEqual(1, len(nodes)) node = nodes[0] self.assertEqual('iZ28n7dkvovZ', node.name) self.assertEqual('i-28n7dkvov', node.id) self.assertEqual(NodeState.PENDING, node.state) self.assertEqual(1, len(node.public_ips)) self.assertEqual('114.215.124.73', node.public_ips[0]) self.assertEqual(1, len(node.private_ips)) self.assertEqual('10.163.197.74', node.private_ips[0]) expected_extra = { 'image_id': 'ubuntu1404_64_20G_aliaegis_20150325.vhd', 'description': '', 'instance_type_family': 'ecs.t1', 'zone_id': 'cn-qingdao-b', 'internet_charge_type': 'PayByTraffic', 'serial_number': 'ca0122d9-374d-4fce-9fc0-71f7c3eaf1c3', 'io_optimized': 'false', 'device_available': 'true', 'instance_network_type': 'classic', 'hostname': 'iZ28n7dkvovZ', 'instance_type': 'ecs.t1.small', 'creation_time': '2015-12-27T07:35Z', 'instance_charge_type': 'PostPaid', 'expired_time': '2999-09-08T16:00Z' } self._validate_extras(expected_extra, node.extra) vpc = { 'vpc_id': '', 'vswitch_id': '', 'private_ip_address': None, 'nat_ip_address': '' } self._validate_extras(vpc, node.extra['vpc_attributes']) eip_address = { 'allocation_id': '', 'ip_address': '', 'internet_charge_type': '', 'bandwidth': None } self._validate_extras(eip_address, node.extra['eip_address']) self.assertIsNone(node.extra['operation_locks']['lock_reason']) def test_list_nodes_with_ex_node_ids(self): ECSMockHttp.type = 'list_nodes_ex_node_ids' nodes = self.driver.list_nodes(ex_node_ids=['i-28n7dkvov', 'not-existed-id']) self.assertIsNotNone(nodes) def test_list_nodes_with_ex_filters(self): ECSMockHttp.type = 'list_nodes_ex_filters' nodes = self.driver.list_nodes(ex_filters={'ZoneId': self.zone}) self.assertIsNotNone(nodes) def _validate_extras(self, expected, actual): self.assertIsNotNone(actual) for key, value in iter(expected.items()): self.assertTrue(key in actual) self.assertEqual(value, actual[key], ('extra %(key)s not equal, ' 'expected: "%(expected)s", ' 'actual: "%(actual)s"' % {'key': key, 'expected': value, 'actual': actual[key]})) def test_create_node(self): ECSMockHttp.type = 'create_node' name = 'test_create_node' node = self.driver.create_node(name=name, image=self.fake_image, size=self.fake_size, ex_security_group_id='sg-28ou0f3xa', ex_description='description', ex_internet_charge_type='PayByTraffic', ex_internet_max_bandwidth_out=1, ex_internet_max_bandwidth_in=200, ex_hostname='hostname', auth=NodeAuthPassword('password'), ex_io_optimized=True, ex_system_disk={'category': 'cloud', 'disk_name': 'root', 'description': 'sys'}, ex_vswitch_id='vswitch-id1', ex_private_ip_address='1.1.1.2', ex_client_token='client_token') self.assertIsNotNone(node) def test_create_node_with_data_disk(self): ECSMockHttp.type = 'create_node_with_data' self.name = 'test_create_node' self.data_disk = { 'size': 5, 'category': self.driver.disk_categories.CLOUD, 'disk_name': 'data1', 'description': 'description', 'device': '/dev/xvdb', 'delete_with_instance': True} node = self.driver.create_node(name=self.name, image=self.fake_image, size=self.fake_size, ex_security_group_id='sg-28ou0f3xa', ex_data_disks=self.data_disk) self.assertIsNotNone(node) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(2, len(sizes)) size = sizes[0] self.assertEqual('ecs.t1.xsmall', size.id) self.assertEqual('ecs.t1.xsmall', size.name) self.assertEqual(0.5, size.ram) self.assertEqual(1, size.extra['cpu_core_count']) self.assertEqual('ecs.t1', size.extra['instance_type_family']) size = sizes[1] self.assertEqual('ecs.s2.small', size.id) self.assertEqual('ecs.s2.small', size.name) self.assertEqual(1.0, size.ram) self.assertEqual(2, size.extra['cpu_core_count']) self.assertEqual('ecs.s2', size.extra['instance_type_family']) def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(9, len(locations)) location = locations[0] self.assertEqual('ap-southeast-1', location.id) self.assertIsNone(location.country) def test_create_node_without_sg_id_exception(self): name = 'test_create_node_without_sg_id_exception' self.assertRaises(AttributeError, self.driver.create_node, name=name, image=self.fake_image, size=self.fake_size) def test_creat_node_paybytraffic_exception(self): name = 'test_create_node_paybytraffic_exception' self.assertRaises(AttributeError, self.driver.create_node, name=name, image=self.fake_image, size=self.fake_size, ex_security_group_id='sg-id1', ex_internet_charge_type='PayByTraffic') def test_create_node_ex_system_disk_exception(self): name = 'test_creat_node_ex_system_disk_exception' self.assertRaises(AttributeError, self.driver.create_node, name=name, image=self.fake_image, size=self.fake_size, ex_security_group_id='sg-id1', ex_system_disk=None) def test_create_node_ex_private_ip_address_exception(self): name = 'test_create_node_ex_private_ip_address_exception' self.assertRaises(AttributeError, self.driver.create_node, name=name, image=self.fake_image, size=self.fake_size, ex_security_group_id='sg-id1', ex_private_ip_address='1.1.1.2') def test_reboot_node(self): ECSMockHttp.type = 'reboot_node' result = self.driver.reboot_node(self.fake_node) self.assertTrue(result) def test_reboot_node_with_ex_force_stop(self): ECSMockHttp.type = 'reboot_node_force_stop' result = self.driver.reboot_node(self.fake_node, ex_force_stop=True) self.assertTrue(result) def test_destroy_node(self): ECSMockHttp.type = 'destroy_node' result = self.driver.destroy_node(self.fake_node) self.assertTrue(result) def test_ex_start_node(self): ECSMockHttp.type = 'start_node' result = self.driver.ex_start_node(self.fake_node) self.assertTrue(result) def test_ex_stop_node(self): ECSMockHttp.type = 'stop_node' result = self.driver.ex_stop_node(self.fake_node) self.assertTrue(result) def test_stop_node_with_ex_force_stop(self): ECSMockHttp.type = 'stop_node_force_stop' result = self.driver.ex_stop_node(self.fake_node, ex_force_stop=True) self.assertTrue(result) def test_create_public_ip(self): ECSMockHttp.type = 'create_public_ip' result = self.driver.create_public_ip(self.fake_instance_id) self.assertTrue(result) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(2, len(volumes)) volume = volumes[0] self.assertEqual('d-28m5zbua0', volume.id) self.assertEqual('', volume.name) self.assertEqual(5, volume.size) self.assertEqual(StorageVolumeState.AVAILABLE, volume.state) expected_extras = { 'region_id': 'cn-qingdao', 'zone_id': 'cn-qingdao-b', 'description': '', 'type': 'data', 'category': 'cloud', 'image_id': '', 'source_snapshot_id': '', 'product_code': '', 'portable': True, 'instance_id': '', 'device': '', 'delete_with_instance': False, 'enable_auto_snapshot': False, 'creation_time': '2014-07-23T02:44:07Z', 'attached_time': '2014-07-23T07:47:35Z', 'detached_time': '2014-07-23T08:28:48Z', 'disk_charge_type': 'PostPaid', 'operation_locks': {'lock_reason': None} } self._validate_extras(expected_extras, volume.extra) volume = volumes[1] self.assertEqual('d-28zfrmo13', volume.id) self.assertEqual('ubuntu1404sys', volume.name) self.assertEqual(5, volume.size) self.assertEqual(StorageVolumeState.INUSE, volume.state) expected_extras = { 'region_id': 'cn-qingdao', 'zone_id': 'cn-qingdao-b', 'description': 'Description', 'type': 'system', 'category': 'cloud', 'image_id': 'ubuntu1404_64_20G_aliaegis_20150325.vhd', 'source_snapshot_id': '', 'product_code': '', 'portable': False, 'instance_id': 'i-28whl2nj2', 'device': '/dev/xvda', 'delete_with_instance': True, 'enable_auto_snapshot': True, 'creation_time': '2014-07-23T02:44:06Z', 'attached_time': '2016-01-04T15:02:17Z', 'detached_time': '', 'disk_charge_type': 'PostPaid', 'operation_locks': {'lock_reason': None} } self._validate_extras(expected_extras, volume.extra) def test_list_volumes_with_ex_volume_ids(self): ECSMockHttp.type = 'list_volumes_ex_volume_ids' volumes = self.driver.list_volumes(ex_volume_ids=['i-28n7dkvov', 'not-existed-id']) self.assertIsNotNone(volumes) def test_list_volumes_with_ex_filters(self): ECSMockHttp.type = 'list_volumes_ex_filters' ex_filters = {'InstanceId': self.fake_node.id} volumes = self.driver.list_volumes(ex_filters=ex_filters) self.assertIsNotNone(volumes) def test_list_volume_snapshots(self): snapshots = self.driver.list_volume_snapshots(self.fake_volume) self.assertEqual(1, len(snapshots)) def test_list_volume_snapshots_with_ex_snapshot_ids(self): ECSMockHttp.type = 'list_volume_snapshots_ex_snapshot_ids' ex_snapshot_ids = ['fake-snapshot1'] self.driver.list_volume_snapshots(self.fake_volume, ex_snapshot_ids=ex_snapshot_ids) def test_list_volume_snapshots_with_ex_filters(self): ECSMockHttp.type = 'list_volume_snapshots_ex_filters' ex_filters = {'InstanceId': self.fake_node.id} self.driver.list_volume_snapshots(self.fake_volume, ex_filters=ex_filters) def test_create_volume(self): ECSMockHttp.type = 'create_volume' self.volume_size = 1 self.volume_name = 'fake-volume-name' self.description = 'fake-description' self.disk_category = 'system' self.client_token = 'client_token' volume = self.driver.create_volume(self.volume_size, self.volume_name, snapshot=self.fake_snapshot, ex_zone_id=self.zone, ex_description=self.description, ex_disk_category=self.disk_category, ex_client_token=self.client_token) self.assertIsNotNone(volume) def test_create_volume_without_ex_zone_id_exception(self): self.assertRaises(AttributeError, self.driver.create_volume, 1, 'fake-volume-name') def test_create_volume_snapshot(self): ECSMockHttp.type = 'create_volume_snapshot' self.snapshot_name = 'fake-snapshot1' self.description = 'fake-description' self.client_token = 'client-token' snapshot = self.driver.create_volume_snapshot( self.fake_volume, name=self.snapshot_name, ex_description=self.description, ex_client_token=self.client_token) self.assertIsNotNone(snapshot) def test_attach_volume(self): self.device = '/dev/sdb' self.delete_with_instance = True attached = self.driver.attach_volume( self.fake_node, self.fake_volume, device=self.device, ex_delete_with_instance=self.delete_with_instance) self.assertTrue(attached) def test_detach_volume(self): self.instance_id = 'fake-node1' result = self.driver.detach_volume(self.fake_volume, ex_instance_id=self.instance_id) self.assertTrue(result) def test_detach_volume_query_instance_id(self): ECSMockHttp.type = 'detach_volume' result = self.driver.detach_volume(self.fake_volume) self.assertTrue(result) def test_detach_volume_query_instance_id_exception(self): self.assertRaises(AttributeError, self.driver.detach_volume, self.fake_volume) def test_destroy_volume(self): ECSMockHttp.type = 'destroy_volume' result = self.driver.destroy_volume(self.fake_volume) self.assertTrue(result) def test_destroy_volume_query_volumes_exception(self): self.assertRaises(LibcloudError, self.driver.destroy_volume, self.fake_volume) def test_destroy_volume_state_exception(self): ECSMockHttp.type = 'destroy_volume_state' self.assertRaises(LibcloudError, self.driver.destroy_volume, self.fake_volume) def test_destroy_volume_snapshot(self): result = self.driver.destroy_volume_snapshot(self.fake_snapshot) self.assertTrue(result) def test_destroy_volume_snapshot_exception(self): self.assertRaises(AttributeError, self.driver.destroy_volume_snapshot, self.fake_volume) def test_list_images(self): images = self.driver.list_images(self.fake_location) self.assertEqual(1, len(images)) image = images[0] self.assertEqual('freebsd1001_64_20G_aliaegis_20150527.vhd', image.id) self.assertEqual('freebsd1001_64_20G_aliaegis_20150527.vhd', image.name) expected_extra = { 'image_version': '1.0.0', 'os_type': 'linux', 'platform': 'Freebsd', 'architecture': 'x86_64', 'description': 'freebsd1001_64_20G_aliaegis_20150527.vhd', 'size': 20, 'image_owner_alias': 'system', 'os_name': 'FreeBSD 10.1 64位', 'product_code': '', 'is_subscribed': False, 'progress': '100%', 'creation_time': '2015-06-19T07:25:42Z', 'usage': 'instance', 'is_copied': False } self._validate_extras(expected_extra, image.extra) expected_dev_mappings = { 'snapshot_id': '', 'size': 20, 'device': '/dev/xvda', 'format': '', 'import_oss_bucket': '', 'import_oss_object': '' } self._validate_extras(expected_dev_mappings, image.extra['disk_device_mappings']) def test_list_images_with_ex_image_ids(self): ECSMockHttp.type = 'list_images_ex_image_ids' self.driver.list_images(location=self.fake_location, ex_image_ids=[self.fake_image.id, 'not-existed']) def test_list_images_with_ex_image_ids_type_exception(self): self.assertRaises(AttributeError, self.driver.list_images, location=self.fake_location, ex_image_ids={'image_ids': 'id1,id2'}) def test_list_images_with_ex_filters(self): ECSMockHttp.type = 'list_images_ex_filters' ex_filters = {'Status': 'Available'} self.driver.list_images(location=self.fake_location, ex_filters=ex_filters) def test_list_images_multiple_pages(self): ECSMockHttp.type = 'list_images_pages' images = self.driver.list_images() self.assertEqual(2, len(images)) def test_create_image(self): self.image_name = 'fake-image1' self.description = 'description' self.image_version = '1.0.0' self.client_token = 'client_token' image = self.driver.create_image(None, self.image_name, self.description, ex_snapshot_id=self.fake_snapshot.id, ex_image_version=self.image_version, ex_client_token=self.client_token) self.assertIsNotNone(image) def test_creaet_image_exception(self): self.assertRaises(AttributeError, self.driver.create_image, None, None) def test_delete_image(self): result = self.driver.delete_image(self.fake_image) self.assertTrue(result) def test_get_image(self): ECSMockHttp.type = 'get_image' image = self.driver.get_image(self.fake_image.id) self.assertIsNotNone(image) def test_get_image_not_found_exception(self): ECSMockHttp.type = 'get_image_not_found' self.assertRaises(LibcloudError, self.driver.get_image, self.fake_image.id) def test_copy_image(self): self.image_name = 'copied-image1' self.description = 'description' self.dest_region = 'cn-hangzhou' self.client_token = 'client-token' image = self.driver.copy_image( self.region, self.fake_image, self.image_name, description=self.description, ex_destination_region_id=self.dest_region, ex_client_token=self.client_token) self.assertIsNotNone(image) def test_copy_image_in_the_same_region(self): ECSMockHttp.type = 'copy_image_same_region' image = self.driver.copy_image(self.region, self.fake_image, None) self.assertIsNotNone(image) def test_ex_create_security_group(self): self.sg_description = 'description' self.client_token = 'client-token' sg_id = self.driver.ex_create_security_group( description=self.sg_description, client_token=self.client_token) self.assertEqual('sg-F876FF7BA', sg_id) def test_ex_list_security_groups(self): sgs = self.driver.ex_list_security_groups() self.assertEqual(1, len(sgs)) sg = sgs[0] self.assertEqual('sg-28ou0f3xa', sg.id) self.assertEqual('sg-28ou0f3xa', sg.name) self.assertEqual('System created security group.', sg.description) self.assertEqual('', sg.vpc_id) self.assertEqual('2015-06-26T08:35:30Z', sg.creation_time) def test_ex_join_security_group(self): result = self.driver.ex_join_security_group( self.fake_node, group_id=self.fake_security_group_id) self.assertTrue(result) def test_ex_leave_security_group(self): result = self.driver.ex_leave_security_group( self.fake_node, group_id=self.fake_security_group_id) self.assertTrue(result) def test_ex_delete_security_group_by_id(self): result = self.driver.ex_delete_security_group_by_id( group_id=self.fake_security_group_id) self.assertTrue(result) def test_ex_modify_security_group_by_id(self): self.sg_name = 'name' self.sg_description = 'description' result = self.driver.ex_modify_security_group_by_id( group_id=self.fake_security_group_id, name=self.sg_name, description=self.sg_description) self.assertTrue(result) def test_ex_list_security_groups_with_ex_filters(self): ECSMockHttp.type = 'list_sgs_filters' self.vpc_id = 'vpc1' ex_filters = {'VpcId': self.vpc_id} sgs = self.driver.ex_list_security_groups(ex_filters=ex_filters) self.assertEqual(1, len(sgs)) def test_ex_list_security_group_attributes(self): self.sga_nictype = 'internet' sgas = self.driver.ex_list_security_group_attributes( group_id=self.fake_security_group_id, nic_type=self.sga_nictype) self.assertEqual(1, len(sgas)) sga = sgas[0] self.assertEqual('ALL', sga.ip_protocol) self.assertEqual('-1/-1', sga.port_range) self.assertEqual('Accept', sga.policy) self.assertEqual('internet', sga.nic_type) def test_ex_list_zones(self): zones = self.driver.ex_list_zones() self.assertEqual(1, len(zones)) zone = zones[0] self.assertEqual('cn-qingdao-b', zone.id) self.assertEqual(self.driver, zone.driver) self.assertEqual('青岛可用区B', zone.name) self.assertIsNotNone(zone.available_resource_types) self.assertEqual('IoOptimized', zone.available_resource_types[0]) self.assertIsNotNone(zone.available_instance_types) self.assertEqual('ecs.m2.medium', zone.available_instance_types[0]) self.assertIsNotNone(zone.available_disk_categories) self.assertEqual('cloud_ssd', zone.available_disk_categories[0]) class ECSMockHttp(MockHttp): fixtures = ComputeFileFixtures('ecs') def _DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _list_nodes_ex_node_ids_DescribeInstances(self, method, url, body, headers): params = {'InstanceIds': '["i-28n7dkvov", "not-existed-id"]'} self.assertUrlContainsQueryParams(url, params) return self._DescribeInstances(method, url, body, headers) def _list_nodes_ex_filters_DescribeInstances(self, method, url, body, headers): params = {'ZoneId': self.test.zone} self.assertUrlContainsQueryParams(url, params) return self._DescribeInstances(method, url, body, headers) def _DescribeInstanceTypes(self, method, url, body, headers): resp_body = self.fixtures.load('describe_instance_types.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DescribeRegions(self, method, url, body, headers): resp_body = self.fixtures.load('describe_regions.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_node_CreateInstance(self, method, url, body, headers): params = {'SecurityGroupId': 'sg-28ou0f3xa', 'Description': 'description', 'InternetChargeType': 'PayByTraffic', 'InternetMaxBandwidthOut': '1', 'InternetMaxBandwidthIn': '200', 'HostName': 'hostname', 'Password': 'password', 'IoOptimized': 'optimized', 'SystemDisk.Category': 'cloud', 'SystemDisk.DiskName': 'root', 'SystemDisk.Description': 'sys', 'VSwitchId': 'vswitch-id1', 'PrivateIpAddress': '1.1.1.2', 'ClientToken': 'client_token'} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('create_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_node_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('create_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_node_StartInstance(self, method, url, body, headers): resp_body = self.fixtures.load('start_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_node_with_data_CreateInstance(self, method, url, body, headers): params = {'SecurityGroupId': 'sg-28ou0f3xa', 'DataDisk.1.Size': '5', 'DataDisk.1.Category': 'cloud', 'DataDisk.1.DiskName': 'data1', 'DataDisk.1.Description': 'description', 'DataDisk.1.Device': '/dev/xvdb', 'DataDisk.1.DeleteWithInstance': 'true'} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('create_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_node_with_data_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('create_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_node_with_data_StartInstance(self, method, url, body, headers): resp_body = self.fixtures.load('start_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _reboot_node_RebootInstance(self, method, url, body, headers): node_id = self.test.fake_node.id self.assertUrlContainsQueryParams(url, {'InstanceId': node_id, 'ForceStop': 'false'}) resp_body = self.fixtures.load('reboot_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _reboot_node_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('reboot_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _reboot_node_force_stop_RebootInstance(self, method, url, body, headers): node_id = self.test.fake_node.id self.assertUrlContainsQueryParams(url, {'InstanceId': node_id, 'ForceStop': 'true'}) resp_body = self.fixtures.load('reboot_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _reboot_node_force_stop_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('reboot_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _destroy_node_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('destroy_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _destroy_node_DeleteInstance(self, method, url, body, headers): node_id = self.test.fake_node.id self.assertUrlContainsQueryParams(url, {'InstanceId': node_id}) resp_body = self.fixtures.load('delete_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _start_node_StartInstance(self, method, url, body, headers): node_id = self.test.fake_node.id self.assertUrlContainsQueryParams(url, {'InstanceId': node_id}) resp_body = self.fixtures.load('start_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _start_node_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('reboot_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _stop_node_StopInstance(self, method, url, body, headers): node_id = self.test.fake_node.id self.assertUrlContainsQueryParams(url, {'InstanceId': node_id, 'ForceStop': 'false'}) resp_body = self.fixtures.load('stop_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _stop_node_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('stop_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _stop_node_force_stop_StopInstance(self, method, url, body, headers): node_id = self.test.fake_node.id self.assertUrlContainsQueryParams(url, {'InstanceId': node_id, 'ForceStop': 'true'}) resp_body = self.fixtures.load('stop_instance.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _stop_node_force_stop_DescribeInstances(self, method, url, body, headers): resp_body = self.fixtures.load('stop_node_describe_instances.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DescribeDisks(self, method, url, body, headers): resp_body = self.fixtures.load('describe_disks.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _list_volumes_ex_volume_ids_DescribeDisks(self, method, url, body, headers): region = self.test.region params = {'DiskIds': '["i-28n7dkvov", "not-existed-id"]', 'RegionId': region} self.assertUrlContainsQueryParams(url, params) return self._DescribeInstances(method, url, body, headers) def _list_volumes_ex_filters_DescribeDisks(self, method, url, body, headers): params = {'InstanceId': self.test.fake_node.id} self.assertUrlContainsQueryParams(url, params) return self._DescribeDisks(method, url, body, headers) def _DescribeSnapshots(self, method, url, body, headers): region = self.test.region volume_id = self.test.fake_volume.id params = {'RegionId': region, 'DiskId': volume_id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('describe_snapshots.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _list_volume_snapshots_ex_snapshot_ids_DescribeSnapshots( self, method, url, body, headers): params = {'RegionId': self.test.region, 'SnapshotIds': '["fake-snapshot1"]'} self.assertUrlContainsQueryParams(url, params) return self._DescribeSnapshots(method, url, body, headers) def _list_volume_snapshots_ex_filters_DescribeSnapshots(self, method, url, body, headers): params = {'InstanceId': self.test.fake_node.id} self.assertUrlContainsQueryParams(url, params) return self._DescribeSnapshots(method, url, body, headers) def _create_volume_CreateDisk(self, method, url, body, headers): params = {'RegionId': self.test.region, 'DiskName': self.test.volume_name, 'Size': str(self.test.volume_size), 'ZoneId': self.test.zone, 'SnapshotId': self.test.fake_snapshot.id, 'Description': self.test.description, 'DiskCategory': self.test.disk_category, 'ClientToken': self.test.client_token} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('create_disk.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_volume_DescribeDisks(self, method, url, body, headers): resp_body = self.fixtures.load('create_volume_describe_disks.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_volume_snapshot_CreateSnapshot(self, method, url, body, headers): params = {'DiskId': self.test.fake_volume.id, 'SnapshotName': self.test.snapshot_name, 'Description': self.test.description, 'ClientToken': self.test.client_token} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('create_snapshot.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_volume_snapshot_DescribeSnapshots(self, method, url, body, headers): resp_body = self.fixtures.load('describe_snapshots.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _AttachDisk(self, method, url, body, headers): delete_with_instance = str(self.test.delete_with_instance).lower() params = {'InstanceId': self.test.fake_node.id, 'DiskId': self.test.fake_volume.id, 'Device': self.test.device, 'DeleteWithInstance': delete_with_instance} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('attach_disk.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DetachDisk(self, method, url, body, headers): params = {'DiskId': self.test.fake_volume.id, 'InstanceId': self.test.instance_id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('detach_disk.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _detach_volume_DescribeDisks(self, method, url, body, headers): params = {'DiskIds': '["' + self.test.fake_volume.id + '"]'} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('detach_volume_describe_disks.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _detach_volume_DetachDisk(self, method, url, body, headers): params = {'DiskId': self.test.fake_volume.id, 'InstanceId': 'i-28whl2nj2'} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('detach_disk.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _destroy_volume_DescribeDisks(self, method, url, body, headers): params = {'DiskIds': '["' + self.test.fake_volume.id + '"]'} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('destroy_volume_describe_disks.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _destroy_volume_DeleteDisk(self, method, url, body, headers): params = {'DiskId': self.test.fake_volume.id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('delete_disk.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _destroy_volume_state_DescribeDisks(self, method, url, body, headers): return self._detach_volume_DescribeDisks(method, url, body, headers) def _DeleteSnapshot(self, method, url, body, header): params = {'SnapshotId': self.test.fake_snapshot.id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('delete_snapshot.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DescribeImages(self, method, url, body, headers): params = {'RegionId': self.test.fake_location.id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('describe_images.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _list_images_pages_DescribeImages(self, method, url, body, headers): if 'PageNumber=2' in url: resp_body = self.fixtures.load('pages_describe_images_page2.xml') else: resp_body = self.fixtures.load('pages_describe_images.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _list_images_ex_image_ids_DescribeImages(self, method, url, body, headers): params = {'ImageId': self.test.fake_image.id + ',not-existed'} self.assertUrlContainsQueryParams(url, params) return self._DescribeImages(method, url, body, headers) def _list_images_ex_filters_DescribeImages(self, method, url, body, headers): params = {'Status': 'Available'} self.assertUrlContainsQueryParams(url, params) return self._DescribeImages(method, url, body, headers) def _CreateImage(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ImageName': self.test.image_name, 'Description': self.test.description, 'SnapshotId': self.test.fake_snapshot.id, 'ImageVersion': self.test.image_version, 'ClientToken': self.test.client_token} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('create_image.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DeleteImage(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ImageId': self.test.fake_image.id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('delete_image.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _get_image_DescribeImages(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ImageId': self.test.fake_image.id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('describe_images.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _get_image_not_found_DescribeImages(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ImageId': self.test.fake_image.id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('get_image_describe_images.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _CopyImage(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ImageId': self.test.fake_image.id, 'DestinationRegionId': self.test.dest_region, 'DestinationImageName': self.test.image_name, 'DestinationDescription': self.test.description, 'ClientToken': self.test.client_token} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('copy_image.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _copy_image_same_region_CopyImage(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ImageId': self.test.fake_image.id, 'DestinationRegionId': self.test.region} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('copy_image.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _copy_image_same_region_DescribeImages(self, method, url, body, headers): return self._DescribeImages(method, url, body, headers) def _DescribeSecurityGroups(self, method, url, body, headers): params = {'RegionId': self.test.region} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('describe_security_groups.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _JoinSecurityGroup(self, method, url, body, headers): params = {'InstanceId': self.test.fake_node.id, 'SecurityGroupId': self.test.fake_security_group_id} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('join_security_group_by_id.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _LeaveSecurityGroup(self, method, url, body, headers): params = {'InstanceId': self.test.fake_node.id, 'SecurityGroupId': self.test.fake_security_group_id} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('leave_security_group_by_id.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _list_sgs_filters_DescribeSecurityGroups(self, method, url, body, headers): params = {'VpcId': self.test.vpc_id} self.assertUrlContainsQueryParams(url, params) return self._DescribeSecurityGroups(method, url, body, headers) def _CreateSecurityGroup(self, method, url, body, headers): params = {'RegionId': self.test.region, 'Description': self.test.sg_description, 'ClientToken': self.test.client_token} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('create_security_group.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DeleteSecurityGroup(self, method, url, body, headers): params = {'RegionId': self.test.region, 'SecurityGroupId': self.test.fake_security_group_id} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('delete_security_group_by_id.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _ModifySecurityGroupAttribute(self, method, url, body, headers): params = {'RegionId': self.test.region, 'SecurityGroupId': self.test.fake_security_group_id, 'SecurityGroupName': self.test.sg_name, 'Description': self.test.sg_description} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('modify_security_group_by_id.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DescribeSecurityGroupAttribute(self, method, url, body, headers): params = {'RegionId': self.test.region, 'SecurityGroupId': self.test.fake_security_group_id, 'NicType': self.test.sga_nictype} self.assertUrlContainsQueryParams(url, params) resp_body = self.fixtures.load('describe_security_group_attributes.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _DescribeZones(self, method, url, body, headers): resp_body = self.fixtures.load('describe_zones.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) def _create_public_ip_AllocatePublicIpAddress(self, method, url, body, headers): resp_body = self.fixtures.load('create_public_ip.xml') return (httplib.OK, resp_body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_elasticstack.py0000664000175000017500000002543013570310635024745 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.utils.py3 import httplib from libcloud.utils.py3 import assertRaisesRegex from libcloud.compute.base import Node from libcloud.compute.drivers.elasticstack import ElasticStackException from libcloud.compute.drivers.elastichosts import \ ElasticHostsNodeDriver as ElasticHosts from libcloud.compute.drivers.skalicloud import \ SkaliCloudNodeDriver as SkaliCloud from libcloud.compute.drivers.serverlove import \ ServerLoveNodeDriver as ServerLove from libcloud.common.types import InvalidCredsError, MalformedResponseError from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import ComputeFileFixtures class ElasticStackTestCase(object): def setUp(self): # Re-use ElasticHosts fixtures for the base ElasticStack platform tests self.mockHttp = ElasticStackMockHttp self.mockHttp.type = None self.node = Node(id=72258, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) def test_invalid_creds(self): self.mockHttp.type = 'UNAUTHORIZED' try: self.driver.list_nodes() except InvalidCredsError as e: self.assertEqual(True, isinstance(e, InvalidCredsError)) else: self.fail('test should have thrown') def test_malformed_response(self): self.mockHttp.type = 'MALFORMED' try: self.driver.list_nodes() except MalformedResponseError: pass else: self.fail('test should have thrown') def test_parse_error(self): self.mockHttp.type = 'PARSE_ERROR' try: self.driver.list_nodes() except Exception as e: self.assertTrue(str(e).find('X-Elastic-Error') != -1) else: self.fail('test should have thrown') def test_ex_set_node_configuration(self): success = self.driver.ex_set_node_configuration(node=self.node, name='name', cpu='2') self.assertTrue(success) def test_ex_set_node_configuration_invalid_keys(self): try: self.driver.ex_set_node_configuration(node=self.node, foo='bar') except ElasticStackException: pass else: self.fail( 'Invalid option specified, but an exception was not thrown') def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertTrue(isinstance(nodes, list)) self.assertEqual(len(nodes), 1) node = nodes[0] self.assertEqual(node.public_ips[0], "1.2.3.4") self.assertEqual(node.public_ips[1], "1.2.3.5") self.assertEqual(node.extra['smp'], 1) self.assertEqual( node.extra['ide:0:0'], "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3") def test_list_offline_node(self): self.mockHttp.type = 'OFFLINE' nodes = self.driver.list_nodes() self.assertTrue(isinstance(nodes, list)) self.assertEqual(len(nodes), 1) node = nodes[0] self.assertEqual(len(node.public_ips), 0, "Public IPs was not empty") self.assertNotIn('smp', node.extra) self.assertNotIn('started', node.extra) self.assertEqual( node.extra['ide:0:0'], "b6049e7a-aa1b-47f9-b21d-cdf2354e28d3") def test_list_sizes(self): images = self.driver.list_sizes() self.assertEqual(len(images), 6) image = [i for i in images if i.id == 'small'][0] self.assertEqual(image.id, 'small') self.assertEqual(image.name, 'Small instance') self.assertEqual(image.cpu, 2000) self.assertEqual(image.ram, 1700) self.assertEqual(image.disk, 160) self.assertTrue(isinstance(image.price, float)) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), len(self.driver._standard_drives)) for uuid, values in list(self.driver._standard_drives.items()): self.assertEqual( len([image for image in images if image.id == uuid]), 1) def test_reboot_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.reboot_node(node)) def test_destroy_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.destroy_node(node)) def test_create_node(self): sizes = self.driver.list_sizes() size = [s for s in sizes if s.id == 'large'][0] image = self.image self.assertTrue(self.driver.create_node(name="api.ivan.net.nz", image=image, size=size)) class ElasticHostsTestCase(ElasticStackTestCase, unittest.TestCase): def setUp(self): ElasticHosts.connectionCls.conn_class = ElasticStackMockHttp self.driver = ElasticHosts('foo', 'bar') images = self.driver.list_images() self.image = [i for i in images if i.id == '38df0986-4d85-4b76-b502-3878ffc80161'][0] super(ElasticHostsTestCase, self).setUp() def test_multiple_drivers_with_different_regions(self): driver1 = ElasticHosts('foo', 'bar', region='lon-p') driver2 = ElasticHosts('foo', 'bar', region='sat-p') self.assertTrue(driver1.connection.host.startswith('api-lon-p')) self.assertTrue(driver2.connection.host.startswith('api-sat-p')) driver1.list_nodes() driver2.list_nodes() driver1.list_nodes() self.assertTrue(driver1.connection.host.startswith('api-lon-p')) self.assertTrue(driver2.connection.host.startswith('api-sat-p')) def test_invalid_region(self): expected_msg = r'Invalid region.+' assertRaisesRegex(self, ValueError, expected_msg, ElasticHosts, 'foo', 'bar', region='invalid') class SkaliCloudTestCase(ElasticStackTestCase, unittest.TestCase): def setUp(self): SkaliCloud.connectionCls.conn_class = ElasticStackMockHttp self.driver = SkaliCloud('foo', 'bar') images = self.driver.list_images() self.image = [i for i in images if i.id == '90aa51f2-15c0-4cff-81ee-e93aa20b9468'][0] super(SkaliCloudTestCase, self).setUp() class ServerLoveTestCase(ElasticStackTestCase, unittest.TestCase): def setUp(self): ServerLove.connectionCls.conn_class = ElasticStackMockHttp self.driver = ServerLove('foo', 'bar') images = self.driver.list_images() self.image = [i for i in images if i.id == '679f5f44-0be7-4745-a658-cccd4334c1aa'][0] super(ServerLoveTestCase, self).setUp() class ElasticStackMockHttp(MockHttp): fixtures = ComputeFileFixtures('elastichosts') def _servers_info_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.NO_CONTENT]) def _servers_info_MALFORMED(self, method, url, body, headers): body = "{malformed: '" return (httplib.OK, body, {}, httplib.responses[httplib.NO_CONTENT]) def _servers_info_PARSE_ERROR(self, method, url, body, headers): return (505, body, {}, httplib.responses[httplib.NO_CONTENT]) def _servers_b605ca90_c3e6_4cee_85f8_a8ebdf8f9903_reset(self, method, url, body, headers): return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _servers_b605ca90_c3e6_4cee_85f8_a8ebdf8f9903_destroy(self, method, url, body, headers): return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _drives_create(self, method, url, body, headers): body = self.fixtures.load('drives_create.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _drives_0012e24a_6eae_4279_9912_3432f698cec8_image_38df0986_4d85_4b76_b502_3878ffc80161_gunzip(self, method, url, body, headers): # ElasticHosts image return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _drives_0012e24a_6eae_4279_9912_3432f698cec8_image_90aa51f2_15c0_4cff_81ee_e93aa20b9468_gunzip(self, method, url, body, headers): # Skalikloud image return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _drives_0012e24a_6eae_4279_9912_3432f698cec8_image_679f5f44_0be7_4745_a658_cccd4334c1aa_gunzip(self, method, url, body, headers): # ServerLove image return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _drives_0012e24a_6eae_4279_9912_3432f698cec8_info(self, method, url, body, headers): body = self.fixtures.load('drives_info.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_create(self, method, url, body, headers): body = self.fixtures.load('servers_create.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_info(self, method, url, body, headers): body = self.fixtures.load('servers_info.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_info_OFFLINE(self, method, url, body, headers): body = self.fixtures.load('offline_servers_info.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_72258_set(self, method, url, body, headers): body = '{}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_exoscale.py0000664000175000017500000000217313535474530024103 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.compute.drivers.exoscale import ExoscaleNodeDriver from libcloud.test.compute.test_cloudstack import CloudStackCommonTestCase from libcloud.test import unittest class ExoscaleNodeDriverTestCase(CloudStackCommonTestCase, unittest.TestCase): driver_klass = ExoscaleNodeDriver if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_gandi.py0000664000175000017500000003450113535474530023362 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import sys import random import string from libcloud.utils.py3 import httplib from libcloud.compute.drivers.gandi import GandiNodeDriver from libcloud.common.gandi import GandiException from libcloud.compute.types import NodeState from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import GANDI_PARAMS from libcloud.test.common.test_gandi import BaseGandiMockHttp class GandiTests(unittest.TestCase): node_name = 'test2' def setUp(self): GandiNodeDriver.connectionCls.conn_class = GandiMockHttp GandiMockHttp.type = None self.driver = GandiNodeDriver(*GANDI_PARAMS) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertTrue(len(nodes) > 0) self.assertTrue(len(nodes[0].public_ips) > 1) def test_list_locations(self): loc = list(filter(lambda x: 'france' in x.country.lower(), self.driver.list_locations()))[0] self.assertEqual(loc.country, 'France') def test_list_images(self): loc = list(filter(lambda x: 'france' in x.country.lower(), self.driver.list_locations()))[0] images = self.driver.list_images(loc) self.assertTrue(len(images) > 2) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertTrue(len(sizes) >= 1) def test_destroy_node_running(self): nodes = self.driver.list_nodes() test_node = list(filter(lambda x: x.state == NodeState.RUNNING, nodes))[0] self.assertTrue(self.driver.destroy_node(test_node)) def test_destroy_node_halted(self): nodes = self.driver.list_nodes() test_node = list(filter(lambda x: x.state == NodeState.TERMINATED, nodes))[0] self.assertTrue(self.driver.destroy_node(test_node)) def test_reboot_node(self): nodes = self.driver.list_nodes() test_node = list(filter(lambda x: x.state == NodeState.RUNNING, nodes))[0] self.assertTrue(self.driver.reboot_node(test_node)) def test_create_node(self): login = 'libcloud' passwd = ''.join(random.choice(string.ascii_letters) for i in range(10)) # Get france datacenter loc = list(filter(lambda x: 'france' in x.country.lower(), self.driver.list_locations()))[0] # Get a debian image images = self.driver.list_images(loc) images = [x for x in images if x.name.lower().startswith('debian')] img = list(filter(lambda x: '5' in x.name, images))[0] # Get a configuration size size = self.driver.list_sizes()[0] node = self.driver.create_node(name=self.node_name, login=login, password=passwd, image=img, location=loc, size=size) self.assertEqual(node.name, self.node_name) def test_create_volume(self): loc = list(filter(lambda x: 'france' in x.country.lower(), self.driver.list_locations()))[0] volume = self.driver.create_volume( size=1024, name='libcloud', location=loc) self.assertEqual(volume.name, 'libcloud') self.assertEqual(volume.size, 1024) def test_list_volumes(self): disks = self.driver.list_volumes() self.assertTrue(len(disks) > 0) def test_destroy_volume(self): volumes = self.driver.list_volumes() test_vol = list(filter(lambda x: x.name == 'test_disk', volumes))[0] self.assertTrue(self.driver.destroy_volume(test_vol)) def test_attach_volume(self): disks = self.driver.list_volumes() nodes = self.driver.list_nodes() res = self.driver.attach_volume(nodes[0], disks[0]) self.assertTrue(res) def test_detach_volume(self): disks = self.driver.list_volumes() nodes = self.driver.list_nodes() res = self.driver.detach_volume(nodes[0], disks[0]) self.assertTrue(res) def test_ex_list_interfaces(self): ifaces = self.driver.ex_list_interfaces() self.assertTrue(len(ifaces) > 0) def test_ex_attach_interface(self): ifaces = self.driver.ex_list_interfaces() nodes = self.driver.list_nodes() res = self.driver.ex_node_attach_interface(nodes[0], ifaces[0]) self.assertTrue(res) def test_ex_detach_interface(self): ifaces = self.driver.ex_list_interfaces() nodes = self.driver.list_nodes() res = self.driver.ex_node_detach_interface(nodes[0], ifaces[0]) self.assertTrue(res) def test_ex_snapshot_disk(self): disks = self.driver.list_volumes() self.assertTrue(self.driver.ex_snapshot_disk(disks[2])) self.assertRaises(GandiException, self.driver.ex_snapshot_disk, disks[0]) def test_ex_update_disk(self): disks = self.driver.list_volumes() self.assertTrue(self.driver.ex_update_disk(disks[0], new_size=4096)) def test_list_key_pairs(self): keys = self.driver.list_key_pairs() self.assertTrue(len(keys) > 0) def test_get_key_pair(self): key = self.driver.get_key_pair(10) self.assertEqual(key.name, 'testkey') def test_import_key_pair_from_string(self): key = self.driver.import_key_pair_from_string('testkey', '12345') self.assertEqual(key.name, 'testkey') self.assertEqual(key.extra['id'], 10) def test_delete_key_pair(self): response = self.driver.delete_key_pair(10) self.assertTrue(response) def test_ex_get_node(self): node = self.driver.ex_get_node(34951) self.assertEqual(node.name, "test2") def test_ex_get_volume(self): volume = self.driver.ex_get_volume(1263) self.assertEqual(volume.name, "libcloud") class GandiRatingTests(unittest.TestCase): """Tests where rating model is involved""" node_name = 'test2' def setUp(self): GandiNodeDriver.connectionCls.conn_class = GandiMockRatingHttp GandiMockRatingHttp.type = None self.driver = GandiNodeDriver(*GANDI_PARAMS) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 4) def test_create_node(self): login = 'libcloud' passwd = ''.join(random.choice(string.ascii_letters) for i in range(10)) # Get france datacenter loc = list(filter(lambda x: 'france' in x.country.lower(), self.driver.list_locations()))[0] # Get a debian image images = self.driver.list_images(loc) images = [x for x in images if x.name.lower().startswith('debian')] img = list(filter(lambda x: '5' in x.name, images))[0] # Get a configuration size size = self.driver.list_sizes()[0] node = self.driver.create_node(name=self.node_name, login=login, password=passwd, image=img, location=loc, size=size) self.assertEqual(node.name, self.node_name) class GandiMockHttp(BaseGandiMockHttp): fixtures = ComputeFileFixtures('gandi') def _xmlrpc__hosting_datacenter_list(self, method, url, body, headers): body = self.fixtures.load('datacenter_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_image_list(self, method, url, body, headers): body = self.fixtures.load('image_list_dc0.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_list(self, method, url, body, headers): body = self.fixtures.load('vm_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_ip_list(self, method, url, body, headers): body = self.fixtures.load('ip_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_account_info(self, method, url, body, headers): body = self.fixtures.load('account_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_info(self, method, url, body, headers): body = self.fixtures.load('vm_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_delete(self, method, url, body, headers): body = self.fixtures.load('vm_delete.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__operation_info(self, method, url, body, headers): body = self.fixtures.load('operation_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_create_from(self, method, url, body, headers): body = self.fixtures.load('vm_create_from.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_reboot(self, method, url, body, headers): body = self.fixtures.load('vm_reboot.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_stop(self, method, url, body, headers): body = self.fixtures.load('vm_stop.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_iface_list(self, method, url, body, headers): body = self.fixtures.load('iface_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_disk_list(self, method, url, body, headers): body = self.fixtures.load('disk_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_iface_attach(self, method, url, body, headers): body = self.fixtures.load('iface_attach.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_iface_detach(self, method, url, body, headers): body = self.fixtures.load('iface_detach.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_disk_attach(self, method, url, body, headers): body = self.fixtures.load('disk_attach.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_disk_detach(self, method, url, body, headers): body = self.fixtures.load('disk_detach.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_disk_create(self, method, url, body, headers): body = self.fixtures.load('disk_create.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_disk_create_from(self, method, url, body, headers): body = self.fixtures.load('disk_create_from.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_disk_info(self, method, url, body, headers): body = self.fixtures.load('disk_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_disk_update(self, method, url, body, headers): body = self.fixtures.load('disk_update.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_disk_delete(self, method, url, body, headers): body = self.fixtures.load('disk_delete.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_ssh_info(self, method, url, body, headers): body = self.fixtures.load('ssh_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_ssh_list(self, method, url, body, headers): body = self.fixtures.load('ssh_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_ssh_create(self, method, url, body, headers): body = self.fixtures.load('ssh_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_ssh_delete(self, method, url, body, headers): body = self.fixtures.load('ssh_delete.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class GandiMockRatingHttp(BaseGandiMockHttp): """Fixtures needed for tests related to rating model""" fixtures = ComputeFileFixtures('gandi') def _xmlrpc__hosting_datacenter_list(self, method, url, body, headers): body = self.fixtures.load('datacenter_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_image_list(self, method, url, body, headers): body = self.fixtures.load('image_list_dc0.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_create_from(self, method, url, body, headers): body = self.fixtures.load('vm_create_from.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__operation_info(self, method, url, body, headers): body = self.fixtures.load('operation_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc__hosting_vm_info(self, method, url, body, headers): body = self.fixtures.load('vm_info.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) # Specific to rating tests def _xmlrpc__hosting_account_info(self, method, url, body, headers): body = self.fixtures.load('account_info_rating.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_gce.py0000664000175000017500000055757013577507766023074 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Tests for Google Compute Engine Driver """ import datetime import mock import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.gce import ( GCENodeDriver, API_VERSION, timestamp_to_datetime, GCEAddress, GCEBackend, GCEBackendService, GCEFirewall, GCEForwardingRule, GCEHealthCheck, GCENetwork, GCENodeImage, GCERoute, GCERegion, GCETargetHttpProxy, GCEUrlMap, GCEZone, GCESubnetwork, GCEProject) from libcloud.common.google import (GoogleBaseAuthConnection, ResourceNotFoundError, ResourceExistsError, GoogleBaseError) from libcloud.test.common.test_google import GoogleAuthMockHttp, GoogleTestCase from libcloud.compute.base import Node, StorageVolume from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import GCE_PARAMS, GCE_KEYWORD_PARAMS class GCENodeDriverTest(GoogleTestCase, TestCaseMixin): """ Google Compute Engine Test Class. """ # Mock out a few specific calls that interact with the user, system or # environment. GCEZone._now = lambda x: datetime.datetime(2013, 6, 26, 19, 0, 0) datacenter = 'us-central1-a' def setUp(self): GCEMockHttp.test = self GCENodeDriver.connectionCls.conn_class = GCEMockHttp GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp GCEMockHttp.type = None kwargs = GCE_KEYWORD_PARAMS.copy() kwargs['auth_type'] = 'IA' kwargs['datacenter'] = self.datacenter self.driver = GCENodeDriver(*GCE_PARAMS, **kwargs) def test_default_scopes(self): self.assertIsNone(self.driver.scopes) def test_timestamp_to_datetime(self): timestamp1 = '2013-06-26T10:05:19.340-07:00' datetime1 = datetime.datetime(2013, 6, 26, 17, 5, 19) self.assertEqual(timestamp_to_datetime(timestamp1), datetime1) timestamp2 = '2013-06-26T17:43:15.000-00:00' datetime2 = datetime.datetime(2013, 6, 26, 17, 43, 15) self.assertEqual(timestamp_to_datetime(timestamp2), datetime2) def test_get_object_by_kind(self): obj = self.driver._get_object_by_kind(None) self.assertIsNone(obj) obj = self.driver._get_object_by_kind('') self.assertIsNone(obj) obj = self.driver._get_object_by_kind( 'https://www.googleapis.com/compute/v1/projects/project_name/' 'global/targetHttpProxies/web-proxy') self.assertEqual(obj.name, 'web-proxy') def test_get_region_from_zone(self): zone1 = self.driver.ex_get_zone('us-central1-a') expected_region1 = 'us-central1' region1 = self.driver._get_region_from_zone(zone1) self.assertEqual(region1.name, expected_region1) zone2 = self.driver.ex_get_zone('europe-west1-b') expected_region2 = 'europe-west1' region2 = self.driver._get_region_from_zone(zone2) self.assertEqual(region2.name, expected_region2) def test_get_volume(self): volume_name = 'lcdisk' volume = self.driver.ex_get_volume(volume_name) self.assertTrue(isinstance(volume, StorageVolume)) self.assertEqual(volume.name, volume_name) def test_get_volume_location(self): volume_name = 'lcdisk' location = self.driver.zone volume = self.driver.ex_get_volume(volume_name, zone=location) self.assertTrue(isinstance(volume, StorageVolume)) self.assertEqual(volume.name, volume_name) def test_get_volume_location_name(self): volume_name = 'lcdisk' location = self.driver.zone volume = self.driver.ex_get_volume(volume_name, zone=location.name) self.assertTrue(isinstance(volume, StorageVolume)) self.assertEqual(volume.name, volume_name) def test_find_zone_or_region(self): zone1 = self.driver._find_zone_or_region('libcloud-demo-np-node', 'instances') self.assertEqual(zone1.name, 'us-central2-a') zone2 = self.driver._find_zone_or_region( 'libcloud-demo-europe-np-node', 'instances') self.assertEqual(zone2.name, 'europe-west1-a') region = self.driver._find_zone_or_region('libcloud-demo-address', 'addresses', region=True) self.assertEqual(region.name, 'us-central1') def test_match_images(self): project = 'debian-cloud' image = self.driver._match_images(project, 'debian-7') self.assertEqual(image.name, 'debian-7-wheezy-v20131120') image = self.driver._match_images(project, 'backports') self.assertEqual(image.name, 'backports-debian-7-wheezy-v20131127') def test_build_disk_gce_struct(self): device_name = 'disk_name' disk_name = None source = self.driver.ex_get_volume('lcdisk') is_boot = True # source as input d = self.driver._build_disk_gce_struct( device_name=device_name, source=source, disk_name=disk_name, is_boot=is_boot) self.assertEqual(source.extra['selfLink'], d['source']) self.assertTrue(d['boot']) self.assertTrue(d['autoDelete']) self.assertEqual('READ_WRITE', d['mode']) self.assertFalse('initializeParams' in d) # image as input device_name = 'disk_name' disk_type = self.driver.ex_get_disktype('pd-ssd', 'us-central1-a') image = self.driver.ex_get_image('debian-7') source = None is_boot = True d = self.driver._build_disk_gce_struct(device_name=device_name, disk_type=disk_type, image=image, is_boot=is_boot) self.assertEqual('READ_WRITE', d['mode']) self.assertEqual('PERSISTENT', d['type']) self.assertTrue('initializeParams' in d and isinstance(d['initializeParams'], dict)) self.assertTrue( all(k in d['initializeParams'] for k in ['sourceImage', 'diskType', 'diskName'])) self.assertTrue(d['initializeParams']['sourceImage'].startswith( 'https://')) self.assertTrue(d['autoDelete']) self.assertTrue(d['boot']) def test_build_network_gce_struct(self): network = self.driver.ex_get_network('lcnetwork') address = self.driver.ex_get_address('lcaddress') internalip = self.driver.ex_get_address('testaddress') subnetwork_name = 'cf-972cf02e6ad49112' subnetwork = self.driver.ex_get_subnetwork(subnetwork_name) d = self.driver._build_network_gce_struct(network, subnetwork, address) self.assertTrue('network' in d) self.assertTrue('subnetwork' in d) self.assertTrue('kind' in d and d['kind'] == 'compute#instanceNetworkInterface') self.assertEqual(d['accessConfigs'][0]['natIP'], address.address) # test with internal IP d = self.driver._build_network_gce_struct(network, subnetwork, address, internal_ip=internalip) self.assertTrue('network' in d) self.assertTrue('subnetwork' in d) self.assertTrue('kind' in d and d['kind'] == 'compute#instanceNetworkInterface') self.assertEqual(d['accessConfigs'][0]['natIP'], address.address) self.assertEqual(d['networkIP'], internalip) network = self.driver.ex_get_network('default') d = self.driver._build_network_gce_struct(network) self.assertTrue('network' in d) self.assertFalse('subnetwork' in d) self.assertTrue('kind' in d and d['kind'] == 'compute#instanceNetworkInterface') def test_build_scheduling_gce_struct(self): self.assertFalse( self.driver._build_scheduling_gce_struct(None, None, None)) # on_host_maintenance bad value should raise a Valueerror self.assertRaises(ValueError, self.driver._build_service_account_gce_struct, 'on_host_maintenance="foobar"') # on_host_maintenance is 'MIGRATE' and prempt is True self.assertRaises(ValueError, self.driver._build_service_account_gce_struct, 'on_host_maintenance="MIGRATE"', 'preemptible=True') # automatic_restart is True and prempt is True self.assertRaises(ValueError, self.driver._build_service_account_gce_struct, 'automatic_restart="True"', 'preemptible=True') actual = self.driver._build_scheduling_gce_struct('TERMINATE', True, False) self.assertTrue('automaticRestart' in actual and actual['automaticRestart'] is True) self.assertTrue('onHostMaintenance' in actual and actual['onHostMaintenance'] == 'TERMINATE') self.assertTrue('preemptible' in actual) self.assertFalse(actual['preemptible']) def test_build_service_account_gce_struct(self): self.assertRaises(ValueError, self.driver._build_service_account_gce_struct, None) input = {'scopes': ['compute-ro']} actual = self.driver._build_service_account_gce_struct(input) self.assertTrue('email' in actual) self.assertTrue('scopes' in actual) input = {'scopes': ['compute-ro'], 'email': 'test@test.com'} actual = self.driver._build_service_account_gce_struct(input) self.assertTrue('email' in actual) self.assertEqual(actual['email'], 'test@test.com') self.assertTrue('scopes' in actual) def test_build_service_account_gce_list(self): # ensure we have a list self.assertRaises(ValueError, self.driver._build_service_accounts_gce_list, 'foo') # no input actual = self.driver._build_service_accounts_gce_list() self.assertTrue(len(actual) == 1) self.assertTrue('email' in actual[0]) self.assertTrue('scopes' in actual[0]) def test_get_selflink_or_name(self): network = self.driver.ex_get_network('lcnetwork') # object as input actual = self.driver._get_selflink_or_name(network, False, 'network') self.assertEqual('lcnetwork', actual) actual = self.driver._get_selflink_or_name(network, True, 'network') self.assertTrue(actual.startswith('https://')) # name-only as input actual = self.driver._get_selflink_or_name('lcnetwork', True, 'network') self.assertTrue(actual.startswith('https://')) actual = self.driver._get_selflink_or_name('lcnetwork', False, 'network') self.assertTrue('lcnetwork', actual) # if selflinks is true, we need objname self.assertRaises(ValueError, self.driver._get_selflink_or_name, 'lcnetwork', True) def test_ex_get_serial_output(self): self.assertRaises(ValueError, self.driver.ex_get_serial_output, 'foo') node = self.driver.ex_get_node('node-name', 'us-central1-a') self.assertTrue( self.driver.ex_get_serial_output(node), 'This is some serial\r\noutput for you.') def test_ex_list(self): d = self.driver # Test the default case for all list methods # (except list_volume_snapshots, which requires an arg) for list_fn in (d.ex_list_addresses, d.ex_list_backendservices, d.ex_list_disktypes, d.ex_list_firewalls, d.ex_list_forwarding_rules, d.ex_list_healthchecks, d.ex_list_networks, d.ex_list_subnetworks, d.ex_list_project_images, d.ex_list_regions, d.ex_list_routes, d.ex_list_snapshots, d.ex_list_targethttpproxies, d.ex_list_targetinstances, d.ex_list_targetpools, d.ex_list_urlmaps, d.ex_list_zones, d.list_images, d.list_locations, d.list_nodes, d.list_sizes, d.list_volumes): full_list = [item.name for item in list_fn()] li = d.ex_list(list_fn) iter_list = [item.name for sublist in li for item in sublist] self.assertEqual(full_list, iter_list) # Test paging & filtering with a single list function as they require # additional test fixtures list_fn = d.ex_list_regions for count, sublist in zip((2, 1), d.ex_list(list_fn).page(2)): self.assertTrue(len(sublist) == count) for sublist in d.ex_list(list_fn).filter('name eq us-central1'): self.assertTrue(len(sublist) == 1) self.assertEqual(sublist[0].name, 'us-central1') def test_ex_list_addresses(self): address_list = self.driver.ex_list_addresses() address_list_all = self.driver.ex_list_addresses('all') address_list_uc1 = self.driver.ex_list_addresses('us-central1') address_list_global = self.driver.ex_list_addresses('global') self.assertEqual(len(address_list), 2) self.assertEqual(len(address_list_all), 5) self.assertEqual(len(address_list_global), 1) self.assertEqual(address_list[0].name, 'libcloud-demo-address') self.assertEqual(address_list_uc1[0].name, 'libcloud-demo-address') self.assertEqual(address_list_global[0].name, 'lcaddressglobal') names = [a.name for a in address_list_all] self.assertTrue('libcloud-demo-address' in names) def test_ex_list_backendservices(self): self.backendservices_mock = 'empty' backendservices_list = self.driver.ex_list_backendservices() self.assertListEqual(backendservices_list, []) self.backendservices_mock = 'web-service' backendservices_list = self.driver.ex_list_backendservices() web_service = backendservices_list[0] self.assertEqual(web_service.name, 'web-service') self.assertEqual(len(web_service.healthchecks), 1) self.assertEqual(len(web_service.backends), 2) def test_ex_list_healthchecks(self): healthchecks = self.driver.ex_list_healthchecks() self.assertEqual(len(healthchecks), 3) self.assertEqual(healthchecks[0].name, 'basic-check') def test_ex_list_firewalls(self): firewalls = self.driver.ex_list_firewalls() self.assertEqual(len(firewalls), 5) self.assertEqual(firewalls[0].name, 'default-allow-internal') def test_ex_list_forwarding_rules(self): forwarding_rules = self.driver.ex_list_forwarding_rules() forwarding_rules_all = self.driver.ex_list_forwarding_rules('all') forwarding_rules_uc1 = self.driver.ex_list_forwarding_rules( 'us-central1') self.assertEqual(len(forwarding_rules), 2) self.assertEqual(len(forwarding_rules_all), 2) self.assertEqual(forwarding_rules[0].name, 'lcforwardingrule') self.assertEqual(forwarding_rules_uc1[0].name, 'lcforwardingrule') names = [f.name for f in forwarding_rules_all] self.assertTrue('lcforwardingrule' in names) def test_ex_list_forwarding_rules_global(self): forwarding_rules = self.driver.ex_list_forwarding_rules( global_rules=True) self.assertEqual(len(forwarding_rules), 2) self.assertEqual(forwarding_rules[0].name, 'http-rule') names = [f.name for f in forwarding_rules] self.assertListEqual(names, ['http-rule', 'http-rule2']) def test_list_images(self): local_images = self.driver.list_images() all_deprecated_images = self.driver.list_images( ex_include_deprecated=True) debian_images = self.driver.list_images(ex_project='debian-cloud') local_plus_deb = self.driver.list_images( ['debian-cloud', 'project_name']) self.assertEqual(len(local_images), 50) self.assertEqual(len(all_deprecated_images), 178) self.assertEqual(len(debian_images), 2) self.assertEqual(len(local_plus_deb), 4) self.assertEqual(local_images[0].name, 'custom-image') self.assertEqual(debian_images[1].name, 'debian-7-wheezy-v20131120') def test_ex_destroy_instancegroup(self): name = 'myname' zone = 'us-central1-a' uig = self.driver.ex_get_instancegroup(name, zone) self.assertTrue(self.driver.ex_destroy_instancegroup(uig)) def test_ex_get_instancegroup(self): name = 'myname' loc = 'us-central1-a' actual = self.driver.ex_get_instancegroup(name, loc) self.assertEqual(actual.name, name) self.assertEqual(actual.zone.name, loc) def test_ex_create_instancegroup(self): name = 'myname' loc = 'us-central1-a' actual = self.driver.ex_create_instancegroup(name, loc) self.assertEqual(actual.name, name) self.assertEqual(actual.zone.name, loc) def test_ex_list_instancegroups(self): loc = 'us-central1-a' actual = self.driver.ex_list_instancegroups(loc) self.assertTrue(len(actual) == 2) self.assertEqual(actual[0].name, 'myname') self.assertEqual(actual[1].name, 'myname2') def test_ex_instancegroup_list_instances(self): name = 'myname' loc = 'us-central1-a' gceobj = self.driver.ex_get_instancegroup(name, loc) actual = self.driver.ex_instancegroup_list_instances(gceobj) self.assertTrue(len(actual) == 2) for node in actual: self.assertTrue(isinstance(node, Node)) self.assertEqual(loc, node.extra['zone'].name) def test_ex_instancegroup_add_instances(self): name = 'myname' loc = 'us-central1-a' gceobj = self.driver.ex_get_instancegroup(name, loc) node_name = self.driver.ex_get_node('node-name', loc) lcnode = self.driver.ex_get_node('lcnode-001', loc) node_list = [node_name, lcnode] self.assertTrue( self.driver.ex_instancegroup_add_instances(gceobj, node_list)) def test_ex_instancegroup_remove_instances(self): name = 'myname' loc = 'us-central1-a' gceobj = self.driver.ex_get_instancegroup(name, loc) node_name = self.driver.ex_get_node('node-name', loc) lcnode = self.driver.ex_get_node('lcnode-001', loc) node_list = [node_name, lcnode] self.assertTrue( self.driver.ex_instancegroup_remove_instances(gceobj, node_list)) def test_ex_instancegroup_set_named_ports(self): name = 'myname' loc = 'us-central1-a' gceobj = self.driver.ex_get_instancegroup(name, loc) named_ports = [{'name': 'foo', 'port': 4444}] # base case self.assertTrue( self.driver.ex_instancegroup_set_named_ports(gceobj, named_ports)) # specify nothing, default is empty list self.assertTrue(self.driver.ex_instancegroup_set_named_ports(gceobj)) # specify empty list self.assertTrue( self.driver.ex_instancegroup_set_named_ports(gceobj, [])) # raise valueerror if string is passed in self.assertRaises(ValueError, self.driver.ex_instancegroup_set_named_ports, gceobj, 'foobar') # raise valueerror if dictionary is passed in self.assertRaises(ValueError, self.driver.ex_instancegroup_set_named_ports, gceobj, {'name': 'foo', 'port': 4444}) def test_ex_instancegroupmanager_set_autohealing_policies(self): kwargs = {'host': 'lchost', 'path': '/lc', 'port': 8000, 'interval': 10, 'timeout': 10, 'unhealthy_threshold': 4, 'healthy_threshold': 3, 'description': 'test healthcheck'} healthcheck_name = 'lchealthcheck' hc = self.driver.ex_create_healthcheck(healthcheck_name, **kwargs) ig_name = 'myinstancegroup' ig_zone = 'us-central1-a' manager = self.driver.ex_get_instancegroupmanager(ig_name, ig_zone) res = self.driver.ex_instancegroupmanager_set_autohealingpolicies( manager=manager, healthcheck=hc, initialdelaysec=2) self.assertTrue(res) res = manager.set_autohealingpolicies(healthcheck=hc, initialdelaysec=2) self.assertTrue(res) def test_ex_create_instancegroupmanager(self): name = 'myinstancegroup' zone = 'us-central1-a' size = 4 template_name = 'my-instance-template1' template = self.driver.ex_get_instancetemplate(template_name) mig = self.driver.ex_create_instancegroupmanager( name, zone, template, size, base_instance_name='base-foo') self.assertEqual(mig.name, name) self.assertEqual(mig.size, size) self.assertEqual(mig.zone.name, zone) def test_ex_create_instancegroupmanager_shared_network(self): name = 'myinstancegroup-shared-network' zone = 'us-central1-a' size = 4 template_name = 'my-instance-template-shared-network' template = self.driver.ex_get_instancetemplate(template_name) mig = self.driver.ex_create_instancegroupmanager( name, zone, template, size, base_instance_name='base-foo') self.assertEqual(mig.name, name) self.assertEqual(mig.size, size) self.assertEqual(mig.zone.name, zone) def test_ex_create_instancetemplate(self): name = 'my-instance-template1' actual = self.driver.ex_create_instancetemplate( name, size='n1-standard-1', image='debian-7', network='default') self.assertEqual(actual.name, name) self.assertEqual(actual.extra['properties']['machineType'], 'n1-standard-1') def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(len(locations), 6) self.assertEqual(locations[0].name, 'asia-east1-a') def test_ex_list_routes(self): routes = self.driver.ex_list_routes() self.assertEqual(len(routes), 3) self.assertTrue('lcdemoroute' in [route.name for route in routes]) def test_ex_list_sslcertificate(self): ssl_name = 'example' certs = self.driver.ex_list_sslcertificates() self.assertEqual(certs[0].name, ssl_name) self.assertTrue(len(certs) == 1) def test_ex_list_subnetworks(self): subnetworks = self.driver.ex_list_subnetworks() self.assertEqual(len(subnetworks), 1) self.assertEqual(subnetworks[0].name, 'cf-972cf02e6ad49112') self.assertEqual(subnetworks[0].cidr, '10.128.0.0/20') subnetworks = self.driver.ex_list_subnetworks('all') self.assertEqual(len(subnetworks), 4) def test_ex_create_sslcertificate(self): ssl_name = 'example' private_key = '-----BEGIN RSA PRIVATE KEY-----\nfoobar==\n-----END RSA PRIVATE KEY-----\n' certificate = '-----BEGIN CERTIFICATE-----\nfoobar==\n-----END CERTIFICATE-----\n' ssl = self.driver.ex_create_sslcertificate( ssl_name, certificate=certificate, private_key=private_key) self.assertEqual(ssl_name, ssl.name) self.assertEqual(certificate, ssl.certificate) def test_ex_create_subnetwork(self): name = 'cf-972cf02e6ad49112' cidr = '10.128.0.0/20' network_name = 'cf' network = self.driver.ex_get_network(network_name) region_name = 'us-central1' region = self.driver.ex_get_region(region_name) description = 'LCTestSubnet' privateipgoogleaccess = True secondaryipranges = [{"rangeName": "secondary", "ipCidrRange": "192.168.168.0/24"}] # test by network/region name subnet = self.driver.ex_create_subnetwork( name, cidr, network_name, region_name, description=description, privateipgoogleaccess=privateipgoogleaccess, secondaryipranges=secondaryipranges) self.assertTrue(isinstance(subnet, GCESubnetwork)) self.assertTrue(isinstance(subnet.region, GCERegion)) self.assertTrue(isinstance(subnet.network, GCENetwork)) self.assertEqual(subnet.name, name) self.assertEqual(subnet.cidr, cidr) self.assertEqual(subnet.extra['privateIpGoogleAccess'], privateipgoogleaccess) self.assertEqual(subnet.extra['secondaryIpRanges'], secondaryipranges) # test by network/region object subnet = self.driver.ex_create_subnetwork(name, cidr, network, region) self.assertTrue(isinstance(subnet, GCESubnetwork)) self.assertTrue(isinstance(subnet.region, GCERegion)) self.assertTrue(isinstance(subnet.network, GCENetwork)) self.assertEqual(subnet.name, name) self.assertEqual(subnet.cidr, cidr) self.assertEqual(subnet.extra['privateIpGoogleAccess'], privateipgoogleaccess) self.assertEqual(subnet.extra['secondaryIpRanges'], secondaryipranges) def test_ex_destroy_subnetwork(self): name = 'cf-972cf02e6ad49112' region_name = 'us-central1' region = self.driver.ex_get_region(region_name) # delete with no region self.assertTrue(self.driver.ex_destroy_subnetwork(name)) # delete with region name self.assertTrue(self.driver.ex_destroy_subnetwork(name, region_name)) # delete with region object self.assertTrue(self.driver.ex_destroy_subnetwork(name, region)) def test_ex_get_sslcertificate(self): ssl_name = 'example' ssl = self.driver.ex_get_sslcertificate(ssl_name) self.assertEqual(ssl.name, ssl_name) self.assertTrue(hasattr(ssl, 'certificate')) self.assertTrue(len(ssl.certificate)) def test_ex_get_accelerator_type(self): name = 'nvidia-tesla-k80' zone = self.driver.ex_get_zone('us-central1-a') accelerator_type = self.driver.ex_get_accelerator_type(name, zone) self.assertEqual(accelerator_type.name, name) self.assertEqual(accelerator_type.zone, zone) def test_ex_get_subnetwork(self): name = 'cf-972cf02e6ad49112' region_name = 'us-central1' region = self.driver.ex_get_region(region_name) # fetch by no region subnetwork = self.driver.ex_get_subnetwork(name) self.assertEqual(subnetwork.name, name) # fetch by region name subnetwork = self.driver.ex_get_subnetwork(name, region_name) self.assertEqual(subnetwork.name, name) # fetch by region object subnetwork = self.driver.ex_get_subnetwork(name, region) self.assertEqual(subnetwork.name, name) # do the same but this time by resource URL url = 'https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112' # fetch by no region subnetwork = self.driver.ex_get_subnetwork(url) self.assertEqual(subnetwork.name, name) self.assertEqual(subnetwork.region.name, region_name) # test with a subnetwork that is under a different project url_other = 'https://www.googleapis.com/compute/v1/projects/other_name/regions/us-central1/subnetworks/cf-972cf02e6ad49114' subnetwork = self.driver.ex_get_subnetwork(url_other) self.assertEqual(subnetwork.name, "cf-972cf02e6ad49114") def test_ex_list_networks(self): networks = self.driver.ex_list_networks() self.assertEqual(len(networks), 3) self.assertEqual(networks[0].name, 'cf') self.assertEqual(networks[0].mode, 'auto') self.assertEqual(len(networks[0].subnetworks), 4) self.assertEqual(networks[1].name, 'custom') self.assertEqual(networks[1].mode, 'custom') self.assertEqual(len(networks[1].subnetworks), 1) self.assertEqual(networks[2].name, 'default') self.assertEqual(networks[2].mode, 'legacy') def test_list_nodes(self): nodes = self.driver.list_nodes() nodes_all = self.driver.list_nodes(ex_zone='all') nodes_uc1a = self.driver.list_nodes(ex_zone='us-central1-a') self.assertEqual(len(nodes), 1) self.assertEqual(len(nodes_all), 8) self.assertEqual(len(nodes_uc1a), 1) self.assertEqual(nodes[0].name, 'node-name') self.assertEqual(nodes_uc1a[0].name, 'node-name') self.assertEqual(nodes_uc1a[0].extra['cpuPlatform'], 'Intel Skylake') self.assertEqual(nodes_uc1a[0].extra['minCpuPlatform'], 'Intel Skylake') names = [n.name for n in nodes_all] self.assertTrue('node-name' in names) states = [n.state for n in nodes_all] self.assertTrue(NodeState.SUSPENDED in states) def test_ex_list_regions(self): regions = self.driver.ex_list_regions() self.assertEqual(len(regions), 3) self.assertEqual(regions[0].name, 'europe-west1') def test_ex_list_snapshots(self): snapshots = self.driver.ex_list_snapshots() self.assertEqual(len(snapshots), 2) self.assertEqual(snapshots[0].name, 'lcsnapshot') def test_ex_list_targethttpproxies(self): target_proxies = self.driver.ex_list_targethttpproxies() self.assertEqual(len(target_proxies), 2) self.assertEqual(target_proxies[0].name, 'web-proxy') names = [t.name for t in target_proxies] self.assertListEqual(names, ['web-proxy', 'web-proxy2']) def test_ex_list_targetinstances(self): target_instances = self.driver.ex_list_targetinstances() target_instances_all = self.driver.ex_list_targetinstances('all') target_instances_uc1 = self.driver.ex_list_targetinstances( 'us-central1-a') self.assertEqual(len(target_instances), 2) self.assertEqual(len(target_instances_all), 2) self.assertEqual(len(target_instances_uc1), 2) self.assertEqual(target_instances[0].name, 'hello') self.assertEqual(target_instances_uc1[0].name, 'hello') names = [t.name for t in target_instances_all] self.assertTrue('lctargetinstance' in names) def test_ex_list_targetpools(self): target_pools = self.driver.ex_list_targetpools() target_pools_all = self.driver.ex_list_targetpools('all') target_pools_uc1 = self.driver.ex_list_targetpools('us-central1') self.assertEqual(len(target_pools), 4) self.assertEqual(len(target_pools_all), 5) self.assertEqual(len(target_pools_uc1), 4) self.assertEqual(target_pools[0].name, 'lctargetpool') self.assertEqual(target_pools_uc1[0].name, 'lctargetpool') names = [t.name for t in target_pools_all] self.assertTrue('www-pool' in names) def test_list_sizes(self): sizes = self.driver.list_sizes() sizes_all = self.driver.list_sizes('all') self.assertEqual(len(sizes), 22) self.assertEqual(len(sizes_all), 100) self.assertEqual(sizes[0].name, 'f1-micro') self.assertEqual(sizes[0].extra['zone'].name, 'us-central1-a') names = [s.name for s in sizes_all] self.assertEqual(names.count('n1-standard-1'), 5) def test_ex_get_license(self): license = self.driver.ex_get_license('suse-cloud', 'sles-12') self.assertEqual(license.name, 'sles-12') self.assertTrue(license.charges_use_fee) def test_list_disktypes(self): disktypes = self.driver.ex_list_disktypes() disktypes_all = self.driver.ex_list_disktypes('all') disktypes_uc1a = self.driver.ex_list_disktypes('us-central1-a') self.assertEqual(len(disktypes), 2) self.assertEqual(len(disktypes_all), 9) self.assertEqual(len(disktypes_uc1a), 2) self.assertEqual(disktypes[0].name, 'pd-ssd') self.assertEqual(disktypes_uc1a[0].name, 'pd-ssd') names = [v.name for v in disktypes_all] self.assertTrue('pd-standard' in names) self.assertTrue('local-ssd' in names) def test_ex_list_instancegroupmanagers(self): instancegroupmanagers = self.driver.ex_list_instancegroupmanagers() instancegroupmanagers_all = self.driver.ex_list_instancegroupmanagers( 'all') instancegroupmanagers_ue1b = self.driver.ex_list_instancegroupmanagers( 'us-east1-b') self.assertEqual(len(instancegroupmanagers), 1) self.assertEqual(len(instancegroupmanagers_all), 2) self.assertEqual(len(instancegroupmanagers_ue1b), 1) def test_ex_instancegroupmanager_list_managed_instances(self): ig_name = 'myinstancegroup' ig_zone = 'us-central1-a' mig = self.driver.ex_get_instancegroupmanager(ig_name, ig_zone) instances = mig.list_managed_instances() self.assertTrue(all([x['currentAction'] == 'NONE' for x in instances])) self.assertTrue('base-foo-2vld' in [x['name'] for x in instances]) self.assertEqual(len(instances), 4) def test_ex_list_instancetemplates(self): instancetemplates = self.driver.ex_list_instancetemplates() self.assertEqual(len(instancetemplates), 1) self.assertEqual(instancetemplates[0].name, 'my-instance-template1') def test_ex_list_autoscalers(self): autoscalers = self.driver.ex_list_autoscalers('all') self.assertEqual(len(autoscalers), 1) self.assertEqual(autoscalers[0].name, 'my-autoscaler') def test_ex_list_urlmaps(self): urlmaps_list = self.driver.ex_list_urlmaps() web_map = urlmaps_list[0] self.assertEqual(web_map.name, 'web-map') self.assertEqual(len(web_map.host_rules), 0) self.assertEqual(len(web_map.path_matchers), 0) self.assertEqual(len(web_map.tests), 0) def test_list_volumes(self): volumes = self.driver.list_volumes() volumes_all = self.driver.list_volumes('all') volumes_uc1a = self.driver.list_volumes('us-central1-a') self.assertEqual(len(volumes), 2) self.assertEqual(len(volumes_all), 17) self.assertEqual(len(volumes_uc1a), 2) self.assertEqual(volumes[0].name, 'lcdisk') self.assertEqual(volumes_uc1a[0].name, 'lcdisk') names = [v.name for v in volumes_all] self.assertTrue('libcloud-demo-europe-boot-disk' in names) def test_ex_list_zones(self): zones = self.driver.ex_list_zones() self.assertEqual(len(zones), 6) self.assertEqual(zones[0].name, 'asia-east1-a') def test_ex_create_address_global(self): address_name = 'lcaddressglobal' address = self.driver.ex_create_address(address_name, 'global') self.assertTrue(isinstance(address, GCEAddress)) self.assertEqual(address.name, address_name) self.assertEqual(address.region, 'global') def test_ex_create_address(self): address_name = 'lcaddress' address = self.driver.ex_create_address(address_name) self.assertTrue(isinstance(address, GCEAddress)) self.assertEqual(address.name, address_name) def test_ex_create_address_internal(self): address_name = 'lcaddressinternal' address = self.driver.ex_create_address(address_name, region='us-central1', address='10.128.0.12', address_type='INTERNAL', subnetwork='subnet-1') self.assertTrue(isinstance(address, GCEAddress)) self.assertEqual(address.name, address_name) self.assertEqual(address.address, '10.128.0.12') self.assertRaises(ValueError, self.driver.ex_create_address, address_name, address_type='WRONG') self.assertRaises(ValueError, self.driver.ex_create_address, address_name, address_type='EXTERNAL', subnetwork='subnet-1') def test_ex_create_backend(self): # Note: this is an internal object, no API call is made # and no fixture is needed specifically for GCEBackend, however # it does rely on an InstanceGroup object. ig = self.driver.ex_get_instancegroup('myinstancegroup', 'us-central1-a') backend = self.driver.ex_create_backend(ig) self.assertTrue(isinstance(backend, GCEBackend)) self.assertEqual(backend.name, '%s/instanceGroups/%s' % (ig.zone.name, ig.name)) self.assertEqual(backend.instance_group.name, ig.name) self.assertEqual(backend.balancing_mode, 'UTILIZATION') def test_ex_create_backendservice(self): backendservice_name = 'web-service' ig1 = self.driver.ex_get_instancegroup('myinstancegroup', 'us-central1-a') backend1 = self.driver.ex_create_backend(ig1) ig2 = self.driver.ex_get_instancegroup('myinstancegroup2', 'us-central1-a') backend2 = self.driver.ex_create_backend(ig2) backendservice = self.driver.ex_create_backendservice( name=backendservice_name, healthchecks=['lchealthcheck'], backends=[backend1, backend2]) self.assertTrue(isinstance(backendservice, GCEBackendService)) self.assertEqual(backendservice.name, backendservice_name) self.assertEqual(len(backendservice.backends), 2) ig_links = [ig1.extra['selfLink'], ig2.extra['selfLink']] for be in backendservice.backends: self.assertTrue(be['group'] in ig_links) def test_ex_create_healthcheck(self): healthcheck_name = 'lchealthcheck' kwargs = {'host': 'lchost', 'path': '/lc', 'port': 8000, 'interval': 10, 'timeout': 10, 'unhealthy_threshold': 4, 'healthy_threshold': 3, 'description': 'test healthcheck'} hc = self.driver.ex_create_healthcheck(healthcheck_name, **kwargs) self.assertTrue(isinstance(hc, GCEHealthCheck)) self.assertEqual(hc.name, healthcheck_name) self.assertEqual(hc.path, '/lc') self.assertEqual(hc.port, 8000) self.assertEqual(hc.interval, 10) self.assertEqual(hc.extra['host'], 'lchost') self.assertEqual(hc.extra['description'], 'test healthcheck') def test_ex_create_image(self): volume = self.driver.ex_get_volume('lcdisk') description = 'CoreOS, CoreOS stable, 1520.6.0, amd64-usr published on 2017-10-12' name = 'coreos' family = 'coreos-stable' licenses = ["projects/coreos-cloud/global/licenses/coreos-stable"] guest_os_features = ['VIRTIO_SCSI_MULTIQUEUE'] expected_features = [{'type': 'VIRTIO_SCSI_MULTIQUEUE'}] mock_request = mock.Mock() mock_request.side_effect = self.driver.connection.async_request self.driver.connection.async_request = mock_request image = self.driver.ex_create_image( name, volume, description=description, family=family, guest_os_features=guest_os_features, ex_licenses=licenses) self.assertTrue(isinstance(image, GCENodeImage)) self.assertTrue(image.name.startswith(name)) self.assertEqual(image.extra['description'], description) self.assertEqual(image.extra['family'], family) self.assertEqual(image.extra['guestOsFeatures'], expected_features) self.assertEqual(image.extra['licenses'][0].name, licenses[0].split("/")[-1]) expected_data = {'description': description, 'family': family, 'guestOsFeatures': expected_features, 'name': name, 'licenses': licenses, 'sourceDisk': volume.extra['selfLink'], 'zone': volume.extra['zone'].name} mock_request.assert_called_once_with('/global/images', data=expected_data, method='POST') def test_ex_copy_image(self): name = 'coreos' url = 'gs://storage.core-os.net/coreos/amd64-generic/247.0.0/coreos_production_gce.tar.gz' description = 'CoreOS, CoreOS stable, 1520.6.0, amd64-usr published on 2017-10-12' family = 'coreos-stable' guest_os_features = ['VIRTIO_SCSI_MULTIQUEUE'] expected_features = [{'type': 'VIRTIO_SCSI_MULTIQUEUE'}] image = self.driver.ex_copy_image(name, url, description=description, family=family, guest_os_features=guest_os_features) self.assertTrue(image.name.startswith(name)) self.assertEqual(image.extra['description'], description) self.assertEqual(image.extra['family'], family) self.assertEqual(image.extra['guestOsFeatures'], expected_features) def test_ex_create_firewall(self): name = 'lcfirewall' priority = 900 description = "Libcloud Test Firewall" allowed = [{'IPProtocol': 'tcp', 'ports': ['4567']}] source_service_accounts = ['lcsource@gserviceaccount.com'] target_tags = ['libcloud'] network = 'default' firewall = self.driver.ex_create_firewall( name, allowed, description=description, network=network, priority=priority, target_tags=target_tags, source_service_accounts=source_service_accounts) self.assertTrue(isinstance(firewall, GCEFirewall)) self.assertEqual(firewall.name, name) def test_ex_create_firewall_egress(self): name = 'lcfirewall-egress' priority = 900 direction = 'EGRESS' description = "Libcloud Egress Firewall" allowed = [{'IPProtocol': 'tcp', 'ports': ['4567']}] target_service_accounts = ['lctarget@gserviceaccount.com'] target_ranges = ['8.8.8.8/32'] network = 'default' firewall = self.driver.ex_create_firewall( name, allowed, description=description, network=network, priority=priority, direction=direction, target_ranges=target_ranges, target_service_accounts=target_service_accounts) self.assertTrue(isinstance(firewall, GCEFirewall)) self.assertEqual(firewall.name, name) def test_ex_create_firewall_deny(self): name = 'lcfirewall-deny' priority = 900 denied = [{'IPProtocol': 'tcp', 'ports': ['4567']}] description = "Libcloud Deny Firewall" source_ranges = ['10.240.100.0/24'] source_tags = ['libcloud'] network = 'default' firewall = self.driver.ex_create_firewall( name, denied=denied, description=description, network=network, priority=priority, source_tags=source_tags, source_ranges=source_ranges) self.assertTrue(isinstance(firewall, GCEFirewall)) self.assertEqual(firewall.name, name) def test_ex_create_forwarding_rule(self): fwr_name = 'lcforwardingrule' targetpool = 'lctargetpool' region = 'us-central1' address = 'lcaddress' port_range = '8000-8500' description = 'test forwarding rule' fwr = self.driver.ex_create_forwarding_rule( fwr_name, targetpool, region=region, address=address, port_range=port_range, description=description) self.assertTrue(isinstance(fwr, GCEForwardingRule)) self.assertEqual(fwr.name, fwr_name) self.assertEqual(fwr.region.name, region) self.assertEqual(fwr.protocol, 'TCP') self.assertEqual(fwr.extra['portRange'], port_range) self.assertEqual(fwr.extra['description'], description) def test_ex_create_forwarding_rule_global(self): fwr_name = 'http-rule' target_name = 'web-proxy' address = 'lcaddressglobal' port_range = '80-80' description = 'global forwarding rule' for target in (target_name, self.driver.ex_get_targethttpproxy(target_name)): fwr = self.driver.ex_create_forwarding_rule( fwr_name, target, global_rule=True, address=address, port_range=port_range, description=description) self.assertTrue(isinstance(fwr, GCEForwardingRule)) self.assertEqual(fwr.name, fwr_name) self.assertEqual(fwr.extra['portRange'], port_range) self.assertEqual(fwr.extra['description'], description) def test_ex_create_forwarding_rule_targetpool_keyword(self): """Test backwards compatibility with the targetpool kwarg.""" fwr_name = 'lcforwardingrule' targetpool = 'lctargetpool' region = 'us-central1' address = self.driver.ex_get_address('lcaddress') port_range = '8000-8500' description = 'test forwarding rule' fwr = self.driver.ex_create_forwarding_rule( fwr_name, targetpool=targetpool, region=region, address=address, port_range=port_range, description=description) self.assertTrue(isinstance(fwr, GCEForwardingRule)) self.assertEqual(fwr.name, fwr_name) self.assertEqual(fwr.region.name, region) self.assertEqual(fwr.protocol, 'TCP') self.assertEqual(fwr.extra['portRange'], port_range) self.assertEqual(fwr.extra['description'], description) def test_ex_create_route(self): route_name = 'lcdemoroute' dest_range = '192.168.25.0/24' priority = 1000 route = self.driver.ex_create_route(route_name, dest_range) self.assertTrue(isinstance(route, GCERoute)) self.assertEqual(route.name, route_name) self.assertEqual(route.priority, priority) self.assertTrue("tag1" in route.tags) self.assertTrue(route.extra['nextHopInstance'].endswith( 'libcloud-100')) self.assertEqual(route.dest_range, dest_range) def test_ex_create_network(self): network_name = 'lcnetwork' cidr = '10.11.0.0/16' routing_mode = 'REGIONAL' network = self.driver.ex_create_network(network_name, cidr, routing_mode='regional') self.assertTrue(isinstance(network, GCENetwork)) self.assertEqual(network.name, network_name) self.assertEqual(network.cidr, cidr) # Test using more options description = 'A custom network' network = self.driver.ex_create_network(network_name, cidr, description=description, routing_mode=routing_mode) self.assertEqual(network.extra['description'], description) self.assertEqual(network.extra['routingConfig']['routingMode'], routing_mode) def test_ex_create_network_bad_options(self): network_name = 'lcnetwork' cidr = '10.11.0.0/16' self.assertRaises(ValueError, self.driver.ex_create_network, network_name, cidr, mode='auto') self.assertRaises(ValueError, self.driver.ex_create_network, network_name, cidr, mode='foobar') self.assertRaises(ValueError, self.driver.ex_create_network, network_name, None, mode='legacy') self.assertRaises(ValueError, self.driver.ex_create_network, network_name, cidr, routing_mode='universal') def test_ex_set_machine_type_notstopped(self): # get running node, change machine type zone = 'us-central1-a' node = self.driver.ex_get_node('node-name', zone) self.assertRaises(GoogleBaseError, self.driver.ex_set_machine_type, node, 'custom-4-61440') def test_ex_set_machine_type(self): # get stopped node, change machine type zone = 'us-central1-a' node = self.driver.ex_get_node('stopped-node', zone) self.assertEqual(node.size, 'n1-standard-1') self.assertEqual(node.extra['status'], 'TERMINATED') self.assertTrue( self.driver.ex_set_machine_type(node, 'custom-4-11264')) def test_ex_node_start(self): zone = 'us-central1-a' node = self.driver.ex_get_node('stopped-node', zone) self.assertTrue(self.driver.ex_start_node(node)) def test_ex_node_stop(self): zone = 'us-central1-a' node = self.driver.ex_get_node('node-name', zone) self.assertTrue(self.driver.ex_stop_node(node)) # try and stop a stopped node (should work) zone = 'us-central1-a' node = self.driver.ex_get_node('stopped-node', zone) self.assertTrue(self.driver.ex_stop_node(node)) def test_create_node_req(self): image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') location = self.driver.zone network = self.driver.ex_get_network('default') tags = ['libcloud'] metadata = [{'key': 'test_key', 'value': 'test_value'}] boot_disk = self.driver.ex_get_volume('lcdisk') node_request, node_data = self.driver._create_node_req( 'lcnode', size, image, location, network, tags, metadata, boot_disk) self.assertEqual(node_request, '/zones/%s/instances' % location.name) self.assertEqual(node_data['metadata']['items'][0]['key'], 'test_key') self.assertEqual(node_data['tags']['items'][0], 'libcloud') self.assertEqual(node_data['name'], 'lcnode') self.assertTrue(node_data['disks'][0]['boot']) self.assertIsInstance(node_data['serviceAccounts'], list) self.assertIsInstance(node_data['serviceAccounts'][0], dict) self.assertEqual(node_data['serviceAccounts'][0]['email'], 'default') self.assertIsInstance(node_data['serviceAccounts'][0]['scopes'], list) self.assertEqual(len(node_data['serviceAccounts'][0]['scopes']), 1) self.assertEqual(len(node_data['networkInterfaces']), 1) self.assertTrue(node_data['networkInterfaces'][0][ 'network'].startswith('https://')) def test_create_node_network_opts(self): node_name = 'node-name' size = self.driver.ex_get_size('n1-standard-1') image = self.driver.ex_get_image('debian-7') zone = self.driver.ex_get_zone('us-central1-a') network = self.driver.ex_get_network('lcnetwork') address = self.driver.ex_get_address('lcaddress') ex_nic_gce_struct = [ { "network": "global/networks/lcnetwork", "accessConfigs": [ { "name": "lcnetwork-test", "type": "ONE_TO_ONE_NAT" } ] } ] # Test using default node = self.driver.create_node(node_name, size, image) self.assertEqual(node.extra['networkInterfaces'][0]["name"], 'nic0') # Test using just the network node = self.driver.create_node(node_name, size, image, location=zone, ex_network=network) self.assertEqual(node.extra['networkInterfaces'][0]["name"], 'nic0') # Test using just the struct node = self.driver.create_node(node_name, size, image, location=zone, ex_nic_gce_struct=ex_nic_gce_struct) self.assertEqual(node.extra['networkInterfaces'][0]["name"], 'nic0') # Test both address and struct, should fail self.assertRaises(ValueError, self.driver.create_node, node_name, size, image, location=zone, external_ip=address, ex_nic_gce_struct=ex_nic_gce_struct) # Test both ex_network and struct, should fail self.assertRaises(ValueError, self.driver.create_node, node_name, size, image, location=zone, ex_network=network, ex_nic_gce_struct=ex_nic_gce_struct) def test_create_node_subnetwork_opts(self): node_name = 'sn-node-name' size = self.driver.ex_get_size('n1-standard-1') image = self.driver.ex_get_image('debian-7') zone = self.driver.ex_get_zone('us-central1-a') network = self.driver.ex_get_network('custom-network') subnetwork = self.driver.ex_get_subnetwork('cf-972cf02e6ad49112') ex_nic_gce_struct = [ { "network": "global/networks/custom-network", "subnetwork": "projects/project_name/regions/us-central1/subnetworks/cf-972cf02e6ad49112", "accessConfigs": [ { "name": "External NAT", "type": "ONE_TO_ONE_NAT" } ] } ] # Test using just the network and subnetwork node = self.driver.create_node(node_name, size, image, location=zone, ex_network=network, ex_subnetwork=subnetwork) self.assertEqual(node.extra['networkInterfaces'][0]["name"], 'nic0') self.assertEqual( node.extra['networkInterfaces'][0]["subnetwork"].split('/')[-1], 'cf-972cf02e6ad49112') # Test using just the struct node = self.driver.create_node(node_name, size, image, location=zone, ex_nic_gce_struct=ex_nic_gce_struct) self.assertEqual(node.extra['networkInterfaces'][0]["name"], 'nic0') self.assertEqual( node.extra['networkInterfaces'][0]["subnetwork"].split('/')[-1], 'cf-972cf02e6ad49112') # Test using subnetwork selfLink node = self.driver.create_node( node_name, size, image, location=zone, ex_network=network, ex_subnetwork=subnetwork.extra['selfLink']) self.assertEqual(node.extra['networkInterfaces'][0]["name"], 'nic0') self.assertEqual( node.extra['networkInterfaces'][0]["subnetwork"].split('/')[-1], 'cf-972cf02e6ad49112') def test_create_node_disk_opts(self): node_name = 'node-name' size = self.driver.ex_get_size('n1-standard-1') image = self.driver.ex_get_image('debian-7') boot_disk = self.driver.ex_get_volume('lcdisk') disk_type = self.driver.ex_get_disktype('pd-ssd', 'us-central1-a') DEMO_BASE_NAME = "lc-test" gce_disk_struct = [ { "type": "PERSISTENT", "deviceName": '%s-gstruct' % DEMO_BASE_NAME, "initializeParams": { "diskName": '%s-gstruct' % DEMO_BASE_NAME, "sourceImage": image.extra['selfLink'] }, "boot": True, "autoDelete": True }, { "type": "SCRATCH", "deviceName": '%s-gstruct-lssd' % DEMO_BASE_NAME, "initializeParams": { "diskType": disk_type.extra['selfLink'] }, "autoDelete": True } ] self.assertRaises(ValueError, self.driver.create_node, node_name, size, None) node = self.driver.create_node(node_name, size, image) self.assertTrue(isinstance(node, Node)) node = self.driver.create_node(node_name, size, None, ex_boot_disk=boot_disk) self.assertTrue(isinstance(node, Node)) node = self.driver.create_node(node_name, size, None, ex_disks_gce_struct=gce_disk_struct) self.assertTrue(isinstance(node, Node)) self.assertRaises(ValueError, self.driver.create_node, node_name, size, None, ex_boot_disk=boot_disk, ex_disks_gce_struct=gce_disk_struct) def test_create_node(self): node_name = 'node-name' image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') node = self.driver.create_node(node_name, size, image) self.assertTrue(isinstance(node, Node)) self.assertEqual(node.name, node_name) def test_create_node_disk_size(self): node_name = 'node-name' image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') disk_size = 25 node = self.driver.create_node(node_name, size, image, ex_disk_size=disk_size) self.assertTrue(isinstance(node, Node)) self.assertEqual(node.name, node_name) self.assertEqual(node.extra['boot_disk'].size, str(disk_size)) def test_create_node_image_family(self): node_name = 'node-name' size = self.driver.ex_get_size('n1-standard-1') node = self.driver.create_node(node_name, size, image=None, ex_image_family='coreos-stable') self.assertTrue(isinstance(node, Node)) self.assertEqual(node.name, node_name) image = self.driver.ex_get_image('debian-7') self.assertRaises(ValueError, self.driver.create_node, node_name, size, image, ex_image_family='coreos-stable') def test_create_node_req_with_serviceaccounts(self): image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') location = self.driver.zone network = self.driver.ex_get_network('default') # ex_service_accounts with specific scopes, default 'email' ex_sa = [{'scopes': ['compute-ro', 'pubsub', 'storage-ro']}] node_request, node_data = self.driver._create_node_req( 'lcnode', size, image, location, network, ex_service_accounts=ex_sa) self.assertIsInstance(node_data['serviceAccounts'], list) self.assertIsInstance(node_data['serviceAccounts'][0], dict) self.assertEqual(node_data['serviceAccounts'][0]['email'], 'default') self.assertIsInstance(node_data['serviceAccounts'][0]['scopes'], list) self.assertEqual(len(node_data['serviceAccounts'][0]['scopes']), 3) self.assertTrue('https://www.googleapis.com/auth/devstorage.read_only' in node_data['serviceAccounts'][0]['scopes']) self.assertTrue('https://www.googleapis.com/auth/compute.readonly' in node_data['serviceAccounts'][0]['scopes']) def test_format_metadata(self): in_md = [{'key': 'k0', 'value': 'v0'}, {'key': 'k1', 'value': 'v1'}] out_md = self.driver._format_metadata('fp', in_md) self.assertTrue('fingerprint' in out_md) self.assertEqual(out_md['fingerprint'], 'fp') self.assertTrue('items' in out_md) self.assertEqual(len(out_md['items']), 2) self.assertTrue(out_md['items'][0]['key'] in ['k0', 'k1']) self.assertTrue(out_md['items'][0]['value'] in ['v0', 'v1']) in_md = [{'k0': 'v0'}, {'k1': 'v1'}] out_md = self.driver._format_metadata('fp', in_md) self.assertTrue('fingerprint' in out_md) self.assertEqual(out_md['fingerprint'], 'fp') self.assertTrue('items' in out_md) self.assertEqual(len(out_md['items']), 2) self.assertTrue(out_md['items'][0]['key'] in ['k0', 'k1']) self.assertTrue(out_md['items'][0]['value'] in ['v0', 'v1']) in_md = {'key': 'k0', 'value': 'v0'} out_md = self.driver._format_metadata('fp', in_md) self.assertTrue('fingerprint' in out_md) self.assertEqual(out_md['fingerprint'], 'fp') self.assertTrue('items' in out_md) self.assertEqual(len(out_md['items']), 1, out_md) self.assertEqual(out_md['items'][0]['key'], 'k0') self.assertEqual(out_md['items'][0]['value'], 'v0') in_md = {'k0': 'v0'} out_md = self.driver._format_metadata('fp', in_md) self.assertTrue('fingerprint' in out_md) self.assertEqual(out_md['fingerprint'], 'fp') self.assertTrue('items' in out_md) self.assertEqual(len(out_md['items']), 1) self.assertEqual(out_md['items'][0]['key'], 'k0') self.assertEqual(out_md['items'][0]['value'], 'v0') in_md = {'k0': 'v0', 'k1': 'v1', 'k2': 'v2'} out_md = self.driver._format_metadata('fp', in_md) self.assertTrue('fingerprint' in out_md) self.assertEqual(out_md['fingerprint'], 'fp') self.assertTrue('items' in out_md) self.assertEqual(len(out_md['items']), 3) keys = [x['key'] for x in out_md['items']] vals = [x['value'] for x in out_md['items']] keys.sort() vals.sort() self.assertEqual(keys, ['k0', 'k1', 'k2']) self.assertEqual(vals, ['v0', 'v1', 'v2']) in_md = {'items': [{'key': 'k0', 'value': 'v0'}, {'key': 'k1', 'value': 'v1'}]} out_md = self.driver._format_metadata('fp', in_md) self.assertTrue('fingerprint' in out_md) self.assertEqual(out_md['fingerprint'], 'fp') self.assertTrue('items' in out_md) self.assertEqual(len(out_md['items']), 2) self.assertTrue(out_md['items'][0]['key'] in ['k0', 'k1']) self.assertTrue(out_md['items'][0]['value'] in ['v0', 'v1']) in_md = {'items': 'foo'} self.assertRaises(ValueError, self.driver._format_metadata, 'fp', in_md) in_md = {'items': {'key': 'k1', 'value': 'v0'}} self.assertRaises(ValueError, self.driver._format_metadata, 'fp', in_md) in_md = ['k0', 'v1'] self.assertRaises(ValueError, self.driver._format_metadata, 'fp', in_md) def test_create_node_with_metadata(self): node_name = 'node-name' image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') zone = self.driver.ex_get_zone('us-central1-a') # md is a list of dicts, each with 'key' and 'value' for # backwards compatibility md = [{'key': 'k0', 'value': 'v0'}, {'key': 'k1', 'value': 'v1'}] request, data = self.driver._create_node_req(node_name, size, image, zone, metadata=md) self.assertTrue('items' in data['metadata']) self.assertEqual(len(data['metadata']['items']), 2) # md doesn't contain "items" key md = {'key': 'key1', 'value': 'value1'} request, data = self.driver._create_node_req(node_name, size, image, zone, metadata=md) self.assertTrue('items' in data['metadata']) self.assertEqual(len(data['metadata']['items']), 1) # md contains "items" key md = {'items': [{'key': 'k0', 'value': 'v0'}]} request, data = self.driver._create_node_req(node_name, size, image, zone, metadata=md) self.assertTrue('items' in data['metadata']) self.assertEqual(len(data['metadata']['items']), 1) self.assertEqual(data['metadata']['items'][0]['key'], 'k0') self.assertEqual(data['metadata']['items'][0]['value'], 'v0') def test_create_node_with_accelerator(self): node_name = 'node-name' image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') zone = self.driver.ex_get_zone('us-central1-a') request, data = self.driver._create_node_req( node_name, size, image, zone, ex_accelerator_type='nvidia-tesla-k80', ex_accelerator_count=3) self.assertTrue('guestAccelerators' in data) self.assertEqual(len(data['guestAccelerators']), 1) self.assertTrue('nvidia-tesla-k80' in data['guestAccelerators'][0]['acceleratorType']) self.assertEqual(data['guestAccelerators'][0]['acceleratorCount'], 3) def test_create_node_with_labels(self): node_name = 'node-name' image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') zone = self.driver.ex_get_zone('us-central1-a') # labels is a dict labels = {'label1': 'v1', 'label2': 'v2'} request, data = self.driver._create_node_req(node_name, size, image, zone, ex_labels=labels) self.assertTrue(data['labels'] is not None) self.assertEqual(len(data['labels']), 2) self.assertEqual(data['labels']['label1'], 'v1') self.assertEqual(data['labels']['label2'], 'v2') def test_create_node_existing(self): node_name = 'libcloud-demo-europe-np-node' image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1', zone='europe-west1-a') self.assertRaises(ResourceExistsError, self.driver.create_node, node_name, size, image, location='europe-west1-a') def test_ex_create_multiple_nodes(self): base_name = 'lcnode' image = self.driver.ex_get_image('debian-7') size = self.driver.ex_get_size('n1-standard-1') number = 2 disk_size = "25" # NOTE: We use small poll_interval to speed up the tests nodes = self.driver.ex_create_multiple_nodes(base_name, size, image, number, ex_disk_size=disk_size, poll_interval=0.1) self.assertEqual(len(nodes), 2) self.assertTrue(isinstance(nodes[0], Node)) self.assertTrue(isinstance(nodes[1], Node)) self.assertEqual(nodes[0].name, '%s-000' % base_name) self.assertEqual(nodes[1].name, '%s-001' % base_name) self.assertEqual(nodes[0].extra['boot_disk'].size, disk_size) self.assertEqual(nodes[1].extra['boot_disk'].size, disk_size) def test_ex_create_multiple_nodes_image_family(self): base_name = 'lcnode' image = None size = self.driver.ex_get_size('n1-standard-1') number = 2 # NOTE: We use small poll_interval to speed up the tests nodes = self.driver.ex_create_multiple_nodes( base_name, size, image, number, ex_image_family='coreos-stable', poll_interval=0.1) self.assertEqual(len(nodes), 2) self.assertTrue(isinstance(nodes[0], Node)) self.assertTrue(isinstance(nodes[1], Node)) self.assertEqual(nodes[0].name, '%s-000' % base_name) self.assertEqual(nodes[1].name, '%s-001' % base_name) image = self.driver.ex_get_image('debian-7') self.assertRaises(ValueError, self.driver.ex_create_multiple_nodes, base_name, size, image, number, ex_image_family='coreos-stable') def test_ex_create_targethttpproxy(self): proxy_name = 'web-proxy' urlmap_name = 'web-map' for urlmap in (urlmap_name, self.driver.ex_get_urlmap(urlmap_name)): proxy = self.driver.ex_create_targethttpproxy(proxy_name, urlmap) self.assertTrue(isinstance(proxy, GCETargetHttpProxy)) self.assertEqual(proxy_name, proxy.name) def test_ex_create_targetinstance(self): targetinstance_name = 'lctargetinstance' zone = 'us-central1-a' node = self.driver.ex_get_node('node-name', zone) targetinstance = self.driver.ex_create_targetinstance( targetinstance_name, zone=zone, node=node) self.assertEqual(targetinstance.name, targetinstance_name) self.assertEqual(targetinstance.zone.name, zone) def test_ex_create_targetpool(self): targetpool_name = 'lctargetpool' region = 'us-central1' healthchecks = ['libcloud-lb-demo-healthcheck'] node1 = self.driver.ex_get_node('libcloud-lb-demo-www-000', 'us-central1-b') node2 = self.driver.ex_get_node('libcloud-lb-demo-www-001', 'us-central1-b') nodes = [node1, node2] targetpool = self.driver.ex_create_targetpool( targetpool_name, region=region, healthchecks=healthchecks, nodes=nodes) self.assertEqual(targetpool.name, targetpool_name) self.assertEqual(len(targetpool.nodes), len(nodes)) self.assertEqual(targetpool.region.name, region) def test_ex_create_targetpool_session_affinity(self): targetpool_name = 'lctargetpool-sticky' region = 'us-central1' session_affinity = 'CLIENT_IP_PROTO' targetpool = self.driver.ex_create_targetpool( targetpool_name, region=region, session_affinity=session_affinity) self.assertEqual(targetpool.name, targetpool_name) self.assertEqual( targetpool.extra.get('sessionAffinity'), session_affinity) def test_ex_create_urlmap(self): urlmap_name = 'web-map' for service in ('web-service', self.driver.ex_get_backendservice('web-service')): urlmap = self.driver.ex_create_urlmap(urlmap_name, service) self.assertTrue(isinstance(urlmap, GCEUrlMap)) self.assertEqual(urlmap_name, urlmap.name) def test_create_volume_image_family(self): volume_name = 'lcdisk' size = 10 volume = self.driver.create_volume(size, volume_name, ex_image_family='coreos-stable') self.assertTrue(isinstance(volume, StorageVolume)) self.assertEqual(volume.name, volume_name) image = self.driver.ex_get_image('debian-7') self.assertRaises(ValueError, self.driver.create_volume, size, volume_name, image=image, ex_image_family='coreos-stable') def test_create_volume_location(self): volume_name = 'lcdisk' size = 10 zone = self.driver.zone volume = self.driver.create_volume(size, volume_name, location=zone) self.assertTrue(isinstance(volume, StorageVolume)) self.assertEqual(volume.name, volume_name) def test_ex_create_volume_snapshot(self): snapshot_name = 'lcsnapshot' volume = self.driver.ex_get_volume('lcdisk') snapshot = volume.snapshot(snapshot_name) self.assertEqual(snapshot.name, snapshot_name) self.assertEqual(snapshot.size, '10') def test_create_volume_ssd(self): volume_name = 'lcdisk' size = 10 volume = self.driver.create_volume(size, volume_name, ex_disk_type='pd-ssd') self.assertTrue(isinstance(volume, StorageVolume)) self.assertEqual(volume.extra['type'], 'pd-ssd') def test_create_volume(self): volume_name = 'lcdisk' size = 10 volume = self.driver.create_volume(size, volume_name) self.assertTrue(isinstance(volume, StorageVolume)) self.assertEqual(volume.name, volume_name) def test_ex_set_volume_labels(self): volume_name = 'lcdisk' zone = self.driver.zone volume_labels = {'one': '1', 'two': '2', 'three': '3'} size = 10 new_vol = self.driver.create_volume(size, volume_name, location=zone) self.assertTrue(self.driver.ex_set_volume_labels(new_vol, labels=volume_labels)) exist_vol = self.driver.ex_get_volume(volume_name, self.driver.zone) self.assertEqual(exist_vol.extra['labels'], volume_labels) def test_ex_update_healthcheck(self): healthcheck_name = 'lchealthcheck' healthcheck = self.driver.ex_get_healthcheck(healthcheck_name) healthcheck.port = 9000 healthcheck2 = self.driver.ex_update_healthcheck(healthcheck) self.assertTrue(isinstance(healthcheck2, GCEHealthCheck)) def test_ex_update_firewall(self): firewall_name = 'lcfirewall' firewall = self.driver.ex_get_firewall(firewall_name) firewall.source_ranges = ['10.0.0.0/16'] firewall.description = "LCFirewall-2" firewall2 = self.driver.ex_update_firewall(firewall) self.assertTrue(isinstance(firewall2, GCEFirewall)) def test_ex_targetpool_gethealth(self): targetpool = self.driver.ex_get_targetpool('lb-pool') health = targetpool.get_health('libcloud-lb-demo-www-000') self.assertEqual(len(health), 1) self.assertTrue('node' in health[0]) self.assertTrue('health' in health[0]) self.assertEqual(health[0]['health'], 'UNHEALTHY') def test_ex_targetpool_with_backup_pool(self): targetpool = self.driver.ex_get_targetpool('lb-pool') self.assertTrue('backupPool' in targetpool.extra) self.assertTrue('failoverRatio' in targetpool.extra) def test_ex_targetpool_setbackup(self): targetpool = self.driver.ex_get_targetpool('lb-pool') backup_targetpool = self.driver.ex_get_targetpool('backup-pool') self.assertTrue( targetpool.set_backup_targetpool(backup_targetpool, 0.1)) def test_ex_targetpool_remove_add_node(self): targetpool = self.driver.ex_get_targetpool('lctargetpool') node = self.driver.ex_get_node('libcloud-lb-demo-www-001', 'us-central1-b') remove_node = self.driver.ex_targetpool_remove_node(targetpool, node) self.assertTrue(remove_node) self.assertEqual(len(targetpool.nodes), 1) add_node = self.driver.ex_targetpool_add_node(targetpool, node.extra['selfLink']) self.assertTrue(add_node) self.assertEqual(len(targetpool.nodes), 2) remove_node = self.driver.ex_targetpool_remove_node( targetpool, node.extra['selfLink']) self.assertTrue(remove_node) self.assertEqual(len(targetpool.nodes), 1) add_node = self.driver.ex_targetpool_add_node(targetpool, node) self.assertTrue(add_node) self.assertEqual(len(targetpool.nodes), 2) # check that duplicates are filtered add_node = self.driver.ex_targetpool_add_node(targetpool, node.extra['selfLink']) self.assertTrue(add_node) self.assertEqual(len(targetpool.nodes), 2) def test_ex_targetpool_remove_add_healthcheck(self): targetpool = self.driver.ex_get_targetpool('lctargetpool') healthcheck = self.driver.ex_get_healthcheck( 'libcloud-lb-demo-healthcheck') remove_healthcheck = self.driver.ex_targetpool_remove_healthcheck( targetpool, healthcheck) self.assertTrue(remove_healthcheck) self.assertEqual(len(targetpool.healthchecks), 0) add_healthcheck = self.driver.ex_targetpool_add_healthcheck( targetpool, healthcheck) self.assertTrue(add_healthcheck) self.assertEqual(len(targetpool.healthchecks), 1) def test_reboot_node(self): node = self.driver.ex_get_node('node-name') reboot = self.driver.reboot_node(node) self.assertTrue(reboot) def test_ex_set_node_tags(self): new_tags = ['libcloud'] node = self.driver.ex_get_node('node-name') set_tags = self.driver.ex_set_node_tags(node, new_tags) self.assertTrue(set_tags) def test_attach_volume_invalid_usecase(self): node = self.driver.ex_get_node('node-name') self.assertRaises(ValueError, self.driver.attach_volume, node, None) self.assertRaises(ValueError, self.driver.attach_volume, node, None, ex_source='foo/bar', device=None) def test_attach_volume(self): volume = self.driver.ex_get_volume('lcdisk') node = self.driver.ex_get_node('node-name') attach = volume.attach(node) self.assertTrue(attach) def test_ex_resize_volume(self): volume = self.driver.ex_get_volume('lcdisk') desired_size = int(volume.size) + 8 resize = self.driver.ex_resize_volume(volume, desired_size) self.assertTrue(resize) def test_detach_volume(self): volume = self.driver.ex_get_volume('lcdisk') node = self.driver.ex_get_node('node-name') # This fails since the node is required detach = volume.detach() self.assertFalse(detach) # This should pass detach = self.driver.detach_volume(volume, node) self.assertTrue(detach) def test_ex_destroy_address_global(self): address = self.driver.ex_get_address('lcaddressglobal', 'global') self.assertEqual(address.name, 'lcaddressglobal') self.assertEqual(address.region, 'global') destroyed = address.destroy() self.assertTrue(destroyed) def test_ex_destroy_address(self): address = self.driver.ex_get_address('lcaddress') destroyed = address.destroy() self.assertTrue(destroyed) def test_ex_destroy_backendservice(self): backendservice = self.driver.ex_get_backendservice('web-service') destroyed = backendservice.destroy() self.assertTrue(destroyed) def test_ex_destroy_healthcheck(self): hc = self.driver.ex_get_healthcheck('lchealthcheck') destroyed = hc.destroy() self.assertTrue(destroyed) def test_ex_delete_image(self): self.assertRaises(ResourceNotFoundError, self.driver.ex_get_image, 'missing-image') self.assertRaises(ResourceNotFoundError, self.driver.ex_delete_image, 'missing-image') image = self.driver.ex_get_image('debian-7') deleted = self.driver.ex_delete_image(image) self.assertTrue(deleted) def test_ex_deprecate_image(self): dep_ts = '2064-03-11T20:18:36.194-07:00' obs_ts = '2074-03-11T20:18:36.194-07:00' del_ts = '2084-03-11T20:18:36.194-07:00' image = self.driver.ex_get_image('debian-7-wheezy-v20131014') deprecated = image.deprecate('debian-7', 'DEPRECATED', deprecated=dep_ts, obsolete=obs_ts, deleted=del_ts) self.assertTrue(deprecated) self.assertEqual(image.extra['deprecated']['deprecated'], dep_ts) self.assertEqual(image.extra['deprecated']['obsolete'], obs_ts) self.assertEqual(image.extra['deprecated']['deleted'], del_ts) def test_ex_destroy_firewall(self): firewall = self.driver.ex_get_firewall('lcfirewall') destroyed = firewall.destroy() self.assertTrue(destroyed) def test_ex_destroy_forwarding_rule(self): fwr = self.driver.ex_get_forwarding_rule('lcforwardingrule') destroyed = fwr.destroy() self.assertTrue(destroyed) def test_ex_destroy_forwarding_rule_global(self): fwr = self.driver.ex_get_forwarding_rule('http-rule', global_rule=True) destroyed = fwr.destroy() self.assertTrue(destroyed) def test_ex_destroy_route(self): route = self.driver.ex_get_route('lcdemoroute') destroyed = route.destroy() self.assertTrue(destroyed) def test_ex_destroy_network(self): network = self.driver.ex_get_network('lcnetwork') destroyed = network.destroy() self.assertTrue(destroyed) def test_destroy_node(self): node = self.driver.ex_get_node('node-name') destroyed = node.destroy() self.assertTrue(destroyed) def test_ex_destroy_multiple_nodes(self): nodes = [] nodes.append(self.driver.ex_get_node('lcnode-000')) nodes.append(self.driver.ex_get_node('lcnode-001')) destroyed = self.driver.ex_destroy_multiple_nodes(nodes) for d in destroyed: self.assertTrue(d) def test_destroy_targethttpproxy(self): proxy = self.driver.ex_get_targethttpproxy('web-proxy') destroyed = proxy.destroy() self.assertTrue(destroyed) def test_destroy_targetinstance(self): targetinstance = self.driver.ex_get_targetinstance('lctargetinstance') self.assertEqual(targetinstance.name, 'lctargetinstance') destroyed = targetinstance.destroy() self.assertTrue(destroyed) def test_destroy_targetpool(self): targetpool = self.driver.ex_get_targetpool('lctargetpool') destroyed = targetpool.destroy() self.assertTrue(destroyed) def test_destroy_urlmap(self): urlmap = self.driver.ex_get_urlmap('web-map') destroyed = urlmap.destroy() self.assertTrue(destroyed) def test_destroy_volume(self): disk = self.driver.ex_get_volume('lcdisk') destroyed = disk.destroy() self.assertTrue(destroyed) def test_ex_set_volume_auto_delete(self): node = self.driver.ex_get_node('node-name') volume = node.extra['boot_disk'] auto_delete = self.driver.ex_set_volume_auto_delete(volume, node) self.assertTrue(auto_delete) def test_destroy_volume_snapshot(self): snapshot = self.driver.ex_get_snapshot('lcsnapshot') destroyed = snapshot.destroy() self.assertTrue(destroyed) def test_ex_get_address_global(self): address_name = 'lcaddressglobal' address = self.driver.ex_get_address(address_name, 'global') self.assertEqual(address.name, address_name) self.assertEqual(address.address, '173.99.99.99') self.assertEqual(address.region, 'global') self.assertEqual(address.extra['status'], 'RESERVED') def test_ex_get_address(self): address_name = 'lcaddress' address = self.driver.ex_get_address(address_name) self.assertEqual(address.name, address_name) self.assertEqual(address.address, '173.255.113.20') self.assertEqual(address.region.name, 'us-central1') self.assertEqual(address.extra['status'], 'RESERVED') def test_ex_get_backendservice(self): web_service = self.driver.ex_get_backendservice('web-service') self.assertEqual(web_service.name, 'web-service') self.assertEqual(web_service.protocol, 'HTTP') self.assertEqual(web_service.port, 80) self.assertEqual(web_service.timeout, 30) self.assertEqual(web_service.healthchecks[0].name, 'basic-check') self.assertEqual(len(web_service.healthchecks), 1) backends = web_service.backends self.assertEqual(len(backends), 2) self.assertEqual(backends[0]['balancingMode'], 'RATE') self.assertEqual(backends[0]['maxRate'], 100) self.assertEqual(backends[0]['capacityScaler'], 1.0) web_service = self.driver.ex_get_backendservice('no-backends') self.assertEqual(web_service.name, 'web-service') self.assertEqual(web_service.healthchecks[0].name, 'basic-check') self.assertEqual(len(web_service.healthchecks), 1) self.assertEqual(len(web_service.backends), 0) def test_ex_get_healthcheck(self): healthcheck_name = 'lchealthcheck' healthcheck = self.driver.ex_get_healthcheck(healthcheck_name) self.assertEqual(healthcheck.name, healthcheck_name) self.assertEqual(healthcheck.port, 8000) self.assertEqual(healthcheck.path, '/lc') def test_ex_get_firewall(self): firewall_name = 'lcfirewall' firewall = self.driver.ex_get_firewall(firewall_name) self.assertEqual(firewall.name, firewall_name) self.assertEqual(firewall.network.name, 'default') self.assertEqual(firewall.target_tags, ['libcloud']) def test_ex_get_forwarding_rule(self): fwr_name = 'lcforwardingrule' fwr = self.driver.ex_get_forwarding_rule(fwr_name) self.assertEqual(fwr.name, fwr_name) self.assertEqual(fwr.extra['portRange'], '8000-8500') self.assertEqual(fwr.targetpool.name, 'lctargetpool') self.assertEqual(fwr.protocol, 'TCP') def test_ex_get_forwarding_rule_global(self): fwr_name = 'http-rule' fwr = self.driver.ex_get_forwarding_rule(fwr_name, global_rule=True) self.assertEqual(fwr.name, fwr_name) self.assertEqual(fwr.extra['portRange'], '80-80') self.assertEqual(fwr.targetpool.name, 'web-proxy') self.assertEqual(fwr.protocol, 'TCP') self.assertEqual(fwr.address, '192.0.2.1') self.assertEqual(fwr.targetpool.name, 'web-proxy') def test_ex_get_image_license(self): image = self.driver.ex_get_image('sles-12-v20141023') self.assertTrue('licenses' in image.extra) self.assertEqual(image.extra['licenses'][0].name, 'sles-12') self.assertTrue(image.extra['licenses'][0].charges_use_fee) def test_ex_get_image(self): partial_name = 'debian-7' image = self.driver.ex_get_image(partial_name) self.assertEqual(image.name, 'debian-7-wheezy-v20131120') # A 'debian-7' image exists in the local project self.assertTrue(image.extra['description'].startswith('Debian')) partial_name = 'debian-6' image = self.driver.ex_get_image(partial_name) self.assertEqual(image.name, 'debian-6-squeeze-v20130926') self.assertTrue(image.extra['description'].startswith('Debian')) partial_name = 'debian-7' image = self.driver.ex_get_image(partial_name, ['debian-cloud']) self.assertEqual(image.name, 'debian-7-wheezy-v20131120') partial_name = 'debian-7' self.assertRaises(ResourceNotFoundError, self.driver.ex_get_image, partial_name, 'suse-cloud', ex_standard_projects=False) def test_ex_get_image_from_family(self): family = 'coreos-beta' description = 'CoreOS beta 522.3.0' image = self.driver.ex_get_image_from_family(family) self.assertEqual(image.name, 'coreos-beta-522-3-0-v20141226') self.assertEqual(image.extra['description'], description) self.assertEqual(image.extra['family'], family) url = ('https://www.googleapis.com/compute/v1/projects/coreos-cloud/' 'global/images/family/coreos-beta') image = self.driver.ex_get_image_from_family(url) self.assertEqual(image.name, 'coreos-beta-522-3-0-v20141226') self.assertEqual(image.extra['description'], description) self.assertEqual(image.extra['family'], family) project_list = ['coreos-cloud'] image = self.driver.ex_get_image_from_family( family, ex_project_list=project_list, ex_standard_projects=False) self.assertEqual(image.name, 'coreos-beta-522-3-0-v20141226') self.assertEqual(image.extra['description'], description) self.assertEqual(image.extra['family'], family) self.assertRaises(ResourceNotFoundError, self.driver.ex_get_image_from_family, 'nofamily') def test_ex_get_route(self): route_name = 'lcdemoroute' route = self.driver.ex_get_route(route_name) self.assertEqual(route.name, route_name) self.assertEqual(route.dest_range, '192.168.25.0/24') self.assertEqual(route.priority, 1000) def test_ex_get_network(self): network_name = 'lcnetwork' network = self.driver.ex_get_network(network_name) self.assertEqual(network.name, network_name) self.assertEqual(network.cidr, '10.11.0.0/16') self.assertEqual(network.extra['gatewayIPv4'], '10.11.0.1') self.assertEqual(network.extra['description'], 'A custom network') # do the same but this time with URL url = 'https://www.googleapis.com/compute/v1/projects/project_name/global/networks/lcnetwork' network = self.driver.ex_get_network(url) self.assertEqual(network.name, network_name) self.assertEqual(network.cidr, '10.11.0.0/16') self.assertEqual(network.extra['gatewayIPv4'], '10.11.0.1') self.assertEqual(network.extra['description'], 'A custom network') # do the same but with a network under a different project url_other = 'https://www.googleapis.com/compute/v1/projects/other_name/global/networks/lcnetwork' network = self.driver.ex_get_network(url_other) self.assertEqual(network.name, network_name) self.assertEqual(network.cidr, '10.11.0.0/16') self.assertEqual(network.extra['gatewayIPv4'], '10.11.0.1') self.assertEqual(network.extra['description'], 'A custom network') def test_ex_get_node(self): node_name = 'node-name' zone = 'us-central1-a' node = self.driver.ex_get_node(node_name, zone) self.assertEqual(node.name, node_name) self.assertEqual(node.size, 'n1-standard-1') removed_node = 'libcloud-lb-demo-www-002' self.assertRaises(ResourceNotFoundError, self.driver.ex_get_node, removed_node, 'us-central1-b') missing_node = 'dummy-node' self.assertRaises(ResourceNotFoundError, self.driver.ex_get_node, missing_node, 'all') def test_ex_get_project(self): project = self.driver.ex_get_project() self.assertEqual(project.name, 'project_name') networks_quota = project.quotas[1] self.assertEqual(networks_quota['usage'], 3) self.assertEqual(networks_quota['limit'], 5) self.assertEqual(networks_quota['metric'], 'NETWORKS') self.assertTrue( 'fingerprint' in project.extra['commonInstanceMetadata']) self.assertTrue('items' in project.extra['commonInstanceMetadata']) self.assertTrue('usageExportLocation' in project.extra) self.assertTrue('bucketName' in project.extra['usageExportLocation']) self.assertEqual(project.extra['usageExportLocation']['bucketName'], 'gs://graphite-usage-reports') def test_ex_add_access_config(self): self.assertRaises(ValueError, self.driver.ex_add_access_config, 'node', 'name', 'nic') node = self.driver.ex_get_node('node-name', 'us-central1-a') self.assertTrue(self.driver.ex_add_access_config(node, 'foo', 'bar')) def test_ex_delete_access_config(self): self.assertRaises(ValueError, self.driver.ex_add_access_config, 'node', 'name', 'nic') node = self.driver.ex_get_node('node-name', 'us-central1-a') self.assertTrue( self.driver.ex_delete_access_config(node, 'foo', 'bar')) def test_ex_set_usage_export_bucket(self): self.assertRaises(ValueError, self.driver.ex_set_usage_export_bucket, 'foo') bucket_name = 'gs://foo' self.driver.ex_set_usage_export_bucket(bucket_name) bucket_name = 'https://www.googleapis.com/foo' self.driver.ex_set_usage_export_bucket(bucket_name) project = GCEProject(id=None, name=None, metadata=None, quotas=None, driver=self.driver) project.set_usage_export_bucket(bucket=bucket_name) def test__set_project_metadata(self): self.assertEqual( len(self.driver._set_project_metadata(None, False, "")), 0) # 'delete' metadata, but retain current sshKeys md = self.driver._set_project_metadata(None, False, "this is a test") self.assertEqual(len(md), 1) self.assertEqual(md[0]['key'], 'sshKeys') self.assertEqual(md[0]['value'], 'this is a test') # 'delete' metadata *and* any existing sshKeys md = self.driver._set_project_metadata(None, True, "this is a test") self.assertEqual(len(md), 0) # add new metadata, keep existing sshKeys, since the new value also # has 'sshKeys', we want the final struct to only have one ke/value # of sshKeys and it should be the "current_keys" gce_md = {'items': [{'key': 'foo', 'value': 'one'}, {'key': 'sshKeys', 'value': 'another test'}]} md = self.driver._set_project_metadata(gce_md, False, "this is a test") self.assertEqual(len(md), 2, str(md)) sshKeys = "" count = 0 for d in md: if d['key'] == 'sshKeys': count += 1 sshKeys = d['value'] self.assertEqual(sshKeys, 'this is a test') self.assertEqual(count, 1) # add new metadata, overwrite existing sshKeys, in this case, the # existing 'sshKeys' value should be replaced gce_md = {'items': [{'key': 'foo', 'value': 'one'}, {'key': 'sshKeys', 'value': 'another test'}]} md = self.driver._set_project_metadata(gce_md, True, "this is a test") self.assertEqual(len(md), 2, str(md)) sshKeys = "" count = 0 for d in md: if d['key'] == 'sshKeys': count += 1 sshKeys = d['value'] self.assertEqual(sshKeys, 'another test') self.assertEqual(count, 1) # add new metadata, remove existing sshKeys. in this case, we had an # 'sshKeys' entry, but it will be removed entirely gce_md = {'items': [{'key': 'foo', 'value': 'one'}, {'key': 'nokeys', 'value': 'two'}]} md = self.driver._set_project_metadata(gce_md, True, "this is a test") self.assertEqual(len(md), 2, str(md)) sshKeys = "" count = 0 for d in md: if d['key'] == 'sshKeys': count += 1 sshKeys = d['value'] self.assertEqual(sshKeys, '') self.assertEqual(count, 0) def test_ex_set_common_instance_metadata(self): # test non-dict self.assertRaises(ValueError, self.driver.ex_set_common_instance_metadata, ['bad', 'type']) # test standard python dict pydict = {'key': 'pydict', 'value': 1} self.driver.ex_set_common_instance_metadata(pydict) # test GCE badly formatted dict bad_gcedict = {'items': 'foo'} self.assertRaises(ValueError, self.driver.ex_set_common_instance_metadata, bad_gcedict) # test gce formatted dict gcedict = {'items': [{'key': 'gcedict1', 'value': 'v1'}, {'key': 'gcedict2', 'value': 'v2'}]} self.driver.ex_set_common_instance_metadata(gcedict) # Verify project notation works project = GCEProject(id=None, name=None, metadata=None, quotas=None, driver=self.driver) project.set_common_instance_metadata(metadata=gcedict) def test_ex_set_node_metadata(self): node = self.driver.ex_get_node('node-name', 'us-central1-a') # test non-dict self.assertRaises(ValueError, self.driver.ex_set_node_metadata, node, ['bad', 'type']) # test standard python dict pydict = {'key': 'pydict', 'value': 1} self.driver.ex_set_node_metadata(node, pydict) # test GCE badly formatted dict bad_gcedict = {'items': 'foo'} self.assertRaises(ValueError, self.driver.ex_set_node_metadata, node, bad_gcedict) # test gce formatted dict gcedict = {'items': [{'key': 'gcedict1', 'value': 'v1'}, {'key': 'gcedict2', 'value': 'v2'}]} self.driver.ex_set_node_metadata(node, gcedict) def test_ex_set_node_labels(self): node = self.driver.ex_get_node('node-name', 'us-central1-a') # Test basic values simplelabel = {'key': 'value'} self.driver.ex_set_node_labels(node, simplelabel) # Test multiple values multilabels = {'item1': 'val1', 'item2': 'val2'} self.driver.ex_set_node_labels(node, multilabels) def test_ex_set_image_labels(self): image = self.driver.ex_get_image('custom-image') # Test basic values simplelabel = {'foo': 'bar'} self.driver.ex_set_image_labels(image, simplelabel) image = self.driver.ex_get_image('custom-image') self.assertTrue('foo' in image.extra['labels']) # Test multiple values multilabels = {'one': '1', 'two': 'two'} self.driver.ex_set_image_labels(image, multilabels) image = self.driver.ex_get_image('custom-image') self.assertEqual(len(image.extra['labels']), 3) self.assertTrue('two' in image.extra['labels']) self.assertTrue('two' in image.extra['labels']) def test_ex_get_region(self): region_name = 'us-central1' region = self.driver.ex_get_region(region_name) self.assertEqual(region.name, region_name) self.assertEqual(region.status, 'UP') self.assertEqual(region.zones[0].name, 'us-central1-a') def test_ex_get_size(self): size_name = 'n1-standard-1' size = self.driver.ex_get_size(size_name) self.assertEqual(size.name, size_name) self.assertEqual(size.extra['zone'].name, 'us-central1-a') self.assertEqual(size.disk, 10) self.assertEqual(size.ram, 3840) self.assertEqual(size.extra['guestCpus'], 1) def test_ex_get_targethttpproxy(self): targethttpproxy_name = 'web-proxy' targethttpproxy = self.driver.ex_get_targethttpproxy( targethttpproxy_name) self.assertEqual(targethttpproxy.name, targethttpproxy_name) self.assertEqual(targethttpproxy.urlmap.name, 'web-map') def test_ex_get_targetinstance(self): targetinstance_name = 'lctargetinstance' targetinstance = self.driver.ex_get_targetinstance(targetinstance_name) self.assertEqual(targetinstance.name, targetinstance_name) self.assertEqual(targetinstance.zone.name, 'us-central1-a') def test_ex_get_targetpool(self): targetpool_name = 'lctargetpool' targetpool = self.driver.ex_get_targetpool(targetpool_name) self.assertEqual(targetpool.name, targetpool_name) self.assertEqual(len(targetpool.nodes), 2) self.assertEqual(targetpool.region.name, 'us-central1') def test_ex_get_instancegroupmanager(self): igmgr_name = 'myinstancegroup' igmgr = self.driver.ex_get_instancegroupmanager(igmgr_name, 'us-central1-b') self.assertEqual(igmgr.name, igmgr_name) self.assertEqual(igmgr.size, 4) self.assertEqual(igmgr.zone.name, 'us-central1-b') # search all zones igmgr = self.driver.ex_get_instancegroupmanager(igmgr_name) self.assertEqual(igmgr.name, igmgr_name) self.assertEqual(igmgr.size, 4) self.assertEqual(igmgr.zone.name, 'us-central1-a') def test_ex_get_instancetemplate(self): instancetemplate_name = 'my-instance-template1' instancetemplate = self.driver.ex_get_instancetemplate( instancetemplate_name) self.assertEqual(instancetemplate.name, instancetemplate_name) self.assertEqual(instancetemplate.extra['properties']['machineType'], 'n1-standard-1') def test_ex_get_snapshot(self): snapshot_name = 'lcsnapshot' snapshot = self.driver.ex_get_snapshot(snapshot_name) self.assertEqual(snapshot.name, snapshot_name) self.assertEqual(snapshot.size, '10') self.assertEqual(snapshot.status, 'READY') def test_ex_get_urlmap(self): urlmap_name = 'web-map' urlmap = self.driver.ex_get_urlmap(urlmap_name) self.assertEqual(urlmap.name, urlmap_name) self.assertEqual(urlmap.default_service.name, 'web-service') def test_ex_get_volume(self): volume_name = 'lcdisk' volume = self.driver.ex_get_volume(volume_name) self.assertEqual(volume.name, volume_name) self.assertEqual(volume.size, '10') self.assertEqual(volume.extra['status'], 'READY') self.assertEqual(volume.extra['type'], 'pd-ssd') def test_ex_get_disktype(self): disktype_name = 'pd-ssd' disktype_zone = 'us-central1-a' disktype = self.driver.ex_get_disktype(disktype_name, disktype_zone) self.assertEqual(disktype.name, disktype_name) self.assertEqual(disktype.zone.name, disktype_zone) self.assertEqual(disktype.extra['description'], 'SSD Persistent Disk') self.assertEqual(disktype.extra['valid_disk_size'], '10GB-10240GB') self.assertEqual(disktype.extra['default_disk_size_gb'], '100') def test_ex_get_zone(self): zone_name = 'us-central1-b' zone = self.driver.ex_get_zone(zone_name) self.assertEqual(zone.name, zone_name) self.assertFalse(zone.time_until_mw) self.assertFalse(zone.next_mw_duration) zone_no_mw = self.driver.ex_get_zone('us-central1-a') self.assertIsNone(zone_no_mw.time_until_mw) class GCEMockHttp(MockHttp): fixtures = ComputeFileFixtures('gce') json_hdr = {'content-type': 'application/json; charset=UTF-8'} def _get_method_name(self, type, use_param, qs, path): api_path = '/compute/%s' % API_VERSION project_path = '/projects/%s' % GCE_KEYWORD_PARAMS['project'] path = path.replace(api_path, '') # This replace is separate, since there is a call with a different # project name path = path.replace(project_path, '') # The path to get project information is the base path, so use a fake # '/project' path instead if not path: path = '/project' method_name = super(GCEMockHttp, self)._get_method_name( type, use_param, qs, path) return method_name def _setUsageExportBucket(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('setUsageExportBucket_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_custom_node(self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_instances_custom_node.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_setMachineType( self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_instances_node_name_setMachineType.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_setMachineType_notstopped( self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_operations_operation_setMachineType_notstopped.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_custom_node_setMachineType( self, method, url, body, header): body = { "error": { "errors": [ { "domain": "global", "reason": "invalid", "message": "Invalid value for field 'resource.machineTypes': " "'projects/project_name/zones/us-central1-a/machineTypes/custom-1-61440'. Resource was not found.", } ], "code": 400, "message": "Invalid value for field 'resource.machineTypes': " "'projects/project_name/zones/us-central1-a/machineTypes/custom-1-61440'. Resource was not found." } } return (httplib.BAD_REQUEST, body, self.json_hdr, httplib.responses[httplib.BAD_REQUEST]) def _zones_us_central1_a_instances_stopped_node_setMachineType( self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_instances_stopped_node_setMachineType.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_setMachineType( self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_operations_operation_setMachineType.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_startnode(self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_operations_operation_startnode.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_stopped_node_start(self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_instances_stopped_node_start.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_stopped_node_stop(self, method, url, body, header): body = self.fixtures.load( 'zones_us_central1_a_instances_stopped_node_stop.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_stopped_node(self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_instances_stopped_node.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_stopnode(self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_operations_operation_stopnode.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_stop(self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_instances_node_name_stop.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_acceleratorTypes_nvidia_tesla_k80(self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_acceleratorTypes_nvidia_tesla_k80.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_setMetadata(self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_instances_node_name_setMetadata_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_setLabels(self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_instances_node_name_setLabels_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_custom_image_setLabels(self, method, url, body, headers): body = self.fixtures.load( 'global_custom_image_setLabels_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _setCommonInstanceMetadata(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('setCommonInstanceMetadata_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_subnetworks(self, method, url, body, headers): body = self.fixtures.load('aggregated_subnetworks.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_addresses(self, method, url, body, headers): body = self.fixtures.load('aggregated_addresses.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_diskTypes(self, method, url, body, headers): body = self.fixtures.load('aggregated_disktypes.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_disks(self, method, url, body, headers): body = self.fixtures.load('aggregated_disks.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_forwardingRules(self, method, url, body, headers): body = self.fixtures.load('aggregated_forwardingRules.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_instances(self, method, url, body, headers): body = self.fixtures.load('aggregated_instances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_instanceGroupManagers(self, method, url, body, headers): body = self.fixtures.load('aggregated_instanceGroupManagers.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_machineTypes(self, method, url, body, headers): body = self.fixtures.load('aggregated_machineTypes.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_targetInstances(self, method, url, body, headers): body = self.fixtures.load('aggregated_targetInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_targetPools(self, method, url, body, headers): body = self.fixtures.load('aggregated_targetPools.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_backendServices(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_backendServices_post.json') else: backend_name = getattr(self.test, 'backendservices_mock', 'web-service') body = self.fixtures.load('global_backendServices-%s.json' % backend_name) return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_backendServices_no_backends(self, method, url, body, headers): body = self.fixtures.load('global_backendServices_no_backends.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_backendServices_web_service(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'global_backendServices_web_service_delete.json') else: body = self.fixtures.load( 'global_backendServices_web_service.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_forwardingRules(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_forwardingRules_post.json') else: body = self.fixtures.load('global_forwardingRules.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_forwardingRules_http_rule(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'global_forwardingRules_http_rule_delete.json') else: body = self.fixtures.load('global_forwardingRules_http_rule.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_httpHealthChecks(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_httpHealthChecks_post.json') else: body = self.fixtures.load('global_httpHealthChecks.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_httpHealthChecks_default_health_check(self, method, url, body, headers): body = self.fixtures.load('global_httpHealthChecks_basic-check.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_httpHealthChecks_basic_check(self, method, url, body, headers): body = self.fixtures.load('global_httpHealthChecks_basic-check.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_httpHealthChecks_libcloud_lb_demo_healthcheck( self, method, url, body, headers): body = self.fixtures.load( 'global_httpHealthChecks_libcloud-lb-demo-healthcheck.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_httpHealthChecks_lchealthcheck(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'global_httpHealthChecks_lchealthcheck_delete.json') elif method == 'PUT': body = self.fixtures.load( 'global_httpHealthChecks_lchealthcheck_put.json') else: body = self.fixtures.load( 'global_httpHealthChecks_lchealthcheck.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_firewalls(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_firewalls_post.json') else: body = self.fixtures.load('global_firewalls.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_firewalls_lcfirewall(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'global_firewalls_lcfirewall_delete.json') elif method == 'PUT': body = self.fixtures.load('global_firewalls_lcfirewall_put.json') else: body = self.fixtures.load('global_firewalls_lcfirewall.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_firewalls_lcfirewall_egress(self, method, url, body, headers): body = self.fixtures.load('global_firewalls_lcfirewall-egress.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_firewalls_lcfirewall_deny(self, method, url, body, headers): body = self.fixtures.load('global_firewalls_lcfirewall-deny.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_images(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_images_post.json') else: body = self.fixtures.load('global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_images_debian_7_wheezy_v20131120(self, method, url, body, headers): body = self.fixtures.load( 'global_images_debian_7_wheezy_v20131120_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_images_debian_7_wheezy_v20131014_deprecate(self, method, url, body, headers): body = self.fixtures.load( 'global_images_debian_7_wheezy_v20131014_deprecate.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_images_family_coreos_beta(self, method, url, body, headers): body = self.fixtures.load('global_images_family_notfound.json') return (httplib.NOT_FOUND, body, self.json_hdr, httplib.responses[httplib.NOT_FOUND]) def _global_images_family_coreos_stable(self, method, url, body, headers): body = self.fixtures.load('global_images_family_notfound.json') return (httplib.NOT_FOUND, body, self.json_hdr, httplib.responses[httplib.NOT_FOUND]) def _global_images_family_nofamily(self, method, url, body, headers): body = self.fixtures.load('global_images_family_notfound.json') return (httplib.NOT_FOUND, body, self.json_hdr, httplib.responses[httplib.NOT_FOUND]) def _global_routes(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_routes_post.json') else: body = self.fixtures.load('global_routes.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_networks(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_networks_post.json') else: body = self.fixtures.load('global_networks.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_networks_custom_network(self, method, url, body, headers): body = self.fixtures.load('global_networks_custom_network.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_networks_cf(self, method, url, body, headers): body = self.fixtures.load('global_networks_cf.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_networks_default(self, method, url, body, headers): body = self.fixtures.load('global_networks_default.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_networks_libcloud_demo_network(self, method, url, body, headers): body = self.fixtures.load('global_networks_libcloud-demo-network.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_networks_libcloud_demo_europe_network(self, method, url, body, headers): body = self.fixtures.load( 'global_networks_libcloud-demo-europe-network.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_routes_lcdemoroute(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load('global_routes_lcdemoroute_delete.json') else: body = self.fixtures.load('global_routes_lcdemoroute.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_networks_lcnetwork(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load('global_networks_lcnetwork_delete.json') else: body = self.fixtures.load('global_networks_lcnetwork.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_snapshots(self, method, url, body, headers): body = self.fixtures.load('global_snapshots.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_snapshots_lcsnapshot(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'global_snapshots_lcsnapshot_delete.json') else: body = self.fixtures.load('global_snapshots_lcsnapshot.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_setUsageExportBucket(self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_setUsageExportBucket.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_setCommonInstanceMetadata( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_setCommonInstanceMetadata.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_backendServices_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_backendServices_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_backendServices_web_service_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_backendServices_web_service_delete' '.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_forwardingRules_http_rule_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_forwardingRules_http_rule_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_forwardingRules_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_forwardingRules_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_httpHealthChecks_lchealthcheck_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_httpHealthChecks_lchealthcheck_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_images_debian7_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_images_debian7_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_httpHealthChecks_lchealthcheck_put( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_httpHealthChecks_lchealthcheck_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_httpHealthChecks_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_httpHealthChecks_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_firewalls_lcfirewall_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_firewalls_lcfirewall_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_firewalls_lcfirewall_put( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_firewalls_lcfirewall_put.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_firewalls_post(self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_firewalls_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_routes_lcdemoroute_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_routes_lcdemoroute_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_networks_lcnetwork_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_networks_lcnetwork_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_routes_post(self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_routes_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_networks_post(self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_networks_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_snapshots_lcsnapshot_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_snapshots_lcsnapshot_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_image_post(self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_image_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_addresses_lcaddressglobal_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_addresses_lcaddressglobal_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_targetHttpProxies_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_targetHttpProxies_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_targetHttpProxies_web_proxy_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_targetHttpProxies_web_proxy_delete' '.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_urlMaps_post(self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_urlMaps_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_urlMaps_web_map_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_urlMaps_web_map_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_targetHttpProxies(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_targetHttpProxies_post.json') else: body = self.fixtures.load('global_targetHttpProxies.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_targetHttpProxies_web_proxy(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'global_targetHttpProxies_web_proxy_delete.json') else: body = self.fixtures.load( 'global_targetHttpProxies_web_proxy.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_urlMaps(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_urlMaps_post.json') else: body = self.fixtures.load('global_urlMaps.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_urlMaps_web_map(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load('global_urlMaps_web_map_delete.json') else: body = self.fixtures.load('global_urlMaps_web_map.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_east1_subnetworks_cf_972cf02e6ad49113(self, method, url, body, headers): body = self.fixtures.load( 'regions_us-east1_subnetworks_cf_972cf02e6ad49113.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_subnetworks_cf_972cf02e6ad49112(self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_subnetworks_cf_972cf02e6ad49112.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_other_name_regions_us_central1(self, method, url, body, headers): body = self.fixtures.load('projects_other_name_regions_us-central1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_other_name_global_networks_lcnetwork(self, method, url, body, headers): body = self.fixtures.load('projects_other_name_global_networks_lcnetwork.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_other_name_global_networks_cf(self, method, url, body, headers): body = self.fixtures.load('projects_other_name_global_networks_cf.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_other_name_global_networks_shared_network_for_mig(self, method, url, body, headers): body = self.fixtures.load('projects_other_name_global_networks_shared_network_for_mig.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_other_name_regions_us_central1_subnetworks_cf_972cf02e6ad49114( self, method, url, body, headers): body = self.fixtures.load( 'projects_other_name_regions_us-central1_subnetworks_cf_972cf02e6ad49114.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_other_name_regions_us_central1_subnetworks_shared_subnetwork_for_mig( self, method, url, body, headers): body = self.fixtures.load( 'projects_other_name_regions_us-central1_subnetworks_shared_subnetwork_for_mig.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_addresses_lcaddress_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_addresses_lcaddress_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_addresses_post(self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_addresses_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_addresses_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_addresses_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_subnetworks_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_subnetworks_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_forwardingRules_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_forwardingRules_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_forwardingRules_lcforwardingrule_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_forwardingRules_lcforwardingrule_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_deleteAccessConfig( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node_name_deleteAccessConfig_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_serialPort(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instances_node_name_getSerialOutput.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_addAccessConfig( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node_name_addAccessConfig_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_setMetadata_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us_central1_a_node_name_setMetadata_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_setLabels_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us_central1_a_node_name_setLabels_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_setImageLabels_post(self, method, url, body, headers): body = self.fixtures.load( 'global_operations_operation_setImageLabels_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_targetInstances_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_targetInstances_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_targetPools_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_targetPools_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_addAccessConfig_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node_name_addAccessConfig_done.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_deleteAccessConfig_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node_name_deleteAccessConfig_done.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_targetInstances_lctargetinstance_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_targetInstances_lctargetinstance_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_targetPools_lctargetpool_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_removeHealthCheck_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_addHealthCheck_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_removeInstance_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_targetPools_lctargetpool_removeInstance_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lb_pool_setBackup_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_targetPools_lb_pool_setBackup_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_operations_operation_regions_us_central1_targetPools_lctargetpool_addInstance_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_regions_us-central1_targetPools_lctargetpool_addInstance_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_lcdisk_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_disks_lcdisk_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_setDiskAutoDelete( self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_instances_node_name_setDiskAutoDelete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_volume_auto_delete( self, method, url, body, headers): body = self.fixtures.load( 'zones_us_central1_a_operations_operation_volume_auto_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_lcdisk_createSnapshot_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_disks_lcdisk_createSnapshot_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_lcdisk_resize_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_disks_lcdisk_resize_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_lcdisk_setLabels_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_disks_lcdisk_setLabels_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_disks_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_disks_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_lcnode_000_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_lcnode-000_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_lcnode_001_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_lcnode-001_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_delete( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node-name_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_attachDisk_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node-name_attachDisk_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_detachDisk_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node-name_detachDisk_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_setTags_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node-name_setTags_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_node_name_reset_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_node-name_reset_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_operations_operation_zones_europe_west1_a_instances_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_europe-west1-a_instances_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instances_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_zones_us-central1-a_instances_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _project(self, method, url, body, headers): body = self.fixtures.load('project.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_windows_cloud_global_licenses_windows_server_2008_r2_dc( self, method, url, body, headers): body = self.fixtures.load( 'projects_windows-cloud_global_licenses_windows_server_2008_r2_dc.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_suse_cloud_global_licenses_sles_11(self, method, url, body, headers): body = self.fixtures.load( 'projects_suse-cloud_global_licenses_sles_11.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_rhel_cloud_global_licenses_rhel_7_server(self, method, url, body, headers): body = self.fixtures.load( 'projects_rhel-cloud_global_licenses_rhel_server.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_coreos_cloud_global_licenses_coreos_stable(self, method, url, body, headers): body = self.fixtures.load( 'projects_coreos-cloud_global_licenses_coreos_stable.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_suse_cloud_global_licenses_sles_12(self, method, url, body, headers): body = self.fixtures.load( 'projects_suse-cloud_global_licenses_sles_12.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_windows_cloud_global_images(self, method, url, body, header): body = self.fixtures.load('projects_windows-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_windows_sql_cloud_global_images(self, method, url, body, header): body = self.fixtures.load('projects_windows-sql-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_rhel_cloud_global_images(self, method, url, body, header): body = self.fixtures.load('projects_rhel-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_coreos_cloud_global_images(self, method, url, body, header): body = self.fixtures.load('projects_coreos-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_coreos_cloud_global_images_family_coreos_beta(self, method, url, body, header): body = self.fixtures.load( 'projects_coreos-cloud_global_images_family_coreos_beta.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_coreos_cloud_global_images_family_coreos_stable(self, method, url, body, header): body = self.fixtures.load( 'projects_coreos-cloud_global_images_family_coreos_stable.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_cos_cloud_global_images(self, method, url, body, header): body = self.fixtures.load('projects_cos-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_opensuse_cloud_global_images(self, method, url, body, header): body = self.fixtures.load('projects_opensuse-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_ubuntu_os_cloud_global_images(self, method, url, body, header): body = self.fixtures.load( 'projects_ubuntu-os-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_centos_cloud_global_images(self, method, url, body, header): body = self.fixtures.load('projects_centos-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_suse_cloud_global_images(self, method, url, body, headers): body = self.fixtures.load('projects_suse-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_suse_byos_cloud_global_images(self, method, url, body, headers): body = self.fixtures.load('projects_suse-byos-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_suse_sap_cloud_global_images(self, method, url, body, headers): body = self.fixtures.load('projects_suse-sap-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _projects_debian_cloud_global_images(self, method, url, body, headers): body = self.fixtures.load('projects_debian-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions(self, method, url, body, headers): if 'pageToken' in url or 'filter' in url: body = self.fixtures.load('regions-paged-2.json') elif 'maxResults' in url: body = self.fixtures.load('regions-paged-1.json') else: body = self.fixtures.load('regions.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_addresses(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_addresses_post.json') else: body = self.fixtures.load('global_addresses.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_europe_west1(self, method, url, body, headers): body = self.fixtures.load('regions_europe-west1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_asia_east1(self, method, url, body, headers): body = self.fixtures.load('regions_asia-east1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1(self, method, url, body, headers): body = self.fixtures.load('regions_us-central1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_east1(self, method, url, body, headers): body = self.fixtures.load('regions_us-east1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_subnetworks(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( 'regions_us-central1_subnetworks_post.json') else: body = self.fixtures.load('regions_us-central1_subnetworks.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_addresses(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( 'regions_us-central1_addresses_post.json') else: body = self.fixtures.load('regions_us-central1_addresses.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_addresses_lcaddressglobal(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'global_addresses_lcaddressglobal_delete.json') else: body = self.fixtures.load('global_addresses_lcaddressglobal.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_addresses_lcaddress(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'regions_us-central1_addresses_lcaddress_delete.json') else: body = self.fixtures.load( 'regions_us-central1_addresses_lcaddress.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_addresses_testaddress(self, method, url, body, headers): body = self.fixtures.load('regions_us-central1_addresses_testaddress.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_subnetworks_subnet_1(self, method, url, body, headers): body = self.fixtures.load('regions_us-central1_subnetworks_subnet_1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_addresses_lcaddressinternal(self, method, url, body, headers): body = self.fixtures.load('regions_us-central1_addresses_lcaddressinternal.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_forwardingRules(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( 'regions_us-central1_forwardingRules_post.json') else: body = self.fixtures.load( 'regions_us-central1_forwardingRules.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_forwardingRules_libcloud_lb_demo_lb( self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_forwardingRules_libcloud-lb-demo-lb.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_forwardingRules_lcforwardingrule( self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'regions_us-central1_forwardingRules_lcforwardingrule_delete.json') else: body = self.fixtures.load( 'regions_us-central1_forwardingRules_lcforwardingrule.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_targetInstances(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( 'zones_us-central1-a_targetInstances_post.json') else: body = self.fixtures.load( 'zones_us-central1-a_targetInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( 'regions_us-central1_targetPools_post.json') else: body = self.fixtures.load('regions_us-central1_targetPools.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_targetInstances_lctargetinstance( self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'zones_us-central1-a_targetInstances_lctargetinstance_delete.json') else: body = self.fixtures.load( 'zones_us-central1-a_targetInstances_lctargetinstance.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lb_pool_getHealth(self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lb_pool_getHealth.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lb_pool(self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lb_pool.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lctargetpool(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'regions_us-central1_targetPools_lctargetpool_delete.json') else: body = self.fixtures.load( 'regions_us-central1_targetPools_lctargetpool.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lctargetpool_sticky(self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lctargetpool_sticky.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_backup_pool(self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_backup_pool.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_libcloud_lb_demo_lb_tp( self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_libcloud-lb-demo-lb-tp.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lctargetpool_removeHealthCheck( self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lctargetpool_removeHealthCheck_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lctargetpool_addHealthCheck( self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lctargetpool_addHealthCheck_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lctargetpool_removeInstance( self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lctargetpool_removeInstance_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lb_pool_setBackup(self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lb_pool_setBackup_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _regions_us_central1_targetPools_lctargetpool_addInstance( self, method, url, body, headers): body = self.fixtures.load( 'regions_us-central1_targetPools_lctargetpool_addInstance_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones(self, method, url, body, headers): body = self.fixtures.load('zones.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_asia_east_1a(self, method, url, body, headers): body = self.fixtures.load('zones_asia-east1-a.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_asia_east1_b(self, method, url, body, headers): body = self.fixtures.load('zones_asia-east1-b.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_east1_b(self, method, url, body, headers): body = self.fixtures.load('zones_us-east1-b.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_diskTypes(self, method, url, body, headers): body = self.fixtures.load('zones_us-central1-a_diskTypes.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_diskTypes_pd_standard(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_diskTypes_pd_standard.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_diskTypes_pd_ssd(self, method, url, body, headers): body = self.fixtures.load('zones_us-central1-a_diskTypes_pd_ssd.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('zones_us-central1-a_disks_post.json') else: body = self.fixtures.load('zones_us-central1-a_disks.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks_lcdisk(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'zones_us-central1-a_disks_lcdisk_delete.json') else: body = self.fixtures.load('zones_us-central1-a_disks_lcdisk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks_lcdisk_createSnapshot(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_disks_lcdisk_createSnapshot_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks_lcdisk_resize(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_disks_lcdisk_resize_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks_lcdisk_setLabels(self, method, url, body, header): body = self.fixtures.load( 'zones_us-central1-a_disks_lcdisk_setLabel_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks_node_name(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks_lcnode_000(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_disks_lcnode_001(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_disks_libcloud_lb_demo_www_000(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_disks_libcloud_lb_demo_www_001(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_disks_libcloud_lb_demo_www_002(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central2_a_disks_libcloud_demo_boot_disk(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central2_a_disks_libcloud_demo_np_node(self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central2_a_disks_libcloud_demo_multiple_nodes_000( self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central2_a_disks_libcloud_demo_multiple_nodes_001( self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_disks(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('zones_us-central1-a_disks_post.json') else: body = self.fixtures.load('zones_us-central1-a_disks.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_disks_libcloud_demo_europe_np_node( self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_disks_libcloud_demo_europe_boot_disk( self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_disks_libcloud_demo_europe_multiple_nodes_000( self, method, url, body, headers): body = self.fixtures.load('generic_disk.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_instances(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( 'zones_europe-west1-a_instances_post.json') else: body = self.fixtures.load('zones_europe-west1-a_instances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_diskTypes_pd_standard(self, method, url, body, headers): body = self.fixtures.load( 'zones_europe-west1-a_diskTypes_pd_standard.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load( 'zones_us-central1-a_instances_post.json') else: body = self.fixtures.load('zones_us-central1-a_instances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_sn_node_name(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instances_sn-node-name.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'zones_us-central1-a_instances_node-name_delete.json') else: body = self.fixtures.load( 'zones_us-central1-a_instances_node-name.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_attachDisk(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instances_node-name_attachDisk_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_detachDisk(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instances_node-name_detachDisk_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_setTags(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instances_node-name_setTags_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_node_name_reset(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instances_node-name_reset_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_lcnode_000(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'zones_us-central1-a_instances_lcnode-000_delete.json') else: body = self.fixtures.load( 'zones_us-central1-a_instances_lcnode-000.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instances_lcnode_001(self, method, url, body, headers): if method == 'DELETE': body = self.fixtures.load( 'zones_us-central1-a_instances_lcnode-001_delete.json') else: body = self.fixtures.load( 'zones_us-central1-a_instances_lcnode-001.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_instances_libcloud_lb_nopubip_001( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-b_instances_libcloud-lb-nopubip-001.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_instances_libcloud_lb_demo_www_000( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-b_instances_libcloud-lb-demo-www-000.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_instances_libcloud_lb_demo_www_001( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-b_instances_libcloud-lb-demo-www-001.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_instances_libcloud_lb_demo_www_002( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-b_instances_libcloud-lb-demo-www-002.json') return (httplib.NOT_FOUND, body, self.json_hdr, httplib.responses[httplib.NOT_FOUND]) def _zones_us_central1_a(self, method, url, body, headers): body = self.fixtures.load('zones_us-central1-a.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_machineTypes(self, method, url, body, headers): body = self.fixtures.load('zones_us-central1-a_machineTypes.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_europe_west1_a_machineTypes_n1_standard_1(self, method, url, body, headers): body = self.fixtures.load( 'zones_europe-west1-a_machineTypes_n1-standard-1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_machineTypes_n1_standard_1(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_machineTypes_n1-standard-1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myinstancegroup(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instanceGroup_myinstancegroup.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myinstancegroup2(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instanceGroup_myinstancegroup2.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_instanceGroups_myinstancegroup(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-b_instanceGroup_myinstancegroup.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_east1_b_instanceGroups_myinstancegroup(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-east1-b_instanceGroup_myinstancegroup.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myinstancegroup_shared_network( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instanceGroup_myinstancegroup_shared_network.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroupManagers_myinstancegroup( self, method, url, body, headers): if method == 'PATCH': # test_ex_instancegroupmanager_set_autohealing_policies body = self.fixtures.load( 'zones_us-central1-a_operations_operation_zones_us-central1-a_instanceGroupManagers_insert_post.json') else: body = self.fixtures.load( 'zones_us-central1-a_instanceGroupManagers_myinstancegroup.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroupManagers_myinstancegroup_shared_network( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instanceGroupManagers_myinstancegroup_shared_network.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_b_instanceGroupManagers_myinstancegroup( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-b_instanceGroupManagers_myinstancegroup.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroupManagers_myinstancegroup_listManagedInstances( self, method, url, body, headers): body = self.fixtures.load( '_zones_us_central1_a_instanceGroupManagers_myinstancegroup_listManagedInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_east1_b_instanceGroupManagers(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-east1-b_instanceGroupManagers.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroupManagers(self, method, url, body, headers): # do an insert. Returns an operations link, which then # returns the MIG URI. if method == 'POST': body = self.fixtures.load( 'zones_us-central1-a_instanceGroupManagers_insert.json') else: body = self.fixtures.load( 'zones_us-central1-a_instanceGroupManagers.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instanceGroupManagers_insert_post( self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_operations_operation_zones_us-central1-a_instanceGroupManagers_insert_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_instanceTemplates(self, method, url, body, headers): if method == 'POST': # insert body = self.fixtures.load('global_instanceTemplates_insert.json') else: # get or list call body = self.fixtures.load('global_instanceTemplates.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_instanceTemplates_my_instance_template1_insert( self, method, url, body, headers): """ Redirects from _global_instanceTemplates """ body = self.fixtures.load( 'operations_operation_global_instanceTemplates_insert.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_instanceTemplates_my_instance_template1(self, method, url, body, headers): body = self.fixtures.load( 'global_instanceTemplates_my_instance_template1.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_instanceTemplates_my_instance_template_shared_network( self, method, url, body, headers): body = self.fixtures.load( 'global_instanceTemplates_my_instance_template_shared_network.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _aggregated_autoscalers(self, method, url, body, headers): body = self.fixtures.load('aggregated_autoscalers.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_sslCertificates(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('global_sslcertificates_post.json') else: body = self.fixtures.load('global_sslcertificates.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_sslCertificates_example(self, method, url, body, headers): body = self.fixtures.load('global_sslcertificates_example.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _global_operations_operation_global_sslcertificates_post( self, method, url, body, headers): body = self.fixtures.load( 'operations_operation_global_sslcertificates_post.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myname(self, method, url, body, headers): if method == 'DELETE': # delete body = self.fixtures.load( 'zones_us_central1_a_instanceGroups_myname_delete.json') else: # get or list call body = self.fixtures.load( 'zones_us_central1_a_instanceGroups_myname.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instanceGroups_myname_delete( self, method, url, body, headers): """ Redirects from _zones_us_central1_a_instanceGroups_myname """ body = self.fixtures.load( 'operations_operation_zones_us_central1_a_instanceGroups_myname_delete.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups(self, method, url, body, headers): if method == 'POST': # insert body = self.fixtures.load( 'zones_us_central1_a_instanceGroups_insert.json') else: # get or list call body = self.fixtures.load( 'zones_us_central1_a_instanceGroups.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instanceGroups_myname_insert( self, method, url, body, headers): """ Redirects from _zones_us_central1_a_instanceGroups """ body = self.fixtures.load( 'operations_operation_zones_us_central1_a_instanceGroups_insert.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myname_listInstances( self, method, url, body, headers): # POST body = self.fixtures.load( 'zones_us_central1_a_instanceGroups_myname_listInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myname_addInstances( self, method, url, body, headers): # POST body = self.fixtures.load( 'zones_us_central1_a_instanceGroups_myname_addInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instanceGroups_myname_addInstances( self, method, url, body, headers): """ Redirects from _zones_us_central1_a_instanceGroups_myname_addInstances """ body = self.fixtures.load( 'operations_operation_zones_us_central1_a_instanceGroups_myname_addInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myname_removeInstances( self, method, url, body, headers): # POST body = self.fixtures.load( 'zones_us_central1_a_instanceGroups_myname_removeInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instanceGroups_myname_removeInstances( self, method, url, body, headers): """ Redirects from _zones_us_central1_a_instanceGroups_myname_removeInstances """ body = self.fixtures.load( 'operations_operation_zones_us_central1_a_instanceGroups_myname_removeInstances.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_instanceGroups_myname_setNamedPorts( self, method, url, body, headers): # POST body = self.fixtures.load( 'zones_us_central1_a_instanceGroups_myname_setNamedPorts.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_operations_operation_zones_us_central1_a_instanceGroups_myname_setNamedPorts( self, method, url, body, headers): """ Redirects from _zones_us_central1_a_instanceGroups_myname_setNamedPorts """ body = self.fixtures.load( 'operations_operation_zones_us_central1_a_instanceGroups_myname_setNamedPorts.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_gogrid.py0000664000175000017500000002625313570310635023552 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qs from libcloud.compute.base import NodeState, NodeLocation from libcloud.common.types import LibcloudError, InvalidCredsError from libcloud.common.gogrid import GoGridIpAddress from libcloud.compute.drivers.gogrid import GoGridNodeDriver from libcloud.compute.base import Node, NodeImage, NodeSize from libcloud.test import MockHttp # pylint: disable-msg=E0611 from libcloud.test.compute import TestCaseMixin # pylint: disable-msg=E0611 from libcloud.test.file_fixtures import ComputeFileFixtures # pylint: disable-msg=E0611 class GoGridTests(unittest.TestCase, TestCaseMixin): def setUp(self): GoGridNodeDriver.connectionCls.conn_class = GoGridMockHttp GoGridMockHttp.type = None self.driver = GoGridNodeDriver("foo", "bar") def _get_test_512Mb_node_size(self): return NodeSize(id='512Mb', name=None, ram=None, disk=None, bandwidth=None, price=None, driver=self.driver) def test_create_node(self): image = NodeImage(1531, None, self.driver) node = self.driver.create_node( name='test1', image=image, size=self._get_test_512Mb_node_size()) self.assertEqual(node.name, 'test1') self.assertTrue(node.id is not None) self.assertEqual(node.extra['password'], 'bebebe') def test_list_nodes(self): node = self.driver.list_nodes()[0] self.assertEqual(node.id, '90967') self.assertEqual(node.extra['password'], 'bebebe') self.assertEqual(node.extra['description'], 'test server') def test_reboot_node(self): node = Node(90967, None, None, None, None, self.driver) ret = self.driver.reboot_node(node) self.assertTrue(ret) def test_reboot_node_not_successful(self): GoGridMockHttp.type = 'FAIL' node = Node(90967, None, None, None, None, self.driver) try: self.driver.reboot_node(node) except Exception: pass else: self.fail('Exception was not thrown') def test_destroy_node(self): node = Node(90967, None, None, None, None, self.driver) ret = self.driver.destroy_node(node) self.assertTrue(ret) def test_list_images(self): images = self.driver.list_images() image = images[0] self.assertEqual(len(images), 4) self.assertEqual(image.name, 'CentOS 5.3 (32-bit) w/ None') self.assertEqual(image.id, '1531') location = NodeLocation( id='gogrid/GSI-939ef909-84b8-4a2f-ad56-02ccd7da05ff.img', name='test location', country='Slovenia', driver=self.driver) images = self.driver.list_images(location=location) image = images[0] self.assertEqual(len(images), 4) self.assertEqual(image.name, 'CentOS 5.3 (32-bit) w/ None') self.assertEqual(image.id, '1531') def test_malformed_reply(self): GoGridMockHttp.type = 'FAIL' try: self.driver.list_images() except LibcloudError as e: self.assertTrue(isinstance(e, LibcloudError)) else: self.fail("test should have thrown") def test_invalid_creds(self): GoGridMockHttp.type = 'FAIL' try: self.driver.list_nodes() except InvalidCredsError as e: self.assertTrue(e.driver is not None) self.assertEqual(e.driver.name, self.driver.name) else: self.fail("test should have thrown") def test_node_creation_without_free_public_ips(self): GoGridMockHttp.type = 'NOPUBIPS' try: image = NodeImage(1531, None, self.driver) self.driver.create_node( name='test1', image=image, size=self._get_test_512Mb_node_size()) except LibcloudError as e: self.assertTrue(isinstance(e, LibcloudError)) self.assertTrue(e.driver is not None) self.assertEqual(e.driver.name, self.driver.name) else: self.fail("test should have thrown") def test_list_locations(self): locations = self.driver.list_locations() location_names = [location.name for location in locations] self.assertEqual(len(locations), 2) for i in 0, 1: self.assertTrue(isinstance(locations[i], NodeLocation)) self.assertTrue("US-West-1" in location_names) self.assertTrue("US-East-1" in location_names) def test_ex_save_image(self): node = self.driver.list_nodes()[0] image = self.driver.ex_save_image(node, "testimage") self.assertEqual(image.name, "testimage") def test_ex_edit_image(self): image = self.driver.list_images()[0] ret = self.driver.ex_edit_image(image=image, public=False, ex_description="test", name="testname") self.assertTrue(isinstance(ret, NodeImage)) def test_ex_edit_node(self): node = Node(id=90967, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = self.driver.ex_edit_node(node=node, size=self._get_test_512Mb_node_size()) self.assertTrue(isinstance(ret, Node)) def test_ex_list_ips(self): ips = self.driver.ex_list_ips() expected_ips = {"192.168.75.66": GoGridIpAddress(id="5348099", ip="192.168.75.66", public=True, state="Unassigned", subnet="192.168.75.64/255.255.255.240"), "192.168.75.67": GoGridIpAddress(id="5348100", ip="192.168.75.67", public=True, state="Assigned", subnet="192.168.75.64/255.255.255.240"), "192.168.75.68": GoGridIpAddress(id="5348101", ip="192.168.75.68", public=False, state="Unassigned", subnet="192.168.75.64/255.255.255.240")} self.assertEqual(len(expected_ips), 3) for ip in ips: self.assertTrue(ip.ip in expected_ips) self.assertEqual(ip.public, expected_ips[ip.ip].public) self.assertEqual(ip.state, expected_ips[ip.ip].state) self.assertEqual(ip.subnet, expected_ips[ip.ip].subnet) del expected_ips[ip.ip] self.assertEqual(len(expected_ips), 0) def test_get_state_invalid(self): state = self.driver._get_state('invalid') self.assertEqual(state, NodeState.UNKNOWN) class GoGridMockHttp(MockHttp): fixtures = ComputeFileFixtures('gogrid') def _api_grid_image_list(self, method, url, body, headers): body = self.fixtures.load('image_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_image_list_FAIL(self, method, url, body, headers): body = "

some non valid json here

" return (httplib.SERVICE_UNAVAILABLE, body, {}, httplib.responses[httplib.SERVICE_UNAVAILABLE]) def _api_grid_server_list(self, method, url, body, headers): body = self.fixtures.load('server_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) _api_grid_server_list_NOPUBIPS = _api_grid_server_list def _api_grid_server_list_FAIL(self, method, url, body, headers): return (httplib.FORBIDDEN, "123", {}, httplib.responses[httplib.FORBIDDEN]) def _api_grid_ip_list(self, method, url, body, headers): body = self.fixtures.load('ip_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_ip_list_NOPUBIPS(self, method, url, body, headers): body = self.fixtures.load('ip_list_empty.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_server_power(self, method, url, body, headers): body = self.fixtures.load('server_power.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_server_power_FAIL(self, method, url, body, headers): body = self.fixtures.load('server_power_fail.json') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.OK]) def _api_grid_server_add(self, method, url, body, headers): body = self.fixtures.load('server_add.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) _api_grid_server_add_NOPUBIPS = _api_grid_server_add def _api_grid_server_delete(self, method, url, body, headers): body = self.fixtures.load('server_delete.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_server_edit(self, method, url, body, headers): body = self.fixtures.load('server_edit.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_support_password_list(self, method, url, body, headers): body = self.fixtures.load('password_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) _api_support_password_list_NOPUBIPS = _api_support_password_list def _api_grid_image_save(self, method, url, body, headers): body = self.fixtures.load('image_save.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_image_edit(self, method, url, body, headers): # edit method is quite similar to save method from the response # perspective body = self.fixtures.load('image_save.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_common_lookup_list(self, method, url, body, headers): _valid_lookups = ("ip.datacenter",) lookup = parse_qs(urlparse.urlparse(url).query)["lookup"][0] if lookup in _valid_lookups: fixture_path = "lookup_list_%s.json" % \ (lookup.replace(".", "_")) else: raise NotImplementedError body = self.fixtures.load(fixture_path) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_gridscale.py0000664000175000017500000004147013570310635024232 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from datetime import datetime from libcloud.utils.iso8601 import UTC from libcloud.utils.py3 import httplib from libcloud.compute.drivers.gridscale import GridscaleNodeDriver from libcloud.compute.base import NodeSize from libcloud.test import LibcloudTestCase, MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import GRIDSCALE_PARAMS class Gridscale_Tests(LibcloudTestCase): def setUp(self): GridscaleNodeDriver.connectionCls.conn_class = GridscaleMockHttp GridscaleMockHttp.type = None self.driver = GridscaleNodeDriver(*GRIDSCALE_PARAMS) def test_create_node_success(self): image = self.driver.list_images()[0] size = NodeSize(id=0, name='test', bandwidth=0, price=0, ram=10240, driver=self.driver, disk=50, extra={'cores': 2}) location = self.driver.list_locations()[0] sshkey = ["b1682d3a-1869-4bdc-8ffe-e74a261d300c"] GridscaleMockHttp.type = 'POST' node = self.driver.create_node(name='test', size=size, image=image, location=location, ex_ssh_key_ids=sshkey) self.assertEqual(node.name, 'test.test') self.assertEqual(node.public_ips, ['185.102.95.236', '2a06:2380:0:1::211']) def test_create_image_success(self): node = self.driver.list_nodes()[0] GridscaleMockHttp.type = 'POST' image = self.driver.create_image(node, 'test.test') self.assertTrue(image) def test_list_nodes_success(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].name, 'test.test') self.assertEqual(nodes[0].public_ips, ['185.102.95.236', '2a06:2380:0:1::211']) self.assertEqual(nodes[0].extra['cores'], 2) self.assertEqual(nodes[0].extra['memory'], 10240) def test_list_locations_success(self): locations = self.driver.list_locations() self.assertTrue(len(locations) >= 1) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 1) volume = volumes[0] self.assertEqual(volume.id, "e66bb753-4a03-4ee2-a069-a601f393c9ee") self.assertEqual(volume.name, "linux") self.assertEqual(volume.size, 50) self.assertEqual(volume.driver, self.driver) def test_list_images_success(self): images = self.driver.list_images() self.assertTrue(len(images) >= 1) image = images[0] self.assertTrue(image.id is not None) self.assertTrue(image.name is not None) def test_list_key_pairs(self): keys = self.driver.list_key_pairs() self.assertEqual(len(keys), 2) self.assertEqual(keys[0].name, 'karl') self.assertEqual(keys[0].public_key, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC") def test_list_volume_snapshots(self): volume = self.driver.list_volumes()[0] snapshots = self.driver.list_volume_snapshots(volume) self.assertEqual(len(snapshots), 1) self.assertEqual(snapshots[0].id, "d755de62-4d75-4d61-addd-a5c9743a5deb") def test_list_volumes_empty(self): GridscaleMockHttp.type = 'EMPTY' volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 0) def test_ex_list_networks(self): networks = self.driver.ex_list_networks()[0] self.assertEqual(networks.id, "1196529b-a8de-417f") def test_ex_list_ips(self): ip = self.driver.ex_list_ips()[0] self.assertEqual(ip.id, "56b8d161-325b-4fd4") def test_ex_destroy_ip(self): ip = self.driver.ex_list_ips()[0] GridscaleMockHttp.type = 'DELETE' self.assertTrue(self.driver.ex_destroy_ip(ip)) def test_ex_destroy_network(self): network = self.driver.ex_list_networks()[0] GridscaleMockHttp.type = 'DELETE' self.assertTrue(self.driver.ex_destroy_network(network)) def test_destroy_node_success(self): # Regular destroy node = self.driver.list_nodes()[0] GridscaleMockHttp.type = 'DELETE' res = self.driver.destroy_node(node) self.assertTrue(res) # Destroy associated resources res = self.driver.destroy_node(node, ex_destroy_associated_resources=True) self.assertTrue(res) def test_destroy_volume(self): volume = self.driver.list_volumes()[0] GridscaleMockHttp.type = 'DELETE' res = self.driver.destroy_volume(volume) self.assertTrue(res) def test_destroy_volume_snapshot(self): volume = self.driver.list_volumes()[0] snapshot = self.driver.list_volume_snapshots(volume)[0] GridscaleMockHttp.type = 'DELETE' res = self.driver.destroy_volume_snapshot(snapshot) self.assertTrue(res) def test_get_image_success(self): image = self.driver.get_image("12345") self.assertEqual(image.id, "12345") def test_list_nodes_fills_created_datetime(self): nodes = self.driver.list_nodes() self.assertEqual(nodes[0].created_at, datetime(2019, 6, 7, 12, 56, 44, tzinfo=UTC)) def test_ex_list_volumes_for_node(self): node = self.driver.list_nodes()[0] volumes = self.driver.ex_list_volumes_for_node(node=node) self.assertEqual(len(volumes), 1) self.assertEqual(volumes[0].size, 50) def test_ex_list_ips_for_node(self): node = self.driver.list_nodes()[0] ips = self.driver.ex_list_ips_for_node(node=node) self.assertEqual(len(ips), 1) self.assertEqual(ips[0].ip_address, '185.102.95.236') def test_ex_rename_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.ex_rename_node(node, name='new-name')) def test_ex_rename_volume(self): volume = self.driver.list_volumes()[0] self.assertTrue(self.driver.ex_rename_volume(volume, name='new-name')) def test_ex_network(self): network = self.driver.ex_list_networks()[0] self.assertTrue(self.driver.ex_rename_network(network, name='new-name')) class GridscaleMockHttp(MockHttp): fixtures = ComputeFileFixtures('gridscale') def _objects_servers(self, method, url, body, headers): body = self.fixtures.load('list_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_locations(self, method, url, body, headers): body = self.fixtures.load('list_locations.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_storages(self, method, url, body, headers): body = self.fixtures.load('list_volumes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_storages_DELETE(self, method, url, body, headers): # test_destroy_node_success body = self.fixtures.load('list_volumes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_ips_DELETE(self, method, url, body, headers): # test_destroy_node_success body = self.fixtures.load('ex_list_ips.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_ips_56b8d161_325b_4fd4_DELETE(self, method, url, body, headers): # test_destroy_node_success return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) def _objects_storages_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_volumes_empty.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_templates(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_sshkeys(self, method, url, body, headers): body = self.fixtures.load('list_key_pairs.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_storages_e66bb753_4a03_4ee2_a069_a601f393c9ee_snapshots( self, method, url, body, headers): body = self.fixtures.load('list_volume_snapshots.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_servers_1479405e_d46c_47a2_91e8_eb43951c899f( self, method, url, body, headers): # test_ex_rename_node if method == 'PATCH': return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_storages_e66bb753_4a03_4ee2_a069_a601f393c9ee( self, method, url, body, headers): # test_ex_rename_node if method == 'PATCH': return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_networks_1196529b_a8de_417f( self, method, url, body, headers): # test_ex_rename_network if method == 'PATCH': return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_servers_POST(self, method, url, body, headers): # create_node if method == 'POST': body = self.fixtures.load('create_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') def _requests_x123xx1x_123x_1x12_123x_123xxx123x1x_POST(self, method, url, body, headers): body = self.fixtures.load('create_node_response_dict.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_servers_690de890_13c0_4e76_8a01_e10ba8786e53_POST(self, method, url, body, headers): body = self.fixtures.load('create_node_dict.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) # create_volume def _objects_storages_POST(self, method, url, body, headers): body = self.fixtures.load('create_volume.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_storages_690de890_13c0_4e76_8a01_e10ba8786e53_POST(self, method, url, body, headers): body = self.fixtures.load('create_volume_response_dict.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_ips_POST(self, method, url, body, headers): # ex_create_ip if method == 'POST': body = self.fixtures.load('create_ip.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_ips_690de890_13c0_4e76_8a01_e10ba8786e53_POST(self, method, url, body, headers): body = self.fixtures.load('create_ip_response_dict.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_servers_1479405e_d46c_47a2_91e8_eb43951c899f_storages_POST(self, method, url, body, headers): body = self.fixtures.load('volume_to_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_servers_1479405e_d46c_47a2_91e8_eb43951c899f_ips_POST(self, method, url, body, headers): body = self.fixtures.load('ips_to_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_networks_POST(self, method, url, body, headers): body = self.fixtures.load('create_network.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_networks_1196529b_a8de_417f_DELETE(self, method, url, body, headers): # test_ex_destroy_network if method == 'DELETE': return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_servers_1479405e_d46c_47a2_91e8_eb43951c899f_networks_POST(self, method, url, body, headers): body = self.fixtures.load('network_to_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_servers_1479405e_d46c_47a2_91e8_eb43951c899f_power_POST(self, method, url, body, headers): if method == 'PATCH': body = self.fixtures.load('ex_start_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_servers_1479405e_d46c_47a2_91e8_eb43951c899f_POST(self, method, url, body, headers): body = self.fixtures.load('create_node_dict.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_networks(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('ex_list_networks.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_ips(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('ex_list_ips.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_servers_1479405e_d46c_47a2_91e8_eb43951c899f_DELETE(self, method, url, body, headers): if method == 'DELETE': return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_storages_e66bb753_4a03_4ee2_a069_a601f393c9ee_DELETE(self, method, url, body, headers): if method == 'DELETE': return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_storages_e66bb753_4a03_4ee2_a069_a601f393c9ee_snapshots_d755de62_4d75_4d61_addd_a5c9743a5deb_DELETE(self, method, url, body, headers): if method == 'DELETE': return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_templates_POST(self, method, url, body, headers): # create_image if method == 'POST': body = self.fixtures.load('create_image.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_storages_e66bb753_4a03_4ee2_a069_a601f393c9ee_snapshots_POST(self, method, url, body, headers): # create_image if method == 'POST': body = self.fixtures.load('create_image.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_storages_e66bb753_4a03_4ee2_a069_a601f393c9ee_snapshots_690de890_13c0_4e76_8a01_e10ba8786e53_POST(self, method, url, body, headers): # create_image body = self.fixtures.load('create_image_dict.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _objects_templates_690de890_13c0_4e76_8a01_e10ba8786e53_POST(self, method, url, body, headers): # create_image if method == 'GET': body = self.fixtures.load('create_image_dict.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') def _objects_templates_12345(self, method, url, body, headers): # get_image if method == 'GET': body = self.fixtures.load('get_image.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: # pragma: no cover raise ValueError('Invalid method') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_gridspot.py0000664000175000017500000001700213535474530024130 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib try: import simplejson as json except ImportError: import json from libcloud.common.types import InvalidCredsError from libcloud.compute.drivers.gridspot import GridspotNodeDriver from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.secrets import GRIDSPOT_PARAMS class GridspotTest(unittest.TestCase, TestCaseMixin): def setUp(self): GridspotNodeDriver.connectionCls.conn_class = GridspotMockHttp GridspotMockHttp.type = None self.driver = GridspotNodeDriver(*GRIDSPOT_PARAMS) def test_invalid_creds(self): """ Tests the error-handling for passing a bad API Key to the Gridspot API """ GridspotMockHttp.type = 'BAD_AUTH' self.assertRaises(InvalidCredsError, self.driver.list_nodes) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) running_node = nodes[0] starting_node = nodes[1] self.assertEqual(running_node.id, 'inst_CP2WrQi2WIS4iheyAVkQYw') self.assertEqual(running_node.state, NodeState.RUNNING) self.assertTrue('69.4.239.74' in running_node.public_ips) self.assertEqual(running_node.extra['port'], 62394) self.assertEqual(running_node.extra['vm_ram'], 1429436743) self.assertEqual(running_node.extra['start_state_time'], 1342108905) self.assertEqual(running_node.extra['vm_num_logical_cores'], 8) self.assertEqual(running_node.extra['vm_num_physical_cores'], 4) self.assertEqual(running_node.extra['winning_bid_id'], 'bid_X5xhotGYiGUk7_RmIqVafA') self.assertFalse('ended_state_time' in running_node.extra) self.assertEqual(running_node.extra['running_state_time'], 1342108989) self.assertEqual(starting_node.id, 'inst_CP2WrQi2WIS4iheyAVkQYw2') self.assertEqual(starting_node.state, NodeState.PENDING) self.assertTrue('69.4.239.74' in starting_node.public_ips) self.assertEqual(starting_node.extra['port'], 62395) self.assertEqual(starting_node.extra['vm_ram'], 1429436744) self.assertEqual(starting_node.extra['start_state_time'], 1342108906) self.assertEqual(starting_node.extra['vm_num_logical_cores'], 7) self.assertEqual(starting_node.extra['vm_num_physical_cores'], 5) self.assertEqual(starting_node.extra['winning_bid_id'], 'bid_X5xhotGYiGUk7_RmIqVafA1') self.assertFalse('ended_state_time' in starting_node.extra) self.assertEqual(starting_node.extra['running_state_time'], 1342108990) def test_create_node(self): """ Gridspot does not implement this functionality """ pass def test_destroy_node(self): """ Test destroy_node for Gridspot driver """ node = self.driver.list_nodes()[0] self.assertTrue(self.driver.destroy_node(node)) def test_destroy_node_failure(self): """ Gridspot does not fail a destroy node unless the parameters are bad, in which case it 404s """ pass def test_reboot_node(self): """ Gridspot does not implement this functionality """ pass def test_reboot_node_failure(self): """ Gridspot does not implement this functionality """ pass def test_resize_node(self): """ Gridspot does not implement this functionality """ pass def test_reboot_node_response(self): """ Gridspot does not implement this functionality """ pass def test_list_images_response(self): """ Gridspot does not implement this functionality """ pass def test_create_node_response(self): """ Gridspot does not implement this functionality """ pass def test_destroy_node_response(self): """ Gridspot does not implement this functionality """ pass def test_list_sizes_response(self): """ Gridspot does not implement this functionality """ pass def test_resize_node_failure(self): """ Gridspot does not implement this functionality """ pass def test_list_images(self): """ Gridspot does not implement this functionality """ pass def test_list_sizes(self): """ Gridspot does not implement this functionality """ pass def test_list_locations(self): """ Gridspot does not implement this functionality """ pass def test_list_locations_response(self): """ Gridspot does not implement this functionality """ pass class GridspotMockHttp(MockHttp): def _compute_api_v1_list_instances_BAD_AUTH(self, method, url, body, headers): return (httplib.NOT_FOUND, "", {}, httplib.responses[httplib.NOT_FOUND]) def _compute_api_v1_list_instances(self, method, url, body, headers): body = json.dumps({ "instances": [ { "instance_id": "inst_CP2WrQi2WIS4iheyAVkQYw", "vm_num_logical_cores": 8, "vm_num_physical_cores": 4, "winning_bid_id": "bid_X5xhotGYiGUk7_RmIqVafA", "vm_ram": 1429436743, "start_state_time": 1342108905, "vm_ssh_wan_ip_endpoint": "69.4.239.74:62394", "current_state": "Running", "ended_state_time": "null", "running_state_time": 1342108989 }, { "instance_id": "inst_CP2WrQi2WIS4iheyAVkQYw2", "vm_num_logical_cores": 7, "vm_num_physical_cores": 5, "winning_bid_id": "bid_X5xhotGYiGUk7_RmIqVafA1", "vm_ram": 1429436744, "start_state_time": 1342108906, "vm_ssh_wan_ip_endpoint": "69.4.239.74:62395", "current_state": "Starting", "ended_state_time": "null", "running_state_time": 1342108990 } ], "exception_name": "" }) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _compute_api_v1_stop_instance(self, method, url, body, headers): body = json.dumps({"exception_name": ""}) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_hostvirtual.py0000664000175000017500000002074613535474530024672 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.hostvirtual import HostVirtualNodeDriver from libcloud.compute.types import NodeState from libcloud.compute.base import NodeAuthPassword from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import HOSTVIRTUAL_PARAMS class HostVirtualTest(unittest.TestCase): def setUp(self): HostVirtualNodeDriver.connectionCls.conn_class = HostVirtualMockHttp self.driver = HostVirtualNodeDriver(*HOSTVIRTUAL_PARAMS) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 4) self.assertEqual(len(nodes[0].public_ips), 1) self.assertEqual(len(nodes[1].public_ips), 1) self.assertEqual(len(nodes[0].private_ips), 0) self.assertEqual(len(nodes[1].private_ips), 0) self.assertTrue('208.111.39.118' in nodes[1].public_ips) self.assertTrue('208.111.45.250' in nodes[0].public_ips) self.assertEqual(nodes[3].state, NodeState.RUNNING) self.assertEqual(nodes[1].state, NodeState.TERMINATED) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 14) self.assertEqual(sizes[0].id, '31') self.assertEqual(sizes[4].id, '71') self.assertEqual(sizes[2].ram, '512MB') self.assertEqual(sizes[2].disk, '20GB') self.assertEqual(sizes[3].bandwidth, '600GB') self.assertEqual(sizes[1].price, '15.00') def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 8) self.assertEqual(images[0].id, '1739') self.assertEqual(images[0].name, 'Gentoo 2012 (0619) i386') def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(locations[0].id, '3') self.assertEqual(locations[0].name, 'SJC - San Jose, CA') self.assertEqual(locations[1].id, '13') self.assertEqual(locations[1].name, 'IAD - Reston, VA') def test_reboot_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.reboot_node(node)) def test_ex_get_node(self): node = self.driver.ex_get_node(node_id='62291') self.assertEqual(node.id, '62291') self.assertEqual(node.name, 'server1.vr-cluster.org') self.assertEqual(node.state, NodeState.TERMINATED) self.assertTrue('208.111.45.250' in node.public_ips) def test_ex_list_packages(self): pkgs = self.driver.ex_list_packages() self.assertEqual(len(pkgs), 3) self.assertEqual(pkgs[1]['mbpkgid'], '176018') self.assertEqual(pkgs[2]['package_status'], 'Suspended') def test_ex_order_package(self): sizes = self.driver.list_sizes() pkg = self.driver.ex_order_package(sizes[0]) self.assertEqual(pkg['id'], '62291') def test_ex_cancel_package(self): node = self.driver.list_nodes()[0] result = self.driver.ex_cancel_package(node) self.assertEqual(result['status'], 'success') def test_ex_unlink_package(self): node = self.driver.list_nodes()[0] result = self.driver.ex_unlink_package(node) self.assertEqual(result['status'], 'success') def test_ex_stop_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.ex_stop_node(node)) def test_ex_start_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.ex_start_node(node)) def test_destroy_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.destroy_node(node)) def test_ex_delete_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.ex_delete_node(node)) def test_create_node(self): auth = NodeAuthPassword('vr!@#hosted#@!') size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] node = self.driver.create_node( name='test.com', image=image, size=size, auth=auth ) self.assertEqual('62291', node.id) self.assertEqual('server1.vr-cluster.org', node.name) def test_ex_provision_node(self): node = self.driver.list_nodes()[0] auth = NodeAuthPassword('vr!@#hosted#@!') self.assertTrue(self.driver.ex_provision_node( node=node, auth=auth )) def test_create_node_in_location(self): auth = NodeAuthPassword('vr!@#hosted#@!') size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[1] node = self.driver.create_node( name='test.com', image=image, size=size, auth=auth, location=location ) self.assertEqual('62291', node.id) self.assertEqual('server1.vr-cluster.org', node.name) class HostVirtualMockHttp(MockHttp): fixtures = ComputeFileFixtures('hostvirtual') def _cloud_servers(self, method, url, body, headers): body = self.fixtures.load('list_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_server(self, method, url, body, headers): body = self.fixtures.load('get_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_packages(self, method, url, body, headers): body = self.fixtures.load('list_packages.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_sizes(self, method, url, body, headers): body = self.fixtures.load('list_sizes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_images(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_locations(self, method, url, body, headers): body = self.fixtures.load('list_locations.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_server_delete(self, method, url, body, headers): body = self.fixtures.load('cancel_package.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_server_reboot(self, method, url, body, headers): body = self.fixtures.load('node_reboot.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_server_shutdown(self, method, url, body, headers): body = self.fixtures.load('node_stop.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_server_start(self, method, url, body, headers): body = self.fixtures.load('node_start.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_server_build(self, method, url, body, headers): body = self.fixtures.load('order_package.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_buy(self, method, url, body, headers): body = self.fixtures.load('order_package.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_cancel(self, method, url, body, headers): body = self.fixtures.load('cancel_package.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cloud_unlink(self, method, url, body, headers): body = self.fixtures.load('unlink_package.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) # vim:autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python apache-libcloud-2.8.0/libcloud/test/compute/test_ikoula.py0000664000175000017500000000216313535474530023563 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.compute.drivers.ikoula import IkoulaNodeDriver from libcloud.test.compute.test_cloudstack import CloudStackCommonTestCase from libcloud.test import unittest class IkoulaNodeDriverTestCase(CloudStackCommonTestCase, unittest.TestCase): driver_klass = IkoulaNodeDriver if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_indosat.py0000664000175000017500000000243713535474530023744 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest from libcloud.compute.drivers.indosat import IndosatNodeDriver from libcloud.test.compute.test_dimensiondata_v2_3 import DimensionDataMockHttp, DimensionData_v2_3_Tests class IndosatNodeDriverTests(DimensionData_v2_3_Tests, unittest.TestCase): def setUp(self): IndosatNodeDriver.connectionCls.conn_class = DimensionDataMockHttp IndosatNodeDriver.connectionCls.active_api_version = '2.3' DimensionDataMockHttp.type = None self.driver = IndosatNodeDriver('user', 'password') apache-libcloud-2.8.0/libcloud/test/compute/test_internetsolutions.py0000664000175000017500000000253313535474530026110 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest from libcloud.compute.drivers.internetsolutions import InternetSolutionsNodeDriver from libcloud.test.compute.test_dimensiondata_v2_3 import DimensionDataMockHttp, DimensionData_v2_3_Tests class InternetSolutionsNodeDriverTests(DimensionData_v2_3_Tests, unittest.TestCase): def setUp(self): InternetSolutionsNodeDriver.connectionCls.conn_class = DimensionDataMockHttp InternetSolutionsNodeDriver.connectionCls.active_api_version = '2.3' DimensionDataMockHttp.type = None self.driver = InternetSolutionsNodeDriver('user', 'password') apache-libcloud-2.8.0/libcloud/test/compute/test_joyent.py0000664000175000017500000001252613535474530023613 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.utils.py3 import httplib from libcloud.utils.py3 import assertRaisesRegex from libcloud.common.types import LibcloudError from libcloud.compute.base import NodeState from libcloud.compute.drivers.joyent import JoyentNodeDriver from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import JOYENT_PARAMS class JoyentTestCase(unittest.TestCase): def setUp(self): JoyentNodeDriver.connectionCls.conn_class = JoyentHttp self.driver = JoyentNodeDriver(*JOYENT_PARAMS) def test_instantiate_multiple_drivers_with_different_region(self): kwargs1 = {'region': 'us-east-1'} kwargs2 = {'region': 'us-west-1'} driver1 = JoyentNodeDriver(*JOYENT_PARAMS, **kwargs1) driver2 = JoyentNodeDriver(*JOYENT_PARAMS, **kwargs2) self.assertTrue(driver1.connection.host.startswith(kwargs1['region'])) self.assertTrue(driver2.connection.host.startswith(kwargs2['region'])) driver1.list_nodes() driver2.list_nodes() driver1.list_nodes() self.assertTrue(driver1.connection.host.startswith(kwargs1['region'])) self.assertTrue(driver2.connection.host.startswith(kwargs2['region'])) def test_location_backward_compatibility(self): kwargs = {'location': 'us-west-1'} driver = JoyentNodeDriver(*JOYENT_PARAMS, **kwargs) self.assertTrue(driver.connection.host.startswith(kwargs['location'])) def test_instantiate_invalid_region(self): expected_msg = 'Invalid region.+' assertRaisesRegex(self, LibcloudError, expected_msg, JoyentNodeDriver, 'user', 'key', location='invalid') assertRaisesRegex(self, LibcloudError, expected_msg, JoyentNodeDriver, 'user', 'key', region='invalid') def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(sizes[0].ram, 16384) def test_list_images(self): images = self.driver.list_images() self.assertEqual(images[0].name, 'nodejs') def test_list_nodes_with_and_without_credentials(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) node = nodes[0] self.assertEqual(node.public_ips[0], '165.225.129.129') self.assertEqual(node.private_ips[0], '10.112.1.130') self.assertEqual(node.state, NodeState.RUNNING) node = nodes[1] self.assertEqual(node.public_ips[0], '165.225.129.128') self.assertEqual(node.private_ips[0], '10.112.1.131') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.extra['password'], 'abc') def test_create_node(self): image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] node = self.driver.create_node(image=image, size=size, name='testlc') self.assertEqual(node.name, 'testlc') def test_ex_stop_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.ex_stop_node(node)) def test_ex_start_node(self): node = self.driver.list_nodes()[0] self.assertTrue(self.driver.ex_start_node(node)) def test_ex_get_node(self): node_id = '2fb67f5f-53f2-40ab-9d99-b9ff68cfb2ab' node = self.driver.ex_get_node(node_id) self.assertEqual(node.name, 'testlc') missing_node = 'dummy-node' self.assertRaises(Exception, self.driver.ex_get_node, missing_node, 'all') class JoyentHttp(MockHttp): fixtures = ComputeFileFixtures('joyent') def _my_packages(self, method, url, body, headers): body = self.fixtures.load('my_packages.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _my_datasets(self, method, url, body, headers): body = self.fixtures.load('my_datasets.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _my_machines(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('my_machines.json') elif method == 'POST': body = self.fixtures.load('my_machines_create.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _my_machines_2fb67f5f_53f2_40ab_9d99_b9ff68cfb2ab(self, method, url, body, headers): body = self.fixtures.load('my_machines_create.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_kili.py0000664000175000017500000000276513535474530023237 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest from libcloud.compute.drivers.kili import KiliCloudNodeDriver, ENDPOINT_ARGS from libcloud.test.compute.test_openstack import OpenStack_1_1_Tests def _ex_connection_class_kwargs(self): kwargs = self.openstack_connection_kwargs() kwargs['get_endpoint_args'] = ENDPOINT_ARGS # Remove keystone from the URL path so that the openstack base tests work kwargs['ex_force_auth_url'] = 'https://api.kili.io/v2.0/tokens' kwargs['ex_tenant_name'] = self.tenant_name return kwargs KiliCloudNodeDriver._ex_connection_class_kwargs = _ex_connection_class_kwargs class KiliCloudNodeDriverTests(OpenStack_1_1_Tests, unittest.TestCase): driver_klass = KiliCloudNodeDriver driver_type = KiliCloudNodeDriver apache-libcloud-2.8.0/libcloud/test/compute/test_ktucloud.py0000664000175000017500000001071213535474530024130 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qsl try: import simplejson as json except ImportError: import json from libcloud.compute.drivers.ktucloud import KTUCloudNodeDriver from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures class KTUCloudNodeDriverTest(unittest.TestCase, TestCaseMixin): def setUp(self): KTUCloudNodeDriver.connectionCls.conn_class = KTUCloudStackMockHttp self.driver = KTUCloudNodeDriver('apikey', 'secret', path='/test/path', host='api.dummy.com') self.driver.path = '/test/path' self.driver.type = -1 KTUCloudStackMockHttp.fixture_tag = 'default' self.driver.connection.poll_interval = 0.0 def test_create_node_immediate_failure(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] KTUCloudStackMockHttp.fixture_tag = 'deployfail' self.assertRaises( Exception, self.driver.create_node, name='node-name', image=image, size=size) def test_create_node_delayed_failure(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] KTUCloudStackMockHttp.fixture_tag = 'deployfail2' self.assertRaises( Exception, self.driver.create_node, name='node-name', image=image, size=size) def test_list_images_no_images_available(self): KTUCloudStackMockHttp.fixture_tag = 'notemplates' images = self.driver.list_images() self.assertEqual(0, len(images)) def test_list_images_available(self): images = self.driver.list_images() self.assertEqual(112, len(images)) def test_list_sizes_available(self): sizes = self.driver.list_sizes() self.assertEqual(112, len(sizes)) def test_list_sizes_nodisk(self): KTUCloudStackMockHttp.fixture_tag = 'nodisk' sizes = self.driver.list_sizes() self.assertEqual(2, len(sizes)) check = False size = sizes[1] if size.id == KTUCloudNodeDriver.EMPTY_DISKOFFERINGID: check = True self.assertTrue(check) class KTUCloudStackMockHttp(MockHttp, unittest.TestCase): fixtures = ComputeFileFixtures('ktucloud') fixture_tag = 'default' def _load_fixture(self, fixture): body = self.fixtures.load(fixture) return body, json.loads(body) def _test_path(self, method, url, body, headers): url = urlparse.urlparse(url) query = dict(parse_qsl(url.query)) self.assertTrue('apiKey' in query) self.assertTrue('command' in query) self.assertTrue('response' in query) self.assertTrue('signature' in query) self.assertTrue(query['response'] == 'json') del query['apiKey'] del query['response'] del query['signature'] command = query.pop('command') if hasattr(self, '_cmd_' + command): return getattr(self, '_cmd_' + command)(**query) else: fixture = command + '_' + self.fixture_tag + '.json' body, obj = self._load_fixture(fixture) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cmd_queryAsyncJobResult(self, jobid): fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json' body, obj = self._load_fixture(fixture) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_libvirt_driver.py0000664000175000017500000000722213535474530025326 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import mock from libcloud.compute.drivers.libvirt_driver import LibvirtNodeDriver from libcloud.compute.drivers.libvirt_driver import have_libvirt from libcloud.utils.py3 import PY3 from libcloud.test import unittest __all__ = [ 'LibvirtNodeDriverTestCase' ] @unittest.skipIf(not have_libvirt, 'libvirt not available, skipping tests') @mock.patch('libcloud.compute.drivers.libvirt_driver.libvirt', autospec=True) class LibvirtNodeDriverTestCase(unittest.TestCase): arp_output_str = """? (1.2.10.80) at 52:54:00:bc:f9:6c [ether] on br0 ? (1.2.10.33) at 52:54:00:04:89:51 [ether] on br0 ? (1.2.10.97) at 52:54:00:c6:40:ec [ether] on br0 ? (1.2.10.40) at 52:54:00:77:1c:83 [ether] on br0""" ip_output_str = """1.2.10.80 dev br0 lladdr 52:54:00:bc:f9:6c STALE 1.2.10.33 dev br0 lladdr 52:54:00:04:89:51 REACHABLE 1.2.10.97 dev br0 lladdr 52:54:00:c6:40:ec DELAY 1.2.10.40 dev br0 lladdr 52:54:00:77:1c:83 STALE""" bad_output_str = """1.2.10.80 dev br0 52:54:00:bc:f9:6c STALE 1.2.10.33 dev br0 lladdr 52:54:00:04:89:51 REACHABLE 1.2.10.97 dev br0 lladdr 1.2.10.40 dev br0 lladdr 52:54:00:77:1c:83 STALE""" if PY3: from libcloud.utils.py3 import b arp_output_str = b(arp_output_str) ip_output_str = b(ip_output_str) bad_output_str = b(bad_output_str) def _assert_arp_table(self, arp_table): self.assertIn('52:54:00:bc:f9:6c', arp_table) self.assertIn('52:54:00:04:89:51', arp_table) self.assertIn('52:54:00:c6:40:ec', arp_table) self.assertIn('52:54:00:77:1c:83', arp_table) self.assertIn('1.2.10.80', arp_table['52:54:00:bc:f9:6c']) self.assertIn('1.2.10.33', arp_table['52:54:00:04:89:51']) self.assertIn('1.2.10.97', arp_table['52:54:00:c6:40:ec']) self.assertIn('1.2.10.40', arp_table['52:54:00:77:1c:83']) def test_arp_map(self, *args, **keywargs): driver = LibvirtNodeDriver('') arp_table = driver._parse_ip_table_arp(self.arp_output_str) self._assert_arp_table(arp_table) def test_ip_map(self, *args, **keywargs): driver = LibvirtNodeDriver('') arp_table = driver._parse_ip_table_neigh(self.ip_output_str) self._assert_arp_table(arp_table) def test_bad_map(self, *args, **keywargs): driver = LibvirtNodeDriver('') arp_table = driver._parse_ip_table_neigh(self.bad_output_str) # we should at least get the correctly formatted lines self.assertEqual(len(arp_table), 2) arp_table = driver._parse_ip_table_neigh(self.arp_output_str) # nothing should match if the wrong output is sent self.assertEqual(len(arp_table), 0) def test_list_nodes(self, *args, **keywargs): driver = LibvirtNodeDriver('') nodes = driver.list_nodes() self.assertEqual(type([]), type(nodes)) self.assertEqual(len(nodes), 0) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_linode.py0000664000175000017500000002111213535474530023544 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Maintainer: Jed Smith # Based upon code written by Alex Polvi # import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.linode import LinodeNodeDriver from libcloud.compute.base import Node, NodeAuthPassword from libcloud.compute.base import NodeAuthSSHKey, StorageVolume from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures class LinodeTest(unittest.TestCase, TestCaseMixin): # The Linode test suite def setUp(self): LinodeNodeDriver.connectionCls.conn_class = LinodeMockHttp LinodeMockHttp.use_param = 'api_action' self.driver = LinodeNodeDriver('foo') def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) node = nodes[0] self.assertEqual(node.id, "8098") self.assertEqual(node.name, 'api-node3') self.assertEqual(node.extra['PLANID'], '2') self.assertTrue('75.127.96.245' in node.public_ips) self.assertEqual(node.private_ips, []) def test_reboot_node(self): # An exception would indicate failure node = self.driver.list_nodes()[0] self.driver.reboot_node(node) def test_destroy_node(self): # An exception would indicate failure node = self.driver.list_nodes()[0] self.driver.destroy_node(node) def test_create_node_password_auth(self): # Will exception on failure self.driver.create_node(name="Test", location=self.driver.list_locations()[0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[6], auth=NodeAuthPassword("test123")) def test_create_node_ssh_key_auth(self): # Will exception on failure node = self.driver.create_node(name="Test", location=self.driver.list_locations()[ 0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[6], auth=NodeAuthSSHKey('foo')) self.assertTrue(isinstance(node, Node)) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 9) for size in sizes: self.assertEqual(size.ram, int(size.name.split(" ")[1])) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 30) def test_create_node_response(self): # should return a node object node = self.driver.create_node(name="node-name", location=self.driver.list_locations()[ 0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[0], auth=NodeAuthPassword("foobar")) self.assertTrue(isinstance(node, Node)) def test_destroy_volume(self): # Will exception on failure node = self.driver.list_nodes()[0] volume = StorageVolume(id=55648, name="test", size=1024, driver=self.driver, extra={"LINODEID": node.id}) self.driver.destroy_volume(volume) def test_ex_create_volume(self): # should return a StorageVolume object node = self.driver.list_nodes()[0] volume = self.driver.ex_create_volume(size=4096, name="Another test image", node=node, fs_type="ext4") self.assertTrue(isinstance(volume, StorageVolume)) def test_ex_list_volumes(self): # should return list of StorageVolume objects node = self.driver.list_nodes()[0] volumes = self.driver.ex_list_volumes(node=node) self.assertTrue(isinstance(volumes, list)) self.assertTrue(isinstance(volumes[0], StorageVolume)) self.assertEqual(len(volumes), 2) class LinodeMockHttp(MockHttp): fixtures = ComputeFileFixtures('linode') def _avail_datacenters(self, method, url, body, headers): body = self.fixtures.load('_avail_datacenters.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _avail_linodeplans(self, method, url, body, headers): body = self.fixtures.load('_avail_linodeplans.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _avail_distributions(self, method, url, body, headers): body = self.fixtures.load('_avail_distributions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_create(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.create","DATA":{"LinodeID":8098}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_disk_create(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.disk.create","DATA":{"JobID":1298,"DiskID":55647}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_disk_delete(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.disk.delete","DATA":{"JobID":1298,"DiskID":55648}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_disk_createfromdistribution(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.disk.createFromDistribution","DATA":{"JobID":1298,"DiskID":55647}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_disk_list(self, method, url, body, headers): body = self.fixtures.load('_linode_disk_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_delete(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.delete","DATA":{"LinodeID":8098}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_update(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.update","DATA":{"LinodeID":8098}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_reboot(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.reboot","DATA":{"JobID":1305}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _avail_kernels(self, method, url, body, headers): body = self.fixtures.load('_avail_kernels.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_boot(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.boot","DATA":{"JobID":1300}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_config_create(self, method, url, body, headers): body = '{"ERRORARRAY":[],"ACTION":"linode.config.create","DATA":{"ConfigID":31239}}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_list(self, method, url, body, headers): body = self.fixtures.load('_linode_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _linode_ip_list(self, method, url, body, headers): body = self.fixtures.load('_linode_ip_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _batch(self, method, url, body, headers): body = self.fixtures.load('_batch.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_maxihost.py0000664000175000017500000001032213570310635024121 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.maxihost import MaxihostNodeDriver from libcloud.compute.base import Node from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures class MaxihostTest(unittest.TestCase, TestCaseMixin): def setUp(self): MaxihostNodeDriver.connectionCls.conn_class = MaxihostMockHttp self.driver = MaxihostNodeDriver('foo') def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 1) def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(len(locations), 3) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 1) image = images[0] self.assertEqual(image.id, 'ubuntu_18_04_x64_lts') def test_list_key_pairs(self): keys = self.driver.list_key_pairs() self.assertEqual(len(keys), 1) key = keys[0] self.assertEqual(key.name, 'test_key') self.assertEqual(key.fingerprint, '77:08:a7:a5:f9:8c:e1:ab:7b:c3:d8:0c:cd:ac:8b:dd') def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) node = nodes[0] self.assertEqual(node.name, 'tester') def test_create_node_response(self): # should return a node object size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] node = self.driver.create_node(name='node-name', image=image, size=size, location=location) self.assertTrue(isinstance(node, Node)) def test_destroy_node_response(self): node = self.driver.list_nodes()[0] ret = self.driver.destroy_node(node) self.assertTrue(ret) class MaxihostMockHttp(MockHttp): fixtures = ComputeFileFixtures('maxihost') def _plans(self, method, url, body, headers): body = self.fixtures.load('plans.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _regions(self, method, url, body, headers): body = self.fixtures.load('regions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _plans_operating_systems(self, method, url, body, headers): body = self.fixtures.load('images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _devices(self, method, url, body, headers): body = self.fixtures.load('nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _devices_1319(self, method, url, body, headers): if method == 'DELETE': body = '{}' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: raise ValueError('Unsupported method: %s' % (method)) def _devices_1319_actions(self, method, url, body, headers): body = self.fixtures.load('node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _account_keys(self, method, url, body, headers): body = self.fixtures.load('keys.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_medone.py0000664000175000017500000000241713535474530023550 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest from libcloud.compute.drivers.medone import MedOneNodeDriver from libcloud.test.compute.test_dimensiondata_v2_3 import DimensionDataMockHttp, DimensionData_v2_3_Tests class MedOneTests(DimensionData_v2_3_Tests, unittest.TestCase): def setUp(self): MedOneNodeDriver.connectionCls.conn_class = DimensionDataMockHttp MedOneNodeDriver.connectionCls.active_api_version = '2.3' DimensionDataMockHttp.type = None self.driver = MedOneNodeDriver('user', 'password') apache-libcloud-2.8.0/libcloud/test/compute/test_nephoscale.py0000664000175000017500000001632213535474530024422 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Created by Markos Gogoulos (https://mist.io) # import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.nephoscale import NephoscaleNodeDriver from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures class NephoScaleTest(unittest.TestCase, TestCaseMixin): def setUp(self): NephoscaleNodeDriver.connectionCls.conn_class = NephoscaleMockHttp self.driver = NephoscaleNodeDriver('user', 'password') def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 13) for size in sizes: self.assertEqual(type(size.disk), int) self.assertEqual(type(size.ram), int) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 18) for image in images: arch = image.extra.get('architecture') self.assertTrue(arch.startswith('x86')) def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(len(locations), 2) self.assertEqual(locations[0].name, "SJC-1") def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) self.assertEqual(nodes[0].extra.get('zone'), 'RIC-1') self.assertEqual(nodes[0].name, 'mongodb-staging') self.assertEqual(nodes[0].extra.get('service_type'), 'CS05 - 0.5GB, 1Core, 25GB') def test_list_keys(self): keys = self.driver.ex_list_keypairs() self.assertEqual(len(keys), 2) self.assertEqual(keys[0].name, 'mistio-ssh') def test_list_ssh_keys(self): ssh_keys = self.driver.ex_list_keypairs(ssh=True) self.assertEqual(len(ssh_keys), 1) self.assertTrue(ssh_keys[0].public_key.startswith('ssh-rsa')) def test_list_password_keys(self): password_keys = self.driver.ex_list_keypairs(password=True) self.assertEqual(len(password_keys), 1) self.assertEqual(password_keys[0].password, '23d493j5') def test_reboot_node(self): node = self.driver.list_nodes()[0] result = self.driver.reboot_node(node) self.assertTrue(result) def test_destroy_node(self): node = self.driver.list_nodes()[0] result = self.driver.destroy_node(node) self.assertTrue(result) def test_stop_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_stop_node(node) self.assertTrue(result) def test_start_node(self): node = self.driver.list_nodes()[0] result = self.driver.ex_start_node(node) self.assertTrue(result) def test_rename_node(self): node = self.driver.list_nodes()[0] result = self.driver.rename_node(node, 'new-name') self.assertTrue(result) def test_create_node(self): name = 'mongodb-staging' size = self.driver.list_sizes()[0] image = self.driver.list_images()[3] node = self.driver.create_node(name=name, size=size, nowait=True, image=image) self.assertEqual(node.name, 'mongodb-staging') def test_create_node_no_name(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[3] self.assertRaises(TypeError, self.driver.create_node, size=size, image=image) def test_delete_ssh_keys(self): self.assertTrue(self.driver.ex_delete_keypair(key_id=72209, ssh=True)) def test_delete_password_keys(self): self.assertTrue(self.driver.ex_delete_keypair(key_id=72211)) class NephoscaleMockHttp(MockHttp): fixtures = ComputeFileFixtures('nephoscale') def _server_type_cloud(self, method, url, body, headers): body = self.fixtures.load('list_sizes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _server_cloud(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('success_action.json') else: body = self.fixtures.load('list_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _image_server(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _datacenter_zone(self, method, url, body, headers): body = self.fixtures.load('list_locations.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _key(self, method, url, body, headers): body = self.fixtures.load('list_keys.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _key_sshrsa(self, method, url, body, headers): body = self.fixtures.load('list_ssh_keys.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _key_password(self, method, url, body, headers): body = self.fixtures.load('list_password_keys.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _server_cloud_88241(self, method, url, body, headers): body = self.fixtures.load('success_action.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _server_cloud_88241_initiator_restart(self, method, url, body, headers): body = self.fixtures.load('success_action.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _server_cloud_88241_initiator_start(self, method, url, body, headers): body = self.fixtures.load('success_action.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _server_cloud_88241_initiator_stop(self, method, url, body, headers): body = self.fixtures.load('success_action.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _key_password_72211(self, method, url, body, headers): body = self.fixtures.load('success_action.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _key_sshrsa_72209(self, method, url, body, headers): body = self.fixtures.load('success_action.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_ntta.py0000664000175000017500000000245313535474530023247 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest from libcloud.compute.drivers.ntta import NTTAmericaNodeDriver from libcloud.test.compute.test_dimensiondata_v2_3 import DimensionDataMockHttp, DimensionData_v2_3_Tests class NTTAmericaNodeDriverTests(DimensionData_v2_3_Tests, unittest.TestCase): def setUp(self): NTTAmericaNodeDriver.connectionCls.conn_class = DimensionDataMockHttp NTTAmericaNodeDriver.connectionCls.active_api_version = '2.3' DimensionDataMockHttp.type = None self.driver = NTTAmericaNodeDriver('user', 'password') apache-libcloud-2.8.0/libcloud/test/compute/test_nttcis.py0000664000175000017500000044163413576514553023622 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from types import GeneratorType import pytest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import ET from libcloud.common.types import InvalidCredsError from libcloud.common.nttcis import NttCisAPIException, NetworkDomainServicePlan from libcloud.common.nttcis import NttCisServerCpuSpecification, NttCisServerDisk, NttCisServerVMWareTools from libcloud.common.nttcis import NttCisTag, NttCisTagKey from libcloud.common.nttcis import ClassFactory from libcloud.common.nttcis import TYPES_URN from libcloud.compute.drivers.nttcis import NttCisNodeDriver as NttCis from libcloud.compute.drivers.nttcis import NttCisNic from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import NTTCIS_PARAMS from libcloud.utils.xml import fixxpath, findtext, findall @pytest.fixture() def driver(): NttCis.connectionCls.active_api_version = "2.7" NttCis.connectionCls.conn_class = NttCisMockHttp NttCisMockHttp.type = None driver = NttCis(*NTTCIS_PARAMS) return driver def test_auth_fails(driver): with pytest.raises(ValueError): NttCis(*NTTCIS_PARAMS, region='blah') def test_get_account_details(driver): NttCisMockHttp.type = None ret = driver.connection.get_account_details() assert ret.full_name == 'Test User' assert ret.first_name == 'Test' assert ret.email == 'test@example.com' def test_invalid_creds(driver): NttCisMockHttp.type = 'UNAUTHORIZED' with pytest.raises(InvalidCredsError): driver.list_nodes() def test_list_locations_response(driver): NttCisMockHttp.type = None ret = driver.list_locations() assert len(ret) == 5 first_loc = ret[0] assert first_loc.id == 'NA3' assert first_loc.name == 'US - West' assert first_loc.country == 'US' def test_list_nodes_response(driver): NttCisMockHttp.type = None ret = driver.list_nodes() assert len(ret) == 7 def test_node_extras(driver): NttCisMockHttp.type = None ret = driver.list_nodes() assert isinstance(ret[0].extra['vmWareTools'], NttCisServerVMWareTools) assert isinstance(ret[0].extra['cpu'], NttCisServerCpuSpecification) assert isinstance(ret[0].extra['disks'], list) assert isinstance(ret[0].extra['disks'][0], NttCisServerDisk) assert ret[0].extra['disks'][0].size_gb, 10 assert isinstance(ret[1].extra['disks'], list) assert isinstance(ret[1].extra['disks'][0], NttCisServerDisk) assert ret[1].extra['disks'][0].size_gb, 10 def test_server_states(driver): NttCisMockHttp.type = None ret = driver.list_nodes() assert ret[0].state == 'running' assert ret[1].state == 'starting' assert ret[2].state == 'stopping' assert ret[3].state == 'reconfiguring' assert ret[4].state == 'running' assert ret[5].state == 'terminated' assert ret[6].state == 'stopped' assert len(ret) == 7 def test_list_nodes_response_PAGINATED(driver): NttCisMockHttp.type = 'PAGINATED' ret = driver.list_nodes() assert len(ret) == 7 def test_paginated_mcp2_call_EMPTY(driver): # cache org driver.connection._get_orgId() NttCisMockHttp.type = 'EMPTY' node_list_generator = driver.connection.paginated_request_with_orgId_api_2('server/server') empty_node_list = [] for node_list in node_list_generator: empty_node_list.extend(node_list) assert len(empty_node_list) == 0 def test_paginated_mcp2_call_PAGED_THEN_EMPTY(driver): # cache org driver.connection._get_orgId() NttCisMockHttp.type = 'PAGED_THEN_EMPTY' node_list_generator = driver.connection.paginated_request_with_orgId_api_2('server/server') final_node_list = [] for node_list in node_list_generator: final_node_list.extend(node_list) assert len(final_node_list) == 2 def test_paginated_mcp2_call_with_page_size(driver): # cache org driver.connection._get_orgId() NttCisMockHttp.type = 'PAGESIZE50' node_list_generator = driver.connection.paginated_request_with_orgId_api_2('server/server', page_size=50) assert isinstance(node_list_generator, GeneratorType) # We're making sure here the filters make it to the URL # See _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts def test_list_nodes_response_strings_ALLFILTERS(driver): NttCisMockHttp.type = 'ALLFILTERS' ret = driver.list_nodes(ex_location='fake_loc', ex_name='fake_name', ex_ipv6='fake_ipv6', ex_ipv4='fake_ipv4', ex_vlan='fake_vlan', ex_image='fake_image', ex_deployed=True, ex_started=True, ex_state='fake_state', ex_network_domain='fake_network_domain') assert isinstance(ret, list) assert len(ret) == 7 node = ret[3] assert isinstance(node.extra['disks'], list) assert isinstance(node.extra['disks'][0], NttCisServerDisk) assert node.image.id == '3ebf3c0f-90fe-4a8b-8585-6e65b316592c' assert node.image.name == 'WIN2008S/32' disk = node.extra['disks'][0] assert disk.id == "c2e1f199-116e-4dbc-9960-68720b832b0a" assert disk.scsi_id == 0 assert disk.size_gb == 50 assert disk.speed == "STANDARD" assert disk.state == "NORMAL" def test_list_nodes_response_LOCATION(driver): NttCisMockHttp.type = None ret = driver.list_locations() first_loc = ret[0] ret = driver.list_nodes(ex_location=first_loc) for node in ret: assert node.extra['datacenterId'] == 'NA3' def test_list_nodes_response_LOCATION_STR(driver): NttCisMockHttp.type = None ret = driver.list_nodes(ex_location='NA3') for node in ret: assert node.extra['datacenterId'] == 'NA3' def test_list_sizes_response(driver): NttCisMockHttp.type = None ret = driver.list_sizes() assert len(ret) == 1 size = ret[0] assert size.name == 'default' def test_list_datacenter_snapshot_windows(driver): NttCisMockHttp.type = None ret = driver.list_snapshot_windows("f1d6a564-490e-4166-b91d-feddc1f92025", "ADVANCED") assert isinstance(ret[0], dict) def test_list_snapshots(driver): NttCisMockHttp.type = None snapshots = driver.list_snapshots('sdk_server_1', page_size=1) assert len(snapshots) == 1 assert snapshots[0]['id'] == "d11940a8-1455-43bf-a2de-b51a38c2aa94" def test_enable_snapshot_service(driver): NttCisMockHttp.type = None window_id = 'ea646520-4272-11e8-838c-180373fb68df' node = 'e1eb7d71-93c9-4b9c-807c-e05932dc8143' result = driver.ex_enable_snapshots(node, window_id) assert result is True def test_initiate_manual_snapshot(driver): NttCisMockHttp.type = None result = driver.ex_initiate_manual_snapshot('test', 'e1eb7d71-93c9-4b9c-807c-e05932dc8143') assert result is True def test_create_snapshot_preview_server(driver): snapshot_id = "dd9a9e7e-2de7-4543-adef-bb1fda7ac030" server_name = "test_snapshot" start = "true" nic_connected = "true" result = driver.ex_create_snapshot_preview_server( snapshot_id, server_name, start, nic_connected) assert result is True def test_disable_node_snapshot(driver): node = "e1eb7d71-93c9-4b9c-807c-e05932dc8143" assert driver.ex_disable_snapshots(node) is True def test_reboot_node_response(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = node.reboot() assert ret is True def test_reboot_node_response_INPROGRESS(driver): NttCisMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) with pytest.raises(NttCisAPIException): node.reboot() def test_destroy_node_response(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = node.destroy() assert ret is True def test_destroy_node_response_RESOURCE_BUSY(driver): NttCisMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) with pytest.raises(NttCisAPIException): node.destroy() def test_list_images(driver): images = driver.list_images() assert len(images) == 3 assert images[0].name == 'RedHat 6 64-bit 2 CPU' assert images[0].id == 'c14b1a46-2428-44c1-9c1a-b20e6418d08c' assert images[0].extra['location'].id == 'NA9' assert images[0].extra['cpu'].cpu_count == 2 assert images[0].extra['OS_displayName'] == 'REDHAT6/64' def test_clean_failed_deployment_response_with_node(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = driver.ex_clean_failed_deployment(node) assert ret is True def test_clean_failed_deployment_response_with_node_id(driver): node = 'e75ead52-692f-4314-8725-c8a4f4d13a87' ret = driver.ex_clean_failed_deployment(node) assert ret is True def test_ex_list_customer_images(driver): images = driver.ex_list_customer_images() assert len(images) == 3 assert images[0].name == 'ImportedCustomerImage' assert images[0].id == '5234e5c7-01de-4411-8b6e-baeb8d91cf5d' assert images[0].extra['location'].id == 'NA9' assert images[0].extra['cpu'].cpu_count == 4 assert images[0].extra['OS_displayName'] == 'REDHAT6/64' def test_create_mcp1_node_optional_param(driver): root_pw = NodeAuthPassword('pass123') image = driver.list_images()[0] network = driver.ex_list_networks()[0] cpu_spec = NttCisServerCpuSpecification(cpu_count='4', cores_per_socket='2', performance='STANDARD') disks = [NttCisServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')] node = driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network=network, ex_is_started=False, ex_memory_gb=8, ex_disks=disks, ex_cpu_specification=cpu_spec, ex_primary_dns='10.0.0.5', ex_secondary_dns='10.0.0.6' ) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_mcp1_node_response_no_pass_random_gen(driver): image = driver.list_images()[0] network = driver.ex_list_networks()[0] node = driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' assert 'password' in node.extra def test_create_mcp1_node_response_no_pass_customer_windows(driver): image = driver.ex_list_customer_images()[1] network = driver.ex_list_networks()[0] node = driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' assert 'password' in node.extra def test_create_mcp1_node_response_no_pass_customer_windows_STR(driver): image = driver.ex_list_customer_images()[1].id network = driver.ex_list_networks()[0] node = driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' assert'password' in node.extra def test_create_mcp1_node_response_no_pass_customer_linux(driver): image = driver.ex_list_customer_images()[0] network = driver.ex_list_networks()[0] node = driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' assert 'password' not in node.extra def test_create_mcp1_node_response_no_pass_customer_linux_STR(driver): image = driver.ex_list_customer_images()[0].id network = driver.ex_list_networks()[0] node = driver.create_node(name='test2', image=image, auth=None, ex_description='test2 node', ex_network=network, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' assert 'password' not in node.extra def test_create_mcp1_node_response_STR(driver): rootPw = 'pass123' image = driver.list_images()[0].id network = driver.ex_list_networks()[0].id node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network=network, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_mcp1_node_no_network(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(InvalidRequestError): driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network=None, ex_is_started=False) def test_create_node_mcp1_ipv4(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network='fakenetwork', ex_primary_ipv4='10.0.0.1', ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_mcp1_network(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network='fakenetwork', ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_response_network_domain(driver): rootPw = NodeAuthPassword('pass123') location = driver.ex_get_location_by_id('NA9') image = driver.list_images(location=location)[0] network_domain = driver.ex_list_network_domains(location=location)[0] vlan = driver.ex_list_vlans(location=location)[0] cpu = NttCisServerCpuSpecification( cpu_count=4, cores_per_socket=1, performance='HIGHPERFORMANCE' ) node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain=network_domain, ex_vlan=vlan, ex_is_started=False, ex_cpu_specification=cpu, ex_memory_gb=4) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_response_network_domain_STR(driver): rootPw = NodeAuthPassword('pass123') location = driver.ex_get_location_by_id('NA9') image = driver.list_images(location=location)[0] network_domain = driver.ex_list_network_domains(location=location)[0].id vlan = driver.ex_list_vlans(location=location)[0].id cpu = NttCisServerCpuSpecification( cpu_count=4, cores_per_socket=1, performance='HIGHPERFORMANCE' ) node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain=network_domain, ex_vlan=vlan, ex_is_started=False, ex_cpu_specification=cpu, ex_memory_gb=4) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_mcp2_vlan(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_vlan='fakevlan', ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_mcp2_ipv4(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_network_domain_no_vlan_or_ipv4(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(ValueError): driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_is_started=False) def test_create_node_response(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan' ) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_ms_time_zone(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan', ex_microsoft_time_zone='040' ) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_ambigious_mcps_fail(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(ValueError): driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_network='fakenetwork', ex_primary_nic_vlan='fakevlan' ) def test_create_node_no_network_domain_fail(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(ValueError): driver.create_node( name='test3', image=image, auth=rootPw, ex_primary_nic_vlan='fakevlan' ) def test_create_node_no_primary_nic_fail(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(ValueError): driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain' ) def test_create_node_primary_vlan_nic(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_vlan='fakevlan', ex_primary_nic_network_adapter='v1000' ) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_primary_ipv4(driver): rootPw = 'pass123' image = driver.list_images()[0] node = driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1' ) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_both_primary_nic_and_vlan_fail(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(ValueError): driver.create_node( name='test3', image=image, auth=rootPw, ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_primary_nic_vlan='fakevlan' ) def test_create_node_cpu_specification(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] cpu_spec = NttCisServerCpuSpecification(cpu_count='4', cores_per_socket='2', performance='STANDARD') node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_cpu_specification=cpu_spec) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_memory(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_memory_gb=8) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_disks(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] disks = [NttCisServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_disks=disks) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_disks_fail(driver): root_pw = NodeAuthPassword('pass123') image = driver.list_images()[0] disks = 'blah' with pytest.raises(TypeError): driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_disks=disks) def test_create_node_ipv4_gateway(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_is_started=False, ex_ipv4_gateway='10.2.2.2') assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_network_domain_no_vlan_no_ipv4_fail(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(ValueError): driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_is_started=False) def test_create_node_mcp2_additional_nics_legacy(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] additional_vlans = ['fakevlan1', 'fakevlan2'] additional_ipv4 = ['10.0.0.2', '10.0.0.3'] node = driver.create_node( name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_additional_nics_vlan=additional_vlans, ex_additional_nics_ipv4=additional_ipv4, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_bad_additional_nics_ipv4(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(TypeError): driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_vlan='fake_vlan', ex_additional_nics_ipv4='badstring', ex_is_started=False) def test_create_node_additional_nics(driver): root_pw = NodeAuthPassword('pass123') image = driver.list_images()[0] nic1 = NttCisNic(vlan='fake_vlan', network_adapter_name='v1000') nic2 = NttCisNic(private_ip_v4='10.1.1.2', network_adapter_name='v1000') additional_nics = [nic1, nic2] node = driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_create_node_additional_nics_vlan_ipv4_coexist_fail(driver): root_pw = NodeAuthPassword('pass123') image = driver.list_images()[0] nic1 = NttCisNic(private_ip_v4='10.1.1.1', vlan='fake_vlan', network_adapter_name='v1000') nic2 = NttCisNic(private_ip_v4='10.1.1.2', vlan='fake_vlan2', network_adapter_name='v1000') additional_nics = [nic1, nic2] with pytest.raises(ValueError): driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False ) def test_create_node_additional_nics_invalid_input_fail(driver): root_pw = NodeAuthPassword('pass123') image = driver.list_images()[0] additional_nics = 'blah' with pytest.raises(TypeError): driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False ) def test_create_node_additional_nics_vlan_ipv4_not_exist_fail(driver): root_pw = NodeAuthPassword('pass123') image = driver.list_images()[0] nic1 = NttCisNic(network_adapter_name='v1000') nic2 = NttCisNic(network_adapter_name='v1000') additional_nics = [nic1, nic2] with pytest.raises(ValueError): driver.create_node(name='test2', image=image, auth=root_pw, ex_description='test2 node', ex_network_domain='fakenetworkdomain', ex_primary_nic_private_ipv4='10.0.0.1', ex_additional_nics=additional_nics, ex_is_started=False) def test_create_node_bad_additional_nics_vlan(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] with pytest.raises(TypeError): driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test2 node', ex_network_domain='fake_network_domain', ex_vlan='fake_vlan', ex_additional_nics_vlan='badstring', ex_is_started=False) def test_create_node_mcp2_indicate_dns(driver): rootPw = NodeAuthPassword('pass123') image = driver.list_images()[0] node = driver.create_node(name='test2', image=image, auth=rootPw, ex_description='test node dns', ex_network_domain='fakenetworkdomain', ex_primary_ipv4='10.0.0.1', ex_primary_dns='8.8.8.8', ex_secondary_dns='8.8.4.4', ex_is_started=False) assert node.id == 'e75ead52-692f-4314-8725-c8a4f4d13a87' assert node.extra['status'].action == 'DEPLOY_SERVER' def test_ex_shutdown_graceful(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = driver.ex_shutdown_graceful(node) assert ret is True def test_ex_shutdown_graceful_INPROGRESS(driver): NttCisMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) with pytest.raises(NttCisAPIException): driver.ex_shutdown_graceful(node) def test_ex_start_node(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = driver.ex_start_node(node) assert ret is True def test_ex_start_node_INPROGRESS(driver): NttCisMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) with pytest.raises(NttCisAPIException): driver.ex_start_node(node) def test_ex_power_off(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = driver.ex_power_off(node) assert ret is True def test_ex_update_vm_tools(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = driver.ex_update_vm_tools(node) assert ret is True def test_ex_power_off_INPROGRESS(driver): NttCisMockHttp.type = 'INPROGRESS' node = Node(id='11', name=None, state='STOPPING', public_ips=None, private_ips=None, driver=driver) with pytest.raises(NttCisAPIException): driver.ex_power_off(node) def test_ex_reset(driver): node = Node(id='11', name=None, state=None, public_ips=None, private_ips=None, driver=driver) ret = driver.ex_reset(node) assert ret is True def test_ex_attach_node_to_vlan(driver): node = driver.ex_get_node_by_id('e75ead52-692f-4314-8725-c8a4f4d13a87') vlan = driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') ret = driver.ex_attach_node_to_vlan(node, vlan) assert ret is True def test_ex_destroy_nic(driver): node = driver.ex_destroy_nic('a202e51b-41c0-4cfc-add0-b1c62fc0ecf6') assert node is True def test_ex_create_network_domain(driver): location = driver.ex_get_location_by_id('NA9') plan = NetworkDomainServicePlan.ADVANCED net = driver.ex_create_network_domain(location=location, name='test', description='test', service_plan=plan) assert net.name == 'test' assert net.id == 'f14a871f-9a25-470c-aef8-51e13202e1aa' def test_ex_create_network_domain_NO_DESCRIPTION(driver): location = driver.ex_get_location_by_id('NA9') plan = NetworkDomainServicePlan.ADVANCED net = driver.ex_create_network_domain(location=location, name='test', service_plan=plan) assert net.name == 'test' assert net.id == 'f14a871f-9a25-470c-aef8-51e13202e1aa' def test_ex_get_network_domain(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') assert net.id == '8cdfd607-f429-4df6-9352-162cfc0891be' assert net.description == 'test2' assert net.name == 'test' def test_ex_update_network_domain(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') net.name = 'new name' net2 = driver.ex_update_network_domain(net) assert net2.name == 'new name' def test_ex_delete_network_domain(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') result = driver.ex_delete_network_domain(net) assert result is True def test_ex_list_network_domains(driver): nets = driver.ex_list_network_domains() assert nets[0].name == 'Aurora' assert isinstance(nets[0].location, NodeLocation) def test_ex_list_network_domains_ALLFILTERS(driver): NttCisMockHttp.type = 'ALLFILTERS' nets = driver.ex_list_network_domains(location='fake_location', name='fake_name', service_plan='fake_plan', state='fake_state') assert nets[0].name == 'Aurora' assert isinstance(nets[0].location, NodeLocation) def test_ex_list_vlans(driver): vlans = driver.ex_list_vlans() assert vlans[0].name == "Primary" def test_ex_list_vlans_ALLFILTERS(driver): NttCisMockHttp.type = 'ALLFILTERS' vlans = driver.ex_list_vlans(location='fake_location', network_domain='fake_network_domain', name='fake_name', ipv4_address='fake_ipv4', ipv6_address='fake_ipv6', state='fake_state') assert vlans[0].name == "Primary" def test_ex_create_vlan(driver,): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') vlan = driver.ex_create_vlan(network_domain=net, name='test', private_ipv4_base_address='10.3.4.0', private_ipv4_prefix_size='24', description='test vlan') assert vlan.id == '0e56433f-d808-4669-821d-812769517ff8' def test_ex_create_vlan_NO_DESCRIPTION(driver,): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') vlan = driver.ex_create_vlan(network_domain=net, name='test', private_ipv4_base_address='10.3.4.0', private_ipv4_prefix_size="24") assert vlan.id == '0e56433f-d808-4669-821d-812769517ff8' def test_ex_get_vlan(driver): vlan = driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') assert vlan.id == '0e56433f-d808-4669-821d-812769517ff8' assert vlan.description == 'test2' assert vlan.status == 'NORMAL' assert vlan.name == 'Production VLAN' assert vlan.private_ipv4_range_address == '10.0.3.0' assert vlan.private_ipv4_range_size == 24 assert vlan.ipv6_range_size == 64 assert vlan.ipv6_range_address == '2607:f480:1111:1153:0:0:0:0' assert vlan.ipv4_gateway == '10.0.3.1' assert vlan.ipv6_gateway == '2607:f480:1111:1153:0:0:0:1' def test_ex_wait_for_state(driver): driver.ex_wait_for_state('NORMAL', driver.ex_get_vlan, vlan_id='0e56433f-d808-4669-821d-812769517ff8', poll_interval=0.1) def test_ex_wait_for_state_NODE(driver): driver.ex_wait_for_state('running', driver.ex_get_node_by_id, id='e75ead52-692f-4314-8725-c8a4f4d13a87', poll_interval=0.1) def test_ex_wait_for_state_FAIL(driver): with pytest.raises(NttCisAPIException) as context: driver.ex_wait_for_state('starting', driver.ex_get_node_by_id, id='e75ead52-692f-4314-8725-c8a4f4d13a87', poll_interval=0.1, timeout=0.1 ) assert context.value.code == 'running' assert 'timed out' in context.value.msg def test_ex_update_vlan(driver): vlan = driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') vlan.name = 'new name' vlan2 = driver.ex_update_vlan(vlan) assert vlan2.name == 'new name' def test_ex_delete_vlan(driver): vlan = driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') result = driver.ex_delete_vlan(vlan) assert result is True def test_ex_expand_vlan(driver): vlan = driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8') vlan.private_ipv4_range_size = '23' vlan = driver.ex_expand_vlan(vlan) assert vlan.private_ipv4_range_size == '23' def test_ex_add_public_ip_block_to_network_domain(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') block = driver.ex_add_public_ip_block_to_network_domain(net) assert block.id == '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8' def test_ex_list_public_ip_blocks(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') blocks = driver.ex_list_public_ip_blocks(net) assert blocks[0].base_ip == '168.128.4.18' assert blocks[0].size == '2' assert blocks[0].id == '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8' assert blocks[0].location.id == 'NA9' assert blocks[0].network_domain.id == net.id def test_ex_get_public_ip_block(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') block = driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') assert block.base_ip == '168.128.4.18' assert block.size == '2' assert block.id == '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8' assert block.location.id == 'NA9' assert block.network_domain.id == net.id def test_ex_delete_public_ip_block(driver): block = driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8') result = driver.ex_delete_public_ip_block(block) assert result is True def test_ex_list_firewall_rules(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) assert rules[0].id == '756cba02-b0bc-48f4-aea5-9445870b6148' assert rules[0].network_domain.id == '8cdfd607-f429-4df6-9352-162cfc0891be' assert rules[0].name == 'CCDEFAULT.BlockOutboundMailIPv4' assert rules[0].action == 'DROP' assert rules[0].ip_version, 'IPV4' assert rules[0].protocol == 'TCP' assert rules[0].source.ip_address == 'ANY' assert rules[0].source.any_ip is True assert rules[0].destination.any_ip is True def test_ex_create_firewall_rule(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) rule = driver.ex_create_firewall_rule(net, rules[0].name, rules[0].action, rules[0].ip_version, rules[0].protocol, rules[0].source, rules[0].destination, 'FIRST') assert rule.id == 'd0a20f59-77b9-4f28-a63b-e58496b73a6c' def test_ex_create_firewall_rule_with_specific_source_ip(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) specific_source_ip_rule = list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] rule = driver.ex_create_firewall_rule(net, specific_source_ip_rule.name, specific_source_ip_rule.action, specific_source_ip_rule.ip_version, specific_source_ip_rule.protocol, specific_source_ip_rule.source, specific_source_ip_rule.destination, 'FIRST') assert rule.id == 'd0a20f59-77b9-4f28-a63b-e58496b73a6c' def test_ex_create_firewall_rule_with_source_ip(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) specific_source_ip_rule = \ list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] specific_source_ip_rule.source.any_ip = False specific_source_ip_rule.source.ip_address = '10.0.0.1' specific_source_ip_rule.source.ip_prefix_size = '15' rule = driver.ex_create_firewall_rule(net, specific_source_ip_rule.name, specific_source_ip_rule.action, specific_source_ip_rule.ip_version, specific_source_ip_rule.protocol, specific_source_ip_rule.source, specific_source_ip_rule.destination, 'FIRST') assert rule.id == 'd0a20f59-77b9-4f28-a63b-e58496b73a6c' def test_ex_create_firewall_rule_with_any_ip(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) specific_source_ip_rule = \ list(filter(lambda x: x.name == 'SpecificSourceIP', rules))[0] specific_source_ip_rule.source.any_ip = True rule = driver.ex_create_firewall_rule(net, specific_source_ip_rule.name, specific_source_ip_rule.action, specific_source_ip_rule.ip_version, specific_source_ip_rule.protocol, specific_source_ip_rule.source, specific_source_ip_rule.destination, 'FIRST') assert rule.id == 'd0a20f59-77b9-4f28-a63b-e58496b73a6c' def test_ex_create_firewall_rule_ip_prefix_size(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_list_firewall_rules(net)[0] rule.source.address_list_id = None rule.source.any_ip = False rule.source.ip_address = '10.2.1.1' rule.source.ip_prefix_size = '10' rule.destination.address_list_id = None rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = '20' driver.ex_create_firewall_rule(net, rule.name, rule.action, rule.ip_version, rule.protocol, rule.source, rule.destination, 'LAST') def test_ex_create_firewall_rule_address_list(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_list_firewall_rules(net)[0] rule.source.address_list_id = '12345' rule.destination.address_list_id = '12345' driver.ex_create_firewall_rule(net, rule.name, rule.action, rule.ip_version, rule.protocol, rule.source, rule.destination, 'LAST') def test_ex_create_firewall_rule_port_list(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_list_firewall_rules(net)[0] rule.source.port_list_id = '12345' rule.destination.port_list_id = '12345' driver.ex_create_firewall_rule(net, rule.name, rule.action, rule.ip_version, rule.protocol, rule.source, rule.destination, 'LAST') def test_ex_create_firewall_rule_port(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_list_firewall_rules(net)[0] rule.source.port_list_id = None rule.source.port_begin = '8000' rule.source.port_end = '8005' rule.destination.port_list_id = None rule.destination.port_begin = '7000' rule.destination.port_end = '7005' driver.ex_create_firewall_rule(net, rule.name, rule.action, rule.ip_version, rule.protocol, rule.source, rule.destination, 'LAST') def test_ex_create_firewall_rule_ALL_VALUES(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) for rule in rules: driver.ex_create_firewall_rule(net, rule.name, rule.action, rule.ip_version, rule.protocol, rule.source, rule.destination, 'LAST') def test_ex_create_firewall_rule_WITH_POSITION_RULE(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) rule = driver.ex_create_firewall_rule(net, rules[-2].name, rules[-2].action, rules[-2].ip_version, rules[-2].protocol, rules[-2].source, rules[-2].destination, 'BEFORE', position_relative_to_rule=rules[-1]) assert rule.id == 'd0a20f59-77b9-4f28-a63b-e58496b73a6c' def test_ex_create_firewall_rule_WITH_POSITION_RULE_STR(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) rule = driver.ex_create_firewall_rule(net, rules[-2].name, rules[-2].action, rules[-2].ip_version, rules[-2].protocol, rules[-2].source, rules[-2].destination, 'BEFORE', position_relative_to_rule='RULE_WITH_SOURCE_AND_DEST') assert rule.id == 'd0a20f59-77b9-4f28-a63b-e58496b73a6c' def test_ex_create_firewall_rule_FAIL_POSITION(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) with pytest.raises(ValueError): driver.ex_create_firewall_rule(net, rules[0].name, rules[0].action, rules[0].ip_version, rules[0].protocol, rules[0].source, rules[0].destination, 'BEFORE') def test_ex_create_firewall_rule_FAIL_POSITION_WITH_RULE(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_firewall_rules(net) with pytest.raises(ValueError): driver.ex_create_firewall_rule(net, rules[0].name, rules[0].action, rules[0].ip_version, rules[0].protocol, rules[0].source, rules[0].destination, 'LAST', position_relative_to_rule='RULE_WITH_SOURCE_AND_DEST') def test_ex_get_firewall_rule(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') assert rule.id == 'd0a20f59-77b9-4f28-a63b-e58496b73a6c' def test_ex_set_firewall_rule_state(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') result = driver.ex_set_firewall_rule_state(rule, False) assert result is True def test_ex_delete_firewall_rule(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') result = driver.ex_delete_firewall_rule(rule) assert result is True def test_ex_edit_firewall_rule(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.any_ip = True result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_source_ipaddresslist(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' rule.source.any_ip = False rule.source.ip_address = '10.0.0.1' rule.source.ip_prefix_size = 10 result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_destination_ipaddresslist(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = 10 result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_destination_ipaddress(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.address_list_id = None rule.source.any_ip = False rule.source.ip_address = '10.0.0.1' rule.source.ip_prefix_size = '10' result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_source_ipaddress(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.address_list_id = None rule.destination.any_ip = False rule.destination.ip_address = '10.0.0.1' rule.destination.ip_prefix_size = '10' result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_with_relative_rule(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') placement_rule = driver.ex_list_firewall_rules( network_domain=net)[-1] result = driver.ex_edit_firewall_rule( rule=rule, position='BEFORE', relative_rule_for_position=placement_rule) assert result is True def test_ex_edit_firewall_rule_with_relative_rule_by_name(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') placement_rule = driver.ex_list_firewall_rules( network_domain=net)[-1] result = driver.ex_edit_firewall_rule( rule=rule, position='BEFORE', relative_rule_for_position=placement_rule.name) assert result is True def test_ex_edit_firewall_rule_source_portlist(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_source_port(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.source.port_list_id = None rule.source.port_begin = '3' rule.source.port_end = '10' result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_destination_portlist(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222' result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_destination_port(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') rule.destination.port_list_id = None rule.destination.port_begin = '3' rule.destination.port_end = '10' result = driver.ex_edit_firewall_rule(rule=rule, position='LAST') assert result is True def test_ex_edit_firewall_rule_invalid_position_fail(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') with pytest.raises(ValueError): driver.ex_edit_firewall_rule(rule=rule, position='BEFORE') def test_ex_edit_firewall_rule_invalid_position_relative_rule_fail(driver): net = driver.ex_get_network_domain( '8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_firewall_rule( net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c') relative_rule = driver.ex_list_firewall_rules( network_domain=net)[-1] with pytest.raises(ValueError): driver.ex_edit_firewall_rule(rule=rule, position='FIRST', relative_rule_for_position=relative_rule) def test_ex_create_nat_rule(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_create_nat_rule(net, '1.2.3.4', '4.3.2.1') assert rule.id == 'd31c2db0-be6b-4d50-8744-9a7a534b5fba' def test_ex_list_nat_rules(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rules = driver.ex_list_nat_rules(net) assert rules[0].id == '2187a636-7ebb-49a1-a2ff-5d617f496dce' assert rules[0].internal_ip == '10.0.0.15' assert rules[0].external_ip == '165.180.12.18' def test_ex_get_nat_rule(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce') assert rule.id == '2187a636-7ebb-49a1-a2ff-5d617f496dce' assert rule.internal_ip == '10.0.0.16' assert rule.external_ip == '165.180.12.19' def test_ex_delete_nat_rule(driver): net = driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be') rule = driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce') result = driver.ex_delete_nat_rule(rule) assert result is True def test_ex_enable_monitoring(driver): node = driver.list_nodes()[0] result = driver.ex_enable_monitoring(node, "ADVANCED") assert result is True def test_ex_disable_monitoring(driver): node = driver.list_nodes()[0] result = driver.ex_disable_monitoring(node) assert result is True def test_ex_change_monitoring_plan(driver): node = driver.list_nodes()[0] result = driver.ex_update_monitoring_plan(node, "ESSENTIALS") assert result is True def test_ex_add_storage_to_node(driver): node = driver.list_nodes()[0] result = driver.ex_add_storage_to_node(30, node, 'PERFORMANCE') assert result is True def test_ex_remove_storage_from_node(driver): node = driver.list_nodes()[0] result = driver.ex_remove_storage_from_node(node, 0) assert result is True def test_ex_change_storage_speed(driver): result = driver.ex_change_storage_speed("1", 'PERFORMANCE') assert result is True def test_ex_change_storage_size(driver): result = driver.ex_change_storage_size("1", 100) assert result is True def test_ex_clone_node_to_image(driver): node = driver.list_nodes()[0] result = driver.ex_clone_node_to_image(node, 'my image', 'a description') assert result is True def test_ex_edit_metadata(driver): node = driver.list_nodes()[0] result = driver.ex_edit_metadata(node, 'my new name', 'a description') assert result is True def test_ex_reconfigure_node(driver): node = driver.list_nodes()[0] result = driver.ex_reconfigure_node(node, 4, 4, 1, 'HIGHPERFORMANCE') assert result is True def test_ex_get_location_by_id(driver): location = driver.ex_get_location_by_id('NA9') assert location.id == 'NA9' def test_ex_get_location_by_id_NO_LOCATION(driver): location = driver.ex_get_location_by_id(None) assert location is None def test_ex_get_base_image_by_id(driver): image_id = driver.list_images()[0].id image = driver.ex_get_base_image_by_id(image_id) assert image.extra['OS_type'] == 'UNIX' def test_ex_get_customer_image_by_id(driver): image_id = driver.ex_list_customer_images()[1].id image = driver.ex_get_customer_image_by_id(image_id) assert image.extra['OS_type'] == 'WINDOWS' def test_ex_get_image_by_id_base_img(driver): image_id = driver.list_images()[1].id image = driver.ex_get_base_image_by_id(image_id) assert image.extra['OS_type'] == 'WINDOWS' def test_ex_get_image_by_id_customer_img(driver): image_id = driver.ex_list_customer_images()[0].id image = driver.ex_get_customer_image_by_id(image_id) assert image.extra['OS_type'] == 'UNIX' def test_ex_get_image_by_id_customer_FAIL(driver): image_id = 'FAKE_IMAGE_ID' with pytest.raises(NttCisAPIException): driver.ex_get_base_image_by_id(image_id) def test_ex_create_anti_affinity_rule(driver): node_list = driver.list_nodes() success = driver.ex_create_anti_affinity_rule([node_list[0], node_list[1]]) assert success is True def test_ex_create_anti_affinity_rule_TUPLE(driver): node_list = driver.list_nodes() success = driver.ex_create_anti_affinity_rule((node_list[0], node_list[1])) assert success is True def test_ex_create_anti_affinity_rule_TUPLE_STR(driver): node_list = driver.list_nodes() success = driver.ex_create_anti_affinity_rule((node_list[0].id, node_list[1].id)) assert success is True def test_ex_create_anti_affinity_rule_FAIL_STR(driver): node_list = 'string' with pytest.raises(TypeError): driver.ex_create_anti_affinity_rule(node_list) def test_ex_create_anti_affinity_rule_FAIL_EXISTING(driver): node_list = driver.list_nodes() NttCisMockHttp.type = 'FAIL_EXISTING' with pytest.raises(NttCisAPIException): driver.ex_create_anti_affinity_rule((node_list[0], node_list[1])) def test_ex_delete_anti_affinity_rule(driver): net_domain = driver.ex_list_network_domains()[0] rule = driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0].id success = driver.ex_delete_anti_affinity_rule(rule) assert success is True def test_ex_delete_anti_affinity_rule_STR(driver): net_domain = driver.ex_list_network_domains()[0] rule = driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] success = driver.ex_delete_anti_affinity_rule(rule.id) assert success is True def test_ex_delete_anti_affinity_rule_FAIL(driver): net_domain = driver.ex_list_network_domains()[0] rule = driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0] NttCisMockHttp.type = 'FAIL' with pytest.raises(NttCisAPIException): driver.ex_delete_anti_affinity_rule(rule.id) def test_ex_list_anti_affinity_rules_NETWORK_DOMAIN(driver): net_domain = driver.ex_list_network_domains()[0] rules = driver.ex_list_anti_affinity_rules(network_domain=net_domain) assert isinstance(rules, list) assert len(rules) == 2 assert isinstance(rules[0].id, str) assert isinstance(rules[0].node_list, list) def test_ex_list_anti_affinity_rules_NODE(driver): node = driver.list_nodes()[0] rules = driver.ex_list_anti_affinity_rules(node=node) assert isinstance(rules, list) assert len(rules) == 2 assert isinstance(rules[0].id, str) assert isinstance(rules[0].node_list, list) def test_ex_list_anti_affinity_rules_PAGINATED(driver): net_domain = driver.ex_list_network_domains()[0] NttCisMockHttp.type = 'PAGINATED' rules = driver.ex_list_anti_affinity_rules(network_domain=net_domain) assert isinstance(rules, list) assert len(rules) == 4 assert isinstance(rules[0].id, str) assert isinstance(rules[0].node_list, list) def test_ex_list_anti_affinity_rules_ALLFILTERS(driver): net_domain = driver.ex_list_network_domains()[0] NttCisMockHttp.type = 'ALLFILTERS' rules = driver.ex_list_anti_affinity_rules(network_domain=net_domain, filter_id='FAKE_ID', filter_state='FAKE_STATE') assert isinstance(rules, list) assert len(rules) == 2 assert isinstance(rules[0].id, str) assert isinstance(rules[0].node_list, list) def test_ex_list_anti_affinity_rules_BAD_ARGS(driver): with pytest.raises(ValueError): driver.ex_list_anti_affinity_rules(network='fake_network', network_domain='fake_network_domain') def test_ex_create_tag_key(driver): success = driver.ex_create_tag_key('MyTestKey') assert success is True def test_ex_create_tag_key_ALLPARAMS(driver): driver.connection._get_orgId() NttCisMockHttp.type = 'ALLPARAMS' success = driver.ex_create_tag_key('MyTestKey', description="Test Key Desc.", value_required=False, display_on_report=False) assert success is True def test_ex_create_tag_key_BADREQUEST(driver): driver.connection._get_orgId() NttCisMockHttp.type = 'BADREQUEST' with pytest.raises(NttCisAPIException): driver.ex_create_tag_key('MyTestKey') def test_ex_list_tag_keys(driver): tag_keys = driver.ex_list_tag_keys() assert isinstance(tag_keys, list) assert isinstance(tag_keys[0], NttCisTagKey) assert isinstance(tag_keys[0].id, str) def test_ex_list_tag_keys_ALLFILTERS(driver): driver.connection._get_orgId() NttCisMockHttp.type = 'ALLFILTERS' driver.ex_list_tag_keys(id='fake_id', name='fake_name', value_required=False, display_on_report=False) def test_ex_get_tag_by_id(driver): tag = driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075') assert isinstance(tag, NttCisTagKey) def test_ex_get_tag_by_id_NOEXIST(driver): driver.connection._get_orgId() NttCisMockHttp.type = 'NOEXIST' with pytest.raises(NttCisAPIException): driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075') def test_ex_get_tag_by_name(driver): driver.connection._get_orgId() NttCisMockHttp.type = 'SINGLE' tag = driver.ex_get_tag_key_by_name('LibcloudTest') assert isinstance(tag, NttCisTagKey) def test_ex_get_tag_by_name_NOEXIST(driver): with pytest.raises(ValueError): driver.ex_get_tag_key_by_name('LibcloudTest') def test_ex_modify_tag_key_NAME(driver): tag_key = driver.ex_list_tag_keys()[0] NttCisMockHttp.type = 'NAME' success = driver.ex_modify_tag_key(tag_key, name='NewName') assert success is True def test_ex_modify_tag_key_NOTNAME(driver): tag_key = driver.ex_list_tag_keys()[0] NttCisMockHttp.type = 'NOTNAME' success = driver.ex_modify_tag_key(tag_key, description='NewDesc', value_required=False, display_on_report=True) assert success is True def test_ex_modify_tag_key_NOCHANGE(driver): tag_key = driver.ex_list_tag_keys()[0] NttCisMockHttp.type = 'NOCHANGE' with pytest.raises(NttCisAPIException): driver.ex_modify_tag_key(tag_key) def test_ex_remove_tag_key(driver): tag_key = driver.ex_list_tag_keys()[0] success = driver.ex_remove_tag_key(tag_key) assert success is True def test_ex_remove_tag_key_NOEXIST(driver): tag_key = driver.ex_list_tag_keys()[0] NttCisMockHttp.type = 'NOEXIST' with pytest.raises(NttCisAPIException): driver.ex_remove_tag_key(tag_key) def test_ex_apply_tag_to_asset(driver): node = driver.list_nodes()[0] success = driver.ex_apply_tag_to_asset(node, 'TagKeyName', 'FakeValue') assert success is True def test_ex_apply_tag_to_asset_NOVALUE(driver): node = driver.list_nodes()[0] NttCisMockHttp.type = 'NOVALUE' success = driver.ex_apply_tag_to_asset(node, 'TagKeyName') assert success is True def test_ex_apply_tag_to_asset_NOTAGKEY(driver): node = driver.list_nodes()[0] NttCisMockHttp.type = 'NOTAGKEY' with pytest.raises(NttCisAPIException): driver.ex_apply_tag_to_asset(node, 'TagKeyNam') def test_ex_remove_tag_from_asset(driver): node = driver.list_nodes()[0] success = driver.ex_remove_tag_from_asset(node, 'TagKeyName') assert success is True def test_ex_remove_tag_from_asset_NOTAG(driver): node = driver.list_nodes()[0] NttCisMockHttp.type = 'NOTAG' with pytest.raises(NttCisAPIException): driver.ex_remove_tag_from_asset(node, 'TagKeyNam') def test_ex_list_tags(driver): tags = driver.ex_list_tags() assert isinstance(tags, list) assert isinstance(tags[0], NttCisTag) assert len(tags) == 3 def test_ex_list_tags_ALLPARAMS(driver): driver.connection._get_orgId() NttCisMockHttp.type = 'ALLPARAMS' tags = driver.ex_list_tags(asset_id='fake_asset_id', asset_type='fake_asset_type', location='fake_location', tag_key_name='fake_tag_key_name', tag_key_id='fake_tag_key_id', value='fake_value', value_required=False, display_on_report=False) assert isinstance(tags, list) assert isinstance(tags[0], NttCisTag) assert len(tags) == 3 def test_list_consistency_groups(driver): cgs = driver.ex_list_consistency_groups() assert isinstance(cgs, list) def test_list_cg_by_src_net_domain(driver): nd = "f9d6a249-c922-4fa1-9f0f-de5b452c4026" cgs = driver.ex_list_consistency_groups(source_network_domain_id=nd) assert cgs[0].name == "sdk_test2_cg" def test_list_cg_by_name(driver): NttCisMockHttp.type = "CG_BY_NAME" name = "sdk_test2_cg" cg = driver.ex_list_consistency_groups(name=name) assert cg[0].id == "195a426b-4559-4c79-849e-f22cdf2bfb6e" def test_get_consistency_group_by_id(driver): NttCisMockHttp.type = None cgs = driver.ex_list_consistency_groups() cg_id = [i for i in cgs if i.name == "sdk_test2_cg"][0].id cg = driver.ex_get_consistency_group(cg_id) assert hasattr(cg, 'description') def test_get_drs_snapshots(driver): NttCisMockHttp.type = None cgs = driver.ex_list_consistency_groups() cg_id = [i for i in cgs if i.name == "sdk_test2_cg"][0].id snaps = driver.ex_list_consistency_group_snapshots(cg_id) assert hasattr(snaps, 'journalUsageGb') assert isinstance(snaps, ClassFactory) def test_get_drs_snapshots_by_min_max(driver): cgs = driver.ex_list_consistency_groups() cg_id = [i for i in cgs if i.name == "sdk_test2_cg"][0].id snaps = driver.ex_list_consistency_group_snapshots( cg_id, create_time_min="2018-11-28T00:00:00.000Z", create_time_max="2018-11-29T00:00:00.000Z") for snap in snaps.snapshot: assert "2018-12" not in snap def test_expand_drs_journal(driver): cgs = driver.ex_list_consistency_groups(name="sdk_test2_cg") cg_id = cgs[0].id expand_by = "100" result = driver.ex_expand_journal(cg_id, expand_by) assert result is True def test_start_drs_snapshot_preview(driver): cg_id = "195a426b-4559-4c79-849e-f22cdf2bfb6e" snapshot_id = "3893" result = driver.ex_start_drs_failover_preview(cg_id, snapshot_id) assert result is True def test_stop_drs_snapshot_preivew(driver): cg_id = "195a426b-4559-4c79-849e-f22cdf2bfb6e" result = driver.ex_stop_drs_failover_preview(cg_id) assert result is True def test_start_drs_failover_invalid_status(driver): NttCisMockHttp.type = "INVALID_STATUS" cg_id = "195a426b-4559-4c79-849e-f22cdf2bfb6e" with pytest.raises(NttCisAPIException) as excinfo: result = driver.ex_initiate_drs_failover(cg_id) assert "INVALID_STATUS" in excinfo.value.code def test_initiate_drs_failover(driver): cg_id = "195a426b-4559-4c79-849e-f22cdf2bfb6e" result = driver.ex_initiate_drs_failover(cg_id) assert result is True def test_create_drs_fail_not_supported(driver): NttCisMockHttp.type = "FAIL_NOT_SUPPORTED" src_id = "032f3967-00e4-4780-b4ef-8587460f9dd4" target_id = "aee58575-38e2-495f-89d3-854e6a886411" with pytest.raises(NttCisAPIException) as excinfo: result = driver.ex_create_consistency_group( "sdk_cg", "100", src_id, target_id, description="A test consistency group") exception_msg = excinfo.value.msg assert exception_msg == 'DRS is not supported between source Data Center NA9 and target Data Center NA12.' def test_create_drs_cg_fail_ineligble(driver): NttCisMockHttp.type = "FAIL_INELIGIBLE" src_id = "032f3967-00e4-4780-b4ef-8587460f9dd4" target_id = "aee58575-38e2-495f-89d3-854e6a886411" with pytest.raises(NttCisAPIException) as excinfo: driver.ex_create_consistency_group( "sdk_test2_cg", "100", src_id, target_id, description="A test consistency group") exception_msg = excinfo.value.msg assert exception_msg == 'The drsEligible flag for target Server aee58575-38e2-495f-89d3-854e6a886411 must be set.' def test_create_drs_cg(driver): src_id = "032f3967-00e4-4780-b4ef-8587460f9dd4" target_id = "aee58575-38e2-495f-89d3-854e6a886411" result = driver.ex_create_consistency_group( "sdk_test2_cg2", "100", src_id, target_id, description="A test consistency group") assert result is True def test_delete_consistency_group(driver): cg_id = "fad067be-6ca7-495d-99dc-7921c5f2ca5" result = driver.ex_delete_consistency_group(cg_id) assert result is True class InvalidRequestError(Exception): def __init__(self, tag): super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag) class NttCisMockHttp(MockHttp): fixtures = ComputeFileFixtures('nttcis') def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_PAGINATED(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_ALLFILTERS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_NET_DOMAIN(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_CG_BY_NAME(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_MIN_MAX(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_MIN(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INVALID_STATUS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_FAIL_INELIGIBLE(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_FAIL_NOT_SUPPORTED(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_DYNAMIC(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation(self, method, url, body, headers): body = self.fixtures.load( 'networkWithLocation.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers): body = self.fixtures.load( 'server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_deleteServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_deleteServer_RESOURCEBUSY.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}rebootServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_rebootServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}rebootServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_rebootServer_RESOURCEBUSY.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers): if url.endswith('datacenterId=NA3'): body = self.fixtures.load( 'server_server_NA3.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGESIZE50(self, method, url, body, headers): if not url.endswith('pageSize=50'): raise ValueError("pageSize is not set as expected") body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_EMPTY(self, method, url, body, headers): body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGED_THEN_EMPTY(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( 'server_server_paginated.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATED(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( 'server_server_paginated.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATEDEMPTY(self, method, url, body, headers): body = self.fixtures.load( 'server_server_paginated_empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_loc' elif key == 'networkId': assert value == 'fake_network' elif key == 'networkDomainId': assert value == 'fake_network_domain' elif key == 'vlanId': assert value == 'fake_vlan' elif key == 'ipv6': assert value == 'fake_ipv6' elif key == 'privateIpv4': assert value == 'fake_ipv4' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' elif key == 'started': assert value == 'True' elif key == 'deployed': assert value == 'True' elif key == 'sourceImageId': assert value == 'fake_image' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'server_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule(self, method, url, body, headers): body = self.fixtures.load( 'server_antiAffinityRule_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'id': assert value == 'FAKE_ID' elif key == 'state': assert value == 'FAKE_STATE' elif key == 'pageSize': assert value == '250' elif key == 'networkDomainId': pass else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'server_antiAffinityRule_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_createAntiAffinityRule(self, method, url, body, headers): body = self.fixtures.load( 'server_createAntiAffinityRule.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_PAGINATED(self, method, url, body, headers): if 'pageNumber=2' in url: body = self.fixtures.load( 'server_antiAffinityRule_list.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) else: body = self.fixtures.load( 'server_antiAffinityRule_list_PAGINATED.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_createAntiAffinityRule_FAIL_EXISTING(self, method, url, body, headers): body = self.fixtures.load( 'server_createAntiAffinityRule_FAIL.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteAntiAffinityRule(self, method, url, body, headers): body = self.fixtures.load( 'server_deleteAntiAffinityRule.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteAntiAffinityRule_FAIL(self, method, url, body, headers): body = self.fixtures.load( 'server_createAntiAffinityRule_FAIL.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_snapshotWindow(self, method, url, body, headers): body = self.fixtures.load( 'datacenter_snapshotWindows.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers): if url.endswith('id=NA9'): body = self.fixtures.load( 'infrastructure_datacenter_NA9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'infrastructure_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_ALLFILTERS(self, method, url, body, headers): if url.endswith('id=NA9'): body = self.fixtures.load( 'infrastructure_datacenter_NA9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) body = self.fixtures.load( 'infrastructure_datacenter.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_updateVmwareTools(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}updateVmwareTools": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_updateVmwareTools.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}startServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_startServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}startServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_startServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_shutdownServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_shutdownServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}resetServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_resetServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_powerOffServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_powerOffServer_INPROGRESS.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_11_INPROGRESS( self, method, url, body, headers): body = self.fixtures.load('server_GetServer.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_location' elif key == 'type': assert value == 'fake_plan' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'network_networkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan(self, method, url, body, headers): body = self.fixtures.load( 'network_vlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'datacenterId': assert value == 'fake_location' elif key == 'networkDomainId': assert value == 'fake_network_domain' elif key == 'ipv6Address': assert value == 'fake_ipv6' elif key == 'privateIpv4Address': assert value == 'fake_ipv4' elif key == 'name': assert value == 'fake_name' elif key == 'state': assert value == 'fake_state' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'network_vlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployServer": raise InvalidRequestError(request.tag) # Make sure the we either have a network tag with an IP or networkId # Or Network info with a primary nic that has privateip or vlanid network = request.find(fixxpath('network', TYPES_URN)) network_info = request.find(fixxpath('networkInfo', TYPES_URN)) if network is not None: if network_info is not None: raise InvalidRequestError("Request has both MCP1 and MCP2 values") ipv4 = findtext(network, 'privateIpv4', TYPES_URN) networkId = findtext(network, 'networkId', TYPES_URN) if ipv4 is None and networkId is None: raise InvalidRequestError('Invalid request MCP1 requests need privateIpv4 or networkId') elif network_info is not None: if network is not None: raise InvalidRequestError("Request has both MCP1 and MCP2 values") primary_nic = network_info.find(fixxpath('primaryNic', TYPES_URN)) ipv4 = findtext(primary_nic, 'privateIpv4', TYPES_URN) vlanId = findtext(primary_nic, 'vlanId', TYPES_URN) if ipv4 is None and vlanId is None: raise InvalidRequestError('Invalid request MCP2 requests need privateIpv4 or vlanId') else: raise InvalidRequestError('Invalid request, does not have network or network_info in XML') body = self.fixtures.load( 'server_deployServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers): body = self.fixtures.load( 'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deployNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be(self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be_ALLFILTERS( self, method, url, body, headers): body = self.fixtures.load( 'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNetworkDomain(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteNetworkDomain": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteNetworkDomain.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deployVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deployVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_0e56433f_d808_4669_821d_812769517ff8(self, method, url, body, headers): body = self.fixtures.load( 'network_vlan_0e56433f_d808_4669_821d_812769517ff8.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_expandVlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}expandVlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_expandVlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_addPublicIpBlock(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}addPublicIpBlock": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_addPublicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8(self, method, url, body, headers): body = self.fixtures.load( 'network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_removePublicIpBlock(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removePublicIpBlock": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_removePublicIpBlock.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule(self, method, url, body, headers): body = self.fixtures.load( 'network_firewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_createFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c(self, method, url, body, headers): body = self.fixtures.load( 'network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_editFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteFirewallRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteFirewallRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteFirewallRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createNatRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createNatRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_createNatRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule(self, method, url, body, headers): body = self.fixtures.load( 'network_natRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce(self, method, url, body, headers): body = self.fixtures.load( 'network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNatRule(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteNatRule": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'network_deleteNatRule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addNic(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}addNic": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_addNic.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeNic(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removeNic": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_removeNic.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_disableServerMonitoring(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}disableServerMonitoring": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_disableServerMonitoring.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_enableServerMonitoring(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}enableServerMonitoring": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_enableServerMonitoring.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeServerMonitoringPlan(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}changeServerMonitoringPlan": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_changeServerMonitoringPlan.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_FAKE_IMAGE_ID(self, method, url, body, headers): body = self.fixtures.load( 'image_osImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_FAKE_IMAGE_ID(self, method, url, body, headers): body = self.fixtures.load( 'image_customerImage_BAD_REQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_reconfigureServer(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}reconfigureServer": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'server_reconfigureServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cleanServer(self, method, url, body, headers): body = self.fixtures.load( 'server_cleanServer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addDisk(self, method, url, body, headers): body = self.fixtures.load( 'server_addDisk.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeDiskSpeed(self, method, url, body, headers): body = self.fixtures.load( 'change_disk_speed.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_expandDisk(self, method, url, body, headers): body = self.fixtures.load( 'change_disk_size.xml') return(httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeDisk(self, method, url, body, headers): body = self.fixtures.load( 'server_removeDisk.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_editServerMetadata(self, method, url, body, headers): body = self.fixtures.load( 'server_editServerMetadata.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is not None: raise ValueError("Default description for a tag should be blank") if value_required is None or value_required != 'true': raise ValueError("Default valueRequired should be true") if display_on_report is None or display_on_report != 'true': raise ValueError("Default displayOnReport should be true") body = self.fixtures.load( 'tag_createTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_ALLPARAMS(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}createTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is None: raise ValueError("Description should have a value") if value_required is None or value_required != 'false': raise ValueError("valueRequired should be false") if display_on_report is None or display_on_report != 'false': raise ValueError("displayOnReport should be false") body = self.fixtures.load( 'tag_createTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_BADREQUEST(self, method, url, body, headers): body = self.fixtures.load( 'tag_createTagKey_BADREQUEST.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_SINGLE(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_list_SINGLE.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_ALLFILTERS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'id': assert value == 'fake_id' elif key == 'name': assert value == 'fake_name' elif key == 'valueRequired': assert value == 'false' elif key == 'displayOnReport': assert value == 'false' elif key == 'pageSize': assert value == '250' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'tag_tagKey_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075_NOEXIST(self, method, url, body, headers): body = self.fixtures.load( 'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NAME(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is None: raise ValueError("Name must have a value in the request") if description is not None: raise ValueError("Description should be empty") if value_required is not None: raise ValueError("valueRequired should be empty") if display_on_report is not None: raise ValueError("displayOnReport should be empty") body = self.fixtures.load( 'tag_editTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOTNAME(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}editTagKey": raise InvalidRequestError(request.tag) name = findtext(request, 'name', TYPES_URN) description = findtext(request, 'description', TYPES_URN) value_required = findtext(request, 'valueRequired', TYPES_URN) display_on_report = findtext(request, 'displayOnReport', TYPES_URN) if name is not None: raise ValueError("Name should be empty") if description is None: raise ValueError("Description should not be empty") if value_required is None: raise ValueError("valueRequired should not be empty") if display_on_report is None: raise ValueError("displayOnReport should not be empty") body = self.fixtures.load( 'tag_editTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOCHANGE(self, method, url, body, headers): body = self.fixtures.load( 'tag_editTagKey_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}deleteTagKey": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'tag_deleteTagKey.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey_NOEXIST(self, method, url, body, headers): body = self.fixtures.load( 'tag_deleteTagKey_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}applyTags": raise InvalidRequestError(request.tag) asset_type = findtext(request, 'assetType', TYPES_URN) asset_id = findtext(request, 'assetId', TYPES_URN) tag = request.find(fixxpath('tag', TYPES_URN)) tag_key_name = findtext(tag, 'tagKeyName', TYPES_URN) value = findtext(tag, 'value', TYPES_URN) if asset_type is None: raise ValueError("assetType should not be empty") if asset_id is None: raise ValueError("assetId should not be empty") if tag_key_name is None: raise ValueError("tagKeyName should not be empty") if value is None: raise ValueError("value should not be empty") body = self.fixtures.load( 'tag_applyTags.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOVALUE(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}applyTags": raise InvalidRequestError(request.tag) asset_type = findtext(request, 'assetType', TYPES_URN) asset_id = findtext(request, 'assetId', TYPES_URN) tag = request.find(fixxpath('tag', TYPES_URN)) tag_key_name = findtext(tag, 'tagKeyName', TYPES_URN) value = findtext(tag, 'value', TYPES_URN) if asset_type is None: raise ValueError("assetType should not be empty") if asset_id is None: raise ValueError("assetId should not be empty") if tag_key_name is None: raise ValueError("tagKeyName should not be empty") if value is not None: raise ValueError("value should be empty") body = self.fixtures.load( 'tag_applyTags.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOTAGKEY(self, method, url, body, headers): body = self.fixtures.load( 'tag_applyTags_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags(self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}removeTags": raise InvalidRequestError(request.tag) body = self.fixtures.load( 'tag_removeTag.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags_NOTAG(self, method, url, body, headers): body = self.fixtures.load( 'tag_removeTag_BADREQUEST.xml' ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag(self, method, url, body, headers): body = self.fixtures.load( 'tag_tag_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag_ALLPARAMS(self, method, url, body, headers): (_, params) = url.split('?') parameters = params.split('&') for parameter in parameters: (key, value) = parameter.split('=') if key == 'assetId': assert value == 'fake_asset_id' elif key == 'assetType': assert value == 'fake_asset_type' elif key == 'valueRequired': assert value == 'false' elif key == 'displayOnReport': assert value == 'false' elif key == 'pageSize': assert value == '250' elif key == 'datacenterId': assert value == 'fake_location' elif key == 'value': assert value == 'fake_value' elif key == 'tagKeyName': assert value == 'fake_tag_key_name' elif key == 'tagKeyId': assert value == 'fake_tag_key_id' else: raise ValueError("Could not find in url parameters {0}:{1}".format(key, value)) body = self.fixtures.load( 'tag_tag_list.xml' ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList( self, method, url, body, headers): body = self.fixtures.load('ip_address_lists.xml') return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList_FILTERBYNAME( self, method, url, body, headers): body = self.fixtures.load('ip_address_lists_FILTERBYNAME.xml') return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "createIpAddressList": raise InvalidRequestError(request.tag) net_domain = findtext(request, 'networkDomainId', TYPES_URN) if net_domain is None: raise ValueError("Network Domain should not be empty") name = findtext(request, 'name', TYPES_URN) if name is None: raise ValueError("Name should not be empty") ip_version = findtext(request, 'ipVersion', TYPES_URN) if ip_version is None: raise ValueError("IP Version should not be empty") ip_address_col_required = findall(request, 'ipAddress', TYPES_URN) child_ip_address_required = findall(request, 'childIpAddressListId', TYPES_URN) if 0 == len(ip_address_col_required) and \ 0 == len(child_ip_address_required): raise ValueError("At least one ipAddress element or " "one childIpAddressListId element must be " "provided.") if ip_address_col_required[0].get('begin') is None: raise ValueError("IP Address should not be empty") body = self.fixtures.load( 'ip_address_list_create.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "editIpAddressList": raise InvalidRequestError(request.tag) ip_address_list = request.get('id') if ip_address_list is None: raise ValueError("IpAddressList ID should not be empty") name = findtext(request, 'name', TYPES_URN) if name is not None: raise ValueError("Name should not exists in request") ip_version = findtext(request, 'ipVersion', TYPES_URN) if ip_version is not None: raise ValueError("IP Version should not exists in request") ip_address_col_required = findall(request, 'ipAddress', TYPES_URN) child_ip_address_required = findall(request, 'childIpAddressListId', TYPES_URN) if 0 == len(ip_address_col_required) and \ 0 == len(child_ip_address_required): raise ValueError("At least one ipAddress element or " "one childIpAddressListId element must be " "provided.") if ip_address_col_required[0].get('begin') is None: raise ValueError("IP Address should not be empty") body = self.fixtures.load( 'ip_address_list_edit.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteIpAddressList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "deleteIpAddressList": raise InvalidRequestError(request.tag) ip_address_list = request.get('id') if ip_address_list is None: raise ValueError("IpAddressList ID should not be empty") body = self.fixtures.load( 'ip_address_list_delete.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList( self, method, url, body, headers): body = self.fixtures.load( 'port_list_lists.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList_c8c92ea3_2da8_4d51_8153_f39bec794d69( self, method, url, body, headers): body = self.fixtures.load( 'port_list_get.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "createPortList": raise InvalidRequestError(request.tag) net_domain = findtext(request, 'networkDomainId', TYPES_URN) if net_domain is None: raise ValueError("Network Domain should not be empty") ports_required = findall(request, 'port', TYPES_URN) child_port_list_required = findall(request, 'childPortListId', TYPES_URN) if 0 == len(ports_required) and \ 0 == len(child_port_list_required): raise ValueError("At least one port element or one " "childPortListId element must be provided") if ports_required[0].get('begin') is None: raise ValueError("PORT begin value should not be empty") body = self.fixtures.load( 'port_list_create.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "editPortList": raise InvalidRequestError(request.tag) ports_required = findall(request, 'port', TYPES_URN) child_port_list_required = findall(request, 'childPortListId', TYPES_URN) if 0 == len(ports_required) and \ 0 == len(child_port_list_required): raise ValueError("At least one port element or one " "childPortListId element must be provided") if ports_required[0].get('begin') is None: raise ValueError("PORT begin value should not be empty") body = self.fixtures.load( 'port_list_edit.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deletePortList( self, method, url, body, headers): request = ET.fromstring(body) if request.tag != "{urn:didata.com:api:cloud:types}" \ "deletePortList": raise InvalidRequestError(request.tag) port_list = request.get('id') if port_list is None: raise ValueError("Port List ID should not be empty") body = self.fixtures.load( 'ip_address_list_delete.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cloneServer( self, method, url, body, headers): body = self.fixtures.load( 'server_clone_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_importImage( self, method, url, body, headers): body = self.fixtures.load( 'import_image_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_exchangeNicVlans( self, method, url, body, headers): body = self.fixtures.load( 'exchange_nic_vlans_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeNetworkAdapter( self, method, url, body, headers): body = self.fixtures.load( 'change_nic_networkadapter_response.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployUncustomizedServer( self, method, url, body, headers): body = self.fixtures.load( 'deploy_customised_server.xml' ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_snapshot_snapshot( self, method, url, body, headers): body = self.fixtures.load( "list_server_snapshots.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_snapshot_enableSnapshotService( self, method, url, body, headers): body = self.fixtures.load( "enable_snapshot_service.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_snapshot_initiateManualSnapshot( self, method, url, body, headers): body = self.fixtures.load( "initiate_manual_snapshot.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e1eb7d71_93c9_4b9c_807c_e05932dc8143( self, method, url, body, headers): body = self.fixtures.load( "manual_snapshot_server.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_snapshot_createSnapshotPreviewServer( self, method, url, body, headers): body = self.fixtures.load( "create_preview_server.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_snapshot_disableSnapshotService( self, method, url, body, headers): body = self.fixtures.load( "disable_server_snapshot_service.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_consistencyGroup( self, method, url, body, headers): body = self.fixtures.load( "list_consistency_groups.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_consistencyGroup_NET_DOMAIN( self, method, url, body, headers): body = self.fixtures.load( "cg_by_src_network_domain.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_consistencyGroup_CG_BY_NAME( self, method, url, body, headers): body = self.fixtures.load( "get_cg_by_name_or_id.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_consistencyGroup_195a426b_4559_4c79_849e_f22cdf2bfb6e( self, method, url, body, headers): body = self.fixtures.load( "get_cg_by_name_or_id.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_snapshot( self, method, url, body, headers): body = self.fixtures.load( "list_drs_snapshots.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_snapshot_MIN_MAX( self, method, url, body, headers): body = self.fixtures.load( "drs_snap_shots_by_min_max_time.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_snapshot_MIN( self, method, url, body, headers): body = self.fixtures.load( "drs_snap_shots_by_min.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_expandJournal( self, method, url, body, headers): body = self.fixtures.load( "drs_expand_journal.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_startPreviewSnapshot( self, method, url, body, headers): body = self.fixtures.load( "drs_start_failover_preview.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_stopPreviewSnapshot( self, method, url, body, headers): body = self.fixtures.load( "drs_stop_failover_preview.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_initiateFailover_INVALID_STATUS( self, method, url, body, headers): body = self.fixtures.load( "drs_invalid_status.xml" ) return httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_initiateFailover( self, method, url, body, headers): body = self.fixtures.load( "drs_initiate_failover.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_createConsistencyGroup_FAIL_INELIGIBLE( self, method, url, body, headers): body = self.fixtures.load( "drs_fail_create_cg_ineligible.xml" ) return httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_createConsistencyGroup_FAIL_NOT_SUPPORTED( self, method, url, body, headers): body = self.fixtures.load( "drs_fail_create_cg_not_supported.xml" ) return httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_createConsistencyGroup( self, method, url, body, headers): body = self.fixtures.load( "drs_create_cg.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_consistencyGroup_deleteConsistencyGroup( self, method, url, body, headers): body = self.fixtures.load( "drs_delete_consistency_group.xml" ) return httplib.OK, body, {}, httplib.responses[httplib.OK] if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_onapp.py0000664000175000017500000001403713570310635023411 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import sys from libcloud.compute.base import Node from libcloud.compute.drivers.onapp import OnAppNodeDriver from libcloud.test import MockHttp, LibcloudTestCase from libcloud.test.secrets import ONAPP_PARAMS from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.utils.py3 import httplib class OnAppNodeTestCase(LibcloudTestCase): driver_klass = OnAppNodeDriver def setUp(self): self.driver_klass.connectionCls.conn_class = OnAppMockHttp self.driver = OnAppNodeDriver(*ONAPP_PARAMS) def test_create_node(self): node = self.driver.create_node( name='onapp-new-fred', ex_memory=512, ex_cpus=4, ex_cpu_shares=4, ex_hostname='onapp-new-fred', ex_template_id='template_id', ex_primary_disk_size=100, ex_swap_disk_size=1, ex_required_virtual_machine_build=0, ex_required_ip_address_assignment=0 ) extra = node.extra self.assertEqual('onapp-new-fred', node.name) self.assertEqual('456789', node.id) self.assertEqual('456789', node.id) self.assertEqual('delivered', node.state) self.assertEqual(True, extra['booted']) self.assertEqual('passwd', extra['initial_root_password']) self.assertEqual('8.8.8.8', extra['local_remote_access_ip_address']) self.assertEqual(['192.168.15.73'], node.private_ips) self.assertEqual([], node.public_ips) def test_destroy_node(self): node = Node('identABC', 'testnode', ['123.123.123.123'], [], {'state': 'test', 'template_id': 88}, None) res = self.driver.destroy_node(node=node) self.assertTrue(res) def test_list_nodes(self): nodes = self.driver.list_nodes() extra = nodes[0].extra private_ips = nodes[0].private_ips self.assertEqual(1, len(nodes)) self.assertEqual('onapp-fred', nodes[0].name) self.assertEqual('123456', nodes[0].id) self.assertEqual(True, extra['booted']) self.assertEqual('passwd', extra['initial_root_password']) self.assertEqual('9.9.9.9', extra['local_remote_access_ip_address']) self.assertEqual(1, len(private_ips)) self.assertEqual('192.168.15.72', private_ips[0]) def test_list_images(self): images = self.driver.list_images() extra = images[0].extra self.assertEqual(1, len(images)) self.assertEqual('CentOS 5.11 x64', images[0].name) self.assertEqual('123456', images[0].id) self.assertEqual(True, extra['allowed_swap']) self.assertEqual(256, extra['min_memory_size']) self.assertEqual('rhel', extra['distribution']) def test_list_key_pairs(self): keys = self.driver.list_key_pairs() self.assertEqual(2, len(keys)) self.assertEqual(1, keys[0].name) self.assertIsNotNone(keys[0].public_key) self.assertIsNotNone(keys[1].public_key) def test_get_key_pair(self): key = self.driver.get_key_pair(1) self.assertEqual(1, key.name) self.assertIsNotNone(key.public_key) def test_import_key_pair_from_string(self): key = self.driver.import_key_pair_from_string( 'name', 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8uuUq') self.assertEqual(3, key.name) self.assertEqual( 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8uuUq', key.public_key) def test_delete_key_pair(self): key = self.driver.get_key_pair(1) response = self.driver.delete_key_pair(key) self.assertTrue(response) class OnAppMockHttp(MockHttp): fixtures = ComputeFileFixtures('onapp') def _virtual_machines_json(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('list_nodes.json') else: body = self.fixtures.load('create_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _virtual_machines_identABC_json(self, method, url, body, headers): return ( httplib.NO_CONTENT, '', {}, httplib.responses[httplib.NO_CONTENT] ) def _templates_json(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _profile_json(self, method, url, body, headers): body = self.fixtures.load('profile.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _users_123_ssh_keys_json(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('list_key_pairs.json') else: body = self.fixtures.load('import_key_pair.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _users_123_ssh_keys_1_json(self, method, url, body, headers): body = self.fixtures.load('get_key_pair.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _settings_ssh_keys_1_json(self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.NO_CONTENT]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_oneandone.py0000664000175000017500000012262413570310635024244 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.compute.base import NodeImage, NodeAuthPassword, NodeLocation from libcloud.utils.py3 import httplib from libcloud.test import unittest, MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.compute.types import Provider, NodeState from libcloud.test.secrets import ONEANDONE_PARAMS from libcloud.compute.providers import get_driver class OneAndOneTests(unittest.TestCase): def setUp(self): oneAndOne = get_driver(Provider.ONEANDONE) oneAndOne.connectionCls.conn_class = OneAndOneMockHttp self.driver = oneAndOne(ONEANDONE_PARAMS) ''' Function tests for listing items ''' def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 4) def test_list_locations(self): sizes = self.driver.list_locations() self.assertEqual(len(sizes), 4) def test_list_images(self): appliances = self.driver.list_images("IMAGE") self.assertEqual(len(appliances), 102) def test_get_image(self): appliance = self.driver.get_image('img_1') self.assertNotEqual(appliance, None) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 5) counter = 0 for node in nodes: if counter == 0: self.assertEqual(node.id, '8A7D5122BDC173B6E52223878CEF2748') self.assertEqual(node.name, 'Docs Content Ubuntu 16.04-1') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['50.21.182.126']) self.assertEqual(node.private_ips, []) if counter == 1: self.assertEqual(node.id, 'E7D36EC025C73796035BF4F171379025') self.assertEqual(node.name, 'Docs Content Test Server: CentOS 7-1') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['62.151.179.99']) self.assertEqual(node.private_ips, []) if counter == 2: self.assertEqual(node.id, 'DDDC4CCA34AAB08132FA1E40F9FEAC25') self.assertEqual(node.name, 'App Dev Server 5') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['70.35.206.196']) self.assertEqual(node.private_ips, []) if counter == 3: self.assertEqual(node.id, 'D5C5C1D01249DE9B88BE3DAE973AA090') self.assertEqual(node.name, 'Docs Test Server: CentOS 7-2') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['74.208.88.88']) self.assertEqual(node.private_ips, []) if counter == 4: self.assertEqual(node.id, 'FB1765588A90364835782061CE48BA8E') self.assertEqual(node.name, 'Docs Content Test Server Ubuntu 16.04-2') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['70.35.206.233']) self.assertEqual(node.private_ips, []) counter += 1 def test_create_node(self): node = self.driver.create_node(name="name", image=NodeImage( id="image_id", name=None, driver=self.driver), ex_fixed_instance_size_id="instance_id", location=NodeLocation( "datacenter_id", name="name", country="GB", driver=self.driver), auth=NodeAuthPassword("password"), ex_ip="1.1.1.1", ex_monitoring_policy_id="mp_id", ex_firewall_policy_id="fw_id", ex_loadbalancer_id="lb_id", ex_description="description", ex_power_on="SHUTDOWN") self.assertEqual(node.id, "E7D36EC025C73796035BF4F171379025") self.assertEqual(node.name, "Docs Content Test Server: CentOS 7-1") self.assertEqual(node.extra["description"], "My server description") self.assertIsNone(node.extra["status"]["percent"]) self.assertEqual(node.extra["status"]["state"], "POWERED_ON") self.assertEqual(node.extra["image"]["id"], "B5F778B85C041347BCDCFC3172AB3F3C") self.assertEqual(node.extra["image"]["name"], "centos7-64std") self.assertEqual(node.extra["datacenter"]["id"], "908DC2072407C94C8054610AD5A53B8C") self.assertEqual(node.extra["datacenter"]["country_code"], "US") self.assertEqual(node.extra["datacenter"]["location"], "United States of America") self.assertEqual(node.extra["hardware"]["fixed_instance_size_id"], "65929629F35BBFBA63022008F773F3EB") self.assertEqual(node.extra["hardware"]["vcore"], 1) self.assertEqual(node.extra["hardware"]["hdds"][0]["id"], "CDB278D95A92CB4C379A9CAAD6759F02") self.assertEqual(node.extra["hardware"]["hdds"][0]["size"], 40) self.assertEqual(node.extra["hardware"]["hdds"][0]["is_main"], True) self.assertEqual(node.extra["hardware"]["cores_per_processor"], 1) self.assertEqual(node.extra["hardware"]["vcore"], 1) self.assertEqual(node.extra["hardware"]["ram"], 1) self.assertEqual(node.extra["ips"][0]["id"], "FDBE99EDD57F8596CBF71B6B64BD0A92") self.assertEqual(node.extra["ips"][0]["ip"], "62.151.179.99") self.assertIsNone(node.extra["monitoring_policy"]) self.assertEqual(node.extra["alerts"], []) self.assertIsNone(node.extra["snapshot"]) self.assertIsNone(node.extra["dvd"]) self.assertIsNone(node.extra["private_networks"]) def test_ex_list_datacenters(self): datacenters = self.driver.ex_list_datacenters() self.assertEqual(len(datacenters), 4) def test_ex_shutdown_server(self): server = self.driver.ex_shutdown_server("srv_1") self.assertNotEqual(server, None) def test_reboot_node(self): node = self.driver.ex_get_server("srv_1") node = self.driver.reboot_node(node) self.assertNotEqual(node, None) def test_ex_get_server(self): server = self.driver.ex_get_server("srv_1") self.assertNotEqual(server, None) def test_destroy_node(self): server = self.driver.ex_get_server("srv_1") node = self.driver.destroy_node(server) self.assertNotEqual(node, None) def test_get_server_hardware(self): hardware = self.driver.ex_get_server_hardware("srv_1") self.assertNotEqual(hardware, None) self.assertEqual(hardware['vcore'], 1) self.assertEqual(hardware['cores_per_processor'], 1) self.assertEqual(hardware['ram'], 2) self.assertEqual(hardware['fixed_instance_size_id'], 0) self.assertNotEqual(hardware['hdds'], None) self.assertEqual(hardware['hdds'][0]['id'], '8C626C1A7005D0D1F527143C413D461E') self.assertEqual(hardware['hdds'][0]['is_main'], True) self.assertEqual(hardware['hdds'][0]['size'], 40) def test_rename_server(self): server = self.driver.ex_rename_server("srv_1", "name") self.assertNotEqual(server, None) def test_ex_modify_server_hardware(self): node = self.driver.ex_modify_server_hardware("srv_1", vcore=1) self.assertNotEqual(node, None) def test_add_hdd(self): node = self.driver.ex_add_hdd("srv_1", 1, True) self.assertNotEqual(node, None) def test_modify_hdd(self): node = self.driver.ex_modify_server_hardware("srv_1", "hdd_id", 50) self.assertNotEqual(node, None) def test_remove_hdd(self): node = self.driver.ex_remove_hdd("srv_1", "hdd_id") self.assertNotEqual(node, None) def test_ex_get_server_image(self): image = self.driver.ex_get_server_image("srv_1") self.assertNotEqual(image, None) self.assertEqual(image['id'], "76EBF29C1250167C8754B2B3D1C05F68") self.assertEqual(image['name'], "centos7-64std") def test_ex_reinstall_server_image(self): node = self.driver.ex_reinstall_server_image("srv_1", "img_id", "password") self.assertNotEqual(node, None) def test_ex_list_server_ips(self): ips = self.driver.ex_list_server_ips("srv_1") self.assertEqual(len(ips), 1) def test_ex_get_server_ip(self): ip = self.driver.ex_get_server_ip("srv_1", "ip_id") self.assertNotEqual(ip, None) def test_ex_assign_server(self): node = self.driver.ex_assign_server_ip("srv_1", "IPV$") self.assertNotEqual(node, None) def test_ex_remove_server_ip(self): node = self.driver.ex_remove_server_ip("srv_1", "ip_id", keep_ip=True) self.assertNotEqual(node, None) def test_ex_create_firewall_policy(self): rules = [ { "protocol": "TCP", "port_from": 80, "port_to": 80, "source": "0.0.0.0" }, { "protocol": "TCP", "port_from": 443, "port_to": 443, "source": "0.0.0.0" } ] firewall = self.driver \ .ex_create_firewall_policy("name", rules, description="desc") self.assertNotEqual(firewall, None) def test_ex_list_firewall_policies(self): firewall = self.driver.ex_list_firewall_policies() self.assertNotEqual(firewall, None) self.assertEqual(len(firewall), 2) def test_ex_get_firewall_policy(self): firewall = self.driver.ex_get_firewall_policy("fw_id") self.assertNotEqual(firewall, None) def test_ex_delete_firewall_policy(self): firewall = self.driver.ex_delete_firewall_policy("fw_id") self.assertNotEqual(firewall, None) def test_ex_get_server_firewall_policies(self): firewall = self.driver \ .ex_get_server_firewall_policies("srv_id", "ip_id") self.assertNotEqual(firewall, None) def test_ex_add_server_firewall_policy(self): node = self.driver \ .ex_add_server_firewall_policy("srv_id", "ip_id", "fw_id") self.assertNotEqual(node, None) def test_ex_list_shared_storages(self): storages = self.driver.ex_list_shared_storages() self.assertEqual(len(storages), 3) def test_ex_get_shared_storage(self): storage = self.driver.ex_get_shared_storage('storage_1') self.assertNotEqual(storage, None) self.assertEqual(storage['id'], "6AD2F180B7B666539EF75A02FE227084") self.assertEqual(storage['size'], 200) self.assertEqual(storage['state'], 'ACTIVE') self.assertEqual(storage['description'], 'My shared storage test description') self.assertEqual(storage['datacenter']['id'], 'D0F6D8C8ED29D3036F94C27BBB7BAD36') self.assertEqual(storage['datacenter']['location'], 'USA') self.assertEqual(storage['datacenter']['country_code'], 'US') self.assertEqual(storage['cloudpanel_id'], 'vid35780') self.assertEqual(storage['size_used'], '0.00') self.assertEqual(storage["cifs_path"], "vid50995.nas1.lanvid50995") self.assertEqual(storage["nfs_path"], "vid50995.nas1.lan/:vid50995") self.assertEqual(storage["name"], "My shared storage test") self.assertEqual(storage["creation_date"], "2015-05-06T08:33:25+00:00") self.assertEqual(storage['servers'][0]['id'], '638ED28205B1AFD7ADEF569C725DD85F') self.assertEqual(storage['servers'][0]["name"], "My server 1") self.assertEqual(storage['servers'][0]["rights"], "RW") def test_ex_create_shared_storage(self): storage = self.driver.ex_create_shared_storage( name='TEST', size=2, datacenter_id='dc_id') self.assertNotEqual(storage, None) def test_ex_delete_shared_storage(self): storage = self.driver.ex_delete_shared_storage('storage_1') self.assertNotEqual(storage, None) def test_ex_attach_server_to_shared_storage(self): storage = self.driver.ex_attach_server_to_shared_storage( 'storage_1', 'srv_1', 'RW') self.assertNotEqual(storage, None) def test_ex_get_shared_storage_server(self): storage = self.driver.ex_get_shared_storage_server( 'storage_1', 'srv_1') self.assertNotEqual(storage, None) def test_ex_detach_server_from_shared_storage(self): storage = self.driver.ex_detach_server_from_shared_storage( 'storage_1', 'srv_1') self.assertNotEqual(storage, None) def test_ex_create_load_balancers(self): rules = [ { "protocol": "TCP", "port_balancer": 80, "port_server": 80, "source": "0.0.0.0" }, { "protocol": "TCP", "port_balancer": 9999, "port_server": 8888, "source": "0.0.0.0" } ] load_balancer = self.driver. \ ex_create_load_balancer(name='name', method='ROUNDROBIN', rules=rules, persistence=True, persistence_time=1) self.assertNotEqual(load_balancer, None) def test_ex_list_load_balancers(self): load_balancers = self.driver.ex_list_load_balancers() self.assertEqual(len(load_balancers), 2) def test_update_load_balancer(self): load_balancer = self.driver. \ ex_update_load_balancer("lb_1", name='new name') self.assertNotEqual(load_balancer, None) def test_ex_add_servers_to_load_balancer(self): load_balancer = self.driver. \ ex_add_servers_to_load_balancer('lb_1', server_ips=["1.1.1.1"]) self.assertNotEqual(load_balancer, None) def test_ex_remove_server_from_load_balancer(self): load_balancer = self.driver. \ ex_remove_server_from_load_balancer('lb_1', server_ip="srv_1") self.assertNotEqual(load_balancer, None) def test_ex_add_load_balancer_rule(self): load_balancer = self.driver. \ ex_add_load_balancer_rule('lb_1', protocol='TCP', port_balancer=82, port_server=81, source='0.0.0.0') self.assertNotEqual(load_balancer, None) def test_ex_remove_load_balancer_rule(self): load_balancer = self.driver. \ ex_remove_load_balancer_rule('lb_1', 'rule_1') self.assertNotEqual(load_balancer, None) def test_ex_get_load_balancer(self): load_balancer = self.driver. \ ex_get_load_balancer('lb_1') self.assertNotEqual(load_balancer, None) def test_ex_get_load_balancer_server_ip(self): server_ip = self.driver. \ ex_get_load_balancer_server_ip('lb_1', 'srv_1') self.assertNotEqual(server_ip, None) def test_ex_list_load_balancer_rules(self): rules = self.driver. \ ex_list_load_balancer_rules('lb_1') self.assertNotEqual(rules, None) self.assertEqual(len(rules), 2) def test_ex_get_load_balancer_rule(self): rule = self.driver. \ ex_get_load_balancer_rule('lb_1', 'rule_1') self.assertNotEqual(rule, None) def test_ex_delete_load_balancer(self): load_balancer = self.driver. \ ex_delete_load_balancer('lb_1') self.assertNotEqual(load_balancer, None) def test_ex_list_public_ips(self): ips = self.driver.ex_list_public_ips() self.assertNotEqual(ips, None) self.assertEqual(len(ips), 3) def test_ex_create_public_ip(self): ip = self.driver.ex_create_public_ip('IPv4') self.assertNotEqual(ip, None) def test_ex_get_public_ip(self): ip = self.driver.ex_get_public_ip('ip_1') self.assertNotEqual(ip, None) def test_ex_delete_public_ip(self): ip = self.driver.ex_delete_public_ip('ip_1') self.assertNotEqual(ip, None) def test_ex_update_public_ip(self): ip = self.driver.ex_update_public_ip('ip_1', "reverse.dns") self.assertNotEqual(ip, None) def test_ex_create_monitoring_policy(self): thresholds = { "cpu": { "warning": { "value": 90, "alert": False }, "critical": { "value": 95, "alert": False } }, "ram": { "warning": { "value": 90, "alert": False }, "critical": { "value": 95, "alert": False } }, "disk": { "warning": { "value": 80, "alert": False }, "critical": { "value": 90, "alert": False } }, "transfer": { "warning": { "value": 1000, "alert": False }, "critical": { "value": 2000, "alert": False } }, "internal_ping": { "warning": { "value": 50, "alert": False }, "critical": { "value": 100, "alert": False } } } ports = [ { "protocol": "TCP", "port": "22", "alert_if": "RESPONDING", "email_notification": True } ] processes = [ { "process": "test", "alert_if": "NOT_RUNNING", "email_notification": True } ] policy = self.driver. \ ex_create_monitoring_policy(name='test_name', thresholds=thresholds, ports=ports, processes=processes, description='description', email='test@domain.com', agent=True) self.assertNotEqual(policy, None) def test_ex_list_monitoring_policies(self): policies = self.driver.ex_list_monitoring_policies() self.assertNotEqual(policies, None) self.assertEqual(len(policies), 2) def test_ex_get_monitoring_policy(self): policy = self.driver.ex_get_monitoring_policy('pol_1') self.assertNotEqual(policy, None) def test_ex_update_monitoring_policy(self): thresholds = { "cpu": { "warning": { "value": 90, "alert": False }, "critical": { "value": 95, "alert": False } }, "ram": { "warning": { "value": 90, "alert": False }, "critical": { "value": 95, "alert": False } }, "disk": { "warning": { "value": 80, "alert": False }, "critical": { "value": 90, "alert": False } }, "transfer": { "warning": { "value": 1000, "alert": False }, "critical": { "value": 2000, "alert": False } }, "internal_ping": { "warning": { "value": 50, "alert": False }, "critical": { "value": 100, "alert": False } } } policy = self.driver. \ ex_update_monitoring_policy('pol_1', email='test@domain.com', thresholds=thresholds, name='new name', description='new description') self.assertNotEqual(policy, None) def test_ex_get_monitoring_policy_ports(self): ports = self.driver. \ ex_get_monitoring_policy_ports('pol_1') self.assertNotEqual(ports, None) self.assertEqual(len(ports), 2) def test_ex_get_monitoring_policy_port(self): port = self.driver. \ ex_get_monitoring_policy_port('pol_1', 'port_1') self.assertNotEqual(port, None) def test_ex_remove_monitoring_policy_port(self): port = self.driver. \ ex_remove_monitoring_policy_port('pol_1', 'port_1') self.assertNotEqual(port, None) def test_ex_add_monitoring_policy_ports(self): new_ports = [ { "protocol": "TCP", "port": "80", "alert_if": "RESPONDING", "email_notification": True } ] ports = self.driver. \ ex_add_monitoring_policy_ports('pol_1', new_ports) self.assertNotEqual(ports, None) self.assertEqual(len(ports), 2) def test_ex_get_monitoring_policy_processes(self): processes = self.driver. \ ex_get_monitoring_policy_processes('pol_1') self.assertNotEqual(processes, None) def test_ex_get_monitoring_policy_process(self): process = self.driver. \ ex_get_monitoring_policy_process('pol_1', 'proc_1') self.assertNotEqual(process, None) def test_ex_remove_monitoring_policy_process(self): policy = self.driver. \ ex_remove_monitoring_policy_process('pol_1', 'proc_1') self.assertNotEqual(policy, None) def test_ex_add_monitoring_policy_processes(self): processes = { "processes": [ { "process": "taskmmgr", "alert_if": "RUNNING", "email_notification": True } ] } processes = self.driver. \ ex_add_monitoring_policy_processes(policy_id='pol_1', processes=processes) self.assertNotEqual(processes, None) self.assertEqual(len(processes), 2) def test_ex_list_monitoring_policy_servers(self): servers = self.driver.ex_list_monitoring_policy_servers('pol_1') self.assertNotEqual(servers, None) self.assertEqual(len(servers), 2) def test_ex_add_servers_to_monitoring_policy(self): servers = self.driver. \ ex_add_servers_to_monitoring_policy('pol_1', 'serv_1') self.assertNotEqual(servers, None) self.assertEqual(len(servers), 2) def test_ex_remove_server_from_monitoring_policy(self): policy = self.driver. \ ex_remove_server_from_monitoring_policy('pol_1', 'serv_1') self.assertNotEqual(policy, None) class OneAndOneMockHttp(MockHttp): fixtures = ComputeFileFixtures('oneandone') ''' Operation on Server Appliances GET - Fetches Server Appliances ''' def _v1_server_appliances(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_server_appliances_img_1(self, method, url, body, headers): body = self.fixtures.load('get_image.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_servers(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('list_servers.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == "POST": body = self.fixtures.load('create_node.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _v1_create_node(self, method, url, body_headers): body = self.fixtures.load('list_servers.json') return ( httplib.ACCEPTED, {}, body, httplib.responses[httplib.ACCEPTED] ) def _v1_datacenters( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_datacenters.json') return ( httplib.OK, body, {'content-type': 'application/json'}, httplib.responses[httplib.OK] ) def _v1_servers_srv_1( self, method, url, body, headers ): pass if method == 'PUT': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {'content-type': 'application/json'}, httplib.responses[httplib.OK] ) if method == 'GET': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {'content-type': 'application/json'}, httplib.responses[httplib.OK] ) if method == 'DELETE': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_servers_srv_1_status_action(self, method, url, body_headers, id): body = self.fixtures.load('describe_server.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _v1_servers_srv_1_hardware( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('server_hardware.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'PUT': body = self.fixtures.load('describe_server.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _v1_servers_srv_1_hardware_hdds( self, method, url, body, headers ): if method == 'POST': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'PUT': body = self.fixtures.load('describe_server.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _v1_servers_srv_1_hardware_hdds_hdd_id( self, method, url, body, headers ): if method == 'DELETE': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'PUT': body = self.fixtures.load('describe_server.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _v1_servers_srv_1_image( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('get_server_image.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'PUT': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_servers_srv_1_ips( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('server_ips.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'POST': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_servers_srv_1_ips_ip_id( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('server_ip.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'DELETE': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_firewall_policies( self, method, url, body, headers ): if method == 'POST': body = self.fixtures.load('describe_firewall_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'GET': body = self.fixtures.load('list_firewall_policies.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_firewall_policy_fw_id( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('describe_firewall_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'DELETE': body = self.fixtures.load('describe_firewall_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_servers_srv_id_ips_ip_id_firewall_policy( self, method, url, body, header ): if method == 'GET': body = self.fixtures.load('describe_id_firewall_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'DELETE': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'POST': body = self.fixtures.load('describe_server.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_shared_storages( self, method, url, body, header ): if method == 'GET' or method == 'POST': body = self.fixtures.load('list_shared_storages.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_shared_storages_storage_1( self, method, url, body, header ): if method == 'GET' or method == 'DELETE': body = self.fixtures.load('shared_storage.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_shared_storages_storage_1_servers( self, method, url, body, header ): if method == 'POST' or method == 'DELETE': body = self.fixtures.load('shared_storage.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_shared_storages_storage_1_servers_srv_1( self, method, url, body, header ): if method == 'GET' or method == 'DELETE': body = self.fixtures.load('shared_storage.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_load_balancers( self, method, url, body, header ): if method == 'POST': body = self.fixtures.load('load_balancer.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'GET': body = self.fixtures.load('list_load_balancer.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_load_balancers_lb_1( self, method, url, body, header ): body = self.fixtures.load('load_balancer.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_load_balancers_lb_1_server_ips( self, method, url, body, header ): if method == 'GET': body = self.fixtures.load('load_balancer_server_ips.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'POST': body = self.fixtures.load('load_balancer.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_load_balancers_lb_1_rules( self, method, url, body, header ): if method == 'POST': body = self.fixtures.load('load_balancer.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'GET': body = self.fixtures.load('load_balancer_rules.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_load_balancers_lb_1_server_ips_srv_1( self, method, url, body, header ): if method == 'DELETE': body = self.fixtures.load('load_balancer.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'GET': body = self.fixtures.load('load_balancer_server_ip.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_load_balancers_lb_1_rules_rule_1( self, method, url, body, header ): if method == 'DELETE': body = self.fixtures.load('load_balancer.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'GET': body = self.fixtures.load('load_balancer_rule.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_public_ips( self, method, url, body, header ): if method == 'GET': body = self.fixtures.load('list_public_ips.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'POST': body = self.fixtures.load('public_ip.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_public_ips_ip_1( self, method, url, body, header ): body = self.fixtures.load('public_ip.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies( self, method, url, body, header ): if method == 'POST': body = self.fixtures.load('monitoring_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if method == 'GET': body = self.fixtures.load('list_monitoring_policies.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies_pol_1( self, method, url, body, header ): body = self.fixtures.load('monitoring_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies_pol_1_ports( self, method, url, body, header ): body = self.fixtures.load('monitoring_policy_ports.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies_pol_1_ports_port_1( self, method, url, body, header ): if method == 'GET': body = self.fixtures.load('monitoring_policy_port.json') elif method == 'POST': body = self.fixtures.load('monitoring_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies_pol_1_processes( self, method, url, body, header ): body = self.fixtures.load('monitoring_policy_processes.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies_pol_1_processes_proc_1( self, method, url, body, header ): if method == 'GET': body = self.fixtures.load('monitoring_policy_process.json') elif method == 'POST': body = self.fixtures.load('monitoring_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies_pol_1_servers( self, method, url, body, header ): body = self.fixtures.load('monitoring_policy_servers.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_monitoring_policies_pol_1_servers_serv_1( self, method, url, body, header ): if method == 'GET': body = self.fixtures.load('monitoring_policy_servers.json') elif method == 'POST': body = self.fixtures.load('monitoring_policy.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _v1_servers_fixed_instance_sizes( self, method, url, body, header ): body = self.fixtures.load('fixed_instance_sizes.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_opennebula.py0000664000175000017500000013062013535474530024427 0ustar kamikami00000000000000# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad # Complutense de Madrid (dsa-research.org) # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ OpenNebula.org test suite. """ __docformat__ = 'epytext' import unittest import sys from libcloud.utils.py3 import httplib from libcloud.compute.base import Node, NodeImage, NodeSize, NodeState from libcloud.compute.drivers.opennebula import OpenNebulaNodeDriver from libcloud.compute.drivers.opennebula import OpenNebulaNetwork from libcloud.compute.drivers.opennebula import OpenNebulaNodeSize from libcloud.compute.drivers.opennebula import ACTION import libcloud.compute.drivers.opennebula from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test import MockHttp from libcloud.test.secrets import OPENNEBULA_PARAMS libcloud.compute.drivers.opennebula.API_HOST = 'dummy' class OpenNebula_1_4_Tests(unittest.TestCase): """ OpenNebula.org test suite for OpenNebula v1.4. """ def setUp(self): """ Setup test environment. """ OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_1_4_MockHttp self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('1.4',), host='dummy') def test_create_node(self): """ Test create_node functionality. """ image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) size = NodeSize(id=1, name='small', ram=None, disk=None, bandwidth=None, price=None, driver=self.driver) networks = list() networks.append(OpenNebulaNetwork(id=5, name='Network 5', address='192.168.0.0', size=256, driver=self.driver)) networks.append(OpenNebulaNetwork(id=15, name='Network 15', address='192.168.1.0', size=256, driver=self.driver)) node = self.driver.create_node(name='Compute 5', image=image, size=size, networks=networks) self.assertEqual(node.id, '5') self.assertEqual(node.name, 'Compute 5') self.assertEqual(node.state, OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) self.assertIsNone(node.public_ips[0].name) self.assertEqual(node.public_ips[0].id, '5') self.assertEqual(node.public_ips[0].address, '192.168.0.1') self.assertEqual(node.public_ips[0].size, 1) self.assertIsNone(node.public_ips[1].name) self.assertEqual(node.public_ips[1].id, '15') self.assertEqual(node.public_ips[1].address, '192.168.1.1') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.private_ips, []) self.assertEqual(node.image.id, '5') self.assertEqual(node.image.extra['dev'], 'sda1') def test_destroy_node(self): """ Test destroy_node functionality. """ node = Node(5, None, None, None, None, self.driver) ret = self.driver.destroy_node(node) self.assertTrue(ret) def test_list_nodes(self): """ Test list_nodes functionality. """ nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 3) node = nodes[0] self.assertEqual(node.id, '5') self.assertEqual(node.name, 'Compute 5') self.assertEqual(node.state, OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) self.assertEqual(node.public_ips[0].id, '5') self.assertIsNone(node.public_ips[0].name) self.assertEqual(node.public_ips[0].address, '192.168.0.1') self.assertEqual(node.public_ips[0].size, 1) self.assertEqual(node.public_ips[1].id, '15') self.assertIsNone(node.public_ips[1].name) self.assertEqual(node.public_ips[1].address, '192.168.1.1') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.private_ips, []) self.assertEqual(node.image.id, '5') self.assertEqual(node.image.extra['dev'], 'sda1') node = nodes[1] self.assertEqual(node.id, '15') self.assertEqual(node.name, 'Compute 15') self.assertEqual(node.state, OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) self.assertEqual(node.public_ips[0].id, '5') self.assertIsNone(node.public_ips[0].name) self.assertEqual(node.public_ips[0].address, '192.168.0.2') self.assertEqual(node.public_ips[0].size, 1) self.assertEqual(node.public_ips[1].id, '15') self.assertIsNone(node.public_ips[1].name) self.assertEqual(node.public_ips[1].address, '192.168.1.2') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.private_ips, []) self.assertEqual(node.image.id, '15') self.assertEqual(node.image.extra['dev'], 'sda1') node = nodes[2] self.assertEqual(node.id, '25') self.assertEqual(node.name, 'Compute 25') self.assertEqual(node.state, NodeState.UNKNOWN) self.assertEqual(node.public_ips[0].id, '5') self.assertIsNone(node.public_ips[0].name) self.assertEqual(node.public_ips[0].address, '192.168.0.3') self.assertEqual(node.public_ips[0].size, 1) self.assertEqual(node.public_ips[1].id, '15') self.assertIsNone(node.public_ips[1].name) self.assertEqual(node.public_ips[1].address, '192.168.1.3') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.private_ips, []) self.assertIsNone(node.image) def test_list_images(self): """ Test list_images functionality. """ images = self.driver.list_images() self.assertEqual(len(images), 2) image = images[0] self.assertEqual(image.id, '5') self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') self.assertEqual(image.extra['size'], '2048') self.assertEqual(image.extra['url'], 'file:///images/ubuntu/jaunty.img') image = images[1] self.assertEqual(image.id, '15') self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') self.assertEqual(image.extra['size'], '2048') self.assertEqual(image.extra['url'], 'file:///images/ubuntu/jaunty.img') def test_list_sizes(self): """ Test list_sizes functionality. """ sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 3) size = sizes[0] self.assertEqual(size.id, '1') self.assertEqual(size.name, 'small') self.assertIsNone(size.ram) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[1] self.assertEqual(size.id, '2') self.assertEqual(size.name, 'medium') self.assertIsNone(size.ram) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[2] self.assertEqual(size.id, '3') self.assertEqual(size.name, 'large') self.assertIsNone(size.ram) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) def test_list_locations(self): """ Test list_locations functionality. """ locations = self.driver.list_locations() self.assertEqual(len(locations), 1) location = locations[0] self.assertEqual(location.id, '0') self.assertEqual(location.name, '') self.assertEqual(location.country, '') def test_ex_list_networks(self): """ Test ex_list_networks functionality. """ networks = self.driver.ex_list_networks() self.assertEqual(len(networks), 2) network = networks[0] self.assertEqual(network.id, '5') self.assertEqual(network.name, 'Network 5') self.assertEqual(network.address, '192.168.0.0') self.assertEqual(network.size, '256') network = networks[1] self.assertEqual(network.id, '15') self.assertEqual(network.name, 'Network 15') self.assertEqual(network.address, '192.168.1.0') self.assertEqual(network.size, '256') def test_ex_node_action(self): """ Test ex_node_action functionality. """ node = Node(5, None, None, None, None, self.driver) ret = self.driver.ex_node_action(node, ACTION.STOP) self.assertTrue(ret) class OpenNebula_2_0_Tests(unittest.TestCase): """ OpenNebula.org test suite for OpenNebula v2.0 through v2.2. """ def setUp(self): """ Setup test environment. """ OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_2_0_MockHttp self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('2.0',), host='dummy') def test_create_node(self): """ Test create_node functionality. """ image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) size = OpenNebulaNodeSize(id=1, name='small', ram=1024, cpu=1, disk=None, bandwidth=None, price=None, driver=self.driver) networks = list() networks.append(OpenNebulaNetwork(id=5, name='Network 5', address='192.168.0.0', size=256, driver=self.driver)) networks.append(OpenNebulaNetwork(id=15, name='Network 15', address='192.168.1.0', size=256, driver=self.driver)) context = {'hostname': 'compute-5'} node = self.driver.create_node(name='Compute 5', image=image, size=size, networks=networks, context=context) self.assertEqual(node.id, '5') self.assertEqual(node.name, 'Compute 5') self.assertEqual(node.state, OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) self.assertEqual(node.public_ips[0].id, '5') self.assertEqual(node.public_ips[0].name, 'Network 5') self.assertEqual(node.public_ips[0].address, '192.168.0.1') self.assertEqual(node.public_ips[0].size, 1) self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:01') self.assertEqual(node.public_ips[1].id, '15') self.assertEqual(node.public_ips[1].name, 'Network 15') self.assertEqual(node.public_ips[1].address, '192.168.1.1') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:01') self.assertEqual(node.private_ips, []) self.assertTrue(len([s for s in self.driver.list_sizes() if s.id == node.size.id]) == 1) self.assertEqual(node.image.id, '5') self.assertEqual(node.image.name, 'Ubuntu 9.04 LAMP') self.assertEqual(node.image.extra['type'], 'DISK') self.assertEqual(node.image.extra['target'], 'hda') context = node.extra['context'] self.assertEqual(context['hostname'], 'compute-5') def test_destroy_node(self): """ Test destroy_node functionality. """ node = Node(5, None, None, None, None, self.driver) ret = self.driver.destroy_node(node) self.assertTrue(ret) def test_list_nodes(self): """ Test list_nodes functionality. """ nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 3) node = nodes[0] self.assertEqual(node.id, '5') self.assertEqual(node.name, 'Compute 5') self.assertEqual(node.state, OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) self.assertEqual(node.public_ips[0].id, '5') self.assertEqual(node.public_ips[0].name, 'Network 5') self.assertEqual(node.public_ips[0].address, '192.168.0.1') self.assertEqual(node.public_ips[0].size, 1) self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:01') self.assertEqual(node.public_ips[1].id, '15') self.assertEqual(node.public_ips[1].name, 'Network 15') self.assertEqual(node.public_ips[1].address, '192.168.1.1') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:01') self.assertEqual(node.private_ips, []) self.assertTrue(len([size for size in self.driver.list_sizes() if size.id == node.size.id]) == 1) self.assertEqual(node.size.id, '1') self.assertEqual(node.size.name, 'small') self.assertEqual(node.size.ram, 1024) self.assertTrue(node.size.cpu is None or isinstance(node.size.cpu, int)) self.assertTrue(node.size.vcpu is None or isinstance(node.size.vcpu, int)) self.assertEqual(node.size.cpu, 1) self.assertIsNone(node.size.vcpu) self.assertIsNone(node.size.disk) self.assertIsNone(node.size.bandwidth) self.assertIsNone(node.size.price) self.assertTrue(len([image for image in self.driver.list_images() if image.id == node.image.id]) == 1) self.assertEqual(node.image.id, '5') self.assertEqual(node.image.name, 'Ubuntu 9.04 LAMP') self.assertEqual(node.image.extra['type'], 'DISK') self.assertEqual(node.image.extra['target'], 'hda') context = node.extra['context'] self.assertEqual(context['hostname'], 'compute-5') node = nodes[1] self.assertEqual(node.id, '15') self.assertEqual(node.name, 'Compute 15') self.assertEqual(node.state, OpenNebulaNodeDriver.NODE_STATE_MAP['ACTIVE']) self.assertEqual(node.public_ips[0].id, '5') self.assertEqual(node.public_ips[0].name, 'Network 5') self.assertEqual(node.public_ips[0].address, '192.168.0.2') self.assertEqual(node.public_ips[0].size, 1) self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:02') self.assertEqual(node.public_ips[1].id, '15') self.assertEqual(node.public_ips[1].name, 'Network 15') self.assertEqual(node.public_ips[1].address, '192.168.1.2') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:02') self.assertEqual(node.private_ips, []) self.assertTrue(len([size for size in self.driver.list_sizes() if size.id == node.size.id]) == 1) self.assertEqual(node.size.id, '1') self.assertEqual(node.size.name, 'small') self.assertEqual(node.size.ram, 1024) self.assertTrue(node.size.cpu is None or isinstance(node.size.cpu, int)) self.assertTrue(node.size.vcpu is None or isinstance(node.size.vcpu, int)) self.assertEqual(node.size.cpu, 1) self.assertIsNone(node.size.vcpu) self.assertIsNone(node.size.disk) self.assertIsNone(node.size.bandwidth) self.assertIsNone(node.size.price) self.assertTrue(len([image for image in self.driver.list_images() if image.id == node.image.id]) == 1) self.assertEqual(node.image.id, '15') self.assertEqual(node.image.name, 'Ubuntu 9.04 LAMP') self.assertEqual(node.image.extra['type'], 'DISK') self.assertEqual(node.image.extra['target'], 'hda') context = node.extra['context'] self.assertEqual(context['hostname'], 'compute-15') node = nodes[2] self.assertEqual(node.id, '25') self.assertEqual(node.name, 'Compute 25') self.assertEqual(node.state, NodeState.UNKNOWN) self.assertEqual(node.public_ips[0].id, '5') self.assertEqual(node.public_ips[0].name, 'Network 5') self.assertEqual(node.public_ips[0].address, '192.168.0.3') self.assertEqual(node.public_ips[0].size, 1) self.assertEqual(node.public_ips[0].extra['mac'], '02:00:c0:a8:00:03') self.assertEqual(node.public_ips[1].id, '15') self.assertEqual(node.public_ips[1].name, 'Network 15') self.assertEqual(node.public_ips[1].address, '192.168.1.3') self.assertEqual(node.public_ips[1].size, 1) self.assertEqual(node.public_ips[1].extra['mac'], '02:00:c0:a8:01:03') self.assertEqual(node.private_ips, []) self.assertIsNone(node.size) self.assertIsNone(node.image) context = node.extra['context'] self.assertEqual(context, {}) def test_list_images(self): """ Test list_images functionality. """ images = self.driver.list_images() self.assertEqual(len(images), 2) image = images[0] self.assertEqual(image.id, '5') self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') self.assertEqual(image.extra['description'], 'Ubuntu 9.04 LAMP Description') self.assertEqual(image.extra['type'], 'OS') self.assertEqual(image.extra['size'], '2048') image = images[1] self.assertEqual(image.id, '15') self.assertEqual(image.name, 'Ubuntu 9.04 LAMP') self.assertEqual(image.extra['description'], 'Ubuntu 9.04 LAMP Description') self.assertEqual(image.extra['type'], 'OS') self.assertEqual(image.extra['size'], '2048') def test_list_sizes(self): """ Test list_sizes functionality. """ sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 4) size = sizes[0] self.assertEqual(size.id, '1') self.assertEqual(size.name, 'small') self.assertEqual(size.ram, 1024) self.assertTrue(size.cpu is None or isinstance(size.cpu, int)) self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) self.assertEqual(size.cpu, 1) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[1] self.assertEqual(size.id, '2') self.assertEqual(size.name, 'medium') self.assertEqual(size.ram, 4096) self.assertTrue(size.cpu is None or isinstance(size.cpu, int)) self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) self.assertEqual(size.cpu, 4) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[2] self.assertEqual(size.id, '3') self.assertEqual(size.name, 'large') self.assertEqual(size.ram, 8192) self.assertTrue(size.cpu is None or isinstance(size.cpu, int)) self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) self.assertEqual(size.cpu, 8) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[3] self.assertEqual(size.id, '4') self.assertEqual(size.name, 'custom') self.assertEqual(size.ram, 0) self.assertEqual(size.cpu, 0) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) def test_list_locations(self): """ Test list_locations functionality. """ locations = self.driver.list_locations() self.assertEqual(len(locations), 1) location = locations[0] self.assertEqual(location.id, '0') self.assertEqual(location.name, '') self.assertEqual(location.country, '') def test_ex_list_networks(self): """ Test ex_list_networks functionality. """ networks = self.driver.ex_list_networks() self.assertEqual(len(networks), 2) network = networks[0] self.assertEqual(network.id, '5') self.assertEqual(network.name, 'Network 5') self.assertEqual(network.address, '192.168.0.0') self.assertEqual(network.size, '256') network = networks[1] self.assertEqual(network.id, '15') self.assertEqual(network.name, 'Network 15') self.assertEqual(network.address, '192.168.1.0') self.assertEqual(network.size, '256') class OpenNebula_3_0_Tests(unittest.TestCase): """ OpenNebula.org test suite for OpenNebula v3.0. """ def setUp(self): """ Setup test environment. """ OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_0_MockHttp self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.0',), host='dummy') def test_ex_list_networks(self): """ Test ex_list_networks functionality. """ networks = self.driver.ex_list_networks() self.assertEqual(len(networks), 2) network = networks[0] self.assertEqual(network.id, '5') self.assertEqual(network.name, 'Network 5') self.assertEqual(network.address, '192.168.0.0') self.assertEqual(network.size, '256') self.assertEqual(network.extra['public'], 'YES') network = networks[1] self.assertEqual(network.id, '15') self.assertEqual(network.name, 'Network 15') self.assertEqual(network.address, '192.168.1.0') self.assertEqual(network.size, '256') self.assertEqual(network.extra['public'], 'NO') def test_ex_node_set_save_name(self): """ Test ex_node_action functionality. """ image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) node = Node(5, None, None, None, None, self.driver, image=image) ret = self.driver.ex_node_set_save_name(node, 'test') self.assertTrue(ret) class OpenNebula_3_2_Tests(unittest.TestCase): """ OpenNebula.org test suite for OpenNebula v3.2. """ def setUp(self): """ Setup test environment. """ OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_2_MockHttp self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.2',), host='dummy') def test_reboot_node(self): """ Test reboot_node functionality. """ image = NodeImage(id=5, name='Ubuntu 9.04 LAMP', driver=self.driver) node = Node(5, None, None, None, None, self.driver, image=image) ret = self.driver.reboot_node(node) self.assertTrue(ret) def test_list_sizes(self): """ Test ex_list_networks functionality. """ sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 3) size = sizes[0] self.assertEqual(size.id, '1') self.assertEqual(size.name, 'small') self.assertEqual(size.ram, 1024) self.assertTrue(size.cpu is None or isinstance(size.cpu, float)) self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) self.assertEqual(size.cpu, 1) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[1] self.assertEqual(size.id, '2') self.assertEqual(size.name, 'medium') self.assertEqual(size.ram, 4096) self.assertTrue(size.cpu is None or isinstance(size.cpu, float)) self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) self.assertEqual(size.cpu, 4) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[2] self.assertEqual(size.id, '3') self.assertEqual(size.name, 'large') self.assertEqual(size.ram, 8192) self.assertTrue(size.cpu is None or isinstance(size.cpu, float)) self.assertTrue(size.vcpu is None or isinstance(size.vcpu, int)) self.assertEqual(size.cpu, 8) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) class OpenNebula_3_6_Tests(unittest.TestCase): """ OpenNebula.org test suite for OpenNebula v3.6. """ def setUp(self): """ Setup test environment. """ OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_6_MockHttp self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.6',), host='dummy') def test_create_volume(self): new_volume = self.driver.create_volume(1000, 'test-volume') self.assertEqual(new_volume.id, '5') self.assertEqual(new_volume.size, 1000) self.assertEqual(new_volume.name, 'test-volume') def test_destroy_volume(self): images = self.driver.list_images() self.assertEqual(len(images), 2) image = images[0] ret = self.driver.destroy_volume(image) self.assertTrue(ret) def test_attach_volume(self): nodes = self.driver.list_nodes() node = nodes[0] images = self.driver.list_images() image = images[0] ret = self.driver.attach_volume(node, image, 'sda') self.assertTrue(ret) def test_detach_volume(self): images = self.driver.list_images() image = images[1] ret = self.driver.detach_volume(image) self.assertTrue(ret) nodes = self.driver.list_nodes() # node with only a single associated image node = nodes[1] ret = self.driver.detach_volume(node.image) self.assertFalse(ret) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 2) volume = volumes[0] self.assertEqual(volume.id, '5') self.assertEqual(volume.size, 2048) self.assertEqual(volume.name, 'Ubuntu 9.04 LAMP') volume = volumes[1] self.assertEqual(volume.id, '15') self.assertEqual(volume.size, 1024) self.assertEqual(volume.name, 'Debian Sid') class OpenNebula_3_8_Tests(unittest.TestCase): """ OpenNebula.org test suite for OpenNebula v3.8. """ def setUp(self): """ Setup test environment. """ OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_8_MockHttp self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.8',), host='dummy') def test_list_sizes(self): """ Test ex_list_networks functionality. """ sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 3) size = sizes[0] self.assertEqual(size.id, '1') self.assertEqual(size.name, 'small') self.assertEqual(size.ram, 1024) self.assertEqual(size.cpu, 1) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[1] self.assertEqual(size.id, '2') self.assertEqual(size.name, 'medium') self.assertEqual(size.ram, 4096) self.assertEqual(size.cpu, 4) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) size = sizes[2] self.assertEqual(size.id, '3') self.assertEqual(size.name, 'large') self.assertEqual(size.ram, 8192) self.assertEqual(size.cpu, 8) self.assertIsNone(size.vcpu) self.assertIsNone(size.disk) self.assertIsNone(size.bandwidth) self.assertIsNone(size.price) class OpenNebula_1_4_MockHttp(MockHttp): """ Mock HTTP server for testing v1.4 of the OpenNebula.org compute driver. """ fixtures = ComputeFileFixtures('opennebula_1_4') def _compute(self, method, url, body, headers): """ Compute pool resources. """ if method == 'GET': body = self.fixtures.load('computes.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('compute_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _storage(self, method, url, body, headers): """ Storage pool resources. """ if method == 'GET': body = self.fixtures.load('storage.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('disk_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _network(self, method, url, body, headers): """ Network pool resources. """ if method == 'GET': body = self.fixtures.load('networks.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('network_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _compute_5(self, method, url, body, headers): """ Compute entry resource. """ if method == 'GET': body = self.fixtures.load('compute_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _compute_15(self, method, url, body, headers): """ Compute entry resource. """ if method == 'GET': body = self.fixtures.load('compute_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _compute_25(self, method, url, body, headers): """ Compute entry resource. """ if method == 'GET': body = self.fixtures.load('compute_25.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _storage_5(self, method, url, body, headers): """ Storage entry resource. """ if method == 'GET': body = self.fixtures.load('disk_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _storage_15(self, method, url, body, headers): """ Storage entry resource. """ if method == 'GET': body = self.fixtures.load('disk_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _network_5(self, method, url, body, headers): """ Network entry resource. """ if method == 'GET': body = self.fixtures.load('network_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _network_15(self, method, url, body, headers): """ Network entry resource. """ if method == 'GET': body = self.fixtures.load('network_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class OpenNebula_2_0_MockHttp(MockHttp): """ Mock HTTP server for testing v2.0 through v3.2 of the OpenNebula.org compute driver. """ fixtures = ComputeFileFixtures('opennebula_2_0') def _compute(self, method, url, body, headers): """ Compute pool resources. """ if method == 'GET': body = self.fixtures.load('compute_collection.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('compute_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _storage(self, method, url, body, headers): """ Storage pool resources. """ if method == 'GET': body = self.fixtures.load('storage_collection.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('storage_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _network(self, method, url, body, headers): """ Network pool resources. """ if method == 'GET': body = self.fixtures.load('network_collection.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('network_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _compute_5(self, method, url, body, headers): """ Compute entry resource. """ if method == 'GET': body = self.fixtures.load('compute_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _compute_15(self, method, url, body, headers): """ Compute entry resource. """ if method == 'GET': body = self.fixtures.load('compute_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _compute_25(self, method, url, body, headers): """ Compute entry resource. """ if method == 'GET': body = self.fixtures.load('compute_25.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _storage_5(self, method, url, body, headers): """ Storage entry resource. """ if method == 'GET': body = self.fixtures.load('storage_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _storage_15(self, method, url, body, headers): """ Storage entry resource. """ if method == 'GET': body = self.fixtures.load('storage_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _network_5(self, method, url, body, headers): """ Network entry resource. """ if method == 'GET': body = self.fixtures.load('network_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _network_15(self, method, url, body, headers): """ Network entry resource. """ if method == 'GET': body = self.fixtures.load('network_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) class OpenNebula_3_0_MockHttp(OpenNebula_2_0_MockHttp): """ Mock HTTP server for testing v3.0 of the OpenNebula.org compute driver. """ fixtures_3_0 = ComputeFileFixtures('opennebula_3_0') def _network(self, method, url, body, headers): """ Network pool resources. """ if method == 'GET': body = self.fixtures_3_0.load('network_collection.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('network_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _network_5(self, method, url, body, headers): """ Network entry resource. """ if method == 'GET': body = self.fixtures_3_0.load('network_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _network_15(self, method, url, body, headers): """ Network entry resource. """ if method == 'GET': body = self.fixtures_3_0.load('network_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) class OpenNebula_3_2_MockHttp(OpenNebula_3_0_MockHttp): """ Mock HTTP server for testing v3.2 of the OpenNebula.org compute driver. """ fixtures_3_2 = ComputeFileFixtures('opennebula_3_2') def _compute_5(self, method, url, body, headers): """ Compute entry resource. """ if method == 'GET': body = self.fixtures.load('compute_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _instance_type(self, method, url, body, headers): """ Instance type pool. """ if method == 'GET': body = self.fixtures_3_2.load('instance_type_collection.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class OpenNebula_3_6_MockHttp(OpenNebula_3_2_MockHttp): """ Mock HTTP server for testing v3.6 of the OpenNebula.org compute driver. """ fixtures_3_6 = ComputeFileFixtures('opennebula_3_6') def _storage(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('storage_collection.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures_3_6.load('storage_5.xml') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _compute_5(self, method, url, body, headers): if method == 'GET': body = self.fixtures_3_6.load('compute_5.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _compute_5_action(self, method, url, body, headers): body = self.fixtures_3_6.load('compute_5.xml') if method == 'POST': return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'GET': return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _compute_15(self, method, url, body, headers): if method == 'GET': body = self.fixtures_3_6.load('compute_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'PUT': body = "" return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) if method == 'DELETE': body = "" return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _storage_10(self, method, url, body, headers): """ Storage entry resource. """ if method == 'GET': body = self.fixtures_3_6.load('disk_10.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _storage_15(self, method, url, body, headers): """ Storage entry resource. """ if method == 'GET': body = self.fixtures_3_6.load('disk_15.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class OpenNebula_3_8_MockHttp(OpenNebula_3_2_MockHttp): """ Mock HTTP server for testing v3.8 of the OpenNebula.org compute driver. """ fixtures_3_8 = ComputeFileFixtures('opennebula_3_8') def _instance_type(self, method, url, body, headers): """ Instance type pool. """ if method == 'GET': body = self.fixtures_3_8.load('instance_type_collection.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _instance_type_small(self, method, url, body, headers): """ Small instance type. """ if method == 'GET': body = self.fixtures_3_8.load('instance_type_small.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _instance_type_medium(self, method, url, body, headers): """ Medium instance type pool. """ if method == 'GET': body = self.fixtures_3_8.load('instance_type_medium.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _instance_type_large(self, method, url, body, headers): """ Large instance type pool. """ if method == 'GET': body = self.fixtures_3_8.load('instance_type_large.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_openstack.py0000664000175000017500000036173013577507766024314 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import os import sys import unittest import datetime import mock import pytest from libcloud.utils.iso8601 import UTC try: import simplejson as json except ImportError: import json from mock import Mock, patch import requests_mock from libcloud.utils.py3 import httplib from libcloud.utils.py3 import method_type from libcloud.utils.py3 import u from libcloud.common.base import LibcloudConnection from libcloud.common.types import InvalidCredsError, MalformedResponseError, \ LibcloudError from libcloud.compute.types import Provider, KeyPairDoesNotExistError, StorageVolumeState, \ VolumeSnapshotState, NodeImageMemberState from libcloud.compute.providers import get_driver from libcloud.compute.drivers.openstack import ( OpenStack_1_0_NodeDriver, OpenStack_1_1_NodeDriver, OpenStackSecurityGroup, OpenStackSecurityGroupRule, OpenStack_1_1_FloatingIpPool, OpenStack_1_1_FloatingIpAddress, OpenStackKeyPair, OpenStack_1_0_Connection, OpenStack_2_FloatingIpPool, OpenStackNodeDriver, OpenStack_2_NodeDriver, OpenStack_2_PortInterfaceState, OpenStackNetwork, OpenStackException) from libcloud.compute.base import Node, NodeImage, NodeSize from libcloud.pricing import set_pricing, clear_pricing_data from libcloud.test import MockHttp, XML_HEADERS from libcloud.test.file_fixtures import ComputeFileFixtures, OpenStackFixtures from libcloud.test.compute import TestCaseMixin from libcloud.test.secrets import OPENSTACK_PARAMS BASE_DIR = os.path.abspath(os.path.split(__file__)[0]) def test_driver_instantiation_invalid_auth(): with pytest.raises(LibcloudError): d = OpenStackNodeDriver( 'user', 'correct_password', ex_force_auth_version='5.0', ex_force_auth_url='http://x.y.z.y:5000', ex_tenant_name='admin') d.list_nodes() class OpenStackAuthTests(unittest.TestCase): def setUp(self): OpenStack_1_0_NodeDriver.connectionCls = OpenStack_1_0_Connection OpenStack_1_0_NodeDriver.connectionCls.conn_class = LibcloudConnection def test_auth_host_passed(self): forced_auth = 'http://x.y.z.y:5000' d = OpenStack_1_0_NodeDriver( 'user', 'correct_password', ex_force_auth_version='2.0_password', ex_force_auth_url='http://x.y.z.y:5000', ex_tenant_name='admin') self.assertEqual(d._ex_force_auth_url, forced_auth) with requests_mock.Mocker() as mock: body2 = ComputeFileFixtures('openstack').load('_v2_0__auth.json') mock.register_uri('POST', 'http://x.y.z.y:5000/v2.0/tokens', text=body2, headers={'content-type': 'application/json; charset=UTF-8'}) d.connection._populate_hosts_and_request_paths() self.assertEqual(d.connection.host, 'test_endpoint.com') class OpenStack_1_0_Tests(TestCaseMixin, unittest.TestCase): should_list_locations = False should_list_volumes = False driver_klass = OpenStack_1_0_NodeDriver driver_args = OPENSTACK_PARAMS driver_kwargs = {} # driver_kwargs = {'ex_force_auth_version': '1.0'} @classmethod def create_driver(self): if self is not OpenStack_1_0_FactoryMethodTests: self.driver_type = self.driver_klass return self.driver_type(*self.driver_args, **self.driver_kwargs) def setUp(self): # monkeypatch get_endpoint because the base openstack driver doesn't actually # work with old devstack but this class/tests are still used by the rackspace # driver def get_endpoint(*args, **kwargs): return "https://servers.api.rackspacecloud.com/v1.0/slug" self.driver_klass.connectionCls.get_endpoint = get_endpoint self.driver_klass.connectionCls.conn_class = OpenStackMockHttp self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" OpenStackMockHttp.type = None self.driver = self.create_driver() # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() clear_pricing_data() @patch('libcloud.common.openstack.OpenStackServiceCatalog') def test_populate_hosts_and_requests_path(self, _): tomorrow = datetime.datetime.today() + datetime.timedelta(1) cls = self.driver_klass.connectionCls count = 5 # Test authentication and token re-use con = cls('username', 'key') osa = con.get_auth_class() mocked_auth_method = Mock() osa.authenticate = mocked_auth_method # Valid token returned on first call, should be reused. for i in range(0, count): con._populate_hosts_and_request_paths() if i == 0: osa.auth_token = '1234' osa.auth_token_expires = tomorrow self.assertEqual(mocked_auth_method.call_count, 1) osa.auth_token = None osa.auth_token_expires = None # ex_force_auth_token provided, authenticate should never be called con = cls('username', 'key', ex_force_base_url='http://ponies', ex_force_auth_token='1234') osa = con.get_auth_class() mocked_auth_method = Mock() osa.authenticate = mocked_auth_method for i in range(0, count): con._populate_hosts_and_request_paths() self.assertEqual(mocked_auth_method.call_count, 0) def test_auth_token_is_set(self): self.driver.connection._populate_hosts_and_request_paths() self.assertEqual( self.driver.connection.auth_token, "aaaaaaaaaaaa-bbb-cccccccccccccc") def test_auth_token_expires_is_set(self): self.driver.connection._populate_hosts_and_request_paths() expires = self.driver.connection.auth_token_expires self.assertEqual(expires.isoformat(), "2999-11-23T21:00:14-06:00") def test_auth(self): if self.driver.connection._auth_version == '2.0': return OpenStackMockHttp.type = 'UNAUTHORIZED' try: self.driver = self.create_driver() self.driver.list_nodes() except InvalidCredsError as e: self.assertEqual(True, isinstance(e, InvalidCredsError)) else: self.fail('test should have thrown') def test_auth_missing_key(self): if self.driver.connection._auth_version == '2.0': return OpenStackMockHttp.type = 'UNAUTHORIZED_MISSING_KEY' try: self.driver = self.create_driver() self.driver.list_nodes() except MalformedResponseError as e: self.assertEqual(True, isinstance(e, MalformedResponseError)) else: self.fail('test should have thrown') def test_auth_server_error(self): if self.driver.connection._auth_version == '2.0': return OpenStackMockHttp.type = 'INTERNAL_SERVER_ERROR' try: self.driver = self.create_driver() self.driver.list_nodes() except MalformedResponseError as e: self.assertEqual(True, isinstance(e, MalformedResponseError)) else: self.fail('test should have thrown') def test_error_parsing_when_body_is_missing_message(self): OpenStackMockHttp.type = 'NO_MESSAGE_IN_ERROR_BODY' try: self.driver.list_images() except Exception as e: self.assertEqual(True, isinstance(e, Exception)) else: self.fail('test should have thrown') def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(len(locations), 1) def test_list_nodes(self): OpenStackMockHttp.type = 'EMPTY' ret = self.driver.list_nodes() self.assertEqual(len(ret), 0) OpenStackMockHttp.type = None ret = self.driver.list_nodes() self.assertEqual(len(ret), 1) node = ret[0] self.assertEqual('67.23.21.33', node.public_ips[0]) self.assertTrue('10.176.168.218' in node.private_ips) self.assertEqual(node.extra.get('flavorId'), '1') self.assertEqual(node.extra.get('imageId'), '11') self.assertEqual(type(node.extra.get('metadata')), type(dict())) OpenStackMockHttp.type = 'METADATA' ret = self.driver.list_nodes() self.assertEqual(len(ret), 1) node = ret[0] self.assertEqual(type(node.extra.get('metadata')), type(dict())) self.assertEqual(node.extra.get('metadata').get('somekey'), 'somevalue') OpenStackMockHttp.type = None def test_list_images(self): ret = self.driver.list_images() expected = {10: {'serverId': None, 'status': 'ACTIVE', 'created': '2009-07-20T09:14:37-05:00', 'updated': '2009-07-20T09:14:37-05:00', 'progress': None, 'minDisk': None, 'minRam': None}, 11: {'serverId': '91221', 'status': 'ACTIVE', 'created': '2009-11-29T20:22:09-06:00', 'updated': '2009-11-29T20:24:08-06:00', 'progress': '100', 'minDisk': '5', 'minRam': '256'}} for ret_idx, extra in list(expected.items()): for key, value in list(extra.items()): self.assertEqual(ret[ret_idx].extra[key], value) def test_create_node(self): image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size) self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra.get('password'), 'racktestvJq7d3') def test_create_node_without_adminPass(self): OpenStackMockHttp.type = 'NO_ADMIN_PASS' image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size) self.assertEqual(node.name, 'racktest') self.assertIsNone(node.extra.get('password')) def test_create_node_ex_shared_ip_group(self): OpenStackMockHttp.type = 'EX_SHARED_IP_GROUP' image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size, ex_shared_ip_group_id='12345') self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra.get('password'), 'racktestvJq7d3') def test_create_node_with_metadata(self): OpenStackMockHttp.type = 'METADATA' image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) metadata = {'a': 'b', 'c': 'd'} files = {'/file1': 'content1', '/file2': 'content2'} node = self.driver.create_node(name='racktest', image=image, size=size, ex_metadata=metadata, ex_files=files) self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra.get('password'), 'racktestvJq7d3') self.assertEqual(node.extra.get('metadata'), metadata) def test_reboot_node(self): node = Node(id=72258, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = node.reboot() self.assertTrue(ret is True) def test_destroy_node(self): node = Node(id=72258, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ret = node.destroy() self.assertTrue(ret is True) def test_ex_limits(self): limits = self.driver.ex_limits() self.assertTrue("rate" in limits) self.assertTrue("absolute" in limits) def test_create_image(self): node = Node(id=444222, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) image = self.driver.create_image(node, "imgtest") self.assertEqual(image.name, "imgtest") self.assertEqual(image.id, "12345") def test_delete_image(self): image = NodeImage(id=333111, name='Ubuntu 8.10 (intrepid)', driver=self.driver) ret = self.driver.delete_image(image) self.assertTrue(ret) def test_ex_list_ip_addresses(self): ret = self.driver.ex_list_ip_addresses(node_id=72258) self.assertEqual(2, len(ret.public_addresses)) self.assertTrue('67.23.10.131' in ret.public_addresses) self.assertTrue('67.23.10.132' in ret.public_addresses) self.assertEqual(1, len(ret.private_addresses)) self.assertTrue('10.176.42.16' in ret.private_addresses) def test_ex_list_ip_groups(self): ret = self.driver.ex_list_ip_groups() self.assertEqual(2, len(ret)) self.assertEqual('1234', ret[0].id) self.assertEqual('Shared IP Group 1', ret[0].name) self.assertEqual('5678', ret[1].id) self.assertEqual('Shared IP Group 2', ret[1].name) self.assertTrue(ret[0].servers is None) def test_ex_list_ip_groups_detail(self): ret = self.driver.ex_list_ip_groups(details=True) self.assertEqual(2, len(ret)) self.assertEqual('1234', ret[0].id) self.assertEqual('Shared IP Group 1', ret[0].name) self.assertEqual(2, len(ret[0].servers)) self.assertEqual('422', ret[0].servers[0]) self.assertEqual('3445', ret[0].servers[1]) self.assertEqual('5678', ret[1].id) self.assertEqual('Shared IP Group 2', ret[1].name) self.assertEqual(3, len(ret[1].servers)) self.assertEqual('23203', ret[1].servers[0]) self.assertEqual('2456', ret[1].servers[1]) self.assertEqual('9891', ret[1].servers[2]) def test_ex_create_ip_group(self): ret = self.driver.ex_create_ip_group('Shared IP Group 1', '5467') self.assertEqual('1234', ret.id) self.assertEqual('Shared IP Group 1', ret.name) self.assertEqual(1, len(ret.servers)) self.assertEqual('422', ret.servers[0]) def test_ex_delete_ip_group(self): ret = self.driver.ex_delete_ip_group('5467') self.assertEqual(True, ret) def test_ex_share_ip(self): ret = self.driver.ex_share_ip('1234', '3445', '67.23.21.133') self.assertEqual(True, ret) def test_ex_unshare_ip(self): ret = self.driver.ex_unshare_ip('3445', '67.23.21.133') self.assertEqual(True, ret) def test_ex_resize(self): node = Node(id=444222, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) self.assertTrue(self.driver.ex_resize(node=node, size=size)) def test_ex_confirm_resize(self): node = Node(id=444222, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) self.assertTrue(self.driver.ex_confirm_resize(node=node)) def test_ex_revert_resize(self): node = Node(id=444222, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) self.assertTrue(self.driver.ex_revert_resize(node=node)) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 7, 'Wrong sizes count') for size in sizes: self.assertTrue(isinstance(size.price, float), 'Wrong size price type') if self.driver.api_name == 'openstack': self.assertEqual(size.price, 0, 'Size price should be zero by default') def test_list_sizes_with_specified_pricing(self): if self.driver.api_name != 'openstack': return pricing = dict((str(i), i) for i in range(1, 8)) set_pricing(driver_type='compute', driver_name='openstack', pricing=pricing) sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 7, 'Wrong sizes count') for size in sizes: self.assertTrue(isinstance(size.price, float), 'Wrong size price type') self.assertEqual(float(size.price), float(pricing[size.id])) class OpenStack_1_0_FactoryMethodTests(OpenStack_1_0_Tests): should_list_locations = False should_list_volumes = False driver_klass = OpenStack_1_0_NodeDriver driver_type = get_driver(Provider.OPENSTACK) driver_args = OPENSTACK_PARAMS + ('1.0',) def test_factory_method_invalid_version(self): try: self.driver_type(*(OPENSTACK_PARAMS + ('15.5',))) except NotImplementedError: pass else: self.fail('Exception was not thrown') class OpenStackMockHttp(MockHttp, unittest.TestCase): fixtures = ComputeFileFixtures('openstack') auth_fixtures = OpenStackFixtures() json_content_headers = {'content-type': 'application/json; charset=UTF-8'} # fake auth token response def _v1_0(self, method, url, body, headers): headers = { 'x-server-management-url': 'https://servers.api.rackspacecloud.com/v1.0/slug', 'x-auth-token': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', 'x-cdn-management-url': 'https://cdn.clouddrive.com/v1/MossoCloudFS_FE011C19-CF86-4F87-BE5D-9229145D7A06', 'x-storage-token': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', 'x-storage-url': 'https://storage4.clouddrive.com/v1/MossoCloudFS_FE011C19-CF86-4F87-BE5D-9229145D7A06'} return (httplib.NO_CONTENT, "", headers, httplib.responses[httplib.NO_CONTENT]) def _v1_0_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _v1_0_INTERNAL_SERVER_ERROR(self, method, url, body, headers): return (httplib.INTERNAL_SERVER_ERROR, "

500: Internal Server Error

", {}, httplib.responses[httplib.INTERNAL_SERVER_ERROR]) def _v1_0_slug_images_detail_NO_MESSAGE_IN_ERROR_BODY(self, method, url, body, headers): body = self.fixtures.load('300_multiple_choices.json') return (httplib.MULTIPLE_CHOICES, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_0_UNAUTHORIZED_MISSING_KEY(self, method, url, body, headers): headers = { 'x-server-management-url': 'https://servers.api.rackspacecloud.com/v1.0/slug', 'x-auth-tokenx': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', 'x-cdn-management-url': 'https://cdn.clouddrive.com/v1/MossoCloudFS_FE011C19-CF86-4F87-BE5D-9229145D7A06'} return (httplib.NO_CONTENT, "", headers, httplib.responses[httplib.NO_CONTENT]) def _v2_0_tokens(self, method, url, body, headers): body = self.auth_fixtures.load('_v2_0__auth.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_EMPTY(self, method, url, body, headers): body = self.fixtures.load('v1_slug_servers_detail_empty.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail(self, method, url, body, headers): body = self.fixtures.load('v1_slug_servers_detail.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers_detail_METADATA(self, method, url, body, headers): body = self.fixtures.load('v1_slug_servers_detail_metadata.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_images_333111(self, method, url, body, headers): if method != "DELETE": raise NotImplementedError() # this is currently used for deletion of an image # as such it should not accept GET/POST return(httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) def _v1_0_slug_images(self, method, url, body, headers): if method != "POST": raise NotImplementedError() # this is currently used for creation of new image with # POST request, don't handle GET to avoid possible confusion body = self.fixtures.load('v1_slug_images_post.xml') return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) def _v1_0_slug_images_detail(self, method, url, body, headers): body = self.fixtures.load('v1_slug_images_detail.xml') return (httplib.OK, body, XML_HEADERS, httplib.responses[httplib.OK]) def _v1_0_slug_servers(self, method, url, body, headers): body = self.fixtures.load('v1_slug_servers.xml') return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) def _v1_0_slug_servers_NO_ADMIN_PASS(self, method, url, body, headers): body = self.fixtures.load('v1_slug_servers_no_admin_pass.xml') return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) def _v1_0_slug_servers_EX_SHARED_IP_GROUP(self, method, url, body, headers): # test_create_node_ex_shared_ip_group # Verify that the body contains sharedIpGroupId XML element body = u(body) self.assertTrue(body.find('sharedIpGroupId="12345"') != -1) body = self.fixtures.load('v1_slug_servers.xml') return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) def _v1_0_slug_servers_METADATA(self, method, url, body, headers): body = self.fixtures.load('v1_slug_servers_metadata.xml') return (httplib.ACCEPTED, body, XML_HEADERS, httplib.responses[httplib.ACCEPTED]) def _v1_0_slug_servers_72258_action(self, method, url, body, headers): if method != "POST" or body[:8] != "500: Internal Server Error", {'content-type': 'text/html'}, httplib.responses[httplib.INTERNAL_SERVER_ERROR]) class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin): should_list_locations = False should_list_volumes = True driver_klass = OpenStack_1_1_NodeDriver driver_type = OpenStack_1_1_NodeDriver driver_args = OPENSTACK_PARAMS driver_kwargs = {'ex_force_auth_version': '2.0'} @classmethod def create_driver(self): if self is not OpenStack_1_1_FactoryMethodTests: self.driver_type = self.driver_klass return self.driver_type(*self.driver_args, **self.driver_kwargs) def setUp(self): self.driver_klass.connectionCls.conn_class = OpenStack_2_0_MockHttp self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" OpenStackMockHttp.type = None OpenStack_1_1_MockHttp.type = None OpenStack_2_0_MockHttp.type = None self.driver = self.create_driver() # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() clear_pricing_data() self.node = self.driver.list_nodes()[1] def _force_reauthentication(self): """ Trash current auth token so driver will be forced to re-authentication on next request. """ self.driver.connection._ex_force_base_url = 'http://ex_force_base_url.com:666/forced_url' self.driver.connection.auth_token = None self.driver.connection.auth_token_expires = None self.driver.connection._osa.auth_token = None self.driver.connection._osa.auth_token_expires = None def test_auth_token_is_set(self): self._force_reauthentication() self.driver.connection._populate_hosts_and_request_paths() self.assertEqual( self.driver.connection.auth_token, "aaaaaaaaaaaa-bbb-cccccccccccccc") def test_auth_token_expires_is_set(self): self._force_reauthentication() self.driver.connection._populate_hosts_and_request_paths() expires = self.driver.connection.auth_token_expires self.assertEqual(expires.isoformat(), "2999-11-23T21:00:14-06:00") def test_ex_force_base_url(self): # change base url and trash the current auth token so we can # re-authenticate self.driver.connection._ex_force_base_url = 'http://ex_force_base_url.com:666/forced_url' self.driver.connection.auth_token = None self.driver.connection._populate_hosts_and_request_paths() # assert that we use the base url and not the auth url self.assertEqual(self.driver.connection.host, 'ex_force_base_url.com') self.assertEqual(self.driver.connection.port, 666) self.assertEqual(self.driver.connection.request_path, '/forced_url') def test_get_endpoint_populates_host_port_and_request_path(self): # simulate a subclass overriding this method self.driver.connection.get_endpoint = lambda: 'http://endpoint_auth_url.com:1555/service_url' self.driver.connection.auth_token = None self.driver.connection._ex_force_base_url = None self.driver.connection._populate_hosts_and_request_paths() # assert that we use the result of get endpoint self.assertEqual(self.driver.connection.host, 'endpoint_auth_url.com') self.assertEqual(self.driver.connection.port, 1555) self.assertEqual(self.driver.connection.request_path, '/service_url') def test_set_auth_token_populates_host_port_and_request_path(self): # change base url and trash the current auth token so we can # re-authenticate self.driver.connection._ex_force_base_url = 'http://some_other_ex_force_base_url.com:1222/some-service' self.driver.connection.auth_token = "preset-auth-token" self.driver.connection._populate_hosts_and_request_paths() # assert that we use the base url and not the auth url self.assertEqual( self.driver.connection.host, 'some_other_ex_force_base_url.com') self.assertEqual(self.driver.connection.port, 1222) self.assertEqual(self.driver.connection.request_path, '/some-service') def test_auth_token_without_base_url_raises_exception(self): kwargs = { 'ex_force_auth_version': '2.0', 'ex_force_auth_token': 'preset-auth-token' } try: self.driver_type(*self.driver_args, **kwargs) self.fail('Expected failure setting auth token without base url') except LibcloudError: pass else: self.fail('Expected failure setting auth token without base url') def test_ex_force_auth_token_passed_to_connection(self): base_url = 'https://servers.api.rackspacecloud.com/v1.1/slug' kwargs = { 'ex_force_auth_version': '2.0', 'ex_force_auth_token': 'preset-auth-token', 'ex_force_base_url': base_url } driver = self.driver_type(*self.driver_args, **kwargs) driver.list_nodes() self.assertEqual(kwargs['ex_force_auth_token'], driver.connection.auth_token) self.assertEqual('servers.api.rackspacecloud.com', driver.connection.host) self.assertEqual('/v1.1/slug', driver.connection.request_path) self.assertEqual(443, driver.connection.port) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) node = nodes[0] self.assertEqual('12065', node.id) # test public IPv4 self.assertTrue('12.16.18.28' in node.public_ips) self.assertTrue('50.57.94.35' in node.public_ips) # fixed public ip self.assertTrue('1.1.1.1' in node.public_ips) # floating public ip self.assertTrue('2.2.2.2' in node.public_ips) # test public IPv6 self.assertTrue( '2001:4801:7808:52:16:3eff:fe47:788a' in node.public_ips) # test private IPv4 self.assertTrue('10.182.64.34' in node.private_ips) # fixed private ip self.assertTrue('10.3.3.3' in node.private_ips) # floating private ip self.assertTrue('192.168.3.3' in node.private_ips) self.assertTrue('172.16.1.1' in node.private_ips) # test private IPv6 self.assertTrue( 'fec0:4801:7808:52:16:3eff:fe60:187d' in node.private_ips) # test creation date self.assertEqual(node.created_at, datetime.datetime(2011, 10, 11, 0, 51, 39, tzinfo=UTC)) self.assertEqual(node.extra.get('flavorId'), '2') self.assertEqual(node.extra.get('imageId'), '7') self.assertEqual(node.extra.get('metadata'), {}) self.assertEqual(node.extra['updated'], '2011-10-11T00:50:04Z') self.assertEqual(node.extra['created'], '2011-10-11T00:51:39Z') self.assertEqual(node.extra.get('userId'), 'rs-reach') self.assertEqual(node.extra.get('hostId'), '912566d83a13fbb357ea' '3f13c629363d9f7e1ba3f' '925b49f3d2ab725') self.assertEqual(node.extra.get('disk_config'), 'AUTO') self.assertEqual(node.extra.get('task_state'), 'spawning') self.assertEqual(node.extra.get('vm_state'), 'active') self.assertEqual(node.extra.get('power_state'), 1) self.assertEqual(node.extra.get('progress'), 25) self.assertEqual(node.extra.get('fault')['id'], 1234) self.assertTrue(node.extra.get('service_name') is not None) self.assertTrue(node.extra.get('uri') is not None) def test_list_nodes_no_image_id_attribute(self): # Regression test for LIBCLOD-455 self.driver_klass.connectionCls.conn_class.type = 'ERROR_STATE_NO_IMAGE_ID' nodes = self.driver.list_nodes() self.assertIsNone(nodes[0].extra['imageId']) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 2) volume = volumes[0] self.assertEqual('cd76a3a1-c4ce-40f6-9b9f-07a61508938d', volume.id) self.assertEqual('test_volume_2', volume.name) self.assertEqual(StorageVolumeState.AVAILABLE, volume.state) self.assertEqual(2, volume.size) self.assertEqual(volume.extra, { 'description': '', 'attachments': [{ 'id': 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d', "device": "/dev/vdb", "serverId": "12065", "volumeId": "cd76a3a1-c4ce-40f6-9b9f-07a61508938d", }], 'snapshot_id': None, 'state': 'available', 'location': 'nova', 'volume_type': 'None', 'metadata': {}, 'created_at': '2013-06-24T11:20:13.000000', }) # also test that unknown state resolves to StorageVolumeState.UNKNOWN volume = volumes[1] self.assertEqual('cfcec3bc-b736-4db5-9535-4c24112691b5', volume.id) self.assertEqual('test_volume', volume.name) self.assertEqual(50, volume.size) self.assertEqual(StorageVolumeState.UNKNOWN, volume.state) self.assertEqual(volume.extra, { 'description': 'some description', 'attachments': [], 'snapshot_id': '01f48111-7866-4cd2-986a-e92683c4a363', 'state': 'some-unknown-state', 'location': 'nova', 'volume_type': 'None', 'metadata': {}, 'created_at': '2013-06-21T12:39:02.000000', }) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 8, 'Wrong sizes count') for size in sizes: self.assertTrue(size.price is None or isinstance(size.price, float), 'Wrong size price type') self.assertTrue(isinstance(size.ram, int)) self.assertTrue(isinstance(size.vcpus, int)) self.assertTrue(isinstance(size.disk, int)) self.assertTrue(isinstance(size.swap, int)) self.assertTrue(isinstance(size.ephemeral_disk, int) or size.ephemeral_disk is None) self.assertTrue(isinstance(size.extra, dict)) if size.id == '1': self.assertEqual(size.ephemeral_disk, 40) self.assertEqual(size.extra, { "policy_class": "standard_flavor", "class": "standard1", "disk_io_index": "2", "number_of_data_disks": "0" }) self.assertEqual(sizes[0].vcpus, 8) def test_list_sizes_with_specified_pricing(self): pricing = dict((str(i), i * 5.0) for i in range(1, 9)) set_pricing(driver_type='compute', driver_name=self.driver.api_name, pricing=pricing) sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 8, 'Wrong sizes count') for size in sizes: self.assertTrue(isinstance(size.price, float), 'Wrong size price type') self.assertEqual(size.price, pricing[size.id], 'Size price should match') def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 13, 'Wrong images count') image = images[0] self.assertEqual(image.id, '13') self.assertEqual(image.name, 'Windows 2008 SP2 x86 (B24)') self.assertEqual(image.extra['updated'], '2011-08-06T18:14:02Z') self.assertEqual(image.extra['created'], '2011-08-06T18:13:11Z') self.assertEqual(image.extra['status'], 'ACTIVE') self.assertEqual(image.extra['metadata']['os_type'], 'windows') self.assertEqual( image.extra['serverId'], '52415800-8b69-11e0-9b19-734f335aa7b3') self.assertEqual(image.extra['minDisk'], 0) self.assertEqual(image.extra['minRam'], 0) def test_create_node(self): image = NodeImage( id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size) self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra['password'], 'racktestvJq7d3') self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1') def test_create_node_with_ex_keyname_and_ex_userdata(self): image = NodeImage( id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size, ex_keyname='devstack', ex_userdata='sample data') self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra['password'], 'racktestvJq7d3') self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1') self.assertEqual(node.extra['key_name'], 'devstack') def test_create_node_with_availability_zone(self): image = NodeImage( id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size, ex_availability_zone='testaz') self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra['password'], 'racktestvJq7d3') self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1') self.assertEqual(node.extra['availability_zone'], 'testaz') def test_create_node_with_ex_disk_config(self): OpenStack_1_1_MockHttp.type = 'EX_DISK_CONFIG' image = NodeImage( id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size, ex_disk_config='AUTO') self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra['disk_config'], 'AUTO') def test_create_node_with_ex_config_drive(self): OpenStack_1_1_MockHttp.type = 'EX_CONFIG_DRIVE' image = NodeImage( id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size, ex_config_drive=True) self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') self.assertEqual(node.name, 'racktest') self.assertTrue(node.extra['config_drive']) def test_create_node_from_bootable_volume(self): size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node( name='racktest', size=size, ex_blockdevicemappings=[ { 'boot_index': 0, 'uuid': 'ee7ee330-b454-4414-8e9f-c70c558dd3af', 'source_type': 'volume', 'destination_type': 'volume', 'delete_on_termination': False }]) self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe') self.assertEqual(node.name, 'racktest') self.assertEqual(node.extra['password'], 'racktestvJq7d3') self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1') def test_destroy_node(self): self.assertTrue(self.node.destroy()) def test_reboot_node(self): self.assertTrue(self.node.reboot()) def test_create_volume(self): volume = self.driver.create_volume(1, 'test') self.assertEqual(volume.name, 'test') self.assertEqual(volume.size, 1) def test_create_volume_passes_location_to_request_only_if_not_none(self): with patch.object(self.driver.connection, 'request') as mock_request: self.driver.create_volume(1, 'test', location='mylocation') name, args, kwargs = mock_request.mock_calls[0] self.assertEqual(kwargs["data"]["volume"]["availability_zone"], "mylocation") def test_create_volume_does_not_pass_location_to_request_if_none(self): with patch.object(self.driver.connection, 'request') as mock_request: self.driver.create_volume(1, 'test') name, args, kwargs = mock_request.mock_calls[0] self.assertFalse("availability_zone" in kwargs["data"]["volume"]) def test_create_volume_passes_volume_type_to_request_only_if_not_none(self): with patch.object(self.driver.connection, 'request') as mock_request: self.driver.create_volume(1, 'test', ex_volume_type='myvolumetype') name, args, kwargs = mock_request.mock_calls[0] self.assertEqual(kwargs["data"]["volume"]["volume_type"], "myvolumetype") def test_create_volume_does_not_pass_volume_type_to_request_if_none(self): with patch.object(self.driver.connection, 'request') as mock_request: self.driver.create_volume(1, 'test') name, args, kwargs = mock_request.mock_calls[0] self.assertFalse("volume_type" in kwargs["data"]["volume"]) def test_destroy_volume(self): volume = self.driver.ex_get_volume( 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d') self.assertEqual(self.driver.destroy_volume(volume), True) def test_attach_volume(self): node = self.driver.list_nodes()[0] volume = self.driver.ex_get_volume( 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d') self.assertEqual( self.driver.attach_volume(node, volume, '/dev/sdb'), True) def test_detach_volume(self): node = self.driver.list_nodes()[0] volume = self.driver.ex_get_volume( 'cd76a3a1-c4ce-40f6-9b9f-07a61508938d') self.assertEqual( self.driver.attach_volume(node, volume, '/dev/sdb'), True) self.assertEqual(self.driver.detach_volume(volume), True) def test_ex_set_password(self): self.assertTrue(self.driver.ex_set_password(self.node, 'New1&53jPass')) def test_ex_rebuild(self): image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) success = self.driver.ex_rebuild(self.node, image=image) self.assertTrue(success) def test_ex_rebuild_with_ex_disk_config(self): image = NodeImage(id=58, name='Ubuntu 10.10 (intrepid)', driver=self.driver) node = Node(id=12066, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) success = self.driver.ex_rebuild(node, image=image, ex_disk_config='MANUAL') self.assertTrue(success) def test_ex_rebuild_with_ex_config_drive(self): image = NodeImage(id=58, name='Ubuntu 10.10 (intrepid)', driver=self.driver) node = Node(id=12066, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) success = self.driver.ex_rebuild(node, image=image, ex_disk_config='MANUAL', ex_config_drive=True) self.assertTrue(success) def test_ex_resize(self): size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) try: self.driver.ex_resize(self.node, size) except Exception as e: self.fail('An error was raised: ' + repr(e)) def test_ex_confirm_resize(self): try: self.driver.ex_confirm_resize(self.node) except Exception as e: self.fail('An error was raised: ' + repr(e)) def test_ex_revert_resize(self): try: self.driver.ex_revert_resize(self.node) except Exception as e: self.fail('An error was raised: ' + repr(e)) def test_create_image(self): image = self.driver.create_image(self.node, 'new_image') self.assertEqual(image.name, 'new_image') self.assertEqual(image.id, '4949f9ee-2421-4c81-8b49-13119446008b') def test_ex_set_server_name(self): old_node = Node( id='12064', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) new_node = self.driver.ex_set_server_name(old_node, 'Bob') self.assertEqual('Bob', new_node.name) def test_ex_set_metadata(self): old_node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) metadata = {'Image Version': '2.1', 'Server Label': 'Web Head 1'} returned_metadata = self.driver.ex_set_metadata(old_node, metadata) self.assertEqual(metadata, returned_metadata) def test_ex_get_metadata(self): node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) metadata = {'Image Version': '2.1', 'Server Label': 'Web Head 1'} returned_metadata = self.driver.ex_get_metadata(node) self.assertEqual(metadata, returned_metadata) def test_ex_update_node(self): old_node = Node( id='12064', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) new_node = self.driver.ex_update_node(old_node, name='Bob') self.assertTrue(new_node) self.assertEqual('Bob', new_node.name) self.assertEqual('50.57.94.30', new_node.public_ips[0]) def test_ex_get_node_details(self): node_id = '12064' node = self.driver.ex_get_node_details(node_id) self.assertEqual(node.id, '12064') self.assertEqual(node.name, 'lc-test') def test_ex_get_node_details_returns_none_if_node_does_not_exist(self): node = self.driver.ex_get_node_details('does-not-exist') self.assertTrue(node is None) def test_ex_get_size(self): size_id = '7' size = self.driver.ex_get_size(size_id) self.assertEqual(size.id, size_id) self.assertEqual(size.name, '15.5GB slice') def test_get_image(self): image_id = '13' image = self.driver.get_image(image_id) self.assertEqual(image.id, image_id) self.assertEqual(image.name, 'Windows 2008 SP2 x86 (B24)') self.assertIsNone(image.extra['serverId']) self.assertEqual(image.extra['minDisk'], "5") self.assertEqual(image.extra['minRam'], "256") self.assertIsNone(image.extra['visibility']) def test_delete_image(self): image = NodeImage( id='26365521-8c62-11f9-2c33-283d153ecc3a', name='My Backup', driver=self.driver) result = self.driver.delete_image(image) self.assertTrue(result) def test_extract_image_id_from_url(self): url = 'http://127.0.0.1/v1.1/68/images/1d4a8ea9-aae7-4242-a42d-5ff4702f2f14' url_two = 'http://127.0.0.1/v1.1/68/images/13' image_id = self.driver._extract_image_id_from_url(url) image_id_two = self.driver._extract_image_id_from_url(url_two) self.assertEqual(image_id, '1d4a8ea9-aae7-4242-a42d-5ff4702f2f14') self.assertEqual(image_id_two, '13') def test_ex_rescue_with_password(self): node = Node(id=12064, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) n = self.driver.ex_rescue(node, 'foo') self.assertEqual(n.extra['password'], 'foo') def test_ex_rescue_no_password(self): node = Node(id=12064, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) n = self.driver.ex_rescue(node) self.assertEqual(n.extra['password'], 'foo') def test_ex_unrescue(self): node = Node(id=12064, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) result = self.driver.ex_unrescue(node) self.assertTrue(result) def test_ex_get_node_security_groups(self): node = Node(id='1c01300f-ef97-4937-8f03-ac676d6234be', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) security_groups = self.driver.ex_get_node_security_groups(node) self.assertEqual( len(security_groups), 2, 'Wrong security groups count') security_group = security_groups[1] self.assertEqual(security_group.id, 4) self.assertEqual(security_group.tenant_id, '68') self.assertEqual(security_group.name, 'ftp') self.assertEqual( security_group.description, 'FTP Client-Server - Open 20-21 ports') self.assertEqual(security_group.rules[0].id, 1) self.assertEqual(security_group.rules[0].parent_group_id, 4) self.assertEqual(security_group.rules[0].ip_protocol, "tcp") self.assertEqual(security_group.rules[0].from_port, 20) self.assertEqual(security_group.rules[0].to_port, 21) self.assertEqual(security_group.rules[0].ip_range, '0.0.0.0/0') def test_ex_list_security_groups(self): security_groups = self.driver.ex_list_security_groups() self.assertEqual( len(security_groups), 2, 'Wrong security groups count') security_group = security_groups[1] self.assertEqual(security_group.id, 4) self.assertEqual(security_group.tenant_id, '68') self.assertEqual(security_group.name, 'ftp') self.assertEqual( security_group.description, 'FTP Client-Server - Open 20-21 ports') self.assertEqual(security_group.rules[0].id, 1) self.assertEqual(security_group.rules[0].parent_group_id, 4) self.assertEqual(security_group.rules[0].ip_protocol, "tcp") self.assertEqual(security_group.rules[0].from_port, 20) self.assertEqual(security_group.rules[0].to_port, 21) self.assertEqual(security_group.rules[0].ip_range, '0.0.0.0/0') def test_ex_create_security_group(self): name = 'test' description = 'Test Security Group' security_group = self.driver.ex_create_security_group( name, description) self.assertEqual(security_group.id, 6) self.assertEqual(security_group.tenant_id, '68') self.assertEqual(security_group.name, name) self.assertEqual(security_group.description, description) self.assertEqual(len(security_group.rules), 0) def test_ex_delete_security_group(self): security_group = OpenStackSecurityGroup( id=6, tenant_id=None, name=None, description=None, driver=self.driver) result = self.driver.ex_delete_security_group(security_group) self.assertTrue(result) def test_ex_create_security_group_rule(self): security_group = OpenStackSecurityGroup( id=6, tenant_id=None, name=None, description=None, driver=self.driver) security_group_rule = self.driver.ex_create_security_group_rule( security_group, 'tcp', 14, 16, '0.0.0.0/0') self.assertEqual(security_group_rule.id, 2) self.assertEqual(security_group_rule.parent_group_id, 6) self.assertEqual(security_group_rule.ip_protocol, 'tcp') self.assertEqual(security_group_rule.from_port, 14) self.assertEqual(security_group_rule.to_port, 16) self.assertEqual(security_group_rule.ip_range, '0.0.0.0/0') self.assertIsNone(security_group_rule.tenant_id) def test_ex_delete_security_group_rule(self): security_group_rule = OpenStackSecurityGroupRule( id=2, parent_group_id=None, ip_protocol=None, from_port=None, to_port=None, driver=self.driver) result = self.driver.ex_delete_security_group_rule(security_group_rule) self.assertTrue(result) def test_list_key_pairs(self): keypairs = self.driver.list_key_pairs() self.assertEqual(len(keypairs), 2, 'Wrong keypairs count') keypair = keypairs[1] self.assertEqual(keypair.name, 'key2') self.assertEqual( keypair.fingerprint, '5d:66:33:ae:99:0f:fb:cb:86:f2:bc:ae:53:99:b6:ed') self.assertTrue(len(keypair.public_key) > 10) self.assertIsNone(keypair.private_key) def test_get_key_pair(self): key_pair = self.driver.get_key_pair(name='test-key-pair') self.assertEqual(key_pair.name, 'test-key-pair') def test_get_key_pair_doesnt_exist(self): self.assertRaises(KeyPairDoesNotExistError, self.driver.get_key_pair, name='doesnt-exist') def test_create_key_pair(self): name = 'key0' keypair = self.driver.create_key_pair(name=name) self.assertEqual(keypair.name, name) self.assertEqual(keypair.fingerprint, '80:f8:03:a7:8e:c1:c3:b1:7e:c5:8c:50:04:5e:1c:5b') self.assertTrue(len(keypair.public_key) > 10) self.assertTrue(len(keypair.private_key) > 10) def test_import_key_pair_from_file(self): name = 'key3' path = os.path.join( os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa.pub') with open(path, 'r') as fp: pub_key = fp.read() keypair = self.driver.import_key_pair_from_file(name=name, key_file_path=path) self.assertEqual(keypair.name, name) self.assertEqual( keypair.fingerprint, '97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a') self.assertEqual(keypair.public_key, pub_key) self.assertIsNone(keypair.private_key) def test_import_key_pair_from_string(self): name = 'key3' path = os.path.join( os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa.pub') with open(path, 'r') as fp: pub_key = fp.read() keypair = self.driver.import_key_pair_from_string(name=name, key_material=pub_key) self.assertEqual(keypair.name, name) self.assertEqual( keypair.fingerprint, '97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a') self.assertEqual(keypair.public_key, pub_key) self.assertIsNone(keypair.private_key) def test_delete_key_pair(self): keypair = OpenStackKeyPair( name='key1', fingerprint=None, public_key=None, driver=self.driver) result = self.driver.delete_key_pair(key_pair=keypair) self.assertTrue(result) def test_ex_list_floating_ip_pools(self): ret = self.driver.ex_list_floating_ip_pools() self.assertEqual(ret[0].name, 'public') self.assertEqual(ret[1].name, 'foobar') def test_ex_attach_floating_ip_to_node(self): image = NodeImage( id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size) node.id = 4242 ip = '42.42.42.42' self.assertTrue(self.driver.ex_attach_floating_ip_to_node(node, ip)) def test_detach_floating_ip_from_node(self): image = NodeImage( id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='racktest', image=image, size=size) node.id = 4242 ip = '42.42.42.42' self.assertTrue(self.driver.ex_detach_floating_ip_from_node(node, ip)) def test_OpenStack_1_1_FloatingIpPool_list_floating_ips(self): pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) ret = pool.list_floating_ips() self.assertEqual(ret[0].id, '09ea1784-2f81-46dc-8c91-244b4df75bde') self.assertEqual(ret[0].pool, pool) self.assertEqual(ret[0].ip_address, '10.3.1.42') self.assertIsNone(ret[0].node_id) self.assertEqual(ret[1].id, '04c5336a-0629-4694-ba30-04b0bdfa88a4') self.assertEqual(ret[1].pool, pool) self.assertEqual(ret[1].ip_address, '10.3.1.1') self.assertEqual( ret[1].node_id, 'fcfc96da-19e2-40fd-8497-f29da1b21143') def test_OpenStack_1_1_FloatingIpPool_get_floating_ip(self): pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) ret = pool.get_floating_ip('10.3.1.42') self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde') self.assertEqual(ret.pool, pool) self.assertEqual(ret.ip_address, '10.3.1.42') self.assertIsNone(ret.node_id) def test_OpenStack_1_1_FloatingIpPool_create_floating_ip(self): pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) ret = pool.create_floating_ip() self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde') self.assertEqual(ret.pool, pool) self.assertEqual(ret.ip_address, '10.3.1.42') self.assertIsNone(ret.node_id) def test_OpenStack_1_1_FloatingIpPool_delete_floating_ip(self): pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool) self.assertTrue(pool.delete_floating_ip(ip)) def test_OpenStack_1_1_FloatingIpAddress_delete(self): pool = OpenStack_1_1_FloatingIpPool('foo', self.driver.connection) pool.delete_floating_ip = Mock() ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool) ip.pool.delete_floating_ip() self.assertEqual(pool.delete_floating_ip.call_count, 1) def test_OpenStack_2_FloatingIpPool_list_floating_ips(self): pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection) ret = pool.list_floating_ips() self.assertEqual(ret[0].id, '09ea1784-2f81-46dc-8c91-244b4df75bde') self.assertEqual(ret[0].pool, pool) self.assertEqual(ret[0].ip_address, '10.3.1.42') self.assertEqual(ret[0].node_id, None) self.assertEqual(ret[1].id, '04c5336a-0629-4694-ba30-04b0bdfa88a4') self.assertEqual(ret[1].pool, pool) self.assertEqual(ret[1].ip_address, '10.3.1.1') self.assertEqual( ret[1].node_id, 'fcfc96da-19e2-40fd-8497-f29da1b21143') self.assertEqual(ret[2].id, '123c5336a-0629-4694-ba30-04b0bdfa88a4') self.assertEqual(ret[2].pool, pool) self.assertEqual(ret[2].ip_address, '10.3.1.2') self.assertEqual( ret[2].node_id, 'cb4fba64-19e2-40fd-8497-f29da1b21143') def test_OpenStack_2_FloatingIpPool_get_floating_ip(self): pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection) ret = pool.get_floating_ip('10.3.1.42') self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde') self.assertEqual(ret.pool, pool) self.assertEqual(ret.ip_address, '10.3.1.42') self.assertEqual(ret.node_id, None) def test_OpenStack_2_FloatingIpPool_create_floating_ip(self): pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection) ret = pool.create_floating_ip() self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde') self.assertEqual(ret.pool, pool) self.assertEqual(ret.ip_address, '10.3.1.42') self.assertEqual(ret.node_id, None) def test_OpenStack_2_FloatingIpPool_delete_floating_ip(self): pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection) ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool) self.assertTrue(pool.delete_floating_ip(ip)) def test_OpenStack_2_FloatingIpAddress_delete(self): pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection) pool.delete_floating_ip = Mock() ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool) ip.pool.delete_floating_ip() self.assertEqual(pool.delete_floating_ip.call_count, 1) def test_ex_get_metadata_for_node(self): image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver) node = self.driver.create_node(name='foo', image=image, size=size) metadata = self.driver.ex_get_metadata_for_node(node) self.assertEqual(metadata['My Server Name'], 'Apache1') self.assertEqual(len(metadata), 1) def test_ex_pause_node(self): node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) ret = self.driver.ex_pause_node(node) self.assertTrue(ret is True) def test_ex_unpause_node(self): node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) ret = self.driver.ex_unpause_node(node) self.assertTrue(ret is True) def test_ex_stop_node(self): node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) ret = self.driver.ex_stop_node(node) self.assertTrue(ret is True) def test_ex_start_node(self): node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) ret = self.driver.ex_start_node(node) self.assertTrue(ret is True) def test_ex_suspend_node(self): node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) ret = self.driver.ex_suspend_node(node) self.assertTrue(ret is True) def test_ex_resume_node(self): node = Node( id='12063', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) ret = self.driver.ex_resume_node(node) self.assertTrue(ret is True) def test_ex_get_console_output(self): node = Node( id='12086', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver, ) resp = self.driver.ex_get_console_output(node) expected_output = 'FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE' self.assertEqual(resp['output'], expected_output) def test_ex_list_snapshots(self): if self.driver_type.type == 'rackspace': self.conn_class.type = 'RACKSPACE' snapshots = self.driver.ex_list_snapshots() self.assertEqual(len(snapshots), 3) self.assertEqual(snapshots[0].created, datetime.datetime(2012, 2, 29, 3, 50, 7, tzinfo=UTC)) self.assertEqual(snapshots[0].extra['created'], "2012-02-29T03:50:07Z") self.assertEqual(snapshots[0].extra['name'], 'snap-001') self.assertEqual(snapshots[0].name, 'snap-001') self.assertEqual(snapshots[0].state, VolumeSnapshotState.AVAILABLE) # invalid date is parsed as None assert snapshots[2].created is None def test_ex_get_snapshot(self): if self.driver_type.type == 'rackspace': self.conn_class.type = 'RACKSPACE' snapshot = self.driver.ex_get_snapshot('3fbbcccf-d058-4502-8844-6feeffdf4cb5') self.assertEqual(snapshot.created, datetime.datetime(2012, 2, 29, 3, 50, 7, tzinfo=UTC)) self.assertEqual(snapshot.extra['created'], "2012-02-29T03:50:07Z") self.assertEqual(snapshot.extra['name'], 'snap-001') self.assertEqual(snapshot.name, 'snap-001') self.assertEqual(snapshot.state, VolumeSnapshotState.AVAILABLE) def test_list_volume_snapshots(self): volume = self.driver.list_volumes()[0] # rackspace needs a different mocked response for snapshots, but not for volumes if self.driver_type.type == 'rackspace': self.conn_class.type = 'RACKSPACE' snapshots = self.driver.list_volume_snapshots(volume) self.assertEqual(len(snapshots), 1) self.assertEqual(snapshots[0].id, '4fbbdccf-e058-6502-8844-6feeffdf4cb5') def test_create_volume_snapshot(self): volume = self.driver.list_volumes()[0] if self.driver_type.type == 'rackspace': self.conn_class.type = 'RACKSPACE' ret = self.driver.create_volume_snapshot(volume, 'Test Volume', ex_description='This is a test', ex_force=True) self.assertEqual(ret.id, '3fbbcccf-d058-4502-8844-6feeffdf4cb5') def test_ex_create_snapshot(self): volume = self.driver.list_volumes()[0] if self.driver_type.type == 'rackspace': self.conn_class.type = 'RACKSPACE' ret = self.driver.ex_create_snapshot(volume, 'Test Volume', description='This is a test', force=True) self.assertEqual(ret.id, '3fbbcccf-d058-4502-8844-6feeffdf4cb5') def test_ex_create_snapshot_does_not_post_optional_parameters_if_none(self): volume = self.driver.list_volumes()[0] with patch.object(self.driver, '_to_snapshot'): with patch.object(self.driver.connection, 'request') as mock_request: self.driver.create_volume_snapshot(volume, name=None, ex_description=None, ex_force=True) name, args, kwargs = mock_request.mock_calls[0] self.assertFalse("display_name" in kwargs["data"]["snapshot"]) self.assertFalse("display_description" in kwargs["data"]["snapshot"]) def test_destroy_volume_snapshot(self): if self.driver_type.type == 'rackspace': self.conn_class.type = 'RACKSPACE' snapshot = self.driver.ex_list_snapshots()[0] ret = self.driver.destroy_volume_snapshot(snapshot) self.assertTrue(ret) def test_ex_delete_snapshot(self): if self.driver_type.type == 'rackspace': self.conn_class.type = 'RACKSPACE' snapshot = self.driver.ex_list_snapshots()[0] ret = self.driver.ex_delete_snapshot(snapshot) self.assertTrue(ret) class OpenStack_2_Tests(OpenStack_1_1_Tests): driver_klass = OpenStack_2_NodeDriver driver_type = OpenStack_2_NodeDriver driver_kwargs = { 'ex_force_auth_version': '2.0', 'ex_force_auth_url': 'https://auth.api.example.com' } def setUp(self): super(OpenStack_2_Tests, self).setUp() self.driver_klass.image_connectionCls.conn_class = OpenStack_2_0_MockHttp self.driver_klass.image_connectionCls.auth_url = "https://auth.api.example.com" # normally authentication happens lazily, but we force it here self.driver.image_connection._populate_hosts_and_request_paths() self.driver_klass.network_connectionCls.conn_class = OpenStack_2_0_MockHttp self.driver_klass.network_connectionCls.auth_url = "https://auth.api.example.com" # normally authentication happens lazily, but we force it here self.driver.network_connection._populate_hosts_and_request_paths() self.driver_klass.volumev2_connectionCls.conn_class = OpenStack_2_0_MockHttp self.driver_klass.volumev2_connectionCls.auth_url = "https://auth.api.example.com" # normally authentication happens lazily, but we force it here self.driver.volumev2_connection._populate_hosts_and_request_paths() def test__paginated_request_single_page(self): snapshots = self.driver._paginated_request( '/snapshots/detail', 'snapshots', self.driver.volumev2_connection )['snapshots'] self.assertEqual(len(snapshots), 3) self.assertEqual(snapshots[0]['name'], 'snap-001') def test__paginated_request_two_pages(self): snapshots = self.driver._paginated_request( '/snapshots/detail?unit_test=paginate', 'snapshots', self.driver.volumev2_connection )['snapshots'] self.assertEqual(len(snapshots), 6) self.assertEqual(snapshots[0]['name'], 'snap-101') self.assertEqual(snapshots[3]['name'], 'snap-001') # NOTE: We use a smaller limit to speed tests up. @mock.patch('libcloud.compute.drivers.openstack.PAGINATION_LIMIT', 10) def test__paginated_request_raises_if_stuck_in_a_loop(self): with pytest.raises(OpenStackException): self.driver._paginated_request( '/snapshots/detail?unit_test=pagination_loop', 'snapshots', self.driver.volumev2_connection ) def test_ex_force_auth_token_passed_to_connection(self): base_url = 'https://servers.api.rackspacecloud.com/v1.1/slug' kwargs = { 'ex_force_auth_version': '2.0', 'ex_force_auth_token': 'preset-auth-token', 'ex_force_auth_url': 'https://auth.api.example.com', 'ex_force_base_url': base_url } driver = self.driver_type(*self.driver_args, **kwargs) driver.list_nodes() self.assertEqual(kwargs['ex_force_auth_token'], driver.connection.auth_token) self.assertEqual('servers.api.rackspacecloud.com', driver.connection.host) self.assertEqual('/v1.1/slug', driver.connection.request_path) self.assertEqual(443, driver.connection.port) def test_get_image(self): image_id = 'f24a3c1b-d52a-4116-91da-25b3eee8f55e' image = self.driver.get_image(image_id) self.assertEqual(image.id, image_id) self.assertEqual(image.name, 'hypernode') self.assertIsNone(image.extra['serverId']) self.assertEqual(image.extra['minDisk'], 40) self.assertEqual(image.extra['minRam'], 0) self.assertEqual(image.extra['visibility'], "shared") def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 2, 'Wrong images count') image = images[0] self.assertEqual(image.id, 'f24a3c1b-d52a-4116-91da-25b3eee8f55e') self.assertEqual(image.name, 'hypernode') self.assertEqual(image.extra['updated'], '2017-11-28T10:19:49Z') self.assertEqual(image.extra['created'], '2017-09-11T13:00:05Z') self.assertEqual(image.extra['status'], 'active') self.assertEqual(image.extra['os_type'], 'linux') self.assertIsNone(image.extra['serverId']) self.assertEqual(image.extra['minDisk'], 40) self.assertEqual(image.extra['minRam'], 0) def test_ex_update_image(self): image_id = 'f24a3c1b-d52a-4116-91da-25b3eee8f55e' data = { 'op': 'replace', 'path': '/visibility', 'value': 'shared' } image = self.driver.ex_update_image(image_id, data) self.assertEqual(image.name, 'hypernode') self.assertIsNone(image.extra['serverId']) self.assertEqual(image.extra['minDisk'], 40) self.assertEqual(image.extra['minRam'], 0) self.assertEqual(image.extra['visibility'], "shared") def test_ex_list_image_members(self): image_id = 'd9a9cd9a-278a-444c-90a6-d24b8c688a63' image_member_id = '016926dff12345e8b10329f24c99745b' image_members = self.driver.ex_list_image_members(image_id) self.assertEqual(len(image_members), 30, 'Wrong image member count') image_member = image_members[0] self.assertEqual(image_member.id, image_member_id) self.assertEqual(image_member.image_id, image_id) self.assertEqual(image_member.state, NodeImageMemberState.ACCEPTED) self.assertEqual(image_member.created, '2017-01-12T12:31:50Z') self.assertEqual(image_member.extra['updated'], '2017-01-12T12:31:54Z') self.assertEqual(image_member.extra['schema'], '/v2/schemas/member') def test_ex_create_image_member(self): image_id = '9af1a54e-a1b2-4df8-b747-4bec97abc799' image_member_id = 'e2151b1fe02d4a8a2d1f5fc331522c0a' image_member = self.driver.ex_create_image_member( image_id, image_member_id ) self.assertEqual(image_member.id, image_member_id) self.assertEqual(image_member.image_id, image_id) self.assertEqual(image_member.state, NodeImageMemberState.PENDING) self.assertEqual(image_member.created, '2018-03-02T14:19:38Z') self.assertEqual(image_member.extra['updated'], '2018-03-02T14:19:38Z') self.assertEqual(image_member.extra['schema'], '/v2/schemas/member') def test_ex_get_image_member(self): image_id = 'd9a9cd9a-278a-444c-90a6-d24b8c688a63' image_member_id = '016926dff12345e8b10329f24c99745b' image_member = self.driver.ex_get_image_member( image_id, image_member_id ) self.assertEqual(image_member.id, image_member_id) self.assertEqual(image_member.image_id, image_id) self.assertEqual(image_member.state, NodeImageMemberState.ACCEPTED) self.assertEqual(image_member.created, '2017-01-12T12:31:50Z') self.assertEqual(image_member.extra['updated'], '2017-01-12T12:31:54Z') self.assertEqual(image_member.extra['schema'], '/v2/schemas/member') def test_ex_accept_image_member(self): image_id = '8af1a54e-a1b2-4df8-b747-4bec97abc799' image_member_id = 'e2151b1fe02d4a8a2d1f5fc331522c0a' image_member = self.driver.ex_accept_image_member( image_id, image_member_id ) self.assertEqual(image_member.id, image_member_id) self.assertEqual(image_member.image_id, image_id) self.assertEqual(image_member.state, NodeImageMemberState.ACCEPTED) self.assertEqual(image_member.created, '2018-03-02T14:19:38Z') self.assertEqual(image_member.extra['updated'], '2018-03-02T14:20:37Z') self.assertEqual(image_member.extra['schema'], '/v2/schemas/member') def test_ex_list_networks(self): networks = self.driver.ex_list_networks() network = networks[0] self.assertEqual(len(networks), 2) self.assertEqual(network.name, 'net1') self.assertEqual(network.extra['subnets'], ['54d6f61d-db07-451c-9ab3-b9609b6b6f0b']) def test_ex_list_subnets(self): subnets = self.driver.ex_list_subnets() subnet = subnets[0] self.assertEqual(len(subnets), 2) self.assertEqual(subnet.name, 'private-subnet') self.assertEqual(subnet.cidr, '10.0.0.0/24') def test_ex_create_subnet(self): network = self.driver.ex_list_networks()[0] subnet = self.driver.ex_create_subnet('name', network, '10.0.0.0/24', ip_version=4, dns_nameservers=["10.0.0.01"]) self.assertEqual(subnet.name, 'name') self.assertEqual(subnet.cidr, '10.0.0.0/24') def test_ex_delete_subnet(self): subnet = self.driver.ex_list_subnets()[0] self.assertTrue(self.driver.ex_delete_subnet(subnet=subnet)) def test_ex_update_subnet(self): subnet = self.driver.ex_list_subnets()[0] subnet = self.driver.ex_update_subnet(subnet, name='net2') self.assertEqual(subnet.name, 'name') def test_ex_list_network(self): networks = self.driver.ex_list_networks() network = networks[0] self.assertEqual(len(networks), 2) self.assertEqual(network.name, 'net1') def test_ex_create_network(self): network = self.driver.ex_create_network(name='net1', cidr='127.0.0.0/24') self.assertEqual(network.name, 'net1') def test_ex_delete_network(self): network = self.driver.ex_list_networks()[0] self.assertTrue(self.driver.ex_delete_network(network=network)) def test_ex_list_ports(self): ports = self.driver.ex_list_ports() port = ports[0] self.assertEqual(port.id, '126da55e-cfcb-41c8-ae39-a26cb8a7e723') self.assertEqual(port.state, OpenStack_2_PortInterfaceState.BUILD) self.assertEqual(port.created, '2018-07-04T14:38:18Z') self.assertEqual( port.extra['network_id'], '123c8a8c-6427-4e8f-a805-2035365f4d43' ) self.assertEqual( port.extra['project_id'], 'abcdec85bee34bb0a44ab8255eb36abc' ) self.assertEqual( port.extra['tenant_id'], 'abcdec85bee34bb0a44ab8255eb36abc' ) self.assertEqual(port.extra['name'], '') def test_ex_create_port(self): network = OpenStackNetwork(id='123c8a8c-6427-4e8f-a805-2035365f4d43', name='test-network', cidr='1.2.3.4', driver=self.driver) port = self.driver.ex_create_port(network=network, description='Some port description', name='Some port name', admin_state_up=True) self.assertEqual(port.id, '126da55e-cfcb-41c8-ae39-a26cb8a7e723') self.assertEqual(port.state, OpenStack_2_PortInterfaceState.BUILD) self.assertEqual(port.created, '2018-07-04T14:38:18Z') self.assertEqual( port.extra['network_id'], '123c8a8c-6427-4e8f-a805-2035365f4d43' ) self.assertEqual( port.extra['project_id'], 'abcdec85bee34bb0a44ab8255eb36abc' ) self.assertEqual( port.extra['tenant_id'], 'abcdec85bee34bb0a44ab8255eb36abc' ) self.assertEqual(port.extra['admin_state_up'], True) self.assertEqual(port.extra['name'], 'Some port name') self.assertEqual(port.extra['description'], 'Some port description') def test_ex_get_port(self): port = self.driver.ex_get_port('126da55e-cfcb-41c8-ae39-a26cb8a7e723') self.assertEqual(port.id, '126da55e-cfcb-41c8-ae39-a26cb8a7e723') self.assertEqual(port.state, OpenStack_2_PortInterfaceState.BUILD) self.assertEqual(port.created, '2018-07-04T14:38:18Z') self.assertEqual( port.extra['network_id'], '123c8a8c-6427-4e8f-a805-2035365f4d43' ) self.assertEqual( port.extra['project_id'], 'abcdec85bee34bb0a44ab8255eb36abc' ) self.assertEqual( port.extra['tenant_id'], 'abcdec85bee34bb0a44ab8255eb36abc' ) self.assertEqual(port.extra['name'], 'Some port name') def test_ex_delete_port(self): ports = self.driver.ex_list_ports() port = ports[0] ret = self.driver.ex_delete_port(port) self.assertTrue(ret) def test_ex_update_port(self): port = self.driver.ex_get_port('126da55e-cfcb-41c8-ae39-a26cb8a7e723') ret = self.driver.ex_update_port(port, port_security_enabled=False) self.assertEqual(ret.extra['name'], 'Some port name') def test_detach_port_interface(self): node = Node(id='1c01300f-ef97-4937-8f03-ac676d6234be', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ports = self.driver.ex_list_ports() port = ports[0] ret = self.driver.ex_detach_port_interface(node, port) self.assertTrue(ret) def test_attach_port_interface(self): node = Node(id='1c01300f-ef97-4937-8f03-ac676d6234be', name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) ports = self.driver.ex_list_ports() port = ports[0] ret = self.driver.ex_attach_port_interface(node, port) self.assertTrue(ret) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 2) volume = volumes[0] self.assertEqual('6edbc2f4-1507-44f8-ac0d-eed1d2608d38', volume.id) self.assertEqual('test-volume-attachments', volume.name) self.assertEqual(StorageVolumeState.INUSE, volume.state) self.assertEqual(2, volume.size) self.assertEqual(volume.extra, { 'description': '', 'attachments': [{ "attachment_id": "3b4db356-253d-4fab-bfa0-e3626c0b8405", "id": '6edbc2f4-1507-44f8-ac0d-eed1d2608d38', "device": "/dev/vdb", "server_id": "f4fda93b-06e0-4743-8117-bc8bcecd651b", "volume_id": "6edbc2f4-1507-44f8-ac0d-eed1d2608d38", }], 'snapshot_id': None, 'state': 'in-use', 'location': 'nova', 'volume_type': 'lvmdriver-1', 'metadata': {}, 'created_at': '2013-06-24T11:20:13.000000' }) # also test that unknown state resolves to StorageVolumeState.UNKNOWN volume = volumes[1] self.assertEqual('cfcec3bc-b736-4db5-9535-4c24112691b5', volume.id) self.assertEqual('test_volume', volume.name) self.assertEqual(50, volume.size) self.assertEqual(StorageVolumeState.UNKNOWN, volume.state) self.assertEqual(volume.extra, { 'description': 'some description', 'attachments': [], 'snapshot_id': '01f48111-7866-4cd2-986a-e92683c4a363', 'state': 'some-unknown-state', 'location': 'nova', 'volume_type': None, 'metadata': {}, 'created_at': '2013-06-21T12:39:02.000000', }) def test_create_volume_passes_location_to_request_only_if_not_none(self): with patch.object(self.driver.volumev2_connection, 'request') as mock_request: self.driver.create_volume(1, 'test', location='mylocation') name, args, kwargs = mock_request.mock_calls[0] self.assertEqual(kwargs["data"]["volume"]["availability_zone"], "mylocation") def test_create_volume_does_not_pass_location_to_request_if_none(self): with patch.object(self.driver.volumev2_connection, 'request') as mock_request: self.driver.create_volume(1, 'test') name, args, kwargs = mock_request.mock_calls[0] self.assertFalse("availability_zone" in kwargs["data"]["volume"]) def test_create_volume_passes_volume_type_to_request_only_if_not_none(self): with patch.object(self.driver.volumev2_connection, 'request') as mock_request: self.driver.create_volume(1, 'test', ex_volume_type='myvolumetype') name, args, kwargs = mock_request.mock_calls[0] self.assertEqual(kwargs["data"]["volume"]["volume_type"], "myvolumetype") def test_create_volume_does_not_pass_volume_type_to_request_if_none(self): with patch.object(self.driver.volumev2_connection, 'request') as mock_request: self.driver.create_volume(1, 'test') name, args, kwargs = mock_request.mock_calls[0] self.assertFalse("volume_type" in kwargs["data"]["volume"]) def test_create_volume_passes_image_ref_to_request_only_if_not_none(self): with patch.object(self.driver.volumev2_connection, 'request') as mock_request: self.driver.create_volume( 1, 'test', ex_image_ref='353c4bd2-b28f-4857-9b7b-808db4397d03') name, args, kwargs = mock_request.mock_calls[0] self.assertEqual( kwargs["data"]["volume"]["imageRef"], "353c4bd2-b28f-4857-9b7b-808db4397d03") def test_create_volume_does_not_pass_image_ref_to_request_if_none(self): with patch.object(self.driver.volumev2_connection, 'request') as mock_request: self.driver.create_volume(1, 'test') name, args, kwargs = mock_request.mock_calls[0] self.assertFalse("imageRef" in kwargs["data"]["volume"]) def test_ex_create_snapshot_does_not_post_optional_parameters_if_none(self): volume = self.driver.list_volumes()[0] with patch.object(self.driver, '_to_snapshot'): with patch.object(self.driver.volumev2_connection, 'request') as mock_request: self.driver.create_volume_snapshot(volume, name=None, ex_description=None, ex_force=True) name, args, kwargs = mock_request.mock_calls[0] self.assertFalse("display_name" in kwargs["data"]["snapshot"]) self.assertFalse("display_description" in kwargs["data"]["snapshot"]) def test_ex_list_routers(self): routers = self.driver.ex_list_routers() router = routers[0] self.assertEqual(len(routers), 2) self.assertEqual(router.name, 'router2') self.assertEqual(router.status, 'ACTIVE') self.assertEqual(router.extra['routes'], [{'destination': '179.24.1.0/24', 'nexthop': '172.24.3.99'}]) def test_ex_create_router(self): router = self.driver.ex_create_router('router1', admin_state_up = True) self.assertEqual(router.name, 'router1') def test_ex_delete_router(self): router = self.driver.ex_list_routers()[1] self.assertTrue(self.driver.ex_delete_router(router=router)) def test_manage_router_interfaces(self): router = self.driver.ex_list_routers()[1] port = self.driver.ex_list_ports()[0] subnet = self.driver.ex_list_subnets()[0] self.assertTrue(self.driver.ex_add_router_port(router, port)) self.assertTrue(self.driver.ex_del_router_port(router, port)) self.assertTrue(self.driver.ex_add_router_subnet(router, subnet)) self.assertTrue(self.driver.ex_del_router_subnet(router, subnet)) def test_detach_volume(self): node = self.driver.list_nodes()[0] volume = self.driver.ex_get_volume( 'abc6a3a1-c4ce-40f6-9b9f-07a61508938d') self.assertEqual( self.driver.attach_volume(node, volume, '/dev/sdb'), True) self.assertEqual(self.driver.detach_volume(volume), True) def test_ex_remove_security_group_from_node(self): security_group = OpenStackSecurityGroup("sgid", None, "sgname", "", self.driver) node = Node("1000", "node", None, [], [], self.driver) ret = self.driver.ex_remove_security_group_from_node(security_group, node) self.assertTrue(ret) class OpenStack_1_1_FactoryMethodTests(OpenStack_1_1_Tests): should_list_locations = False should_list_volumes = True driver_klass = OpenStack_1_1_NodeDriver driver_type = get_driver(Provider.OPENSTACK) driver_args = OPENSTACK_PARAMS + ('1.1',) driver_kwargs = {'ex_force_auth_version': '2.0'} class OpenStack_1_1_MockHttp(MockHttp, unittest.TestCase): fixtures = ComputeFileFixtures('openstack_v1.1') auth_fixtures = OpenStackFixtures() json_content_headers = {'content-type': 'application/json; charset=UTF-8'} def _v2_0_tokens(self, method, url, body, headers): body = self.auth_fixtures.load('_v2_0__auth.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_0(self, method, url, body, headers): headers = { 'x-auth-token': 'FE011C19-CF86-4F87-BE5D-9229145D7A06', 'x-server-management-url': 'https://api.example.com/v1.1/slug', } return (httplib.NO_CONTENT, "", headers, httplib.responses[httplib.NO_CONTENT]) def _v1_1_slug_servers_detail(self, method, url, body, headers): body = self.fixtures.load('_servers_detail.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers_detail_ERROR_STATE_NO_IMAGE_ID(self, method, url, body, headers): body = self.fixtures.load('_servers_detail_ERROR_STATE.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_servers_does_not_exist(self, *args, **kwargs): return httplib.NOT_FOUND, None, {}, httplib.responses[httplib.NOT_FOUND] def _v1_1_slug_flavors_detail(self, method, url, body, headers): body = self.fixtures.load('_flavors_detail.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_images_detail(self, method, url, body, headers): body = self.fixtures.load('_images_detail.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers(self, method, url, body, headers): if method == "POST": body = self.fixtures.load('_servers_create.json') elif method == "GET": body = self.fixtures.load('_servers.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( '_servers_26f7fbee_8ce1_4c28_887a_bfe8e4bb10fe.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers_12065_action(self, method, url, body, headers): if method != "POST": self.fail('HTTP method other than POST to action URL') return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) def _v1_1_slug_servers_12064_action(self, method, url, body, headers): if method != "POST": self.fail('HTTP method other than POST to action URL') if "createImage" in json.loads(body): return (httplib.ACCEPTED, "", {"location": "http://127.0.0.1/v1.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b"}, httplib.responses[httplib.ACCEPTED]) elif "rescue" in json.loads(body): return (httplib.OK, '{"adminPass": "foo"}', {}, httplib.responses[httplib.OK]) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) def _v1_1_slug_servers_12066_action(self, method, url, body, headers): if method != "POST": self.fail('HTTP method other than POST to action URL') if "rebuild" not in json.loads(body): self.fail("Did not get expected action (rebuild) in action URL") self.assertTrue('\"OS-DCF:diskConfig\": \"MANUAL\"' in body, msg="Manual disk configuration option was not specified in rebuild body: " + body) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) def _v1_1_slug_servers_12065(self, method, url, body, headers): if method == "DELETE": return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) else: raise NotImplementedError() def _v1_1_slug_servers_12064(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_servers_12064.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == "PUT": body = self.fixtures.load('_servers_12064_updated_name_bob.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == "DELETE": return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) else: raise NotImplementedError() def _v1_1_slug_servers_12062(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_servers_12064.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers_12063_metadata(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_servers_12063_metadata_two_keys.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == "PUT": body = self.fixtures.load('_servers_12063_metadata_two_keys.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers_EX_DISK_CONFIG(self, method, url, body, headers): if method == "POST": body = u(body) self.assertTrue(body.find('\"OS-DCF:diskConfig\": \"AUTO\"')) body = self.fixtures.load('_servers_create_disk_config.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_flavors_7(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_flavors_7.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_images_13(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_images_13.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_images_f24a3c1b_d52a_4116_91da_25b3eee8f55e(self, method, url, body, headers): if method == "GET" or method == "PATCH": body = self.fixtures.load('_images_f24a3c1b-d52a-4116-91da-25b3eee8f55e.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_images_9af1a54e_a1b2_4df8_b747_4bec97abc799_members(self, method, url, body, headers): if method == "POST": body = self.fixtures.load('_images_9af1a54e_a1b2_4df8_b747_4bec97abc799_members.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_images_8af1a54e_a1b2_4df8_b747_4bec97abc799_members_e2151b1fe02d4a8a2d1f5fc331522c0a(self, method, url, body, headers): if method == "PUT": body = self.fixtures.load('_images_8af1a54e_a1b2_4df8_b747_4bec97abc799_members.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members_016926dff12345e8b10329f24c99745b(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( '_images_d9a9cd9a_278a_444c_90a6_d24b8c688a63_members_016926dff12345e8b10329f24c99745b.json' ) return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_images(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_images_v2.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_images_26365521_8c62_11f9_2c33_283d153ecc3a(self, method, url, body, headers): if method == "DELETE": return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) else: raise NotImplementedError() def _v1_1_slug_images_4949f9ee_2421_4c81_8b49_13119446008b(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( '_images_4949f9ee_2421_4c81_8b49_13119446008b.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_images_4949f9ee_2421_4c81_8b49_13119446008b(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( '_images_f24a3c1b-d52a-4116-91da-25b3eee8f55d.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_0_ports(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_ports_v2.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == "POST": body = self.fixtures.load('_port_v2.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v2_1337_v2_0_ports_126da55e_cfcb_41c8_ae39_a26cb8a7e723(self, method, url, body, headers): if method == "DELETE": return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) elif method == "GET": body = self.fixtures.load('_port_v2.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == "PUT": if body: body = self.fixtures.load('_port_v2.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: return (httplib.INTERNAL_SERVER_ERROR, "", {}, httplib.responses[httplib.INTERNAL_SERVER_ERROR]) else: raise NotImplementedError() def _v2_1337_servers_1c01300f_ef97_4937_8f03_ac676d6234be_os_interface_126da55e_cfcb_41c8_ae39_a26cb8a7e723(self, method, url, body, headers): if method == "DELETE": return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) else: raise NotImplementedError() def _v2_1337_servers_1c01300f_ef97_4937_8f03_ac676d6234be_os_interface(self, method, url, body, headers): if method == "POST": return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) else: raise NotImplementedError() def _v1_1_slug_servers_1c01300f_ef97_4937_8f03_ac676d6234be_os_security_groups(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( '_servers_1c01300f-ef97-4937-8f03-ac676d6234be_os-security-groups.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_security_groups(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_os_security_groups.json') elif method == "POST": body = self.fixtures.load('_os_security_groups_create.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_security_groups_6(self, method, url, body, headers): if method == "DELETE": return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) else: raise NotImplementedError() def _v1_1_slug_os_security_group_rules(self, method, url, body, headers): if method == "POST": body = self.fixtures.load('_os_security_group_rules_create.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_security_group_rules_2(self, method, url, body, headers): if method == "DELETE": return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT]) else: raise NotImplementedError() def _v1_1_slug_os_keypairs(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_os_keypairs.json') elif method == "POST": if 'public_key' in body: body = self.fixtures.load('_os_keypairs_create_import.json') else: body = self.fixtures.load('_os_keypairs_create.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_keypairs_test_key_pair(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_keypairs_get_one.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_keypairs_doesnt_exist(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_keypairs_not_found.json') else: raise NotImplementedError() return (httplib.NOT_FOUND, body, self.json_content_headers, httplib.responses[httplib.NOT_FOUND]) def _v1_1_slug_os_keypairs_key1(self, method, url, body, headers): if method == "DELETE": return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) else: raise NotImplementedError() def _v1_1_slug_os_volumes(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_os_volumes.json') elif method == "POST": body = self.fixtures.load('_os_volumes_create.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( '_os_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d.json') elif method == "DELETE": body = '' else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers_12065_os_volume_attachments(self, method, url, body, headers): if method == "POST": body = self.fixtures.load( '_servers_12065_os_volume_attachments.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_servers_12065_os_volume_attachments_cd76a3a1_c4ce_40f6_9b9f_07a61508938d(self, method, url, body, headers): if method == "DELETE": body = '' else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_floating_ip_pools(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_floating_ip_pools.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_os_floating_ips_foo_bar_id(self, method, url, body, headers): if method == "DELETE": body = '' return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_os_floating_ips(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('_floating_ips.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == "POST": body = self.fixtures.load('_floating_ip.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_servers_4242_action(self, method, url, body, headers): if method == "POST": body = '' return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_os_networks(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_networks.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == 'POST': body = self.fixtures.load('_os_networks_POST.json') return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v1_1_slug_os_networks_f13e5051_feea_416b_827a_1a0acc2dad14(self, method, url, body, headers): if method == 'DELETE': body = '' return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v1_1_slug_servers_72258_action(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_servers_suspend.json') return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_servers_12063_action(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_servers_unpause.json') return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_servers_12086_action(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_servers_12086_console_output.json') return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) else: raise NotImplementedError() def _v1_1_slug_os_snapshots(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_snapshots.json') elif method == 'POST': body = self.fixtures.load('_os_snapshots_create.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_snapshots_3fbbcccf_d058_4502_8844_6feeffdf4cb5(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_snapshot.json') status_code = httplib.OK elif method == 'DELETE': body = '' status_code = httplib.NO_CONTENT else: raise NotImplementedError() return (status_code, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_snapshots_3fbbcccf_d058_4502_8844_6feeffdf4cb5_RACKSPACE(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_snapshot_rackspace.json') status_code = httplib.OK elif method == 'DELETE': body = '' status_code = httplib.NO_CONTENT else: raise NotImplementedError() return (status_code, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v1_1_slug_os_snapshots_RACKSPACE(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_snapshots_rackspace.json') elif method == 'POST': body = self.fixtures.load('_os_snapshots_create_rackspace.json') else: raise NotImplementedError() return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_networks(self, method, url, body, headers): if method == 'GET': if "router:external=True" in url: body = self.fixtures.load('_v2_0__networks_public.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) else: body = self.fixtures.load('_v2_0__networks.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == 'POST': body = self.fixtures.load('_v2_0__networks_POST.json') return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v2_1337_v2_0_networks_d32019d3_bc6e_4319_9c1d_6722fc136a22(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_v2_0__networks_POST.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_subnets_08eae331_0402_425a_923c_34f7cfe39c1b(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_v2_0__subnet.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == 'PUT': body = self.fixtures.load('_v2_0__subnet.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_subnets(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_v2_0__subnet.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK]) else: body = self.fixtures.load('_v2_0__subnets.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_volumes_detail(self, method, url, body, headers): body = self.fixtures.load('_v2_0__volumes.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_volumes(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_v2_0__volume.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_volumes_cd76a3a1_c4ce_40f6_9b9f_07a61508938d(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_v2_0__volume.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_volumes_abc6a3a1_c4ce_40f6_9b9f_07a61508938d(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_v2_0__volume_abc6a3a1_c4ce_40f6_9b9f_07a61508938d.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_snapshots_detail(self, method, url, body, headers): if ('unit_test=paginate' in url and 'marker' not in url) or \ 'unit_test=pagination_loop' in url: body = self.fixtures.load('_v2_0__snapshots_paginate_start.json') else: body = self.fixtures.load('_v2_0__snapshots.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_snapshots(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_v2_0__snapshot.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_snapshots_3fbbcccf_d058_4502_8844_6feeffdf4cb5(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_v2_0__snapshot.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_security_groups(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_v2_0__security_group.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'GET': body = self.fixtures.load('_v2_0__security_groups.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_security_groups_6(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_v2_0__security_group.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_security_group_rules(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_v2_0__security_group_rule.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_security_group_rules_2(self, method, url, body, headers): if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_floatingips(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_v2_0__floatingip.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'GET': body = self.fixtures.load('_v2_0__floatingips.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_floatingips_foo_bar_id(self, method, url, body, headers): if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_routers_f8a44de0_fc8e_45df_93c7_f79bf3b01c95(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_v2_0__router.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) if method == 'DELETE': body = '' return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_routers(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('_v2_0__router.json') return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK]) else: body = self.fixtures.load('_v2_0__routers.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_routers_f8a44de0_fc8e_45df_93c7_f79bf3b01c95_add_router_interface(self, method, url, body, headers): if method == 'PUT': body = self.fixtures.load('_v2_0__router_interface.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_v2_0_routers_f8a44de0_fc8e_45df_93c7_f79bf3b01c95_remove_router_interface(self, method, url, body, headers): if method == 'PUT': body = self.fixtures.load('_v2_0__router_interface.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) def _v2_1337_servers_1000_action(self, method, url, body, headers): if method != 'POST' or body != '{"removeSecurityGroup": {"name": "sgname"}}': raise NotImplementedError(body) return httplib.ACCEPTED, None, {}, httplib.responses[httplib.ACCEPTED] # This exists because the nova compute url in devstack has v2 in there but the v1.1 fixtures # work fine. class OpenStack_2_0_MockHttp(OpenStack_1_1_MockHttp): def __init__(self, *args, **kwargs): super(OpenStack_2_0_MockHttp, self).__init__(*args, **kwargs) methods1 = OpenStack_1_1_MockHttp.__dict__ names1 = [m for m in methods1 if m.find('_v1_1') == 0] for name in names1: method = methods1[name] new_name = name.replace('_v1_1_slug_', '_v2_1337_') setattr(self, new_name, method_type(method, self, OpenStack_2_0_MockHttp)) class OpenStack_1_1_Auth_2_0_Tests(OpenStack_1_1_Tests): driver_args = OPENSTACK_PARAMS + ('1.1',) driver_kwargs = {'ex_force_auth_version': '2.0'} def setUp(self): self.driver_klass.connectionCls.conn_class = OpenStack_2_0_MockHttp self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" OpenStackMockHttp.type = None OpenStack_1_1_MockHttp.type = None OpenStack_2_0_MockHttp.type = None self.driver = self.create_driver() # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() clear_pricing_data() self.node = self.driver.list_nodes()[1] def test_auth_user_info_is_set(self): self.driver.connection._populate_hosts_and_request_paths() self.assertEqual(self.driver.connection.auth_user_info, { 'id': '7', 'name': 'testuser', 'roles': [{'description': 'Default Role.', 'id': 'identity:default', 'name': 'identity:default'}]}) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_ovh.py0000664000175000017500000002457013535474530023101 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from mock import patch from libcloud.utils.py3 import httplib from libcloud.compute.drivers.ovh import OvhNodeDriver from libcloud.test.common.test_ovh import BaseOvhMockHttp from libcloud.test.secrets import OVH_PARAMS from libcloud.test.file_fixtures import ComputeFileFixtures class OvhMockHttp(BaseOvhMockHttp): """Fixtures needed for tests related to rating model""" fixtures = ComputeFileFixtures('ovh') def _json_1_0_auth_time_get(self, method, url, body, headers): body = self.fixtures.load('auth_time_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_region_get(self, method, url, body, headers): body = self.fixtures.load('region_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_flavor_get(self, method, url, body, headers): body = self.fixtures.load('flavor_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_flavor_region_SBG1_get(self, method, url, body, headers): body = self.fixtures.load('flavor_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_flavor_foo_id_get(self, method, url, body, headers): body = self.fixtures.load('flavor_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_image_get(self, method, url, body, headers): body = self.fixtures.load('image_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_image_foo_id_get(self, method, url, body, headers): body = self.fixtures.load('image_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_sshkey_region_SBG1_get(self, method, url, body, headers): body = self.fixtures.load('ssh_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_sshkey_post(self, method, url, body, headers): body = self.fixtures.load('ssh_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_ssh_mykey_get(self, method, url, body, headers): body = self.fixtures.load('ssh_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_instance_get(self, method, url, body, headers): body = self.fixtures.load('instance_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_instance_foo_get(self, method, url, body, headers): body = self.fixtures.load('instance_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_instance_foo_delete(self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_instance_post(self, method, url, body, headers): body = self.fixtures.load('instance_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_get(self, method, url, body, headers): body = self.fixtures.load('volume_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_post(self, method, url, body, headers): body = self.fixtures.load('volume_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_foo_get(self, method, url, body, headers): body = self.fixtures.load('volume_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_foo_delete(self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_foo_attach_post(self, method, url, body, headers): body = self.fixtures.load('volume_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_foo_detach_post(self, method, url, body, headers): body = self.fixtures.load('volume_get_detail.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_snapshot_region_SBG_1_get(self, method, url, body, headers): body = self.fixtures.load('volume_snapshot_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_snapshot_get(self, method, url, body, headers): body = self.fixtures.load('volume_snapshot_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_snapshot_foo_get(self, method, url, body, headers): body = self.fixtures.load('volume_snapshot_get_details.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_snapshot_foo_snap_delete(self, method, url, body, headers): return (httplib.OK, None, {}, httplib.responses[httplib.OK]) def _json_1_0_cloud_project_project_id_volume_foo_snapshot__post(self, method, url, body, headers): body = self.fixtures.load('volume_snapshot_get_details.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) @patch('libcloud.common.ovh.OvhConnection._timedelta', 42) class OvhTests(unittest.TestCase): def setUp(self): OvhNodeDriver.connectionCls.conn_class = OvhMockHttp OvhMockHttp.type = None self.driver = OvhNodeDriver(*OVH_PARAMS) def test_list_locations(self): images = self.driver.list_locations() self.assertTrue(len(images) > 0) def test_list_images(self): images = self.driver.list_images() self.assertTrue(len(images) > 0) def test_get_image(self): image = self.driver.get_image('foo-id') self.assertEqual(image.id, 'foo-id') def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertTrue(len(sizes) > 0) def test_get_size(self): size = self.driver.ex_get_size('foo-id') self.assertEqual(size.id, 'foo-id') def test_list_key_pairs(self): keys = self.driver.list_sizes() self.assertTrue(len(keys) > 0) def test_get_key_pair(self): location = self.driver.list_locations()[0] key = self.driver.get_key_pair('mykey', location) self.assertEqual(key.name, 'mykey') def test_import_key_pair_from_string(self): location = self.driver.list_locations()[0] key = self.driver.import_key_pair_from_string('mykey', 'material', location) self.assertEqual(key.name, 'mykey') def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertTrue(len(nodes) > 0) def test_get_node(self): node = self.driver.ex_get_node('foo') self.assertEqual(node.name, 'test_vm') def test_create_node(self): location = self.driver.list_locations()[0] image = self.driver.list_sizes(location)[0] size = self.driver.list_sizes(location)[0] node = self.driver.create_node(name='test_vm', image=image, size=size, location=location) self.assertEqual(node.name, 'test_vm') def test_destroy_node(self): node = self.driver.list_nodes()[0] self.driver.destroy_node(node) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertTrue(len(volumes) > 0) def test_get_volume(self): volume = self.driver.ex_get_volume('foo') self.assertEqual(volume.name, 'testvol') def test_create_volume(self): location = self.driver.list_locations()[0] volume = self.driver.create_volume(size=10, name='testvol', location=location) self.assertEqual(volume.name, 'testvol') def test_destroy_volume(self): volume = self.driver.list_volumes()[0] self.driver.destroy_volume(volume) def test_attach_volume(self): node = self.driver.list_nodes()[0] volume = self.driver.ex_get_volume('foo') response = self.driver.attach_volume(node=node, volume=volume) self.assertTrue(response) def test_detach_volume(self): node = self.driver.list_nodes()[0] volume = self.driver.ex_get_volume('foo') response = self.driver.detach_volume(ex_node=node, volume=volume) self.assertTrue(response) def test_ex_list_snapshots(self): self.driver.ex_list_snapshots() def test_ex_get_volume_snapshot(self): self.driver.ex_get_volume_snapshot('foo') def test_list_volume_snapshots(self): volume = self.driver.ex_get_volume('foo') self.driver.list_volume_snapshots(volume) def test_create_volume_snapshot(self): volume = self.driver.ex_get_volume('foo') self.driver.create_volume_snapshot(volume) def test_destroy_volume_snapshot(self): snapshot = self.driver.ex_get_volume_snapshot('foo') result = self.driver.destroy_volume_snapshot(snapshot) self.assertTrue(result) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_packet.py0000664000175000017500000005156713576514553023567 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Maintainer: Aaron Welch # Based on code written by Jed Smith who based it on # code written by Alex Polvi # import sys import unittest import json from libcloud.utils.py3 import httplib from libcloud.compute.drivers.packet import PacketNodeDriver from libcloud.compute.base import Node, KeyPair from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures # This is causing test failures inder Python 3.5 import libcloud.compute.drivers.packet libcloud.compute.drivers.packet.USE_ASYNC_IO_IF_AVAILABLE = False __all__ = [ 'PacketTest' ] class PacketTest(unittest.TestCase, TestCaseMixin): def setUp(self): PacketNodeDriver.connectionCls.conn_class = PacketMockHttp self.driver = PacketNodeDriver('foo') def test_list_nodes(self): nodes = self.driver.list_nodes('project-id') self.assertEqual(len(nodes), 1) node = nodes[0] self.assertEqual(node.id, '1e52437e-bbbb-cccc-dddd-74a9dfd3d3bb') self.assertEqual(node.name, 'test-node') self.assertEqual(node.state, NodeState.RUNNING) self.assertTrue('147.75.255.255' in node.public_ips) self.assertTrue('2604:EEEE::EE' in node.public_ips) self.assertTrue('10.0.0.255' in node.private_ips) self.assertEqual(node.extra['created_at'], '2015-05-03T15:50:49Z') self.assertEqual(node.extra['updated_at'], '2015-05-03T16:00:08Z') self.assertEqual(node.extra['billing_cycle'], 'hourly') self.assertEqual(node.extra['locked'], False) self.assertEqual(node.size.id, 'baremetal_1') self.assertEqual(node.size.name, 'Type 1 - 16GB RAM') self.assertEqual(node.size.ram, 16384) self.assertEqual(node.size.disk, 240) self.assertEqual(node.size.price, 0.4) self.assertEqual(node.size.extra['line'], 'baremetal') self.assertEqual(node.image.id, 'ubuntu_14_04') self.assertEqual(node.image.name, 'Ubuntu 14.04 LTS') self.assertEqual(node.image.extra['distro'], 'ubuntu') self.assertEqual(node.image.extra['version'], '14.04') def test_list_nodes_response(self): nodes = self.driver.list_nodes('project-id') self.assertTrue(isinstance(nodes, list)) for node in nodes: self.assertTrue(isinstance(node, Node)) def test_list_locations(self): locations = self.driver.list_locations() self.assertEqual(len(locations), 1) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 4) def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 1) def test_create_node(self): node = self.driver.create_node(ex_project_id="project-id", name="node-name", size=self.driver.list_sizes()[0], image=self.driver.list_images()[0], location=self.driver.list_locations()[ 0]) self.assertTrue(isinstance(node, Node)) def test_create_node_response(self): size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] location = self.driver.list_locations()[0] node = self.driver.create_node(ex_project_id="project-id", name='node-name', image=image, size=size, location=location) self.assertTrue(isinstance(node, Node)) def test_reboot_node(self): node = self.driver.list_nodes('project-id')[0] self.driver.reboot_node(node) def test_reboot_node_response(self): node = self.driver.list_nodes('project-id')[0] self.driver.reboot_node(node) def test_destroy_node(self): node = self.driver.list_nodes('project-id')[0] self.driver.destroy_node(node) def test_destroy_node_response(self): node = self.driver.list_nodes('project-id')[0] self.driver.destroy_node(node) def test_reinstall_node(self): node = self.driver.list_nodes('project-id')[0] self.driver.ex_reinstall_node(node) def test_rescue_node(self): node = self.driver.list_nodes('project-id')[0] self.driver.ex_rescue_node(node) def test_list_key_pairs(self): keys = self.driver.list_key_pairs() self.assertEqual(len(keys), 3) def test_create_key_pair(self): key = self.driver.create_key_pair(name="sshkey-name", public_key="ssh-rsa AAAAB3NzaC1yc2EA\ AAADAQABAAABAQDI4pIqzpb5g3992h+yr527VRcaB68KE4vPjWPPoiQws49KIs2NMcOzS9QE4641uW\ 1u5ML2HgQdfYKMF/YFGnI1Y6xV637DjhDyZYV9LasUH49npSSJjsBcsk9JGfUpNAOdcgpFzK8V90ei\ OrOC5YncxdwwG8pwjFI9nNVPCl4hYEu1iXdyysHvkFfS2fklsNjLWrzfafPlaen+qcBxygCA0sFdW/\ 7er50aJeghdBHnE2WhIKLUkJxnKadznfAge7oEe+3LLAPfP+3yHyvp2+H0IzmVfYvAjnzliYetqQ8p\ g5ZW2BiJzvqz5PebGS70y/ySCNW1qQmJURK/Wc1bt9en root@libcloud") self.assertTrue(isinstance(key, KeyPair)) def test_delete_key_pair(self): key = self.driver.list_key_pairs()[0] self.driver.delete_key_pair(key) def test_ex_list_projects(self): projects = self.driver.ex_list_projects() self.assertEqual(len(projects), 3) def test_ex_get_bgp_config_for_project(self): config = self.driver.ex_get_bgp_config_for_project(ex_project_id='4b653fce-6405-4300-9f7d-c587b7888fe5') self.assertEqual(config.get('status'), 'enabled') def test_ex_get_bgp_config(self): config = self.driver.ex_get_bgp_config() self.assertEqual(len(config), 2) def test_ex_list_nodes_for_project(self): nodes = self.driver.ex_list_nodes_for_project(ex_project_id='4b653fce-6405-4300-9f7d-c587b7888fe5') self.assertEqual(nodes[0].public_ips, ['147.75.102.193', '2604:1380:2000:c100::3']) def test_ex_create_bgp_session(self): node = self.driver.list_nodes('project-id')[0] session = self.driver.ex_create_bgp_session(node, 'ipv4') self.assertEqual(session['status'], 'unknown') def test_ex_get_bgp_session(self): session = self.driver.ex_get_bgp_session(self.driver.ex_list_bgp_sessions()[0]['id']) self.assertEqual(session['status'], 'down') def test_ex_list_bgp_sessions_for_project(self): sessions = self.driver.ex_list_bgp_sessions_for_project(ex_project_id='4b653fce-6405-4300-9f7d-c587b7888fe5') self.assertEqual(sessions['bgp_sessions'][0]['status'], 'down') def test_ex_list_bgp_sessions_for_node(self): sessions = self.driver.ex_list_bgp_sessions_for_node(self.driver.list_nodes()[0]) self.assertEqual(sessions['bgp_sessions'][0]['status'], 'down') def test_ex_list_bgp_sessions(self): sessions = self.driver.ex_list_bgp_sessions() self.assertEqual(sessions[0]['status'], 'down') def test_ex_delete_bgp_session(self): self.driver.ex_delete_bgp_session(session_uuid='08f6b756-758b-4f1f-bfaf-b9b5479822d7') def test_ex_list_events_for_node(self): events = self.driver.ex_list_events_for_node(self.driver.list_nodes()[0]) self.assertEqual(events['events'][0]['ip'], '157.52.105.28') def test_ex_list_events_for_project(self): events = self.driver.ex_list_events_for_project(self.driver.ex_list_projects()[0]) self.assertEqual(events['meta']['total'], len(events['events'])) def test_ex_get_node_bandwidth(self): node = self.driver.list_nodes('project-id')[0] bw = self.driver.ex_get_node_bandwidth(node, 1553194476, 1553198076) self.assertTrue(len(bw['bandwidth'][0]['datapoints'][0]) > 0) def test_ex_update_node(self): node = self.driver.list_nodes('project-id')[0] self.driver.ex_update_node(node, description='new_description') def test_ex_describe_all_addresses_for_project(self): addresses = self.driver.ex_describe_all_addresses_for_project( '4b653fce-6405-4300-9f7d-c587b7888fe5') self.assertEqual(len(addresses), 5) def test_ex_describe_address(self): address = self.driver.ex_describe_address( ex_address_id='01c184f5-1413-4b0b-9f6d-ac993f6c9241') self.assertEqual(address['network'], '147.75.33.32') def test_ex_request_address_reservation(self): response = self.driver.ex_request_address_reservation( ex_project_id='3d27fd13-0466-4878-be22-9a4b5595a3df') assert response['global_ip'] def test_ex_associate_address_with_node(self): node = self.driver.list_nodes('project-id')[0] response = self.driver.ex_associate_address_with_node(node, '147.75.40.2/32') assert response['enabled'] def test_ex_disassociate_address_with_node(self): node = self.driver.list_nodes('project-id')[0] assignments = self.driver.ex_list_ip_assignments_for_node(node) for ip_assignment in assignments['ip_addresses']: if ip_assignment['gateway'] == '147.75.40.2': self.driver.ex_disassociate_address( ip_assignment['id']) break def test_list_volumes(self): volumes = self.driver.list_volumes() assert len(volumes) == 2 assert len(volumes[0].extra['attachments']) == 0 def test_create_volume(self): location = self.driver.list_locations()[0] volume = self.driver.create_volume( 10, location, description="test volume", plan="storage_1", ex_project_id='3d27fd13-0466-4878-be22-9a4b5595a3df') assert len(volume.extra['attachments']) == 0 assert not volume.extra['locked'] def test_attach_volume(self): attached = False volumes = self.driver.ex_list_volumes_for_project(ex_project_id='3d27fd13-0466-4878-be22-9a4b5595a3df') node = self.driver.ex_list_nodes_for_project(ex_project_id='3d27fd13-0466-4878-be22-9a4b5595a3df')[0] for vol in volumes: if len(vol.extra['attachments']) == 0: attached = self.driver.attach_volume(node, vol) break assert attached def test_detach_volume(self): detached = False volumes = self.driver.ex_list_volumes_for_project(ex_project_id='3d27fd13-0466-4878-be22-9a4b5595a3df') for vol in volumes: if len(vol.extra['attachments']) > 0: detached = self.driver.detach_volume(vol) break assert detached def test_destroy_volume(self): destroyed = False volumes = self.driver.ex_list_volumes_for_project(ex_project_id='3d27fd13-0466-4878-be22-9a4b5595a3df') for vol in volumes: if len(vol.extra['attachments']) == 0: destroyed = self.driver.destroy_volume(vol) break assert destroyed class PacketMockHttp(MockHttp): fixtures = ComputeFileFixtures('packet') def _facilities(self, method, url, body, headers): body = self.fixtures.load('facilities.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _plans(self, method, url, body, headers): body = self.fixtures.load('plans.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_3d27fd13_0466_4878_be22_9a4b5595a3df_plans(self, method, url, body, headers): body = self.fixtures.load('plans.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects(self, method, url, body, headers): body = self.fixtures.load('projects.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4b653fce_6405_4300_9f7d_c587b7888fe5_devices(self, method, url, body, headers): body = self.fixtures.load('devices_for_project.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4a4bce6b_d2ef_41f8_95cf_0e2f32996440_devices(self, method, url, body, headers): body = self.fixtures.load('devices_for_project.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_3d27fd13_0466_4878_be22_9a4b5595a3df_devices(self, method, url, body, headers): body = self.fixtures.load('devices_for_project.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4b653fce_6405_4300_9f7d_c587b7888fe5_ips(self, method, url, body, headers): body = self.fixtures.load('project_ips.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_3d27fd13_0466_4878_be22_9a4b5595a3df_ips(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('reserve_ip.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4b653fce_6405_4300_9f7d_c587b7888fe5_bgp_config(self, method, url, body, headers): body = self.fixtures.load('bgp_config_project_1.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_3d27fd13_0466_4878_be22_9a4b5595a3df_bgp_config(self, method, url, body, headers): body = self.fixtures.load('bgp_config_project_1.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4a4bce6b_d2ef_41f8_95cf_0e2f32996440_bgp_config(self, method, url, body, headers): body = self.fixtures.load('bgp_config_project_3.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _operating_systems(self, method, url, body, headers): body = self.fixtures.load('operatingsystems.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ssh_keys(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('sshkeys.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if method == 'POST': body = self.fixtures.load('sshkey_create.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ssh_keys_2c1a7f23_1dc6_4a37_948e_d9857d9f607c(self, method, url, body, headers): if method == 'DELETE': return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _projects_project_id_devices(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('device_create.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'GET': body = self.fixtures.load('devices.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _devices_1e52437e_bbbb_cccc_dddd_74a9dfd3d3bb(self, method, url, body, headers): if method in ['DELETE', 'PUT']: return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _devices_1e52437e_bbbb_cccc_dddd_74a9dfd3d3bb_actions( self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _devices_1e52437e_bbbb_cccc_dddd_74a9dfd3d3bb_bgp_sessions(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('bgp_session_create.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _bgp_sessions_08f6b756_758b_4f1f_bfaf_b9b5479822d7(self, method, url, body, headers): body = self.fixtures.load('bgp_session_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4b653fce_6405_4300_9f7d_c587b7888fe5_bgp_sessions(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('bgp_sessions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _devices_905037a4_967c_4e81_b364_3a0603aa071b_bgp_sessions(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('bgp_sessions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4a4bce6b_d2ef_41f8_95cf_0e2f32996440_bgp_sessions(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('bgp_sessions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_3d27fd13_0466_4878_be22_9a4b5595a3df_bgp_sessions(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('bgp_sessions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_3d27fd13_0466_4878_be22_9a4b5595a3df_events(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('project_events.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _devices_905037a4_967c_4e81_b364_3a0603aa071b_events(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('device_events.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _devices_1e52437e_bbbb_cccc_dddd_74a9dfd3d3bb_bandwidth(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('node_bandwidth.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ips_01c184f5_1413_4b0b_9f6d_ac993f6c9241(self, method, url, body, headers): body = self.fixtures.load('ip_address.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _devices_1e52437e_bbbb_cccc_dddd_74a9dfd3d3bb_ips(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('ip_assignments.json') elif method == 'POST': body = self.fixtures.load('associate_ip.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ips_aea4ee0c_675f_4b77_8337_8e13b868dd9c(self, method, url, body, headers): if method == 'DELETE': return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _projects_3d27fd13_0466_4878_be22_9a4b5595a3df_storage(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('volumes.json') elif method == 'POST': body = self.fixtures.load('create_volume.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4a4bce6b_d2ef_41f8_95cf_0e2f32996440_storage(self, method, url, body, headers): if method == 'GET': body = json.dumps({"volumes": []}) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _projects_4b653fce_6405_4300_9f7d_c587b7888fe5_storage(self, method, url, body, headers): if method == 'GET': body = json.dumps({"volumes": []}) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _storage_74f11291_fde8_4abf_8150_e51cda7308c3(self, method, url, body, headers): if method == 'DELETE': return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.NO_CONTENT]) def _storage_a08aaf76_e0ce_43aa_b9cd_cce0d4ae4f4c_attachments(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('attach_volume.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _storage_a08aaf76_e0ce_43aa_b9cd_cce0d4ae4f4c(self, method, url, body, headers): if method == 'DELETE': return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.NO_CONTENT]) def _storage_attachments_2c16a96f_bb4f_471b_8e2e_b5820b9e1603(self, method, url, body, headers): if method == 'DELETE': return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.NO_CONTENT]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_profitbricks.py0000664000175000017500000036220713535474530025010 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from six import assertRegex from libcloud.utils.py3 import httplib from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.compute.types import Provider from libcloud.compute.types import NodeState from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey from libcloud.compute.providers import get_driver from libcloud.test import unittest from libcloud.test.secrets import PROFIT_BRICKS_PARAMS from libcloud.common.exceptions import BaseHTTPError class ProfitBricksTests(unittest.TestCase): def setUp(self): ProfitBricks = get_driver(Provider.PROFIT_BRICKS) ProfitBricks.connectionCls.conn_class = ProfitBricksMockHttp self.driver = ProfitBricks(*PROFIT_BRICKS_PARAMS) ''' Function tests for listing items ''' def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 7) def test_list_images(self): """ Fetch all images and then fetch with filters """ all_images = self.driver.list_images() hdd_images = self.driver.list_images('HDD') cdd_images = self.driver.list_images('CDROM') private_images = self.driver.list_images(is_public=False) self.assertEqual(len(all_images), 4) self.assertEqual(len(hdd_images), 2) self.assertEqual(len(cdd_images), 2) self.assertEqual(len(private_images), 2) image = all_images[0] extra = image.extra ''' Standard properties ''' self.assertEqual(image.id, 'img-1') self.assertEqual(image.name, 'Test-Image-Two-CDROM') ''' Extra metadata ''' self.assertEqual(extra['created_date'], '2014-11-14T15:22:19Z') self.assertEqual(extra['created_by'], 'System') self.assertEqual(extra['etag'], '957e0eac7456fa7554e73bf0d18860eb') self.assertEqual(extra['last_modified_date'], '2014-11-14T15:22:19Z') self.assertEqual(extra['last_modified_by'], 'System') ''' Extra properties ''' self.assertEqual(extra['name'], 'Test-Image-Two-CDROM') self.assertEqual(extra['description'], '') self.assertEqual(extra['location'], 'us/las') self.assertEqual(extra['size'], 4) self.assertEqual(extra['cpu_hot_plug'], False) self.assertEqual(extra['cpu_hot_unplug'], False) self.assertEqual(extra['ram_hot_plug'], False) self.assertEqual(extra['ram_hot_unplug'], False) self.assertEqual(extra['nic_hot_plug'], False) self.assertEqual(extra['nic_hot_unplug'], False) self.assertEqual(extra['disc_virtio_hot_plug'], False) self.assertEqual(extra['disc_virtio_hot_unplug'], False) self.assertEqual(extra['disc_scsi_hot_plug'], False) self.assertEqual(extra['disc_scsi_hot_unplug'], False) self.assertEqual(extra['licence_type'], 'OTHER') self.assertEqual(extra['image_type'], 'CDROM') self.assertEqual(extra['public'], True) self.assertIsInstance(extra['image_aliases'], list) def test_list_locations(self): locations = self.driver.list_locations() self.assertTrue(len(locations) > 0) ''' Standard properties ''' location = locations[2] self.assertEqual(location.id, 'us/las') self.assertEqual(location.name, 'lasvegas') self.assertEqual(location.country, 'us') def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) node = nodes[0] extra = node.extra ''' Standard properties ''' self.assertEqual( node.id, 'srv-1' ) self.assertEqual( node.name, 'libcloud Test' ) self.assertEqual( node.state, NodeState.RUNNING ) self.assertEqual( node.public_ips, [] ) self.assertEqual( node.private_ips, [] ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-18T07:28:05Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'e7cf186125f51f3d9511754a40dcd12c' ) self.assertEqual( extra['last_modified_date'], '2016-10-18T07:28:05Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['availability_zone'], 'AUTO' ) self.assertEqual( extra['boot_cdrom'], None ) self.assertEqual( extra['boot_volume']['id'], 'bvol-1' ) self.assertEqual( extra['boot_volume']['href'], ( '/cloudapi/v4/datacenters/dc-1' '/volumes/bvol-1' ) ) self.assertEqual( extra['boot_volume']['properties']['name'], 'libcloud Test' ) self.assertEqual( extra['boot_volume']['properties']['type'], 'HDD' ) self.assertEqual( extra['boot_volume']['properties']['size'], 2 ) self.assertEqual( extra['boot_volume']['properties']['image'], 'bvol-img' ) self.assertEqual( extra['cpu_family'], 'AMD_OPTERON' ) ''' Other miscellaneous ''' self.assertEqual( len(extra['entities']), 3 ) self.assertNotIn( 'status_url', extra ) def test_ex_list_availability_zones(self): zones = self.driver.ex_list_availability_zones() self.assertEqual(len(zones), 3) zones_sorted = sorted(list(a.name for a in zones)) zones_expected = ['AUTO', 'ZONE_1', 'ZONE_2'] self.assertEqual(zones_sorted, zones_expected) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertTrue(len(volumes) > 0) def test_ex_list_datacenters(self): datacenters = self.driver.ex_list_datacenters() self.assertTrue(len(datacenters) > 0) datacenter = datacenters[0] extra = datacenter.extra ''' Standard properties ''' self.assertEqual( datacenter.id, 'dc-1' ) self.assertEqual( datacenter.href, '/cloudapi/v4/datacenters/dc-1' ) self.assertEqual( datacenter.name, 'libcloud Test' ) self.assertEqual( datacenter.version, 3 ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['description'], 'libcloud test datacenter' ) self.assertEqual( extra['location'], 'us/las' ) self.assertEqual( extra['version'], 3 ) self.assertEqual( extra['features'], ['SSD', 'MULTIPLE_CPU'] ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-14T07:24:59Z' ) self.assertEqual( extra['created_by'], 'test@test.test' ) self.assertEqual( extra['etag'], 'bdddec2287cb7723e86ac088bf644606' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T15:27:25Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.test' ) self.assertEqual( extra['state'], 'AVAILABLE' ) self.assertEqual( extra['provisioning_state'], NodeState.RUNNING ) self.assertEqual( len(extra['entities']), 4 ) self.assertNotIn( 'status_url', extra ) def test_list_snapshots(self): volume_snapshots = self.driver.list_snapshots() self.assertTrue(len(volume_snapshots) > 0) snapshot = volume_snapshots[0] ''' Standard properties ''' self.assertEqual( snapshot.id, 'sshot' ) self.assertEqual( snapshot.size, 10 ) self.assertEqual( snapshot.created, '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.state, NodeState.RUNNING) self.assertEqual( snapshot.name, 'Balancer Testing 1 Storage-Snapshot-10/26/2016' ) ''' Extra properties ''' self.assertEqual( snapshot.extra['name'], 'Balancer Testing 1 Storage-Snapshot-10/26/2016' ) self.assertEqual( snapshot.extra['description'], ( 'Created from \"Balancer Testing 1' ' Storage\" in Data Center \"Snapshot\"' ) ) self.assertEqual( snapshot.extra['location'], 'us/las' ) self.assertEqual( snapshot.extra['size'], 10 ) self.assertEqual( snapshot.extra['cpu_hot_plug'], True ) self.assertEqual( snapshot.extra['cpu_hot_unplug'], False ) self.assertEqual( snapshot.extra['ram_hot_plug'], True ) self.assertEqual( snapshot.extra['ram_hot_unplug'], False ) self.assertEqual( snapshot.extra['nic_hot_plug'], True ) self.assertEqual( snapshot.extra['nic_hot_unplug'], True ) self.assertEqual( snapshot.extra['disc_virtio_hot_plug'], True ) self.assertEqual( snapshot.extra['disc_virtio_hot_unplug'], True ) self.assertEqual( snapshot.extra['disc_scsi_hot_plug'], False ) self.assertEqual( snapshot.extra['disc_scsi_hot_unplug'], False ) self.assertEqual( snapshot.extra['licence_type'], 'LINUX' ) ''' Extra metadata ''' self.assertEqual( snapshot.extra['created_date'], '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.extra['created_by'], 'test@test.te' ) self.assertEqual( snapshot.extra['etag'], '01873262ac042b5f44ed33b4241225b4' ) self.assertEqual( snapshot.extra['last_modified_date'], '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.extra['last_modified_by'], 'test@test.te' ) self.assertEqual( snapshot.extra['state'], 'AVAILABLE' ) ''' Function tests for operations on volume snapshots ''' def test_create_volume_snapshot(self): volume = self.driver.ex_describe_volume( ( '/cloudapi/v4/datacenters/' 'dc-1/' 'volumes/vol-2' ) ) snapshot = self.driver.create_volume_snapshot(volume=volume) ''' Standard properties ''' self.assertEqual( snapshot.id, 'sshot' ) self.assertEqual( snapshot.size, 10 ) self.assertEqual( snapshot.created, '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.state, NodeState.PENDING ) self.assertEqual( snapshot.name, 'libcloud Test' ) ''' Extra properties ''' self.assertEqual( snapshot.extra['name'], 'libcloud Test' ) self.assertEqual( snapshot.extra['description'], 'libcloud test snapshot' ) self.assertEqual( snapshot.extra['location'], 'us/las' ) self.assertEqual( snapshot.extra['size'], 10 ) self.assertEqual( snapshot.extra['cpu_hot_plug'], True ) self.assertEqual( snapshot.extra['cpu_hot_unplug'], False ) self.assertEqual( snapshot.extra['ram_hot_plug'], True ) self.assertEqual( snapshot.extra['ram_hot_unplug'], False ) self.assertEqual( snapshot.extra['nic_hot_plug'], True ) self.assertEqual( snapshot.extra['nic_hot_unplug'], True ) self.assertEqual( snapshot.extra['disc_virtio_hot_plug'], True ) self.assertEqual( snapshot.extra['disc_virtio_hot_unplug'], True ) self.assertEqual( snapshot.extra['disc_scsi_hot_plug'], False ) self.assertEqual( snapshot.extra['disc_scsi_hot_unplug'], False ) self.assertEqual( snapshot.extra['licence_type'], 'LINUX' ) ''' Extra metadata ''' self.assertEqual( snapshot.extra['created_date'], '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.extra['created_by'], 'test@test.te' ) self.assertEqual( snapshot.extra['etag'], '01873262ac042b5f44ed33b4241225b4' ) self.assertEqual( snapshot.extra['last_modified_date'], '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.extra['last_modified_by'], 'test@test.te' ) self.assertEqual( snapshot.extra['state'], 'BUSY' ) def test_create_volume_snapshot_failure(self): with self.assertRaises(AttributeError): 'Raises attribute error if no volume' self.driver.create_volume_snapshot(volume=None) def test_ex_describe_snapshot(self): snapshot_w_href = self.driver.ex_describe_snapshot( ex_href='/cloudapi/v4/snapshots/sshot' ) snapshot_w_id = self.driver.ex_describe_snapshot( ex_snapshot_id='sshot' ) self._verify_snapshot(snapshot=snapshot_w_href) self._verify_snapshot(snapshot=snapshot_w_id) def test_ex_describe_snapshot_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_snapshot( ex_snapshot_id='00000000' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_snapshot(self, snapshot): """ Standard properties """ self.assertEqual( snapshot.id, 'sshot' ) self.assertEqual( snapshot.size, 10 ) self.assertEqual( snapshot.created, '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.state, NodeState.RUNNING ) self.assertEqual( snapshot.name, 'libcloud Test' ) ''' Extra properties ''' self.assertEqual( snapshot.extra['name'], 'libcloud Test' ) self.assertEqual( snapshot.extra['description'], 'libcloud test snapshot' ) self.assertEqual( snapshot.extra['location'], 'us/las' ) self.assertEqual( snapshot.extra['size'], 10 ) self.assertEqual( snapshot.extra['cpu_hot_plug'], True ) self.assertEqual( snapshot.extra['cpu_hot_unplug'], False ) self.assertEqual( snapshot.extra['ram_hot_plug'], True ) self.assertEqual( snapshot.extra['ram_hot_unplug'], False ) self.assertEqual( snapshot.extra['nic_hot_plug'], True ) self.assertEqual( snapshot.extra['nic_hot_unplug'], True ) self.assertEqual( snapshot.extra['disc_virtio_hot_plug'], True ) self.assertEqual( snapshot.extra['disc_virtio_hot_unplug'], True ) self.assertEqual( snapshot.extra['disc_scsi_hot_plug'], False ) self.assertEqual( snapshot.extra['disc_scsi_hot_unplug'], False ) self.assertEqual( snapshot.extra['licence_type'], 'LINUX' ) ''' Extra metadata ''' self.assertEqual( snapshot.extra['created_date'], '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.extra['created_by'], 'test@test.te' ) self.assertEqual( snapshot.extra['etag'], '01873262ac042b5f44ed33b4241225b4' ) self.assertEqual( snapshot.extra['last_modified_date'], '2016-10-26T11:38:45Z' ) self.assertEqual( snapshot.extra['last_modified_by'], 'test@test.te' ) self.assertEqual( snapshot.extra['state'], 'AVAILABLE' ) def test_ex_update_snapshot(self): snapshot = self.driver.ex_describe_snapshot( ex_href='/cloudapi/v4/snapshots/sshot' ) updated = self.driver.ex_update_snapshot( snapshot=snapshot, name='libcloud Test - RENAME', description='libcloud test snapshot - RENAME' ) self.assertEqual( updated.name, 'libcloud Test - RENAME' ) self.assertEqual( updated.extra['description'], 'libcloud test snapshot - RENAME' ) def test_restore_volume_snapshot(self): volume = self.driver.ex_describe_volume( ex_datacenter_id='dc-1', ex_volume_id='vol-2' ) snapshot = self.driver.ex_describe_snapshot( ex_snapshot_id='sshot' ) restored = self.driver.ex_restore_volume_snapshot( volume=volume, snapshot=snapshot ) self.assertTrue(restored) def test_destroy_volume_snapshot(self): snapshot = self.driver.ex_describe_snapshot( ex_href='/cloudapi/v4/snapshots/sshot' ) destroyed = self.driver.destroy_volume_snapshot(snapshot) self.assertTrue(destroyed) ''' Function tests for operations on nodes (servers) ''' def test_reboot_node(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/dc-1' '/servers/srv-1' ) ) rebooted = self.driver.reboot_node(node=node) self.assertTrue(rebooted) def test_create_node(self): image = self.driver.ex_describe_image( ex_href='/cloudapi/v4/images/img-2' ) datacenter = self.driver.ex_describe_datacenter( ex_href='/cloudapi/v4/datacenters/dc-1' ) ssh_key = NodeAuthSSHKey('ssh-rsa AAAAB3NzaC1') password = NodeAuthPassword('secretpassword1233') node = self.driver.create_node( name='libcloud Test', image=image, ex_ram=1024, ex_cores=1, ex_disk=2, ex_bus_type='VIRTIO', ex_disk_type='HDD', ex_cpu_family='INTEL_XEON', ex_password=password, ex_ssh_keys=[ssh_key], ex_datacenter=datacenter ) extra = node.extra ''' Standard properties ''' self.assertEqual( node.id, 'srv-2' ) self.assertEqual( node.name, 'libcloud Test' ) self.assertEqual( node.state, NodeState.UNKNOWN ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-19T13:25:19Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '9bea2412ac556b402a07260fc0d1603f' ) self.assertEqual( extra['last_modified_date'], '2016-10-19T13:25:19Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['cores'], 1 ) self.assertEqual( extra['ram'], 1024 ) self.assertEqual( extra['availability_zone'], 'ZONE_1' ) self.assertEqual( extra['vm_state'], None ) self.assertEqual( extra['boot_cdrom'], None ) self.assertEqual( extra['boot_volume'], None ) self.assertEqual( extra['cpu_family'], 'INTEL_XEON' ) ''' Extra entities ''' self.assertEqual( len(extra['entities']['volumes']['items']), 1 ) def test_create_node_failure(self): image = self.driver.ex_describe_image( ex_href='/cloudapi/v4/images/img-2' ) datacenter = self.driver.ex_describe_datacenter( ex_href='/cloudapi/v4/datacenters/dc-1' ) sizes = self.driver.list_sizes() with self.assertRaises(ValueError): 'Raises value error if no size or ex_ram' self.driver.create_node( name='libcloud Test', image=image, ex_disk=40, ex_cores=1 ) with self.assertRaises(ValueError): 'Raises value error if no size or ex_cores' self.driver.create_node( name='libcloud Test', image=image, ex_disk=40, ex_ram=1024 ) with self.assertRaises(ValueError): 'Raises value error if no size or ex_disk' self.driver.create_node( name='libcloud Test', image=image, ex_cores=2, ex_ram=1024 ) with self.assertRaises(ValueError): 'Raises value error if no ssh keys or password' self.driver.create_node( name='libcloud Test', image=image, size=sizes[1], ex_datacenter=datacenter ) def test_destroy_node(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) destroyed = self.driver.destroy_node( node=node ) self.assertTrue(destroyed) def test_ex_list_attached_volumes(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/servers/' 'srv-1' ) ) attached_volumes = self.driver.ex_list_attached_volumes(node) self.assertTrue(len(attached_volumes) > 0) def test_attach_volume(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) volume = self.driver.ex_describe_volume( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'volumes/vol-2' ) ) attached = self.driver.attach_volume(node=node, volume=volume) extra = attached.extra ''' Standard properties ''' self.assertEqual( attached.id, 'vol-2' ) self.assertEqual( attached.name, 'libcloud Test' ) self.assertEqual( attached.size, 2 ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T13:13:36Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'c1800ce349033f9cd2c095ea1ea4976a' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T13:47:52Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['type'], 'HDD' ) self.assertEqual( extra['size'], 2 ) self.assertEqual( extra['image'], 'bvol-img' ) self.assertEqual( extra['image_password'], None ) self.assertEqual( extra['ssh_keys'], None ) self.assertEqual( extra['bus'], 'VIRTIO' ) self.assertEqual( extra['licence_type'], 'UNKNOWN' ) self.assertEqual( extra['cpu_hot_plug'], True ) self.assertEqual( extra['cpu_hot_unplug'], False ) self.assertEqual( extra['ram_hot_plug'], True ) self.assertEqual( extra['ram_hot_unplug'], False ) self.assertEqual( extra['nic_hot_plug'], True ) self.assertEqual( extra['nic_hot_unplug'], True ) self.assertEqual( extra['disc_virtio_hot_plug'], True ) self.assertEqual( extra['disc_virtio_hot_unplug'], True ) self.assertEqual( extra['disc_scsi_hot_plug'], False ) self.assertEqual( extra['disc_scsi_hot_unplug'], False ) self.assertEqual( extra['device_number'], 2 ) self.assertNotIn( 'availability_zone', extra ) def test_detach_volume(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) volume = self.driver.ex_describe_volume( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'volumes/vol-2' ) ) detached = self.driver.detach_volume( node=node, volume=volume ) self.assertTrue(detached) def test_ex_stop_node(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) stopped = self.driver.ex_stop_node(node) self.assertTrue(stopped) def test_ex_start_node(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) started = self.driver.ex_start_node(node) self.assertTrue(started) def test_ex_describe_node(self): node_w_href = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) node_w_id = self.driver.ex_describe_node( ex_datacenter_id='dc-1', ex_node_id='srv-1' ) self._verify_node(node=node_w_href) self._verify_node(node=node_w_id) def test_ex_describe_node_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_node( ex_datacenter_id='dc-1', ex_node_id='00000000' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_node(self, node): extra = node.extra ''' Standard properties ''' self.assertEqual( node.id, 'srv-1' ) self.assertEqual( node.name, 'libcloud Test' ) self.assertEqual( node.state, NodeState.RUNNING ) self.assertEqual( node.public_ips, [] ) self.assertEqual( node.private_ips, [] ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-18T07:28:05Z' ) self.assertEqual( extra['created_by'], 'test@test.test' ) self.assertEqual( extra['etag'], 'e7cf186125f51f3d9511754a40dcd12c') self.assertEqual( extra['last_modified_date'], '2016-10-18T07:28:05Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.test' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['availability_zone'], 'ZONE_1' ) self.assertEqual( extra['boot_cdrom'], None ) self.assertEqual( extra['boot_volume']['id'], 'bvol-1' ) self.assertEqual( extra['boot_volume']['href'], ( '/cloudapi/v4/datacenters/' 'dc-1/' 'volumes/bvol-1' ) ) self.assertEqual( extra['boot_volume']['properties']['name'], 'libcloud Test' ) self.assertEqual( extra['boot_volume']['properties']['type'], 'HDD' ) self.assertEqual( extra['boot_volume']['properties']['size'], 2 ) self.assertEqual( extra['boot_volume']['properties']['image'], 'bvol-img' ) self.assertEqual( extra['cpu_family'], 'AMD_OPTERON' ) ''' Other miscellaneous ''' self.assertEqual( len(extra['entities']), 3 ) self.assertNotIn( 'status_url', extra ) def test_ex_update_node(self): node = self.driver.ex_describe_node( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) updated = self.driver.ex_update_node( node=node, name='libcloud Test RENAME' ) self.assertEqual( updated.id, 'srv-1' ) self.assertEqual( updated.name, 'libcloud Test RENAME' ) ''' Function tests for operations on volumes ''' def test_create_volume(self): datacenter = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) image = self.driver.ex_describe_image( ex_href='/cloudapi/v4/images/img-2' ) created = self.driver.create_volume( size=30, name='Test volume', ex_type='HDD', ex_datacenter=datacenter, image=image, ex_ssh_keys=[NodeAuthSSHKey('ssh-rsa AAAAB3NzaC1')] ) self.assertTrue(created) def test_create_volume_failure(self): datacenter = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) with self.assertRaises(ValueError): 'Raises value error if no size' self.driver.create_volume( size=30, name='libcloud Test', ex_type='HDD', ex_bus_type='IDE', ex_datacenter=datacenter, image=None ) def test_destroy_volume(self): volume = self.driver.ex_describe_volume( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/volumes/' 'vol-2' ) ) destroyed = self.driver.destroy_volume(volume=volume) self.assertTrue(destroyed) def test_ex_update_volume(self): volume = self.driver.ex_describe_volume( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'volumes/vol-2' ) ) updated = self.driver.ex_update_volume( volume=volume, ex_storage_name='Updated volume', size=48, ex_bus_type='VIRTIO' ) extra = updated.extra ''' Standard properties ''' self.assertEqual( updated.id, 'vol-2' ) self.assertEqual( updated.name, 'libcloud Test - RENAME' ) self.assertEqual( updated.size, 5 ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T13:13:36Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'c1800ce349033f9cd2c095ea1ea4976a' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T13:47:52Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test - RENAME' ) self.assertEqual( extra['type'], 'HDD' ) self.assertEqual( extra['size'], 5 ) self.assertEqual( extra['availability_zone'], 'ZONE_3' ) self.assertEqual( extra['image'], 'bvol-img' ) self.assertEqual( extra['image_password'], None ) self.assertEqual( extra['ssh_keys'], None ) self.assertEqual( extra['bus'], 'VIRTIO' ) self.assertEqual( extra['licence_type'], 'UNKNOWN' ) self.assertEqual( extra['cpu_hot_plug'], True ) self.assertEqual( extra['cpu_hot_unplug'], False ) self.assertEqual( extra['ram_hot_plug'], True ) self.assertEqual( extra['ram_hot_unplug'], False ) self.assertEqual( extra['nic_hot_plug'], True ) self.assertEqual( extra['nic_hot_unplug'], True ) self.assertEqual( extra['disc_virtio_hot_plug'], True ) self.assertEqual( extra['disc_virtio_hot_unplug'], True ) self.assertEqual( extra['disc_scsi_hot_plug'], False ) self.assertEqual( extra['disc_scsi_hot_unplug'], False ) self.assertEqual( extra['device_number'], 3 ) return {} def test_ex_describe_volume(self): volume_w_href = self.driver.ex_describe_volume( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'volumes/vol-2' ) ) volume_w_id = self.driver.ex_describe_volume( ex_datacenter_id='dc-1', ex_volume_id='vol-2' ) self._verify_volume(volume=volume_w_href) self._verify_volume(volume=volume_w_id) def test_ex_describe_volume_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_volume( ex_datacenter_id='dc-1', ex_volume_id='00000000' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_volume(self, volume): extra = volume.extra ''' Standard properties ''' self.assertEqual( volume.id, 'vol-2' ) self.assertEqual( volume.name, 'libcloud Test' ) self.assertEqual( volume.size, 2 ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T13:13:36Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'c1800ce349033f9cd2c095ea1ea4976a' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T13:47:52Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['type'], 'HDD' ) self.assertEqual( extra['size'], 2 ) self.assertEqual( extra['availability_zone'], 'ZONE_3' ) self.assertEqual( extra['image'], 'bvol-img' ) self.assertEqual( extra['image_password'], None ) self.assertEqual( extra['ssh_keys'], None ) self.assertEqual( extra['bus'], 'VIRTIO' ) self.assertEqual( extra['licence_type'], 'UNKNOWN' ) self.assertEqual( extra['cpu_hot_plug'], True ) self.assertEqual( extra['cpu_hot_unplug'], False ) self.assertEqual( extra['ram_hot_plug'], True ) self.assertEqual( extra['ram_hot_unplug'], False ) self.assertEqual( extra['nic_hot_plug'], True ) self.assertEqual( extra['nic_hot_unplug'], True ) self.assertEqual( extra['disc_virtio_hot_plug'], True ) self.assertEqual( extra['disc_virtio_hot_unplug'], True ) self.assertEqual( extra['disc_scsi_hot_plug'], False ) self.assertEqual( extra['disc_scsi_hot_unplug'], False ) self.assertEqual( extra['device_number'], 3 ) self.assertNotIn( 'status_url', extra ) ''' Function tests for operations on data centers ''' def test_ex_create_datacenter(self): location = self.driver.ex_describe_location(ex_location_id='us/las') datacenter = self.driver.ex_create_datacenter( name='libcloud Test', location=location, description='libcloud test datacenter' ) extra = datacenter.extra ''' Standard properties ''' self.assertEqual( datacenter.id, 'dc-1' ) self.assertEqual( datacenter.href, '/cloudapi/v4/datacenters/dc-1' ) self.assertEqual( datacenter.name, 'libcloud Test' ) self.assertEqual( datacenter.version, None ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-18T17:20:56Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'c2d3d4d9bbdc0fff7d3c5c3864a68a46' ) self.assertEqual( extra['last_modified_date'], '2016-10-18T17:20:56Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['description'], 'libcloud test datacenter' ) self.assertEqual( extra['location'], 'us/las' ) self.assertEqual( extra['version'], None ) self.assertEqual( extra['features'], [] ) ''' Miscellaneous properties ''' self.assertNotIn( 'entities', extra ) self.assertEqual( extra['provisioning_state'], NodeState.PENDING ) def test_ex_create_datacenter_failure(self): with self.assertRaises(AttributeError): 'Raises attribute error if no location' self.driver.ex_create_datacenter( name='libcloud Test', location=None, description='libcloud test datacenter' ) def test_ex_destroy_datacenter(self): datacenter = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) destroyed = self.driver.ex_destroy_datacenter( datacenter=datacenter ) self.assertTrue(destroyed) def test_ex_describe_datacenter(self): datacenter_w_href = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) datacenter_w_id = self.driver.ex_describe_datacenter( ex_datacenter_id='dc-1' ) self._verify_datacenter(datacenter=datacenter_w_href) self._verify_datacenter(datacenter=datacenter_w_id) def test_ex_describe_datacenter_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_datacenter(ex_datacenter_id='00000000') self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_datacenter(self, datacenter): extra = datacenter.extra ''' Standard properties ''' self.assertEqual( datacenter.id, 'dc-1' ) self.assertEqual( datacenter.href, '/cloudapi/v4/datacenters/dc-1' ) self.assertEqual( datacenter.name, 'libcloud Test' ) self.assertEqual( datacenter.version, 35 ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T11:33:11Z' ) self.assertEqual( extra['created_by'], 'test@test.test' ) self.assertEqual( extra['etag'], '53b215b8ec0356a649955dab019845a4' ) self.assertEqual( extra['last_modified_date'], '2016-10-18T15:13:44Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.test' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['description'], 'libcloud test datacenter' ) self.assertEqual( extra['location'], 'us/las' ) self.assertEqual( extra['version'], 35 ) self.assertEqual( extra['features'], ['SSD', 'MULTIPLE_CPU'] ) self.assertNotIn( 'status_url', extra ) self.assertEqual( extra['provisioning_state'], NodeState.RUNNING ) self.assertEqual( len(extra['entities']), 4 ) def test_ex_rename_datacenter(self): datacenter = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) renamed = self.driver.ex_rename_datacenter( datacenter=datacenter, name='libcloud Test - RENAME' ) extra = renamed.extra ''' Standard properties ''' self.assertEqual( renamed.id, 'dc-1' ) self.assertEqual( renamed.href, '/cloudapi/v4/datacenters/dc-1' ) self.assertEqual( renamed.name, 'libcloud Test - RENAME' ) self.assertEqual( renamed.version, 35 ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T11:33:11Z' ) self.assertEqual( extra['created_by'], 'test@test.test' ) self.assertEqual( extra['etag'], '53b215b8ec0356a649955dab019845a4' ) self.assertEqual( extra['last_modified_date'], '2016-10-18T15:13:44Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.test' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test - RENAME' ) self.assertEqual( extra['description'], 'libcloud test datacenter' ) self.assertEqual( extra['location'], 'us/las' ) self.assertEqual( extra['version'], 35 ) self.assertEqual( extra['features'], ['SSD', 'MULTIPLE_CPU'] ) self.assertNotIn( 'status_url', extra ) self.assertEqual( extra['provisioning_state'], NodeState.PENDING ) self.assertEqual( len(extra['entities']), 4 ) ''' Function tests for operations on images ''' def test_ex_describe_image(self): image_w_href = self.driver.ex_describe_image( ex_href=( '/cloudapi/v4/images/' 'img-2' ) ) image_w_id = self.driver.ex_describe_image( ex_image_id='img-2' ) self._verify_image(image=image_w_href) self._verify_image(image=image_w_id) def test_ex_describe_image_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_image(ex_image_id='00000000') self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_image(self, image): extra = image.extra ''' Standard properties ''' self.assertEqual( image.id, 'img-2' ) self.assertEqual( image.name, 'vivid-server-cloudimg-amd64-disk1.img' ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2015-10-09T12:06:34Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'bbf76112358af2fc5dd1bf21de8988db' ) self.assertEqual( extra['last_modified_date'], '2015-11-11T15:23:20Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'vivid-server-cloudimg-amd64-disk1.img' ) self.assertEqual( extra['description'], None ) self.assertEqual( extra['location'], 'us/las' ) self.assertEqual( extra['size'], 2 ) self.assertEqual( extra['cpu_hot_plug'], False ) self.assertEqual( extra['cpu_hot_unplug'], False ) self.assertEqual( extra['ram_hot_plug'], False ) self.assertEqual( extra['ram_hot_unplug'], False ) self.assertEqual( extra['nic_hot_plug'], False ) self.assertEqual( extra['nic_hot_unplug'], False ) self.assertEqual( extra['disc_virtio_hot_plug'], False ) self.assertEqual( extra['disc_virtio_hot_unplug'], False ) self.assertEqual( extra['disc_scsi_hot_plug'], False ) self.assertEqual( extra['disc_scsi_hot_unplug'], False ) self.assertEqual( extra['licence_type'], 'UNKNOWN' ) self.assertEqual( extra['image_type'], 'HDD' ) self.assertEqual( extra['public'], False ) self.assertEqual( extra['href'], '/cloudapi/v4/images/img-2' ) self.assertIsInstance( extra['image_aliases'], list ) def test_ex_update_image(self): image = self.driver.ex_describe_image( ex_href=( '/cloudapi/v4/images/' 'img-2' ) ) updated = self.driver.ex_update_image( image=image, name='my-updated-image.img' ) extra = updated.extra self.assertEqual( updated.name, 'my-updated-image.img' ) self.assertEqual( extra['last_modified_date'], '2016-11-11T15:23:20Z' ) def test_ex_delete_image(self): image = self.driver.ex_describe_image( ex_href=( '/cloudapi/v4/images/' 'img-2' ) ) deleted = self.driver.ex_delete_image(image) self.assertTrue(deleted) ''' Function tests for operations on network interfaces ''' def test_ex_list_network_interfaces(self): network_interfaces = self.driver.ex_list_network_interfaces() self.assertTrue(len(network_interfaces) > 0) network_interface = network_interfaces[0] extra = network_interface.extra ''' Standard properties ''' self.assertEqual( network_interface.id, 'nic-1' ) self.assertEqual( network_interface.name, 'libcloud Test' ) self.assertEqual( network_interface.href, ( '/cloudapi/v4/datacenters/' 'dc-1/servers/' 's-3/nics/' 'nic-1' ) ) self.assertEqual( network_interface.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T15:46:38Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'dbd8216137cf0ec9951170f93fa8fa53' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T18:19:43Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['mac'], '02:01:0b:9d:4d:ce' ) self.assertEqual( extra['ips'], ['10.15.124.11'] ) self.assertEqual( extra['dhcp'], False ) self.assertEqual( extra['lan'], 2 ) self.assertEqual( extra['firewall_active'], True ) self.assertEqual( extra['nat'], False ) def test_ex_describe_network_interface(self): nic_w_href = self.driver.ex_describe_network_interface( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3' '/nics/nic-2' ) ) nic_w_id = self.driver.ex_describe_network_interface( ex_datacenter_id='dc-1', ex_server_id='s-3', ex_nic_id='nic-2' ) self._verify_network_interface(network_interface=nic_w_href) self._verify_network_interface(network_interface=nic_w_id) def test_ex_describe_network_interface_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_network_interface( ex_datacenter_id='dc-1', ex_server_id='s-3', ex_nic_id='00000000' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_network_interface(self, network_interface): extra = network_interface.extra ''' Standard properties ''' self.assertEqual( network_interface.id, 'nic-2' ) self.assertEqual( network_interface.name, 'libcloud Test' ) self.assertEqual( network_interface.href, ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2' ) ) self.assertEqual( network_interface.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T15:46:38Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'dbd8216137cf0ec9951170f93fa8fa53' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T18:19:43Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['mac'], '02:01:0b:9d:4d:ce' ) self.assertEqual( extra['ips'], ['10.15.124.11'] ) self.assertEqual( extra['dhcp'], True ) self.assertEqual( extra['lan'], 2 ) self.assertEqual( extra['firewall_active'], True ) self.assertEqual( extra['nat'], False ) ''' Miscellaneous ''' self.assertTrue( len(extra['entities']), 1 ) def test_ex_create_network_interface(self): node = self.driver.ex_describe_node( ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' ) ) network_interface = self.driver.ex_create_network_interface( node=node, lan_id=1, dhcp_active=True, nic_name='libcloud Test' ) extra = network_interface.extra ''' Standard properties ''' self.assertEqual( network_interface.id, 'nic-2' ) self.assertEqual( network_interface.name, 'libcloud Test' ) self.assertEqual( network_interface.href, ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/srv-1' '/nics/nic-2' ) ) self.assertEqual( network_interface.state, NodeState.PENDING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-19T08:18:50Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '8679142b0b1b70c8b8c09a8b31e6ded9' ) self.assertEqual( extra['last_modified_date'], '2016-10-19T08:18:50Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['mac'], None ) self.assertEqual( extra['ips'], ['10.0.0.1'] ) self.assertEqual( extra['dhcp'], True ) self.assertEqual( extra['lan'], 1 ) self.assertEqual( extra['firewall_active'], None ) self.assertEqual( extra['nat'], None ) def test_ex_create_network_interface_failure(self): with self.assertRaises(AttributeError): 'Raises attribute error if no node' self.driver.ex_create_network_interface( node=None, lan_id=1, nic_name='libcloud Test' ) def test_ex_update_network_interface(self): network_interface = self.driver.ex_describe_network_interface( ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3' '/nics/nic-2' ) ) updated = self.driver.ex_update_network_interface( network_interface=network_interface, name='libcloud Test - RENAME' ) extra = updated.extra ''' Standard properties ''' self.assertEqual( updated.id, 'nic-2' ) self.assertEqual( updated.name, 'libcloud Test - RENAME' ) self.assertEqual( updated.href, ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2' ) ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test - RENAME' ) def test_ex_destroy_network_interface(self): network_interface = self.driver.ex_describe_network_interface( ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3' '/nics/nic-2' ) ) destroyed = self.driver.ex_destroy_network_interface( network_interface=network_interface ) self.assertTrue(destroyed) def test_ex_set_inet_access(self): network_interface = self.driver.ex_describe_network_interface( ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3' '/nics/nic-2' ) ) updated = self.driver.ex_set_inet_access( network_interface=network_interface, internet_access=False) self.assertTrue(updated) return {} ''' Function tests for operations on locations ''' def test_ex_describe_location(self): location_w_href = self.driver.ex_describe_location( ex_href=( '/cloudapi/v4/locations/us/las' ) ) location_w_id = self.driver.ex_describe_location( ex_location_id='us/las' ) self._verify_location(location=location_w_href) self._verify_location(location=location_w_id) def test_ex_describe_location_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_location(ex_location_id='us/000') self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_location(self, location): self.assertEqual( location.id, 'us/las' ) self.assertEqual( location.name, 'lasvegas' ) self.assertEqual( location.country, 'us' ) ''' Function tests for operations on firewall rules ''' def test_ex_list_firewall_rules(self): network_interface = self.driver.ex_describe_network_interface( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2' ) ) firewall_rules = self.driver.ex_list_firewall_rules(network_interface) self.assertTrue( len(firewall_rules) > 0 ) firewall_rule = firewall_rules[0] extra = firewall_rule.extra ''' Standard properties ''' self.assertEqual( firewall_rule.id, 'fwr-1' ) self.assertEqual( firewall_rule.name, 'Test updated firewall rule' ) self.assertEqual( firewall_rule.href, ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2/' 'firewallrules/fwr-1' ) ) self.assertEqual( firewall_rule.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-19T11:08:10Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'b91a2e082a7422dafb79d84a07fb2a28' ) self.assertEqual( extra['last_modified_date'], '2016-10-19T11:19:04Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'Test updated firewall rule' ) self.assertEqual( extra['protocol'], 'TCP' ) self.assertEqual( extra['source_mac'], None ) self.assertEqual( extra['source_ip'], None ) self.assertEqual( extra['target_ip'], None ) self.assertEqual( extra['icmp_code'], None ) self.assertEqual( extra['icmp_type'], None ) self.assertEqual( extra['port_range_start'], 80 ) self.assertEqual( extra['port_range_end'], 80 ) def test_ex_describe_firewall_rule(self): firewall_rule_w_href = self.driver.ex_describe_firewall_rule( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/servers/' 's-3/nics/' 'nic-2/firewallrules' '/fw2' ) ) firewall_rule_w_id = self.driver.ex_describe_firewall_rule( ex_datacenter_id='dc-1', ex_server_id='s-3', ex_nic_id='nic-2', ex_firewall_rule_id='fw2' ) self._verify_firewall_rule(firewall_rule=firewall_rule_w_href) self._verify_firewall_rule(firewall_rule=firewall_rule_w_id) def test_ex_describe_firewall_rule_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_firewall_rule( ex_datacenter_id='dc-1', ex_server_id='s-3', ex_nic_id='nic-2', ex_firewall_rule_id='00' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_firewall_rule(self, firewall_rule): extra = firewall_rule.extra ''' Standard properties ''' self.assertEqual( firewall_rule.id, 'fw2' ) self.assertEqual( firewall_rule.name, 'SSH' ) self.assertEqual( firewall_rule.href, ( '/cloudapi/v4/datacenters/' 'dc-1/servers/' 's-3/nics/' 'nic-2/' 'firewallrules/fw2' ) ) self.assertEqual( firewall_rule.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-19T09:55:10Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '00bb5b86562db1ed19ca38697e485160' ) self.assertEqual( extra['last_modified_date'], '2016-10-19T09:55:10Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'SSH' ) self.assertEqual( extra['protocol'], 'TCP' ) self.assertEqual( extra['source_mac'], '01:23:45:67:89:00' ) self.assertEqual( extra['source_ip'], None ) self.assertEqual( extra['target_ip'], None ) self.assertEqual( extra['icmp_code'], None ) self.assertEqual( extra['icmp_type'], None ) self.assertEqual( extra['port_range_start'], 22 ) self.assertEqual( extra['port_range_end'], 22 ) def test_ex_create_firewall_rule(self): network_interface = self.driver.ex_describe_network_interface( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2' ) ) firewall_rule = self.driver.ex_create_firewall_rule( network_interface=network_interface, protocol='TCP', name='SSH', port_range_start=22, port_range_end=22 ) extra = firewall_rule.extra ''' Standard properties ''' self.assertEqual( firewall_rule.id, 'fwr-1' ) self.assertEqual( firewall_rule.name, 'SSH' ) self.assertEqual( firewall_rule.href, ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2/' 'firewallrules/fwr-1' ) ) self.assertEqual( firewall_rule.state, NodeState.PENDING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-19T11:08:04Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '2a21551ba4adf85d9fb04b05a6938bcc' ) self.assertEqual( extra['last_modified_date'], '2016-10-19T11:08:04Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'SSH' ) self.assertEqual( extra['protocol'], 'TCP' ) self.assertEqual( extra['source_mac'], '01:23:45:67:89:00' ) self.assertEqual( extra['source_ip'], None ) self.assertEqual( extra['target_ip'], None ) self.assertEqual( extra['icmp_code'], None ) self.assertEqual( extra['icmp_type'], None ) self.assertEqual( extra['port_range_start'], 22 ) self.assertEqual( extra['port_range_end'], 22 ) def test_ex_create_firewall_rule_failure(self): with self.assertRaises(AttributeError): 'Raises attribute error if no network interface' self.driver.ex_create_firewall_rule( network_interface=None, protocol='TCP', name='SSH' ) def test_ex_update_firewall_rule(self): firewall_rule = self.driver.ex_describe_firewall_rule( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2/' 'firewallrules/fw2' ) ) updated = self.driver.ex_update_firewall_rule( firewall_rule=firewall_rule, name='SSH - RENAME' ) extra = updated.extra ''' Standard properties ''' self.assertEqual( updated.id, 'fw2' ) self.assertEqual( updated.name, 'SSH - RENAME' ) self.assertEqual( extra['name'], 'SSH - RENAME' ) def test_ex_delete_firewall_rule(self): firewall_rule = self.driver.ex_describe_firewall_rule( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2/' 'firewallrules/fw2' ) ) deleted = self.driver.ex_delete_firewall_rule(firewall_rule) self.assertTrue(deleted) ''' Function tests for operations on lans ''' def test_ex_list_lans(self): datacenter = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) lans = self.driver.ex_list_lans( datacenter=datacenter ) lan = lans[0] extra = lan.extra self.assertEqual( len(lans), 1 ) ''' Standard properties ''' self.assertEqual( lan.id, '1' ) self.assertEqual( lan.href, ( '/cloudapi/v4/datacenters/' 'dc-1/lans/1' ) ) self.assertEqual( lan.name, 'libcloud Test' ) self.assertEqual( lan.is_public, False ) self.assertEqual( lan.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-24T08:03:22Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['last_modified_date'], '2016-10-24T08:03:22Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['is_public'], False ) ''' Miscellaneous ''' self.assertEqual( len(extra['entities']), 1 ) def test_ex_create_lan(self): datacenter = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) lan = self.driver.ex_create_lan( datacenter=datacenter, is_public=True ) extra = lan.extra ''' Standard properties ''' self.assertEqual( lan.id, '10' ) self.assertEqual( lan.href, ( '/cloudapi/v4/datacenters/' 'dc-1/lans/10' ) ) self.assertEqual( lan.name, 'libcloud Test' ) self.assertEqual( lan.is_public, True ) self.assertEqual( lan.state, NodeState.PENDING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T11:33:11Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '53b215b8ec0356a649955dab019845a4' ) self.assertEqual( extra['last_modified_date'], '2016-10-18T15:13:44Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['is_public'], True ) def test_ex_create_lan_failure(self): with self.assertRaises(AttributeError): 'Raises attribute error if no datacenter' self.driver.ex_create_lan( datacenter=None ) def test_ex_describe_lan(self): lan_w_href = self.driver.ex_describe_lan( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/lans/10' ) ) lan_w_id = self.driver.ex_describe_lan( ex_datacenter_id='dc-1', ex_lan_id='10' ) self._verify_lan(lan=lan_w_href) self._verify_lan(lan=lan_w_id) def test_ex_describe_lan_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_lan( ex_datacenter_id='dc-1', ex_lan_id='0' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_lan(self, lan): extra = lan.extra ''' Standard properties ''' self.assertEqual( lan.id, '10' ) self.assertEqual( lan.href, ( '/cloudapi/v4/datacenters/' 'dc-1/lans/10' ) ) self.assertEqual( lan.name, 'libcloud Test' ) self.assertEqual( lan.is_public, True ) self.assertEqual( lan.state, NodeState.PENDING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T11:33:11Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '53b215b8ec0356a649955dab019845a4' ) self.assertEqual( extra['last_modified_date'], '2016-10-18T15:13:44Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['is_public'], True ) def test_ex_update_lan(self): lan = self.driver.ex_describe_lan( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/lans/10' ) ) updated = self.driver.ex_update_lan( lan=lan, is_public=False, name='libcloud Test - RENAME' ) extra = updated.extra ''' Standard properties ''' self.assertEqual( updated.id, '10' ) self.assertEqual( updated.href, ( '/cloudapi/v4/datacenters/' 'dc-1/lans/10' ) ) self.assertEqual( updated.name, 'libcloud Test - RENAME' ) self.assertEqual( updated.is_public, False ) self.assertEqual( updated.state, NodeState.PENDING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T11:33:11Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '53b215b8ec0356a649955dab019845a4' ) self.assertEqual( extra['last_modified_date'], '2016-10-18T15:13:44Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test - RENAME' ) self.assertEqual( extra['is_public'], False ) def test_ex_delete_lan(self): lan = self.driver.ex_describe_lan( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/lans/10' ) ) deleted = self.driver.ex_delete_lan(lan) self.assertTrue(deleted) ''' Function tests for operations on load balancers ''' def test_ex_list_load_balancers(self): load_balancers = self.driver.ex_list_load_balancers() self.assertTrue( len(load_balancers) > 0 ) def test_ex_describe_load_balancer(self): load_balancer_w_href = self.driver.ex_describe_load_balancer( ex_href=( '/cloudapi/v4/datacenters/' 'dc-2/' 'loadbalancers/bal-1' ) ) load_balancer_w_id = self.driver.ex_describe_load_balancer( ex_datacenter_id='dc-2', ex_load_balancer_id='bal-1' ) self._verify_load_balancer(load_balancer=load_balancer_w_href) self._verify_load_balancer(load_balancer=load_balancer_w_id) def test_ex_describe_load_balancer_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_load_balancer( ex_datacenter_id='dc-2', ex_load_balancer_id='00000000' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_load_balancer(self, load_balancer): """ Standard properties """ self.assertEqual( load_balancer.id, 'bal-1' ) self.assertEqual( load_balancer.href, ( '/cloudapi/v4/datacenters/' 'dc-2/' 'loadbalancers/bal-1' ) ) self.assertEqual( load_balancer.name, 'libcloud Test' ) self.assertEqual( load_balancer.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( load_balancer.extra['created_date'], '2016-10-26T13:02:33Z' ) self.assertEqual( load_balancer.extra['created_by'], 'test@test.te' ) self.assertEqual( load_balancer.extra['etag'], '71e8df57a58615b9e15400ede4138b41' ) self.assertEqual( load_balancer.extra['last_modified_date'], '2016-10-26T13:02:33Z' ) self.assertEqual( load_balancer.extra['last_modified_by'], 'test@test.te' ) self.assertEqual( load_balancer.extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( load_balancer.extra['name'], 'libcloud Test' ) self.assertIsNotNone( load_balancer.extra['ip'] ) self.assertEqual( load_balancer.extra['dhcp'], True ) def test_ex_create_load_balancer(self): datacenter = self.driver.ex_describe_datacenter( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1' ) ) nics = self.driver.ex_list_network_interfaces() created = self.driver.ex_create_load_balancer( datacenter=datacenter, name='libcloud Test', dhcp=True, nics=[nics[0]] ) ''' Standard properties ''' self.assertEqual( created.id, 'bal-1' ) self.assertEqual( created.href, ( '/cloudapi/v4/datacenters' '/dc-1' '/loadbalancers/bal-1' ) ) self.assertEqual( created.name, 'libcloud Test' ) self.assertEqual( created.state, NodeState.PENDING ) ''' Extra metadata ''' self.assertEqual( created.extra['created_date'], '2016-10-26T13:02:33Z' ) self.assertEqual( created.extra['created_by'], 'test@test.te' ) self.assertEqual( created.extra['etag'], '71e8df57a58615b9e15400ede4138b41' ) self.assertEqual( created.extra['last_modified_date'], '2016-10-26T13:02:33Z' ) self.assertEqual( created.extra['last_modified_by'], 'test@test.te' ) self.assertEqual( created.extra['state'], 'BUSY' ) ''' Extra properties ''' self.assertEqual( created.extra['name'], 'libcloud Test' ) self.assertEqual( created.extra['ip'], None ) self.assertEqual( created.extra['dhcp'], True ) self.assertIsNotNone( created.extra['entities']['balancednics'] ) def test_ex_create_load_balancer_failure(self): with self.assertRaises(AttributeError): 'Raises attribute error if no datacenter' self.driver.ex_create_load_balancer( datacenter=None, name='libcloud Test' ) def test_ex_update_load_balancer(self): load_balancer = self.driver.ex_describe_load_balancer( ex_href=( '/cloudapi/v4/datacenters/' 'dc-2/' 'loadbalancers/bal-1' ) ) updated = self.driver.ex_update_load_balancer( load_balancer=load_balancer, name='libcloud Test - RENAME' ) self.assertEqual( updated.name, 'libcloud Test - RENAME' ) def test_ex_list_load_balanced_nics(self): load_balancer = self.driver.ex_describe_load_balancer( ex_href=( '/cloudapi/v4/datacenters/' 'dc-2/' 'loadbalancers/bal-1' ) ) network_interfaces = self.driver.ex_list_load_balanced_nics( load_balancer ) self.assertTrue( len(network_interfaces) > 0 ) network_interface = network_interfaces[0] extra = network_interface.extra ''' Standard properties ''' self.assertEqual( network_interface.id, 'nic-1' ) self.assertEqual( network_interface.name, 'libcloud Test' ) self.assertEqual( network_interface.href, ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-1' ) ) self.assertEqual( network_interface.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T15:46:38Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'dbd8216137cf0ec9951170f93fa8fa53' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T18:19:43Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) self.assertEqual( extra['mac'], '02:01:0b:9d:4d:ce' ) self.assertEqual( extra['ips'], ['10.15.124.11'] ) self.assertEqual( extra['dhcp'], False ) self.assertEqual( extra['lan'], 2 ) self.assertEqual( extra['firewall_active'], True ) self.assertEqual( extra['nat'], False ) def test_ex_describe_load_balanced_nic(self): network_interface_w_href = self.driver.ex_describe_network_interface( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2' ) ) network_interface_w_id = self.driver.ex_describe_network_interface( ex_datacenter_id='dc-1', ex_server_id='s-3', ex_nic_id='nic-2' ) self._verify_load_balanced_nic( network_interface=network_interface_w_href ) self._verify_load_balanced_nic( network_interface=network_interface_w_id ) def _verify_load_balanced_nic(self, network_interface): extra = network_interface.extra ''' Standard properties ''' self.assertEqual( network_interface.id, 'nic-2' ) self.assertEqual( network_interface.name, 'libcloud Test' ) self.assertEqual( network_interface.href, ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3' '/nics/nic-2' ) ) self.assertEqual( network_interface.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-17T15:46:38Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'dbd8216137cf0ec9951170f93fa8fa53' ) self.assertEqual( extra['last_modified_date'], '2016-10-17T18:19:43Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) ''' Extra properties ''' self.assertEqual( extra['name'], 'libcloud Test' ) assertRegex( self, extra['mac'], '^([0-9a-f]{2}[:]){5}([0-9a-f]{2})$' ) self.assertTrue( len(extra['ips']) > 0 ) self.assertEqual( extra['dhcp'], True ) self.assertIsInstance( extra['lan'], int ) self.assertEqual( extra['firewall_active'], True ) self.assertEqual( extra['nat'], False ) def test_ex_attach_nic_to_load_balancer(self): network_interface = self.driver.ex_describe_network_interface( ex_href=( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3' '/nics/nic-2' ) ) load_balancer = self.driver.ex_describe_load_balancer( ex_href=( '/cloudapi/v4/datacenters/' 'dc-2/' 'loadbalancers/bal-1' ) ) attached = self.driver.ex_attach_nic_to_load_balancer( load_balancer=load_balancer, network_interface=network_interface ) self.assertTrue(attached) def test_ex_remove_nic_from_load_balancer(self): network_interface = self.driver.ex_describe_network_interface( ex_href=( ( '/cloudapi/v4/datacenters/' 'dc-1/' 'servers/s-3/' 'nics/nic-2' ) ) ) load_balancer = self.driver.ex_describe_load_balancer( ex_href=( '/cloudapi/v4/datacenters/' 'dc-2/' 'loadbalancers/bal-1' ) ) detached = self.driver.ex_remove_nic_from_load_balancer( load_balancer=load_balancer, network_interface=network_interface ) self.assertTrue(detached) def test_ex_delete_load_balancer(self): load_balancer = self.driver.ex_describe_load_balancer( ex_href=( '/cloudapi/v4/datacenters/' 'dc-2/' 'loadbalancers/bal-1' ) ) deleted = self.driver.ex_delete_load_balancer(load_balancer) self.assertTrue(deleted) ''' Function tests for operations on IP blocks ''' def test_ex_list_ip_blocks(self): ip_blocks = self.driver.ex_list_ip_blocks() self.assertTrue( len(ip_blocks) > 0 ) def test_ex_create_ip_block(self): location = self.driver.ex_describe_location(ex_location_id='us/las') created = self.driver.ex_create_ip_block( location=location, size=2, name='libcloud Test' ) extra = created.extra ''' Standard properties ''' self.assertEqual( created.id, 'ipb-1' ) self.assertEqual( created.name, 'libcloud Test' ) self.assertEqual( created.href, '/cloudapi/v4/ipblocks/ipb-1' ) self.assertEqual( created.location, 'us/las' ) self.assertEqual( created.size, 2 ) self.assertEqual( len(created.ips), 2 ) self.assertEqual( created.state, NodeState.PENDING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-26T15:05:36Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], 'acbf00bacf7ee48d4b8bc4e7413e1f30' ) self.assertEqual( extra['last_modified_date'], '2016-10-26T15:05:36Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'BUSY' ) def test_ex_create_ip_block_failure(self): with self.assertRaises(AttributeError): 'Raises attribute error if no location' self.driver.ex_create_ip_block( location=None, size=2, name='libcloud Test' ) def test_ex_describe_ip_block(self): ip_block_w_href = self.driver.ex_describe_ip_block( ex_href=( '/cloudapi/v4/ipblocks/' 'ipb-2' ) ) ip_block_w_id = self.driver.ex_describe_ip_block( ex_ip_block_id='ipb-2' ) self._verify_ip_block(ip_block=ip_block_w_href) self._verify_ip_block(ip_block=ip_block_w_id) def test_ex_describe_ip_block_failure(self): with self.assertRaises(BaseHTTPError) as cm: self.driver.ex_describe_ip_block( ex_ip_block_id='00000000' ) self.assertIn('Resource does not exist', cm.exception.message.value) def _verify_ip_block(self, ip_block): extra = ip_block.extra ''' Standard properties ''' self.assertEqual( ip_block.id, 'ipb-2' ) self.assertEqual( ip_block.name, 'libcloud Test' ) self.assertEqual( ip_block.href, ( '/cloudapi/v4/ipblocks/ipb-2' ) ) self.assertEqual( ip_block.location, 'us/las' ) self.assertEqual( ip_block.size, 2 ) self.assertEqual( len(ip_block.ips), 2 ) self.assertEqual( ip_block.state, NodeState.RUNNING ) ''' Extra metadata ''' self.assertEqual( extra['created_date'], '2016-10-26T15:05:12Z' ) self.assertEqual( extra['created_by'], 'test@test.te' ) self.assertEqual( extra['etag'], '43e05b766899950bc8a5aeee0fd89b05' ) self.assertEqual( extra['last_modified_date'], '2016-10-26T15:05:12Z' ) self.assertEqual( extra['last_modified_by'], 'test@test.te' ) self.assertEqual( extra['state'], 'AVAILABLE' ) def test_ex_delete_ip_block(self): ip_block = self.driver.ex_describe_ip_block( ex_href=( '/cloudapi/v4/ipblocks/' 'ipb-2' ) ) deleted = self.driver.ex_delete_ip_block(ip_block) self.assertTrue(deleted) class ProfitBricksMockHttp(MockHttp): fixtures = ComputeFileFixtures('profitbricks') ''' Operations on images GET - fetches images ''' def _cloudapi_v4_images( self, method, url, body, headers ): body = self.fixtures.load('list_images.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) ''' Operations on locations GET - fetches locations ''' def _cloudapi_v4_locations( self, method, url, body, headers ): body = self.fixtures.load('list_locations.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) ''' Operations on a data centers GET - fetches data centers PATCH - creates a data center ''' def _cloudapi_v4_datacenters( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_datacenters.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('ex_create_datacenter.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a data center GET - fetches a data center DELETE - destroys a data center PATCH - updates a data center ''' def _cloudapi_v4_datacenters_dc_1( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_datacenter.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'PATCH': body = self.fixtures.load('ex_rename_datacenter.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_00000000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on data center nodes (servers) GET - fetches a list of nodes (servers) for a data center POST - creates a node (server) for a data center ''' def _cloudapi_v4_datacenters_dc_1_servers( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('list_nodes.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('create_node.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on data center volumes GET - fetches a list of volumes for a data center POST - creates a volume for a data center ''' def _cloudapi_v4_datacenters_dc_1_volumes( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('list_volumes.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('create_volume.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a node (server) GET - fetches a node (server) DELETE - destroys a node (server) PATCH - updates a node ''' def _cloudapi_v4_datacenters_dc_1_servers_srv_1( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_node.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_node.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_dc_1_servers_00000000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on a node (server) POST - reboots, then starts and stops a node ''' 'reboot a node' def _cloudapi_v4_datacenters_dc_1_servers_srv_1_reboot( self, method, url, body, headers ): return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) 'start a node' def _cloudapi_v4_datacenters_dc_1_servers_srv_1_stop( self, method, url, body, headers ): return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) 'stop a node' def _cloudapi_v4_datacenters_dc_1_servers_srv_1_start( self, method, url, body, headers ): return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) """ Operations on an image GET - fetches an image DELETE - deletes an image PATCH - updates an image """ def _cloudapi_v4_images_img_2( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_image.json') return ( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_image.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_images_00000000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on a volume GET - fetches a volume DELETE - destroys a volume PATCH - updates a volume ''' def _cloudapi_v4_datacenters_dc_1_volumes_vol_2( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_volume.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_volume.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_dc_1_volumes_00000000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on a volume connected to a node (server) DELETE - destroys the link between a volume and a server but does delete the volume. ''' def _cloudapi_v4_datacenters_dc_1_servers_srv_1_volumes_vol_2( self, method, url, body, headers ): return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a location GET - fetches a location ''' def _cloudapi_v4_locations_us_las( self, method, url, body, headers ): body = self.fixtures.load('ex_describe_location.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) def _cloudapi_v4_locations_us_000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on volumes connected to nodes (servers) GET - fetch volumes connected to a server POST - attach a volume to a node (server) ''' def _cloudapi_v4_datacenters_dc_1_servers_srv_1_volumes( self, method, url, body, headers ): if(method == 'GET'): body = self.fixtures.load('ex_list_attached_volumes.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('attach_volume.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on network interfaces connected to a server GET - fetch network interfaces for a node (server) POST - create a network interface for a node (server) ''' def _cloudapi_v4_datacenters_dc_1_servers_srv_1_nics( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_network_interfaces.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('ex_create_network_interface.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on network interfaces GET - fetch a network interface DELETE - destroy a network interface PATCH - update a network interface ''' def _cloudapi_v4_datacenters_dc_1_servers_s_3_nics_nic_2( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_network_interface.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_network_interface.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_dc_1_servers_s_3_nics_00000000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on firewall rules GET - fetch a firewall rule DELETE - destroy a firewall rule PATCH - update a firewall rule ''' def _cloudapi_v4_datacenters_dc_1_servers_s_3_nics_nic_2_firewallrules_fw2( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_firewall_rule.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_firewall_rule.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_dc_1_servers_s_3_nics_nic_2_firewallrules_00( self, method, url, body, headers ): return self._get_not_found() ''' Operations on firewall rules connected to a network interface GET - fetch a list of firewall rules connected to a network interface POST - create a firewall rule for a network interface ''' def _cloudapi_v4_datacenters_dc_1_servers_s_3_nics_nic_2_firewallrules( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_firewall_rules.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('ex_create_firewall_rule.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on lans GET - fetch a list of lans POST - create a lan ''' def _cloudapi_v4_datacenters_dc_1_lans( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_lans.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('ex_create_lan.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a single lan GET - fetch a lan DELETE - Destroy a lan PATCH - update a lan ''' def _cloudapi_v4_datacenters_dc_1_lans_10( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_lan.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_lan.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_dc_1_lans_0( self, method, url, body, headers ): return self._get_not_found() ''' Operations on snapshots GET - fetch a list of snapshots ''' def _cloudapi_v4_snapshots( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('list_snapshots.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) ''' Operations on volume snapshots POST - create a volume snapshot POST - restore a volume snapshot ''' def _cloudapi_v4_datacenters_dc_1_volumes_vol_2_create_snapshot( self, method, url, body, headers ): if method == 'POST': body = self.fixtures.load('create_volume_snapshot.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_dc_1_volumes_vol_2_restore_snapshot( self, method, url, body, headers ): if method == 'POST': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a single snapshot GET - get information on a snapshot DELETE - delete a snapshot PATCH - update a snapshot ''' def _cloudapi_v4_snapshots_sshot( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_snapshot.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_snapshot.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_snapshots_00000000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on load balancers GET - list load balancers POST - create a load balancer for this datacenter ''' def _cloudapi_v4_datacenters_dc_1_loadbalancers( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_load_balancers.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('ex_create_load_balancer.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a single load balancer GET - get information on a load balancer DELETE - delete a load balancer PATCH - update a load balancer ''' def _cloudapi_v4_datacenters_dc_2_loadbalancers_bal_1( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_load_balancer.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) elif method == 'PATCH': body = self.fixtures.load('ex_update_load_balancer.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_datacenters_dc_2_loadbalancers_00000000( self, method, url, body, headers ): return self._get_not_found() ''' Operations on a load balancers nics GET - get load balanced nics ''' def _cloudapi_v4_datacenters_dc_2_loadbalancers_bal_1_balancednics( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_load_balanced_nics.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a load balanced nic DELETE - remove the nic from a load balancer ''' def _cloudapi_v4_datacenters_dc_2_loadbalancers_bal_1_balancednics_nic_2( self, method, url, body, headers ): if method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on IP blocks GET - list IP blocks POST - create an IP block ''' def _cloudapi_v4_ipblocks( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_list_ip_blocks.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'POST': body = self.fixtures.load('ex_create_ip_block.json') return ( httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED] ) ''' Operations on a single IP block GET - fetch an IP block DELETE - delete an IP block ''' def _cloudapi_v4_ipblocks_ipb_2( self, method, url, body, headers ): if method == 'GET': body = self.fixtures.load('ex_describe_ip_block.json') return( httplib.OK, body, {}, httplib.responses[httplib.OK] ) elif method == 'DELETE': return ( httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED] ) def _cloudapi_v4_ipblocks_00000000( self, method, url, body, headers ): return self._get_not_found() def _get_not_found(self): body = self.fixtures.load('error_resource_not_found.json') return ( httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND] ) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_rackspace.py0000664000175000017500000001751713570310635024236 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import method_type from libcloud.utils.py3 import httplib from libcloud.compute.types import Provider from libcloud.compute.providers import get_driver from libcloud.compute.drivers.rackspace import RackspaceFirstGenNodeDriver from libcloud.compute.drivers.rackspace import RackspaceNodeDriver from libcloud.test.compute.test_openstack import OpenStack_1_0_Tests from libcloud.test.compute.test_openstack import OpenStack_1_1_Tests, \ OpenStack_1_1_MockHttp from libcloud.pricing import clear_pricing_data from libcloud.test.secrets import RACKSPACE_NOVA_PARAMS from libcloud.test.secrets import RACKSPACE_PARAMS DEPRECATED_RACKSPACE_PROVIDERS = [Provider.RACKSPACE_UK, Provider.RACKSPACE_NOVA_BETA, Provider.RACKSPACE_NOVA_DFW, Provider.RACKSPACE_NOVA_LON, Provider.RACKSPACE_NOVA_ORD] class RackspaceusFirstGenUsTests(OpenStack_1_0_Tests): should_list_locations = True should_have_pricing = True driver_klass = RackspaceFirstGenNodeDriver driver_type = RackspaceFirstGenNodeDriver driver_args = RACKSPACE_PARAMS driver_kwargs = {'region': 'us'} def test_error_is_thrown_on_accessing_old_constant(self): for provider in DEPRECATED_RACKSPACE_PROVIDERS: try: get_driver(provider) except Exception as e: self.assertTrue(str(e).find('has been removed') != -1) else: self.fail('Exception was not thrown') def test_list_sizes_pricing(self): sizes = self.driver.list_sizes() for size in sizes: self.assertTrue(size.price > 0) class RackspaceusFirstGenUkTests(OpenStack_1_0_Tests): should_list_locations = True should_have_pricing = True driver_klass = RackspaceFirstGenNodeDriver driver_type = RackspaceFirstGenNodeDriver driver_args = RACKSPACE_PARAMS driver_kwargs = {'region': 'uk'} def test_list_sizes_pricing(self): sizes = self.driver.list_sizes() for size in sizes: self.assertTrue(size.price > 0) class RackspaceNovaMockHttp(OpenStack_1_1_MockHttp): def __init__(self, *args, **kwargs): super(RackspaceNovaMockHttp, self).__init__(*args, **kwargs) methods1 = OpenStack_1_1_MockHttp.__dict__ names1 = [m for m in methods1 if m.find('_v1_1') == 0] for name in names1: method = methods1[name] new_name = name.replace('_v1_1_slug_', '_v2_1337_') setattr(self, new_name, method_type(method, self, RackspaceNovaMockHttp)) def _v2_1337_os_networksv2(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_os_networks.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) elif method == 'POST': body = self.fixtures.load('_os_networks_POST.json') return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() def _v2_1337_os_networksv2_f13e5051_feea_416b_827a_1a0acc2dad14(self, method, url, body, headers): if method == 'DELETE': body = '' return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK]) raise NotImplementedError() class RackspaceNovaLonMockHttp(RackspaceNovaMockHttp): def _v2_0_tokens(self, method, url, body, headers): body = self.auth_fixtures.load('_v2_0__auth_lon.json') return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) # Does not derive from TestCase because it should not be used by setup.py test class BaseRackspaceNovaTestCase(object): conn_class = RackspaceNovaMockHttp auth_url = 'https://auth.api.example.com' def create_driver(self): return self.driver_type(*self.driver_args, **self.driver_kwargs) def setUp(self): self.driver_klass.connectionCls.conn_class = self.conn_class self.driver_klass.connectionCls.auth_url = self.auth_url self.conn_class.type = None self.driver = self.create_driver() # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() clear_pricing_data() self.node = self.driver.list_nodes()[1] def test_service_catalog_contais_right_endpoint(self): self.assertEqual(self.driver.connection.get_endpoint(), self.expected_endpoint) def test_list_sizes_pricing(self): sizes = self.driver.list_sizes() for size in sizes: if size.ram > 256: self.assertTrue(size.price > 0) class RackspaceNovaDfwTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): driver_klass = RackspaceNodeDriver driver_type = RackspaceNodeDriver driver_args = RACKSPACE_NOVA_PARAMS driver_kwargs = {'region': 'dfw'} expected_endpoint = 'https://dfw.servers.api.rackspacecloud.com/v2/1337' class RackspaceNovaOrdTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): driver_klass = RackspaceNodeDriver driver_type = RackspaceNodeDriver driver_args = RACKSPACE_NOVA_PARAMS driver_kwargs = {'region': 'ord'} expected_endpoint = 'https://ord.servers.api.rackspacecloud.com/v2/1337' class RackspaceNovaIadTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): driver_klass = RackspaceNodeDriver driver_type = RackspaceNodeDriver driver_args = RACKSPACE_NOVA_PARAMS driver_kwargs = {'region': 'iad'} expected_endpoint = 'https://iad.servers.api.rackspacecloud.com/v2/1337' class RackspaceNovaLonTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): driver_klass = RackspaceNodeDriver driver_type = RackspaceNodeDriver driver_args = RACKSPACE_NOVA_PARAMS driver_kwargs = {'region': 'lon'} conn_class = RackspaceNovaLonMockHttp auth_url = 'https://lon.auth.api.example.com' expected_endpoint = 'https://lon.servers.api.rackspacecloud.com/v2/1337' class RackspaceNovaSydTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): driver_klass = RackspaceNodeDriver driver_type = RackspaceNodeDriver driver_args = RACKSPACE_NOVA_PARAMS driver_kwargs = {'region': 'syd'} expected_endpoint = 'https://syd.servers.api.rackspacecloud.com/v2/1337' class RackspaceNovaHkgTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): driver_klass = RackspaceNodeDriver driver_type = RackspaceNodeDriver driver_args = RACKSPACE_NOVA_PARAMS driver_kwargs = {'region': 'hkg'} expected_endpoint = 'https://hkg.servers.api.rackspacecloud.com/v2/1337' if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_rimuhosting.py0000664000175000017500000001031413535474530024644 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Copyright 2009 RedRata Ltd import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.rimuhosting import RimuHostingNodeDriver from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures class RimuHostingTest(unittest.TestCase, TestCaseMixin): def setUp(self): RimuHostingNodeDriver.connectionCls.conn_class = RimuHostingMockHttp self.driver = RimuHostingNodeDriver('foo') def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) node = nodes[0] self.assertEqual(node.public_ips[0], "1.2.3.4") self.assertEqual(node.public_ips[1], "1.2.3.5") self.assertEqual(node.extra['order_oid'], 88833465) self.assertEqual(node.id, "order-88833465-api-ivan-net-nz") def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 1) size = sizes[0] self.assertEqual(size.ram, 950) self.assertEqual(size.disk, 20) self.assertEqual(size.bandwidth, 75) self.assertEqual(size.price, 32.54) def test_list_images(self): images = self.driver.list_images() self.assertEqual(len(images), 6) image = images[0] self.assertEqual(image.name, "Debian 5.0 (aka Lenny, RimuHosting" " recommended distro)") self.assertEqual(image.id, "lenny") def test_reboot_node(self): # Raises exception on failure node = self.driver.list_nodes()[0] self.driver.reboot_node(node) def test_destroy_node(self): # Raises exception on failure node = self.driver.list_nodes()[0] self.driver.destroy_node(node) def test_create_node(self): # Raises exception on failure size = self.driver.list_sizes()[0] image = self.driver.list_images()[0] self.driver.create_node(name="api.ivan.net.nz", image=image, size=size) class RimuHostingMockHttp(MockHttp): fixtures = ComputeFileFixtures('rimuhosting') def _r_orders(self, method, url, body, headers): body = self.fixtures.load('r_orders.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _r_pricing_plans(self, method, url, body, headers): body = self.fixtures.load('r_pricing_plans.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _r_distributions(self, method, url, body, headers): body = self.fixtures.load('r_distributions.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _r_orders_new_vps(self, method, url, body, headers): body = self.fixtures.load('r_orders_new_vps.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _r_orders_order_88833465_api_ivan_net_nz_vps(self, method, url, body, headers): body = self.fixtures.load( 'r_orders_order_88833465_api_ivan_net_nz_vps.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _r_orders_order_88833465_api_ivan_net_nz_vps_running_state( self, method, url, body, headers): body = self.fixtures.load( 'r_orders_order_88833465_api_ivan_net_nz_vps_running_state.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_scaleway.py0000664000175000017500000003253713535474530024117 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from datetime import datetime from libcloud.utils.iso8601 import UTC try: import simplejson as json except ImportError: import json # NOQA from libcloud.utils.py3 import httplib from libcloud.utils.py3 import assertRaisesRegex from libcloud.common.exceptions import BaseHTTPError from libcloud.compute.base import NodeImage from libcloud.compute.drivers.scaleway import ScalewayNodeDriver from libcloud.test import LibcloudTestCase, MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import SCALEWAY_PARAMS # class ScalewayTests(unittest.TestCase, TestCaseMixin): class Scaleway_Tests(LibcloudTestCase): def setUp(self): ScalewayNodeDriver.connectionCls.conn_class = ScalewayMockHttp ScalewayMockHttp.type = None self.driver = ScalewayNodeDriver(*SCALEWAY_PARAMS) def test_authentication(self): ScalewayMockHttp.type = 'UNAUTHORIZED' assertRaisesRegex(self, BaseHTTPError, 'Authentication error', self.driver.list_nodes) def test_list_locations_success(self): locations = self.driver.list_locations() self.assertTrue(len(locations) >= 1) location = locations[0] self.assertEqual(location.id, 'par1') self.assertEqual(location.name, 'Paris 1') def test_list_sizes_success(self): sizes = self.driver.list_sizes() self.assertTrue(len(sizes) >= 1) size = sizes[0] self.assertTrue(size.id is not None) self.assertEqual(size.name, 'ARM64-4GB') self.assertEqual(size.ram, 4096) size = sizes[1] self.assertTrue(size.id is not None) self.assertEqual(size.name, 'START1-XS') self.assertEqual(size.ram, 1024) size = sizes[2] self.assertTrue(size.id is not None) self.assertEqual(size.name, 'X64-120GB') self.assertEqual(size.ram, 122880) def test_list_images_success(self): images = self.driver.list_images() self.assertTrue(len(images) >= 1) image = images[0] self.assertTrue(image.id is not None) self.assertTrue(image.name is not None) def test_create_image_success(self): node = self.driver.list_nodes()[0] ScalewayMockHttp.type = 'POST' image = self.driver.create_image(node, 'my_image') self.assertEqual(image.name, 'my_image') self.assertEqual(image.id, '98bf3ac2-a1f5-471d-8c8f-1b706ab57ef0') self.assertEqual(image.extra['arch'], 'arm') def test_delete_image_success(self): image = self.driver.get_image(12345) ScalewayMockHttp.type = 'DELETE' result = self.driver.delete_image(image) self.assertTrue(result) def test_get_image_success(self): image = self.driver.get_image(12345) self.assertEqual(image.name, 'my_image') self.assertEqual(image.id, '12345') self.assertEqual(image.extra['arch'], 'arm') def test_list_nodes_success(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) self.assertEqual(nodes[0].name, 'my_server') self.assertEqual(nodes[0].public_ips, []) self.assertEqual(nodes[0].extra['volumes']['0']['id'], "c1eb8f3a-4f0b-4b95-a71c-93223e457f5a") self.assertEqual(nodes[0].extra['organization'], '000a115d-2852-4b0a-9ce8-47f1134ba95a') def test_list_nodes_fills_created_datetime(self): nodes = self.driver.list_nodes() self.assertEqual(nodes[0].created_at, datetime(2014, 5, 22, 12, 57, 22, 514298, tzinfo=UTC)) def test_create_node_success(self): image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] location = self.driver.list_locations()[0] ScalewayMockHttp.type = 'POST' node = self.driver.create_node(name='test', size=size, image=image, region=location) self.assertEqual(node.name, 'my_server') self.assertEqual(node.public_ips, []) self.assertEqual(node.extra['volumes']['0']['id'], "d9257116-6919-49b4-a420-dcfdff51fcb1") self.assertEqual(node.extra['organization'], '000a115d-2852-4b0a-9ce8-47f1134ba95a') def test_create_node_invalid_size(self): image = NodeImage(id='01234567-89ab-cdef-fedc-ba9876543210', name=None, driver=self.driver) size = self.driver.list_sizes()[0] location = self.driver.list_locations()[0] ScalewayMockHttp.type = 'INVALID_IMAGE' expected_msg = '" not found' assertRaisesRegex(self, Exception, expected_msg, self.driver.create_node, name='test', size=size, image=image, region=location) def test_reboot_node_success(self): node = self.driver.list_nodes()[0] ScalewayMockHttp.type = 'REBOOT' result = self.driver.reboot_node(node) self.assertTrue(result) def test_destroy_node_success(self): node = self.driver.list_nodes()[0] ScalewayMockHttp.type = 'TERMINATE' result = self.driver.destroy_node(node) self.assertTrue(result) def test_list_volumes(self): volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 2) volume = volumes[0] self.assertEqual(volume.id, "f929fe39-63f8-4be8-a80e-1e9c8ae22a76") self.assertEqual(volume.name, "volume-0-1") self.assertEqual(volume.size, 10) self.assertEqual(volume.driver, self.driver) def test_list_volumes_empty(self): ScalewayMockHttp.type = 'EMPTY' volumes = self.driver.list_volumes() self.assertEqual(len(volumes), 0) def test_list_volume_snapshots(self): volume = self.driver.list_volumes()[0] snapshots = self.driver.list_volume_snapshots(volume) self.assertEqual(len(snapshots), 2) snapshot1, snapshot2 = snapshots self.assertEqual(snapshot1.id, "6f418e5f-b42d-4423-a0b5-349c74c454a4") self.assertEqual(snapshot2.id, "c6ff5501-eb35-44b8-aa01-8777211a830b") def test_create_volume(self): par1 = [r for r in self.driver.list_locations() if r.id == 'par1'][0] ScalewayMockHttp.type = 'POST' volume = self.driver.create_volume(10, 'volume-0-3', par1) self.assertEqual(volume.id, "c675f420-cfeb-48ff-ba2a-9d2a4dbe3fcd") self.assertEqual(volume.name, "volume-0-3") self.assertEqual(volume.size, 10) self.assertEqual(volume.driver, self.driver) def test_create_volume_snapshot(self): volume = self.driver.list_volumes()[0] ScalewayMockHttp.type = 'POST' snapshot = self.driver.create_volume_snapshot(volume, 'snapshot-0-1') self.assertEqual(snapshot.id, "f0361e7b-cbe4-4882-a999-945192b7171b") self.assertEqual(snapshot.extra['volume_type'], 'l_ssd') self.assertEqual(volume.driver, self.driver) def test_destroy_volume(self): volume = self.driver.list_volumes()[0] ScalewayMockHttp.type = 'DELETE' resp = self.driver.destroy_volume(volume) self.assertTrue(resp) def test_destroy_volume_snapshot(self): volume = self.driver.list_volumes()[0] snapshot = self.driver.list_volume_snapshots(volume)[0] ScalewayMockHttp.type = 'DELETE' result = self.driver.destroy_volume_snapshot(snapshot) self.assertTrue(result) def test_list_key_pairs(self): keys = self.driver.list_key_pairs() self.assertEqual(len(keys), 1) self.assertEqual(keys[0].name, 'example') self.assertEqual(keys[0].public_key, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDGk5") self.assertEqual(keys[0].fingerprint, "f5:d1:78:ed:28:72:5f:e1:ac:94:fd:1f:e0:a3:48:6d") def test_import_key_pair_from_string(self): result = self.driver.import_key_pair_from_string( name="example", key_material="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDGk5" ) self.assertTrue(result) def test_delete_key_pair(self): key = self.driver.list_key_pairs()[0] result = self.driver.delete_key_pair(key) self.assertTrue(result) class ScalewayMockHttp(MockHttp): fixtures = ComputeFileFixtures('scaleway') def _products_servers(self, method, url, body, headers): body = self.fixtures.load('list_sizes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _products_servers_availability(self, method, url, body, headers): body = self.fixtures.load('list_availability.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_UNAUTHORIZED(self, method, url, body, headers): body = self.fixtures.load('error.json') return (httplib.UNAUTHORIZED, body, {}, httplib.responses[httplib.UNAUTHORIZED]) def _images(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _images_POST(self, method, url, body, headers): # create_image body = self.fixtures.load('create_image.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _images_12345_DELETE(self, method, url, body, headers): # delete_image return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _images_12345(self, method, url, body, headers): # get_image body = self.fixtures.load('get_image.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers(self, method, url, body, headers): body = self.fixtures.load('list_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_POST(self, method, url, body, headers): body = self.fixtures.load('create_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _servers_741db378_action_POST(self, method, url, body, headers): # reboot_node return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _servers_INVALID_IMAGE(self, method, url, body, headers): body = self.fixtures.load('error_invalid_image.json') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) def _servers_741db378_action_REBOOT(self, method, url, body, headers): # reboot_node body = self.fixtures.load('reboot_node.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _servers_741db378_action_TERMINATE(self, method, url, body, headers): # destroy_node return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT]) def _volumes(self, method, url, body, headers): body = self.fixtures.load('list_volumes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _volumes_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_volumes_empty.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _snapshots( self, method, url, body, headers): body = self.fixtures.load('list_volume_snapshots.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _volumes_POST(self, method, url, body, headers): body = self.fixtures.load('create_volume.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _snapshots_POST(self, method, url, body, headers): body = self.fixtures.load('create_volume_snapshot.json') return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED]) def _volumes_f929fe39_63f8_4be8_a80e_1e9c8ae22a76_DELETE( self, method, url, body, headers): return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) def _snapshots_6f418e5f_b42d_4423_a0b5_349c74c454a4_DELETE( self, method, url, body, headers): return (httplib.NO_CONTENT, None, {}, httplib.responses[httplib.NO_CONTENT]) def _tokens_token(self, method, url, body, headers): body = self.fixtures.load('token_info.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _users_5bea0358(self, method, url, body, headers): body = self.fixtures.load('user_info.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_softlayer.py0000664000175000017500000003035113577507766024325 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import sys import pytest from libcloud.common.types import InvalidCredsError from libcloud.utils.py3 import httplib from libcloud.utils.py3 import xmlrpclib from libcloud.utils.py3 import next from libcloud.compute.drivers.softlayer import SoftLayerNodeDriver as SoftLayer from libcloud.compute.drivers.softlayer import SoftLayerException, \ NODE_STATE_MAP from libcloud.compute.types import NodeState, KeyPairDoesNotExistError from libcloud.test import unittest from libcloud.test import MockHttp # pylint: disable-msg=E0611 from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import SOFTLAYER_PARAMS null_fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \ '00:00:00:00:00' class SoftLayerTests(unittest.TestCase): def setUp(self): SoftLayer.connectionCls.conn_class = SoftLayerMockHttp SoftLayerMockHttp.type = None self.driver = SoftLayer(*SOFTLAYER_PARAMS) def test_list_nodes(self): nodes = self.driver.list_nodes() node = nodes[0] self.assertEqual(node.name, 'libcloud-testing1.example.com') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.extra['password'], 'L3TJVubf') def test_initializing_state(self): nodes = self.driver.list_nodes() node = nodes[1] self.assertEqual(node.state, NODE_STATE_MAP['INITIATING']) def test_list_locations(self): locations = self.driver.list_locations() dal = next(l for l in locations if l.id == 'dal05') self.assertEqual(dal.country, 'US') self.assertEqual(dal.id, 'dal05') self.assertEqual(dal.name, 'Dallas - Central U.S.') def test_list_images(self): images = self.driver.list_images() image = images[0] self.assertEqual(image.id, 'CENTOS_6_64') def test_get_image(self): image = self.driver.get_image('CENTOS_6_64') self.assertEqual(image.id, 'CENTOS_6_64') def test_fail_get_image(self): self.assertRaises( SoftLayerException, self.driver.get_image, 'NOT_IMAGE') def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 13) for size in sizes: self.assertTrue(size.price > 0.0) def test_create_node(self): node = self.driver.create_node(name="libcloud-testing", location=self.driver.list_locations()[0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[0]) self.assertEqual(node.name, 'libcloud-testing.example.com') self.assertEqual(node.state, NODE_STATE_MAP['RUNNING']) def test_create_node_ex_hourly_True(self): SoftLayerMockHttp.type = 'HOURLY_BILLING_TRUE' node = self.driver.create_node(name="libcloud-testing", location=self.driver.list_locations()[0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[0], ex_hourly=True) self.assertEqual(node.name, 'libcloud-testing.example.com') self.assertEqual(node.state, NODE_STATE_MAP['RUNNING']) SoftLayerMockHttp.type = 'HOURLY_BILLING_FALSE' node = self.driver.create_node(name="libcloud-testing", location=self.driver.list_locations()[0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[0], ex_hourly=False) self.assertEqual(node.name, 'libcloud-testing.example.com') self.assertEqual(node.state, NODE_STATE_MAP['RUNNING']) def test_create_fail(self): SoftLayerMockHttp.type = "SOFTLAYEREXCEPTION" self.assertRaises( SoftLayerException, self.driver.create_node, name="SOFTLAYEREXCEPTION", location=self.driver.list_locations()[0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[0]) def test_create_creds_error(self): SoftLayerMockHttp.type = "INVALIDCREDSERROR" self.assertRaises( InvalidCredsError, self.driver.create_node, name="INVALIDCREDSERROR", location=self.driver.list_locations()[0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[0]) def test_create_node_no_location(self): self.driver.create_node(name="Test", size=self.driver.list_sizes()[0], image=self.driver.list_images()[0]) def test_create_node_no_image(self): self.driver.create_node(name="Test", size=self.driver.list_sizes()[0]) def test_create_node_san(self): self.driver.create_node(name="Test", ex_local_disk=False) def test_create_node_domain_for_name(self): self.driver.create_node(name="libcloud.org") def test_create_node_ex_options(self): self.driver.create_node(name="Test", location=self.driver.list_locations()[0], size=self.driver.list_sizes()[0], image=self.driver.list_images()[0], ex_domain='libcloud.org', ex_cpus=2, ex_ram=2048, ex_disk=100, ex_keyname='test1', ex_bandwidth=10, ex_local_disk=False, ex_datacenter='Dal05', ex_os='UBUNTU_LATEST') def test_reboot_node(self): node = self.driver.list_nodes()[0] self.driver.reboot_node(node) def test_destroy_node(self): node = self.driver.list_nodes()[0] self.driver.destroy_node(node) def test_list_keypairs(self): keypairs = self.driver.list_key_pairs() self.assertEqual(len(keypairs), 2) self.assertEqual(keypairs[0].name, 'test1') self.assertEqual(keypairs[0].fingerprint, null_fingerprint) def test_get_key_pair(self): key_pair = self.driver.get_key_pair(name='test1') self.assertEqual(key_pair.name, 'test1') def test_get_key_pair_does_not_exist(self): self.assertRaises(KeyPairDoesNotExistError, self.driver.get_key_pair, name='test-key-pair') @pytest.mark.skip(reason="no way of currently testing this") def test_create_key_pair(self): key_pair = self.driver.create_key_pair(name='my-key-pair') fingerprint = ('1f:51:ae:28:bf:89:e9:d8:1f:25:5d' ':37:2d:7d:b8:ca:9f:f5:f1:6f') self.assertEqual(key_pair.name, 'my-key-pair') self.assertEqual(key_pair.fingerprint, fingerprint) self.assertTrue(key_pair.private_key is not None) def test_delete_key_pair(self): success = self.driver.delete_key_pair('test1') self.assertTrue(success) class SoftLayerMockHttp(MockHttp, unittest.TestCase): fixtures = ComputeFileFixtures('softlayer') def _get_method_name(self, type, use_param, qs, path): return "_xmlrpc" def _xmlrpc(self, method, url, body, headers): params, meth_name = xmlrpclib.loads(body) url = url.replace("/", "_") meth_name = "%s_%s" % (url, meth_name) return getattr(self, meth_name)(method, url, body, headers) def _xmlrpc_v3_SoftLayer_Virtual_Guest_getCreateObjectOptions( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Account_getVirtualGuests( self, method, url, body, headers): body = self.fixtures.load('v3_SoftLayer_Account_getVirtualGuests.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Location_Datacenter_getDatacenters( self, method, url, body, headers): body = self.fixtures.load( 'v3_SoftLayer_Location_Datacenter_getDatacenters.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Virtual_Guest_createObject( self, method, url, body, headers): fixture = { None: 'v3__SoftLayer_Virtual_Guest_createObject.xml', 'INVALIDCREDSERROR': 'SoftLayer_Account.xml', 'SOFTLAYEREXCEPTION': 'fail.xml', 'HOURLY_BILLING_TRUE': 'v3__SoftLayer_Virtual_Guest_createObject.xml', 'HOURLY_BILLING_FALSE': 'v3__SoftLayer_Virtual_Guest_createObject.xml', }[self.type] if self.type == 'HOURLY_BILLING_TRUE': # Verify parameter is sent as a boolean and not as a string expected_value = """ hourlyBillingFlag 1 """.strip() self.assertTrue(expected_value in body, 'Request body is missing hourlyBillingFlag attribute') elif self.type == 'HOURLY_BILLING_FALSE': # Verify parameter is sent as a boolean and not as a string expected_value = """ hourlyBillingFlag 0 """.strip() self.assertTrue(expected_value in body, 'Request body is missing hourlyBillingFlag attribute') body = self.fixtures.load(fixture) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Virtual_Guest_getObject( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Virtual_Guest_getObject.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Virtual_Guest_rebootSoft( self, method, url, body, headers): body = self.fixtures.load('empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Virtual_Guest_deleteObject( self, method, url, body, headers): body = self.fixtures.load('empty.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Account_getSshKeys( self, method, url, body, headers): body = self.fixtures.load('v3__SoftLayer_Account_getSshKeys.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Security_Ssh_Key_getObject( self, method, url, body, headers): body = self.fixtures.load('v3__SoftLayer_Security_Ssh_Key_getObject.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Security_Ssh_Key_createObject( self, method, url, body, headers): body = self.fixtures.load('v3__SoftLayer_Security_Ssh_Key_createObject.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Security_Ssh_Key_deleteObject( self, method, url, body, headers): body = self.fixtures.load('v3__SoftLayer_Security_Ssh_Key_deleteObject.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_ssh_client.py0000664000175000017500000004612713600144066024431 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more§ # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import absolute_import from __future__ import with_statement import os import sys import tempfile from libcloud import _init_once from libcloud.test import LibcloudTestCase from libcloud.test import unittest from libcloud.compute.ssh import ParamikoSSHClient from libcloud.compute.ssh import ShellOutSSHClient from libcloud.compute.ssh import have_paramiko from libcloud.utils.py3 import StringIO from libcloud.utils.py3 import u from libcloud.utils.py3 import assertRaisesRegex from mock import patch, Mock, MagicMock if not have_paramiko: ParamikoSSHClient = None # NOQA paramiko_version = '0.0.0' else: import paramiko paramiko_version = paramiko.__version__ @unittest.skipIf(not have_paramiko, 'Skipping because paramiko is not available') class ParamikoSSHClientTests(LibcloudTestCase): @patch('paramiko.SSHClient', Mock) def setUp(self): """ Creates the object patching the actual connection. """ conn_params = {'hostname': 'dummy.host.org', 'port': 8822, 'username': 'ubuntu', 'key': '~/.ssh/ubuntu_ssh', 'timeout': '600'} _, self.tmp_file = tempfile.mkstemp() os.environ['LIBCLOUD_DEBUG'] = self.tmp_file _init_once() self.ssh_cli = ParamikoSSHClient(**conn_params) @patch('paramiko.SSHClient', Mock) def test_create_with_password(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'password': 'ubuntu'} mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = {'username': 'ubuntu', 'password': 'ubuntu', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn) self.assertLogMsg('Connecting to server') @patch('paramiko.SSHClient', Mock) def test_deprecated_key_argument(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'key': 'id_rsa'} mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = {'username': 'ubuntu', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'key_filename': 'id_rsa', 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn) self.assertLogMsg('Connecting to server') def test_key_files_and_key_material_arguments_are_mutual_exclusive(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'key_files': 'id_rsa', 'key_material': 'key'} expected_msg = ('key_files and key_material arguments are mutually ' 'exclusive') assertRaisesRegex(self, ValueError, expected_msg, ParamikoSSHClient, **conn_params) @patch('paramiko.SSHClient', Mock) def test_key_material_argument(self): path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa.key') with open(path, 'r') as fp: private_key = fp.read() conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'key_material': private_key} mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key)) expected_conn = {'username': 'ubuntu', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'pkey': pkey, 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn) self.assertLogMsg('Connecting to server') @patch('paramiko.SSHClient', Mock) def test_key_material_argument_invalid_key(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'key_material': 'id_rsa'} mock = ParamikoSSHClient(**conn_params) expected_msg = 'Invalid or unsupported key type' assertRaisesRegex(self, paramiko.ssh_exception.SSHException, expected_msg, mock.connect) @patch('paramiko.SSHClient', Mock) @unittest.skipIf(paramiko_version >= '2.7.0', 'New versions of paramiko support OPENSSH key format') def test_key_file_non_pem_format_error(self): path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa_non_pem_format.key') # Supplied as key_material with open(path, 'r') as fp: private_key = fp.read() conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'key_material': private_key} mock = ParamikoSSHClient(**conn_params) expected_msg = 'Invalid or unsupported key type' assertRaisesRegex(self, paramiko.ssh_exception.SSHException, expected_msg, mock.connect) def test_key_material_valid_pem_keys_invalid_header_auto_conversion(self): # Test a scenario where valid PEM keys with invalid headers which is # not recognized by paramiko are automatically converted in a format # which is recognized by paramiko conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) # 1. RSA key type with header which is not supported by paramiko path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa_non_paramiko_recognized_header.key') with open(path, 'r') as fp: private_key = fp.read() pkey = client._get_pkey_object(key=private_key) self.assertTrue(pkey) self.assertTrue(isinstance(pkey, paramiko.RSAKey)) # 2. DSA key type with header which is not supported by paramiko path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_dsa_non_paramiko_recognized_header.key') with open(path, 'r') as fp: private_key = fp.read() pkey = client._get_pkey_object(key=private_key) self.assertTrue(pkey) self.assertTrue(isinstance(pkey, paramiko.DSSKey)) # 3. ECDSA key type with header which is not supported by paramiko path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_ecdsa_non_paramiko_recognized_header.key') with open(path, 'r') as fp: private_key = fp.read() pkey = client._get_pkey_object(key=private_key) self.assertTrue(pkey) self.assertTrue(isinstance(pkey, paramiko.ECDSAKey)) def test_key_material_valid_pem_keys(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) # 1. RSA key type with header which is not supported by paramiko path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_rsa.key') with open(path, 'r') as fp: private_key = fp.read() pkey = client._get_pkey_object(key=private_key) self.assertTrue(pkey) self.assertTrue(isinstance(pkey, paramiko.RSAKey)) # 2. DSA key type with header which is not supported by paramiko path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_dsa.key') with open(path, 'r') as fp: private_key = fp.read() pkey = client._get_pkey_object(key=private_key) self.assertTrue(pkey) self.assertTrue(isinstance(pkey, paramiko.DSSKey)) # 3. ECDSA key type with header which is not supported by paramiko path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc', 'test_ecdsa.key') with open(path, 'r') as fp: private_key = fp.read() pkey = client._get_pkey_object(key=private_key) self.assertTrue(pkey) self.assertTrue(isinstance(pkey, paramiko.ECDSAKey)) @patch('paramiko.SSHClient', Mock) def test_create_with_key(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'key_files': 'id_rsa'} mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = {'username': 'ubuntu', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'key_filename': 'id_rsa', 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn) self.assertLogMsg('Connecting to server') @patch('paramiko.SSHClient', Mock) def test_create_with_password_and_key(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu', 'password': 'ubuntu', 'key': 'id_rsa'} mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = {'username': 'ubuntu', 'password': 'ubuntu', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'key_filename': 'id_rsa', 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn) self.assertLogMsg('Connecting to server') @patch('paramiko.SSHClient', Mock) def test_create_without_credentials(self): """ Initialize object with no credentials. Just to have better coverage, initialize the object without 'password' neither 'key'. """ conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = {'username': 'ubuntu', 'hostname': 'dummy.host.org', 'allow_agent': True, 'look_for_keys': True, 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn) @patch.object(ParamikoSSHClient, '_consume_stdout', MagicMock(return_value=StringIO(''))) @patch.object(ParamikoSSHClient, '_consume_stderr', MagicMock(return_value=StringIO(''))) def test_basic_usage_absolute_path(self): """ Basic execution. """ mock = self.ssh_cli # script to execute sd = "/root/random_script.sh" # Connect behavior mock.connect() mock_cli = mock.client # The actual mocked object: SSHClient expected_conn = {'username': 'ubuntu', 'key_filename': '~/.ssh/ubuntu_ssh', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'timeout': '600', 'port': 8822} mock_cli.connect.assert_called_once_with(**expected_conn) mock.put(sd) # Make assertions over 'put' method mock_cli.open_sftp().chdir.assert_called_with('root') mock_cli.open_sftp().file.assert_called_once_with('random_script.sh', mode='w') mock.run(sd) # Make assertions over 'run' method mock_cli.get_transport().open_session().exec_command \ .assert_called_once_with(sd) self.assertLogMsg('Executing command (cmd=/root/random_script.sh)') self.assertLogMsg('Command finished') mock.close() def test_delete_script(self): """ Provide a basic test with 'delete' action. """ mock = self.ssh_cli # script to execute sd = '/root/random_script.sh' mock.connect() mock.delete(sd) # Make assertions over the 'delete' method mock.client.open_sftp().unlink.assert_called_with(sd) self.assertLogMsg('Deleting file') mock.close() self.assertLogMsg('Closing server connection') def assertLogMsg(self, expected_msg): with open(self.tmp_file, 'r') as fp: content = fp.read() self.assertTrue(content.find(expected_msg) != -1) def test_consume_stdout(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) client.CHUNK_SIZE = 1024 chan = Mock() chan.recv_ready.side_effect = [True, True, False] chan.recv.side_effect = ['123', '456'] stdout = client._consume_stdout(chan).getvalue() self.assertEqual(u('123456'), stdout) self.assertEqual(len(stdout), 6) conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) client.CHUNK_SIZE = 1024 chan = Mock() chan.recv_ready.side_effect = [True, True, False] chan.recv.side_effect = ['987', '6543210'] stdout = client._consume_stdout(chan).getvalue() self.assertEqual(u('9876543210'), stdout) self.assertEqual(len(stdout), 10) def test_consume_stderr(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) client.CHUNK_SIZE = 1024 chan = Mock() chan.recv_stderr_ready.side_effect = [True, True, False] chan.recv_stderr.side_effect = ['123', '456'] stderr = client._consume_stderr(chan).getvalue() self.assertEqual(u('123456'), stderr) self.assertEqual(len(stderr), 6) conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) client.CHUNK_SIZE = 1024 chan = Mock() chan.recv_stderr_ready.side_effect = [True, True, False] chan.recv_stderr.side_effect = ['987', '6543210'] stderr = client._consume_stderr(chan).getvalue() self.assertEqual(u('9876543210'), stderr) self.assertEqual(len(stderr), 10) def test_consume_stdout_chunk_contains_part_of_multi_byte_utf8_character(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) client.CHUNK_SIZE = 1 chan = Mock() chan.recv_ready.side_effect = [True, True, True, True, False] chan.recv.side_effect = ['\xF0', '\x90', '\x8D', '\x88'] stdout = client._consume_stdout(chan).getvalue() self.assertEqual('\xf0\x90\x8d\x88', stdout.encode('utf-8')) self.assertTrue(len(stdout) in [1, 2]) def test_consume_stderr_chunk_contains_part_of_multi_byte_utf8_character(self): conn_params = {'hostname': 'dummy.host.org', 'username': 'ubuntu'} client = ParamikoSSHClient(**conn_params) client.CHUNK_SIZE = 1 chan = Mock() chan.recv_stderr_ready.side_effect = [True, True, True, True, False] chan.recv_stderr.side_effect = ['\xF0', '\x90', '\x8D', '\x88'] stderr = client._consume_stderr(chan).getvalue() self.assertEqual('\xf0\x90\x8d\x88', stderr.encode('utf-8')) self.assertTrue(len(stderr) in [1, 2]) class ShellOutSSHClientTests(LibcloudTestCase): def test_password_auth_not_supported(self): try: ShellOutSSHClient(hostname='localhost', username='foo', password='bar') except ValueError as e: msg = str(e) self.assertTrue('ShellOutSSHClient only supports key auth' in msg) else: self.fail('Exception was not thrown') def test_ssh_executable_not_available(self): class MockChild(object): returncode = 127 def communicate(*args, **kwargs): pass def mock_popen(*args, **kwargs): return MockChild() with patch('subprocess.Popen', mock_popen): try: ShellOutSSHClient(hostname='localhost', username='foo') except ValueError as e: msg = str(e) self.assertTrue('ssh client is not available' in msg) else: self.fail('Exception was not thrown') def test_connect_success(self): client = ShellOutSSHClient(hostname='localhost', username='root') self.assertTrue(client.connect()) def test_close_success(self): client = ShellOutSSHClient(hostname='localhost', username='root') self.assertTrue(client.close()) def test_get_base_ssh_command(self): client1 = ShellOutSSHClient(hostname='localhost', username='root') client2 = ShellOutSSHClient(hostname='localhost', username='root', key='/home/my.key') client3 = ShellOutSSHClient(hostname='localhost', username='root', key='/home/my.key', timeout=5) cmd1 = client1._get_base_ssh_command() cmd2 = client2._get_base_ssh_command() cmd3 = client3._get_base_ssh_command() self.assertEqual(cmd1, ['ssh', 'root@localhost']) self.assertEqual(cmd2, ['ssh', '-i', '/home/my.key', 'root@localhost']) self.assertEqual(cmd3, ['ssh', '-i', '/home/my.key', '-oConnectTimeout=5', 'root@localhost']) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_types.py0000664000175000017500000000620213576514553023446 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from unittest import TestCase from libcloud.compute.types import Provider, NodeState, StorageVolumeState, \ VolumeSnapshotState, Type class TestType(Type): INUSE = "inuse" NOTINUSE = "NOTINUSE" class TestTestType(TestCase): model = TestType def test_provider_tostring(self): self.assertEqual(Provider.tostring(TestType.INUSE), "INUSE") self.assertEqual(Provider.tostring(TestType.NOTINUSE), "NOTINUSE") def test_provider_fromstring(self): self.assertEqual(TestType.fromstring("inuse"), TestType.INUSE) self.assertEqual(TestType.fromstring("NOTINUSE"), TestType.NOTINUSE) def test_provider_fromstring_caseinsensitive(self): self.assertEqual(TestType.fromstring("INUSE"), TestType.INUSE) self.assertEqual(TestType.fromstring("notinuse"), TestType.NOTINUSE) def test_compare_as_string(self): self.assertTrue(TestType.INUSE == 'inuse') self.assertFalse(TestType.INUSE == 'bar') class TestProvider(TestCase): def test_provider_tostring(self): self.assertEqual(Provider.tostring(Provider.RACKSPACE), "RACKSPACE") def test_provider_fromstring(self): self.assertEqual(Provider.fromstring("rackspace"), Provider.RACKSPACE) class TestNodeState(TestCase): def test_nodestate_tostring(self): self.assertEqual(NodeState.tostring(NodeState.RUNNING), "RUNNING") def test_nodestate_fromstring(self): self.assertEqual(NodeState.fromstring("running"), NodeState.RUNNING) class TestStorageVolumeState(TestCase): def test_storagevolumestate_tostring(self): self.assertEqual( StorageVolumeState.tostring(StorageVolumeState.AVAILABLE), "AVAILABLE" ) def test_storagevolumestate_fromstring(self): self.assertEqual( StorageVolumeState.fromstring("available"), StorageVolumeState.AVAILABLE ) class TestVolumeSnapshotState(TestCase): def test_volumesnapshotstate_tostring(self): self.assertEqual( VolumeSnapshotState.tostring(VolumeSnapshotState.AVAILABLE), "AVAILABLE" ) def test_volumesnapshotstate_fromstring(self): self.assertEqual( VolumeSnapshotState.fromstring("available"), VolumeSnapshotState.AVAILABLE ) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_upcloud.py0000664000175000017500000002743013535474530023756 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import sys import re import json import base64 from libcloud.utils.py3 import httplib, ensure_string from libcloud.compute.drivers.upcloud import UpcloudDriver from libcloud.common.types import InvalidCredsError from libcloud.compute.drivers.upcloud import UpcloudResponse from libcloud.compute.types import NodeState, Provider from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, NodeAuthSSHKey, Node from libcloud.compute import providers from libcloud.test import LibcloudTestCase, unittest, MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import UPCLOUD_PARAMS class UpcloudPersistResponse(UpcloudResponse): def parse_body(self): import os path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.pardir, 'compute', 'fixtures', 'upcloud')) filename = 'api' + self.request.path_url.replace('/', '_').replace('.', '_') + '.json' filename = os.path.join(path, filename) if not os.path.exists(filename): with open(filename, 'w+') as f: f.write(self.body) return super(UpcloudPersistResponse, self).parse_body() class UpcloudAuthenticationTests(LibcloudTestCase): def setUp(self): UpcloudDriver.connectionCls.conn_class = UpcloudMockHttp self.driver = UpcloudDriver("nosuchuser", "nopwd") def test_authentication_fails(self): with self.assertRaises(InvalidCredsError): self.driver.list_locations() class UpcloudDriverTests(LibcloudTestCase): def setUp(self): UpcloudDriver.connectionCls.conn_class = UpcloudMockHttp # UpcloudDriver.connectionCls.responseCls = UpcloudPersistResponse self.driver = UpcloudDriver(*UPCLOUD_PARAMS) def test_creating_driver(self): cls = providers.get_driver(Provider.UPCLOUD) self.assertIs(cls, UpcloudDriver) def test_features(self): features = self.driver.features['create_node'] self.assertIn('ssh_key', features) self.assertIn('generates_password', features) def test_list_locations(self): locations = self.driver.list_locations() self.assertTrue(len(locations) >= 1) expected_node_location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver=self.driver) self.assert_object(expected_node_location, objects=locations) def test_list_sizes(self): location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver=self.driver) sizes = self.driver.list_sizes(location) self.assertTrue(len(sizes) >= 1) expected_node_size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048, price=2.232, driver=self.driver, extra={'core_number': 1, 'storage_tier': 'maxiops'}) self.assert_object(expected_node_size, objects=sizes) def test_list_images(self): images = self.driver.list_images() self.assertTrue(len(images) >= 1) expected_node_image = NodeImage(id='01000000-0000-4000-8000-000010010101', name='Windows Server 2003 R2 Standard (CD 1)', driver=self.driver, extra={'access': 'public', 'license': 0, 'size': 1, 'state': 'online', 'type': 'cdrom'}) self.assert_object(expected_node_image, objects=images) def test_create_node_from_template(self): image = NodeImage(id='01000000-0000-4000-8000-000030060200', name='Ubuntu Server 16.04 LTS (Xenial Xerus)', extra={'type': 'template'}, driver=self.driver) location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver=self.driver) size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048, extra={'storage_tier': 'maxiops'}, price=None, driver=self.driver) node = self.driver.create_node(name='test_server', size=size, image=image, location=location, ex_hostname='myhost.somewhere') self.assertTrue(re.match('^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$', node.id)) self.assertEqual(node.name, 'test_server') self.assertEqual(node.state, NodeState.STARTING) self.assertTrue(len(node.public_ips) > 0) self.assertTrue(len(node.private_ips) > 0) self.assertEqual(node.driver, self.driver) self.assertTrue(len(node.extra['password']) > 0) self.assertTrue(len(node.extra['vnc_password']) > 0) def test_create_node_with_ssh_keys(self): image = NodeImage(id='01000000-0000-4000-8000-000030060200', name='Ubuntu Server 16.04 LTS (Xenial Xerus)', extra={'type': 'template'}, driver=self.driver) location = NodeLocation(id='fi-hel1', name='Helsinki #1', country='FI', driver=self.driver) size = NodeSize(id='1xCPU-1GB', name='1xCPU-1GB', ram=1024, disk=30, bandwidth=2048, extra={'storage_tier': 'maxiops'}, price=None, driver=self.driver) auth = NodeAuthSSHKey('publikey') node = self.driver.create_node(name='test_server', size=size, image=image, location=location, auth=auth) self.assertTrue(re.match('^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$', node.id)) self.assertEqual(node.name, 'test_server') self.assertEqual(node.state, NodeState.STARTING) self.assertTrue(len(node.public_ips) > 0) self.assertTrue(len(node.private_ips) > 0) self.assertEqual(node.driver, self.driver) def test_list_nodes(self): nodes = self.driver.list_nodes() self.assertTrue(len(nodes) >= 1) node = nodes[0] self.assertEqual(node.name, 'test_server') self.assertEqual(node.state, NodeState.RUNNING) self.assertTrue(len(node.public_ips) > 0) self.assertTrue(len(node.private_ips) > 0) self.assertEqual(node.driver, self.driver) def test_reboot_node(self): nodes = self.driver.list_nodes() success = self.driver.reboot_node(nodes[0]) self.assertTrue(success) def test_destroy_node(self): if UpcloudDriver.connectionCls.conn_class == UpcloudMockHttp: nodes = [Node(id='00893c98_5d5a_4363_b177_88df518a2b60', name='', state='', public_ips=[], private_ips=[], driver=self.driver)] else: nodes = self.driver.list_nodes() success = self.driver.destroy_node(nodes[0]) self.assertTrue(success) def assert_object(self, expected_object, objects): same_data = any([self.objects_equals(expected_object, obj) for obj in objects]) self.assertTrue(same_data, "Objects does not match") def objects_equals(self, expected_obj, obj): for name in vars(expected_obj): expected_data = getattr(expected_obj, name) actual_data = getattr(obj, name) same_data = self.data_equals(expected_data, actual_data) if not same_data: break return same_data def data_equals(self, expected_data, actual_data): if isinstance(expected_data, dict): return self.dicts_equals(expected_data, actual_data) else: return expected_data == actual_data def dicts_equals(self, d1, d2): dict_keys_same = set(d1.keys()) == set(d2.keys()) if not dict_keys_same: return False for key in d1.keys(): if d1[key] != d2[key]: return False return True class UpcloudMockHttp(MockHttp): fixtures = ComputeFileFixtures('upcloud') def _1_2_zone(self, method, url, body, headers): auth = headers['Authorization'].split(' ')[1] username, password = ensure_string(base64.b64decode(auth)).split(':') if username == 'nosuchuser' and password == 'nopwd': body = self.fixtures.load('api_1_2_zone_failed_auth.json') status_code = httplib.UNAUTHORIZED else: body = self.fixtures.load('api_1_2_zone.json') status_code = httplib.OK return (status_code, body, {}, httplib.responses[httplib.OK]) def _1_2_plan(self, method, url, body, headers): body = self.fixtures.load('api_1_2_plan.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _1_2_storage_cdrom(self, method, url, body, headers): body = self.fixtures.load('api_1_2_storage_cdrom.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _1_2_storage_template(self, method, url, body, headers): body = self.fixtures.load('api_1_2_storage_template.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _1_2_price(self, method, url, body, headers): body = self.fixtures.load('api_1_2_price.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _1_2_server(self, method, url, body, headers): if method == 'POST': dbody = json.loads(body) storages = dbody['server']['storage_devices']['storage_device'] if any(['type' in storage and storage['type'] == 'cdrom' for storage in storages]): body = self.fixtures.load('api_1_2_server_from_cdrom.json') else: body = self.fixtures.load('api_1_2_server_from_template.json') else: body = self.fixtures.load('api_1_2_server.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _1_2_server_00f8c525_7e62_4108_8115_3958df5b43dc(self, method, url, body, headers): body = self.fixtures.load('api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _1_2_server_00f8c525_7e62_4108_8115_3958df5b43dc_restart(self, method, url, body, headers): body = self.fixtures.load('api_1_2_server_00f8c525-7e62-4108-8115-3958df5b43dc_restart.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _1_2_server_00893c98_5d5a_4363_b177_88df518a2b60(self, method, url, body, headers): body = self.fixtures.load('api_1_2_server_00893c98-5d5a-4363-b177-88df518a2b60.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_vcl.py0000664000175000017500000001132513535474530023063 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import sys from libcloud.utils.py3 import httplib from libcloud.utils.py3 import xmlrpclib from libcloud.compute.drivers.vcl import VCLNodeDriver as VCL from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import VCL_PARAMS class VCLTests(unittest.TestCase): def setUp(self): VCL.connectionCls.conn_class = VCLMockHttp VCLMockHttp.type = None self.driver = VCL(*VCL_PARAMS) def test_list_nodes(self): node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] self.assertEqual(node.name, 'CentOS 5.4 Base (32 bit VM)') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.extra['pass'], 'ehkNGW') def test_list_images(self): images = self.driver.list_images() image = images[0] self.assertEqual(image.id, '8') def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 1) def test_create_node(self): image = self.driver.list_images()[0] node = self.driver.create_node(image=image) self.assertEqual(node.id, '51') def test_destroy_node(self): node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] self.assertTrue(self.driver.destroy_node(node)) def test_ex_update_node_access(self): node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] node = self.driver.ex_update_node_access(node, ipaddr='192.168.1.2') self.assertEqual(node.name, 'CentOS 5.4 Base (32 bit VM)') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.extra['pass'], 'ehkNGW') def test_ex_extend_request_time(self): node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] self.assertTrue(self.driver.ex_extend_request_time(node, 60)) def test_ex_get_request_end_time(self): node = self.driver.list_nodes(ipaddr='192.168.1.1')[0] self.assertEqual( self.driver.ex_get_request_end_time(node), 1334168100 ) class VCLMockHttp(MockHttp): fixtures = ComputeFileFixtures('vcl') def _get_method_name(self, type, use_param, qs, path): return "_xmlrpc" def _xmlrpc(self, method, url, body, headers): params, meth_name = xmlrpclib.loads(body) if self.type: meth_name = "%s_%s" % (meth_name, self.type) return getattr(self, meth_name)(method, url, body, headers) def XMLRPCgetImages(self, method, url, body, headers): body = self.fixtures.load('XMLRPCgetImages.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def XMLRPCextendRequest(self, method, url, body, headers): body = self.fixtures.load('XMLRPCextendRequest.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def XMLRPCgetRequestIds(self, method, url, body, headers): body = self.fixtures.load( 'XMLRPCgetRequestIds.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def XMLRPCgetRequestStatus(self, method, url, body, headers): body = self.fixtures.load( 'XMLRPCgetRequestStatus.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def XMLRPCendRequest(self, method, url, body, headers): body = self.fixtures.load( 'XMLRPCendRequest.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def XMLRPCaddRequest(self, method, url, body, headers): body = self.fixtures.load( 'XMLRPCaddRequest.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def XMLRPCgetRequestConnectData(self, method, url, body, headers): body = self.fixtures.load( 'XMLRPCgetRequestConnectData.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_vcloud.py0000664000175000017500000014745013577507766023622 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import print_function import datetime import re import sys import traceback import unittest from libcloud.utils.py3 import httplib, b, assertRaisesRegex, PY2 from libcloud.utils.py3 import ET from libcloud.utils.iso8601 import UTC from libcloud.compute.drivers.vcloud import TerremarkDriver, VCloudNodeDriver, Subject, Lease, fixxpath, get_url_path from libcloud.compute.drivers.vcloud import VCloud_1_5_NodeDriver, ControlAccess, Instantiate_1_5_VAppXML from libcloud.compute.drivers.vcloud import VCloud_5_1_NodeDriver from libcloud.compute.drivers.vcloud import VCloud_5_5_NodeDriver from libcloud.compute.drivers.vcloud import Vdc from libcloud.compute.base import Node, NodeImage from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures from mock import Mock, patch, mock_open from libcloud.test.secrets import VCLOUD_PARAMS BUILTINS = '__builtin__' if PY2 else 'builtins' def print_parameterized_failure(names_values): """ Print failure information for a failed, parameterized test. This includes a traceback and parameter values. :param names_values: Name, value pairs for parameters of test at failure :type names_values: ``list`` of (``str``, ``Any``) :return: None :rtype: ``None`` """ formatted_names_values = ( ' {name}={value}'.format(name=name, value=value) for name, value in names_values ) traceback.print_exc() print( 'Data values:\n{values}\n'.format(values='\n'.join(formatted_names_values)), file=sys.stderr ) class CallException(Exception): """ For halting method execution with mocking """ pass class TerremarkTests(unittest.TestCase, TestCaseMixin): def setUp(self): VCloudNodeDriver.connectionCls.host = "test" VCloudNodeDriver.connectionCls.conn_class = TerremarkMockHttp TerremarkMockHttp.type = None self.driver = TerremarkDriver(*VCLOUD_PARAMS) def test_list_images(self): ret = self.driver.list_images() self.assertEqual( ret[0].id, 'https://services.vcloudexpress.terremark.com/api/v0.8/vAppTemplate/5') def test_list_sizes(self): ret = self.driver.list_sizes() self.assertEqual(ret[0].ram, 512) def test_create_node(self): image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] node = self.driver.create_node( name='testerpart2', image=image, size=size, ex_vdc='https://services.vcloudexpress.terremark.com/api/v0.8/vdc/224', ex_network='https://services.vcloudexpress.terremark.com/api/v0.8/network/725', ex_cpus=2, ) self.assertTrue(isinstance(node, Node)) self.assertEqual( node.id, 'https://services.vcloudexpress.terremark.com/api/v0.8/vapp/14031') self.assertEqual(node.name, 'testerpart2') def test_list_nodes(self): ret = self.driver.list_nodes() node = ret[0] self.assertEqual( node.id, 'https://services.vcloudexpress.terremark.com/api/v0.8/vapp/14031') self.assertEqual(node.name, 'testerpart2') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, []) self.assertEqual(node.private_ips, ['10.112.78.69']) def test_reboot_node(self): node = self.driver.list_nodes()[0] ret = self.driver.reboot_node(node) self.assertTrue(ret) def test_destroy_node(self): node = self.driver.list_nodes()[0] ret = self.driver.destroy_node(node) self.assertTrue(ret) class VCloud_1_5_Tests(unittest.TestCase, TestCaseMixin): def setUp(self): VCloudNodeDriver.connectionCls.host = 'test' VCloudNodeDriver.connectionCls.conn_class = VCloud_1_5_MockHttp VCloud_1_5_MockHttp.type = None self.driver = VCloud_1_5_NodeDriver(*VCLOUD_PARAMS) def test_list_images(self): ret = self.driver.list_images() self.assertEqual( 'https://vm-vcloud/api/vAppTemplate/vappTemplate-ac1bc027-bf8c-4050-8643-4971f691c158', ret[0].id) def test_list_sizes(self): ret = self.driver.list_sizes() self.assertEqual(ret[0].ram, 512) def test_networks(self): ret = self.driver.networks self.assertEqual( ret[0].get('href'), 'https://vm-vcloud/api/network/dca8b667-6c8f-4c3e-be57-7a9425dba4f4') def test_create_node(self): image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] node = self.driver.create_node( name='testNode', image=image, size=size, ex_vdc='MyVdc', ex_network='vCloud - Default', cpus=2, ) self.assertTrue(isinstance(node, Node)) self.assertEqual( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', node.id) self.assertEqual('testNode', node.name) def test_create_node_clone(self): image = self.driver.list_nodes()[0] node = self.driver.create_node(name='testNode', image=image) self.assertTrue(isinstance(node, Node)) self.assertEqual( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', node.id) self.assertEqual('testNode', node.name) def test_list_nodes(self): ret = self.driver.list_nodes() node = ret[0] self.assertEqual( node.id, 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a') self.assertEqual(node.name, 'testNode') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['65.41.67.2']) self.assertEqual(node.private_ips, ['65.41.67.2']) self.assertEqual( node.extra, { 'description': None, 'lease_settings': Lease( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a/leaseSettingsSection/', deployment_lease=0, storage_lease=0 ), 'vdc': 'MyVdc', 'vms': [ { 'id': 'https://vm-vcloud/api/vApp/vm-dd75d1d3-5b7b-48f0-aff3-69622ab7e045', 'name': 'testVm', 'state': NodeState.RUNNING, 'public_ips': ['65.41.67.2'], 'private_ips': ['65.41.67.2'], 'os_type': 'rhel5_64Guest' } ] } ) node = ret[1] self.assertEqual( node.id, 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b') self.assertEqual(node.name, 'testNode2') self.assertEqual(node.state, NodeState.RUNNING) self.assertEqual(node.public_ips, ['192.168.0.103']) self.assertEqual(node.private_ips, ['192.168.0.100']) self.assertEqual( node.extra, { 'description': None, 'lease_settings': Lease( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b/leaseSettingsSection/', deployment_lease=0, storage_lease=0 ), 'vdc': 'MyVdc', 'vms': [ { 'id': 'https://vm-vcloud/api/vApp/vm-dd75d1d3-5b7b-48f0-aff3-69622ab7e046', 'name': 'testVm2', 'state': NodeState.RUNNING, 'public_ips': ['192.168.0.103'], 'private_ips': ['192.168.0.100'], 'os_type': 'rhel5_64Guest' } ] } ) def test_reboot_node(self): node = self.driver.list_nodes()[0] ret = self.driver.reboot_node(node) self.assertTrue(ret) def test_destroy_node(self): node = self.driver.list_nodes()[0] ret = self.driver.destroy_node(node) self.assertTrue(ret) def test_validate_vm_names(self): # valid inputs self.driver._validate_vm_names(['host-n-ame-name']) self.driver._validate_vm_names(['tc-mybuild-b1']) self.driver._validate_vm_names(None) # invalid inputs self.assertRaises( ValueError, self.driver._validate_vm_names, ['invalid.host']) self.assertRaises( ValueError, self.driver._validate_vm_names, ['inv-alid.host']) self.assertRaises( ValueError, self.driver._validate_vm_names, ['hostnametoooolong']) self.assertRaises( ValueError, self.driver._validate_vm_names, ['host$name']) def test_change_vm_names(self): self.driver._change_vm_names( '/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', ['changed1', 'changed2']) def test_change_vm_admin_password(self): self.driver.ex_change_vm_admin_password( '/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', "12345678") def test_is_node(self): self.assertTrue(self.driver._is_node( Node('testId', 'testNode', state=0, public_ips=[], private_ips=[], driver=self.driver))) self.assertFalse(self.driver._is_node( NodeImage('testId', 'testNode', driver=self.driver))) def test_ex_deploy(self): node = self.driver.ex_deploy_node( Node('/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a', 'testNode', state=0, public_ips=[], private_ips=[], driver=self.driver), ex_force_customization=False) self.assertEqual(node.state, NodeState.RUNNING) def test_ex_undeploy(self): node = self.driver.ex_undeploy_node( Node('https://test/api/vApp/undeployTest', 'testNode', state=0, public_ips=[], private_ips=[], driver=self.driver)) self.assertEqual(node.state, NodeState.STOPPED) def test_ex_undeploy_with_error(self): node = self.driver.ex_undeploy_node( Node('https://test/api/vApp/undeployErrorTest', 'testNode', state=0, public_ips=[], private_ips=[], driver=self.driver)) self.assertEqual(node.state, NodeState.STOPPED) def test_ex_undeploy_power_off(self): node = self.driver.ex_undeploy_node( Node('https://test/api/vApp/undeployPowerOffTest', 'testNode', state=0, public_ips=[], private_ips=[], driver=self.driver), shutdown=False) self.assertEqual(node.state, NodeState.STOPPED) def test_ex_find_node(self): node = self.driver.ex_find_node('testNode') self.assertEqual(node.name, "testNode") node = self.driver.ex_find_node('testNode', self.driver.vdcs[0]) self.assertEqual(node.name, "testNode") node = self.driver.ex_find_node('testNonExisting', self.driver.vdcs[0]) self.assertIsNone(node) def test_ex_add_vm_disk__with_invalid_values(self): self.assertRaises( ValueError, self.driver.ex_add_vm_disk, 'dummy', 'invalid value') self.assertRaises( ValueError, self.driver.ex_add_vm_disk, 'dummy', '-1') def test_ex_add_vm_disk(self): self.driver.ex_add_vm_disk('https://test/api/vApp/vm-test', '20') def test_ex_set_vm_cpu__with_invalid_values(self): self.assertRaises(ValueError, self.driver.ex_set_vm_cpu, 'dummy', 50) self.assertRaises(ValueError, self.driver.ex_set_vm_cpu, 'dummy', -1) def test_ex_set_vm_cpu(self): self.driver.ex_set_vm_cpu('https://test/api/vApp/vm-test', 4) def test_ex_set_vm_memory__with_invalid_values(self): self.assertRaises( ValueError, self.driver.ex_set_vm_memory, 'dummy', 777) self.assertRaises( ValueError, self.driver.ex_set_vm_memory, 'dummy', -1024) def test_ex_set_vm_memory(self): self.driver.ex_set_vm_memory('https://test/api/vApp/vm-test', 1024) def test_vdcs(self): vdcs = self.driver.vdcs self.assertEqual(len(vdcs), 1) self.assertEqual( vdcs[0].id, 'https://vm-vcloud/api/vdc/3d9ae28c-1de9-4307-8107-9356ff8ba6d0') self.assertEqual(vdcs[0].name, 'MyVdc') self.assertEqual(vdcs[0].allocation_model, 'AllocationPool') self.assertEqual(vdcs[0].storage.limit, 5120000) self.assertEqual(vdcs[0].storage.used, 1984512) self.assertEqual(vdcs[0].storage.units, 'MB') self.assertEqual(vdcs[0].cpu.limit, 160000) self.assertEqual(vdcs[0].cpu.used, 0) self.assertEqual(vdcs[0].cpu.units, 'MHz') self.assertEqual(vdcs[0].memory.limit, 527360) self.assertEqual(vdcs[0].memory.used, 130752) self.assertEqual(vdcs[0].memory.units, 'MB') def test_ex_list_nodes(self): self.assertEqual( len(self.driver.ex_list_nodes()), len(self.driver.list_nodes())) def test_ex_list_nodes__masked_exception(self): """ Test that we don't mask other exceptions. """ brokenVdc = Vdc('/api/vdc/brokenVdc', 'brokenVdc', self.driver) self.assertRaises(AnotherError, self.driver.ex_list_nodes, (brokenVdc)) def test_ex_power_off(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) self.driver.ex_power_off_node(node) def test_ex_query(self): results = self.driver.ex_query( 'user', filter='name==jrambo', page=2, page_size=30, sort_desc='startDate') self.assertEqual(len(results), 1) self.assertEqual(results[0]['type'], 'UserRecord') self.assertEqual(results[0]['name'], 'jrambo') self.assertEqual(results[0]['isLdapUser'], 'true') def test_ex_get_control_access(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) control_access = self.driver.ex_get_control_access(node) self.assertEqual( control_access.everyone_access_level, ControlAccess.AccessLevel.READ_ONLY) self.assertEqual(len(control_access.subjects), 1) self.assertEqual(control_access.subjects[0].type, 'group') self.assertEqual(control_access.subjects[0].name, 'MyGroup') self.assertEqual(control_access.subjects[ 0].id, 'https://vm-vcloud/api/admin/group/b8202c48-7151-4e61-9a6c-155474c7d413') self.assertEqual(control_access.subjects[ 0].access_level, ControlAccess.AccessLevel.FULL_CONTROL) def test_ex_set_control_access(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) control_access = ControlAccess(node, None, [Subject( name='MyGroup', type='group', access_level=ControlAccess.AccessLevel.FULL_CONTROL)]) self.driver.ex_set_control_access(node, control_access) def test_ex_get_metadata(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) metadata = self.driver.ex_get_metadata(node) self.assertEqual(metadata, {'owners': 'msamia@netsuite.com'}) def test_ex_set_metadata_entry(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) self.driver.ex_set_metadata_entry(node, 'foo', 'bar') def test_ex_find_vm_nodes(self): nodes = self.driver.ex_find_vm_nodes('testVm2') self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].id, 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b') def test_get_node(self): node = self.driver._ex_get_node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a') self.assertEqual(node.name, 'testNode') def test_get_node_forbidden(self): self.assertRaises( Exception, self.driver._ex_get_node, 'https://vm-vcloud/api/vApp/vapp-access-to-resource-forbidden' ) def test_to_node_description(self): node = self.driver._ex_get_node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a') self.assertIsNone(node.extra['description']) node = self.driver._ex_get_node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6d') self.assertEqual(node.extra['description'], 'Test Description') def test_to_node_lease_settings(self): node = self.driver._ex_get_node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a') lease = Lease( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a/leaseSettingsSection/', deployment_lease=0, storage_lease=0 ) self.assertEqual(node.extra['lease_settings'], lease) node = self.driver._ex_get_node('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6d') # 2019-10-07T14:06:29.980725 lease = Lease( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6d/leaseSettingsSection/', deployment_lease=86400, storage_lease=172800, deployment_lease_expiration=datetime.datetime( year=2019, month=10, day=7, hour=14, minute=6, second=29, microsecond=980725, tzinfo=UTC ), storage_lease_expiration=datetime.datetime( year=2019, month=10, day=8, hour=14, minute=6, second=29, microsecond=980725, tzinfo=UTC ) ) self.assertEqual(node.extra['lease_settings'], lease) def test_remove_admin_password(self): pass_enabled_xml = '{text}' pass_enabled_true = pass_enabled_xml.format(text='true') pass_enabled_false = pass_enabled_xml.format(text='false') pass_auto_xml = '{text}' pass_auto_true = pass_auto_xml.format(text='true') pass_auto_false = pass_auto_xml.format(text='false') passwd = 'testpassword' assertion_error = False for admin_pass_enabled, admin_pass_auto, admin_pass, pass_exists in ( (pass_enabled_true, pass_auto_true, passwd, False), (pass_enabled_true, pass_auto_true, '', False), (pass_enabled_true, pass_auto_false, passwd, True), (pass_enabled_true, pass_auto_false, '', False), (pass_enabled_true, '', passwd, False), (pass_enabled_true, '', '', False), (pass_enabled_false, pass_auto_true, passwd, False), (pass_enabled_false, pass_auto_true, '', False), (pass_enabled_false, pass_auto_false, passwd, False), (pass_enabled_false, pass_auto_false, '', False), (pass_enabled_false, '', passwd, False), (pass_enabled_false, '', '', False), ('', pass_auto_true, passwd, False), ('', pass_auto_true, '', False), ('', pass_auto_false, passwd, False), ('', pass_auto_false, '', False), ('', '', passwd, False), ('', '', '', False) ): try: guest_customization_section = ET.fromstring( '' + admin_pass_enabled + admin_pass_auto + admin_pass + '' ) self.driver._remove_admin_password(guest_customization_section) admin_pass_element = guest_customization_section.find( fixxpath(guest_customization_section, 'AdminPassword') ) if pass_exists: self.assertIsNotNone(admin_pass_element) else: self.assertIsNone(admin_pass_element) except AssertionError: assertion_error = True print_parameterized_failure([ ('admin_pass_enabled', admin_pass_enabled), ('admin_pass_auto', admin_pass_auto), ('admin_pass', admin_pass), ('pass_exists', pass_exists) ]) if assertion_error: self.fail(msg='Assertion error(s) encountered. Details above.') @patch('libcloud.compute.drivers.vcloud.VCloud_1_5_NodeDriver._get_vm_elements', side_effect=CallException('Called')) def test_change_vm_script_text_and_file_logic(self, _): assertion_error = False for vm_script_file, vm_script_text, open_succeeds, open_call_count, returned_early in ( (None, None, True, 0, True), (None, None, False, 0, True), (None, 'script text', True, 0, False), (None, 'script text', False, 0, False), ('file.sh', None, True, 1, False), ('file.sh', None, False, 1, True), ('file.sh', 'script text', True, 0, False), ('file.sh', 'script text', False, 0, False) ): try: if open_succeeds: open_mock = patch(BUILTINS + '.open', mock_open(read_data='script text')) else: open_mock = patch(BUILTINS + '.open', side_effect=Exception()) with open_mock as mocked_open: try: self.driver._change_vm_script( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6d', vm_script=vm_script_file, vm_script_text=vm_script_text) returned_early_res = True except CallException: returned_early_res = False self.assertEqual(mocked_open.call_count, open_call_count) self.assertEqual(returned_early_res, returned_early) except AssertionError: assertion_error = True print_parameterized_failure([ ('vm_script_file', vm_script_file), ('vm_script_text', vm_script_text), ('open_succeeds', open_succeeds), ('open_call_count', open_call_count), ('returned_early', returned_early) ]) if assertion_error: self.fail(msg='Assertion error(s) encountered. Details above.') def test_build_xmltree_description(self): instantiate_xml = Instantiate_1_5_VAppXML( name='testNode', template='https://vm-vcloud/api/vAppTemplate/vappTemplate-ac1bc027-bf8c-4050-8643-4971f691c158', network=None, vm_network=None, vm_fence=None, description=None ) self.assertIsNone(instantiate_xml.description) self.assertIsNone(instantiate_xml.root.find('Description')) test_description = 'Test Description' instantiate_xml = Instantiate_1_5_VAppXML( name='testNode', template='https://vm-vcloud/api/vAppTemplate/vappTemplate-ac1bc027-bf8c-4050-8643-4971f691c158', network=None, vm_network=None, vm_fence=None, description=test_description ) self.assertEqual(instantiate_xml.description, test_description) description_elem = instantiate_xml.root.find('Description') self.assertIsNotNone(description_elem) self.assertEqual(description_elem.text, test_description) def test_to_lease(self): res = self.driver.connection.request( get_url_path('https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6d'), headers={'Content-Type': 'application/vnd.vmware.vcloud.vApp+xml'} ) lease_settings_section = res.object.find(fixxpath(res.object, 'LeaseSettingsSection')) lease = Lease.to_lease(lease_element=lease_settings_section) self.assertEqual(lease.deployment_lease, 86400) self.assertEqual( lease.deployment_lease_expiration, datetime.datetime( year=2019, month=10, day=7, hour=14, minute=6, second=29, microsecond=980725, tzinfo=UTC ) ) self.assertEqual(lease.storage_lease, 172800) self.assertEqual( lease.storage_lease_expiration, datetime.datetime( year=2019, month=10, day=8, hour=14, minute=6, second=29, microsecond=980725, tzinfo=UTC ) ) def test_lease_get_time_deployed(self): deployment_datetime = datetime.datetime( year=2019, month=10, day=6, hour=14, minute=6, second=29, microsecond=980725, tzinfo=UTC ) deployment_lease_exp_actual = datetime.datetime( year=2019, month=10, day=7, hour=14, minute=6, second=29, microsecond=980725, tzinfo=UTC ) storage_lease_exp_actual = datetime.datetime( year=2019, month=10, day=8, hour=14, minute=6, second=29, microsecond=980725, tzinfo=UTC ) assertion_error = False for deployment_lease, storage_lease, deployment_lease_exp, storage_lease_exp, exception, res in ( (None, None, None, None, True, None), (None, None, None, storage_lease_exp_actual, True, None), (None, None, deployment_lease_exp_actual, None, True, None), (None, None, deployment_lease_exp_actual, storage_lease_exp_actual, True, None), (None, 172800, None, None, True, None), (None, 172800, None, storage_lease_exp_actual, False, deployment_datetime), (None, 172800, deployment_lease_exp_actual, None, True, deployment_datetime), (None, 172800, deployment_lease_exp_actual, storage_lease_exp_actual, False, deployment_datetime), (86400, None, None, None, True, None), (86400, None, None, storage_lease_exp_actual, True, None), (86400, None, deployment_lease_exp_actual, None, False, deployment_datetime), (86400, None, deployment_lease_exp_actual, storage_lease_exp_actual, False, deployment_datetime), (86400, 172800, None, None, True, None), (86400, 172800, None, storage_lease_exp_actual, False, deployment_datetime), (86400, 172800, deployment_lease_exp_actual, None, False, deployment_datetime), (86400, 172800, deployment_lease_exp_actual, storage_lease_exp_actual, False, deployment_datetime) ): try: lease = Lease( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6a/leaseSettingsSection/', deployment_lease=deployment_lease, storage_lease=storage_lease, deployment_lease_expiration=deployment_lease_exp, storage_lease_expiration=storage_lease_exp ) if exception: with assertRaisesRegex( self, Exception, re.escape('Cannot get time deployed. Missing complete lease and expiration information.'), ): lease.get_deployment_time() else: self.assertEqual(lease.get_deployment_time(), res) except AssertionError: assertion_error = True print_parameterized_failure([ ('deployment_lease', deployment_lease), ('storage_lease', storage_lease), ('deployment_lease_exp', deployment_lease_exp), ('storage_lease_exp', storage_lease_exp), ('exception', exception), ('res', res) ]) if assertion_error: self.fail(msg='Assertion error(s) encountered. Details above.') class VCloud_5_1_Tests(unittest.TestCase, TestCaseMixin): def setUp(self): VCloudNodeDriver.connectionCls.host = 'test' VCloudNodeDriver.connectionCls.conn_class = VCloud_1_5_MockHttp VCloud_1_5_MockHttp.type = None self.driver = VCloudNodeDriver( *VCLOUD_PARAMS, **{'api_version': '5.1'}) self.assertTrue(isinstance(self.driver, VCloud_5_1_NodeDriver)) def _test_create_node_valid_ex_vm_memory(self): # TODO: Hook up the fixture values = [4, 1024, 4096] image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] for value in values: self.driver.create_node( name='testerpart2', image=image, size=size, vdc='https://services.vcloudexpress.terremark.com/api/v0.8/vdc/224', network='https://services.vcloudexpress.terremark.com/api/v0.8/network/725', cpus=2, ex_vm_memory=value ) def test_create_node_invalid_ex_vm_memory(self): values = [1, 3, 7] image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] for value in values: try: self.driver.create_node( name='testerpart2', image=image, size=size, vdc='https://services.vcloudexpress.terremark.com/api/v0.8/vdc/224', network='https://services.vcloudexpress.terremark.com/api/v0.8/network/725', cpus=2, ex_vm_memory=value ) except ValueError: pass else: self.fail('Exception was not thrown') def test_list_images(self): ret = self.driver.list_images() self.assertEqual( 'https://vm-vcloud/api/vAppTemplate/vappTemplate-ac1bc027-bf8c-4050-8643-4971f691c158', ret[0].id) class VCloud_5_5_Tests(unittest.TestCase, TestCaseMixin): def setUp(self): VCloudNodeDriver.connectionCls.host = 'test' VCloudNodeDriver.connectionCls.conn_class = VCloud_5_5_MockHttp VCloud_5_5_MockHttp.type = None self.driver = VCloudNodeDriver( *VCLOUD_PARAMS, **{'api_version': '5.5'}) self.assertTrue(isinstance(self.driver, VCloud_5_5_NodeDriver)) def test_ex_create_snapshot(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) self.driver.ex_create_snapshot(node) def test_ex_remove_snapshots(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) self.driver.ex_remove_snapshots(node) def test_ex_revert_to_snapshot(self): node = Node( 'https://vm-vcloud/api/vApp/vapp-8c57a5b6-e61b-48ca-8a78-3b70ee65ef6b', 'testNode', NodeState.RUNNING, [], [], self.driver) self.driver.ex_revert_to_snapshot(node) def test_ex_acquire_mks_ticket(self): node = self.driver.ex_find_node('testNode') self.driver.ex_acquire_mks_ticket(node.id) def test_get_auth_headers(self): headers = self.driver.connection._get_auth_headers() self.assertEqual(headers['Accept'], 'application/*+xml;version=5.5') class TerremarkMockHttp(MockHttp): fixtures = ComputeFileFixtures('terremark') def _api_v0_8_login(self, method, url, body, headers): headers['set-cookie'] = 'vcloud-token=testtoken' body = self.fixtures.load('api_v0_8_login.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_v0_8_org_240(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_org_240.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_v0_8_vdc_224(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_vdc_224.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_v0_8_vdc_224_catalog(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_vdc_224_catalog.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_v0_8_catalogItem_5(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_catalogItem_5.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_v0_8_vdc_224_action_instantiateVAppTemplate(self, method, url, body, headers): body = self.fixtures.load( 'api_v0_8_vdc_224_action_instantiateVAppTemplate.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _api_v0_8_vapp_14031_action_deploy(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_vapp_14031_action_deploy.xml') return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _api_v0_8_task_10496(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_task_10496.xml') return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _api_v0_8_vapp_14031_power_action_powerOn(self, method, url, body, headers): body = self.fixtures.load( 'api_v0_8_vapp_14031_power_action_powerOn.xml') return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _api_v0_8_vapp_14031(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('api_v0_8_vapp_14031_get.xml') elif method == 'DELETE': body = '' return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _api_v0_8_vapp_14031_power_action_reset(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_vapp_14031_power_action_reset.xml') return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _api_v0_8_vapp_14031_power_action_poweroff(self, method, url, body, headers): body = self.fixtures.load( 'api_v0_8_vapp_14031_power_action_poweroff.xml') return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _api_v0_8_task_11001(self, method, url, body, headers): body = self.fixtures.load('api_v0_8_task_11001.xml') return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) class AnotherErrorMember(Exception): """ helper class for the synthetic exception """ def __init__(self): self.tag = 'Error' def get(self, foo): return 'ACCESS_TO_RESOURCE_IS_FORBIDDEN_1' class AnotherError(Exception): pass class VCloud_1_5_MockHttp(MockHttp, unittest.TestCase): fixtures = ComputeFileFixtures('vcloud_1_5') def request(self, method, url, body=None, headers=None, raw=False, stream=False): self.assertTrue(url.startswith('/api/'), ('"%s" is invalid. Needs to ' 'start with "/api". The passed URL should be just ' 'the path, not full URL.', url)) super(VCloud_1_5_MockHttp, self).request(method, url, body, headers, raw) def _api_sessions(self, method, url, body, headers): headers['x-vcloud-authorization'] = 'testtoken' body = self.fixtures.load('api_sessions.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_org(self, method, url, body, headers): body = self.fixtures.load('api_org.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a(self, method, url, body, headers): body = self.fixtures.load( 'api_org_96726c78_4ae3_402f_b08b_7a78c6903d2a.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4(self, method, url, body, headers): body = self.fixtures.load( 'api_network_dca8b667_6c8f_4c3e_be57_7a9425dba4f4.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0(self, method, url, body, headers): body = self.fixtures.load( 'api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vdc_brokenVdc(self, method, url, body, headers): body = self.fixtures.load('api_vdc_brokenVdc.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_errorRaiser(self, method, url, body, headers): m = AnotherErrorMember() raise AnotherError(m) def _api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate(self, method, url, body, headers): body = self.fixtures.load( 'api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_instantiateVAppTemplate.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_powerOn(self, method, url, body, headers): return self._api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(method, url, body, headers) # Clone def _api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp(self, method, url, body, headers): body = self.fixtures.load( 'api_vdc_3d9ae28c_1de9_4307_8107_9356ff8ba6d0_action_cloneVApp.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_networkConnectionSection(self, method, url, body, headers): body = self.fixtures.load( 'api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a(self, method, url, body, headers): status = httplib.OK if method == 'GET': body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a.xml') status = httplib.OK elif method == 'DELETE': body = self.fixtures.load( 'api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml') status = httplib.ACCEPTED return status, body, headers, httplib.responses[status] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b(self, method, url, body, headers): body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c(self, method, url, body, headers): body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6c.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045(self, method, url, body, headers): body = self.fixtures.load( 'put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'get_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml') status = httplib.OK else: body = self.fixtures.load( 'put_api_vApp_vm_dd75d1d3_5b7b_48f0_aff3_69622ab7e045_guestCustomizationSection.xml') status = httplib.ACCEPTED return status, body, headers, httplib.responses[status] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_reset(self, method, url, body, headers): return self._api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(method, url, body, headers) def _api_task_b034df55_fe81_4798_bc81_1f0fd0ead450(self, method, url, body, headers): body = self.fixtures.load( 'api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4(self, method, url, body, headers): body = self.fixtures.load( 'api_catalog_cddb3cb2_3394_4b14_b831_11fbc4028da4.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_catalogItem_3132e037_759b_4627_9056_ca66466fa607(self, method, url, body, headers): body = self.fixtures.load( 'api_catalogItem_3132e037_759b_4627_9056_ca66466fa607.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_deployTest(self, method, url, body, headers): body = self.fixtures.load('api_task_deploy.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_action_deploy(self, method, url, body, headers): body = self.fixtures.load('api_task_deploy.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_task_deploy(self, method, url, body, headers): body = self.fixtures.load('api_task_deploy.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_vApp_undeployTest(self, method, url, body, headers): body = self.fixtures.load('api_vApp_undeployTest.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_undeployTest_action_undeploy(self, method, url, body, headers): body = self.fixtures.load('api_task_undeploy.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_task_undeploy(self, method, url, body, headers): body = self.fixtures.load('api_task_undeploy.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_undeployErrorTest(self, method, url, body, headers): body = self.fixtures.load('api_vApp_undeployTest.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_undeployErrorTest_action_undeploy(self, method, url, body, headers): if b('shutdown') in b(body): body = self.fixtures.load('api_task_undeploy_error.xml') else: body = self.fixtures.load('api_task_undeploy.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_task_undeployError(self, method, url, body, headers): body = self.fixtures.load('api_task_undeploy_error.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_undeployPowerOffTest(self, method, url, body, headers): return self._api_vApp_undeployTest(method, url, body, headers) def _api_vApp_undeployPowerOffTest_action_undeploy(self, method, url, body, headers): self.assertIn(b('powerOff'), b(body)) return self._api_vApp_undeployTest_action_undeploy(method, url, body, headers) def _api_vApp_vapp_access_to_resource_forbidden(self, method, url, body, headers): raise Exception( ET.fromstring(self.fixtures.load('api_vApp_vapp_access_to_resource_forbidden.xml'))) def _api_vApp_vm_test(self, method, url, body, headers): body = self.fixtures.load('api_vApp_vm_test.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vm_test_virtualHardwareSection_disks(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'get_api_vApp_vm_test_virtualHardwareSection_disks.xml') status = httplib.OK else: body = self.fixtures.load( 'put_api_vApp_vm_test_virtualHardwareSection_disks.xml') status = httplib.ACCEPTED return status, body, headers, httplib.responses[status] def _api_vApp_vm_test_virtualHardwareSection_cpu(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'get_api_vApp_vm_test_virtualHardwareSection_cpu.xml') status = httplib.OK else: body = self.fixtures.load( 'put_api_vApp_vm_test_virtualHardwareSection_cpu.xml') status = httplib.ACCEPTED return status, body, headers, httplib.responses[status] def _api_vApp_vm_test_virtualHardwareSection_memory(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'get_api_vApp_vm_test_virtualHardwareSection_memory.xml') status = httplib.OK else: body = self.fixtures.load( 'put_api_vApp_vm_test_virtualHardwareSection_memory.xml') status = httplib.ACCEPTED return status, body, headers, httplib.responses[status] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_powerOff(self, method, url, body, headers): return self._api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(method, url, body, headers) def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_power_action_all(self, method, url, body, headers): assert method == 'POST' body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_power_action_all.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] def _api_query(self, method, url, body, headers): assert method == 'GET' if 'type=user' in url: self.assertTrue('page=2' in url) self.assertTrue('filter=(name==jrambo)' in url) self.assertTrue('sortDesc=startDate') body = self.fixtures.load('api_query_user.xml') elif 'type=group' in url: body = self.fixtures.load('api_query_group.xml') elif 'type=vm' in url and 'filter=(name==testVm2)' in url: body = self.fixtures.load('api_query_vm.xml') else: raise AssertionError('Unexpected query type') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_metadata(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('api_vapp_post_metadata.xml') return httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED] else: body = self.fixtures.load('api_vapp_get_metadata.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_controlAccess(self, method, url, body, headers): body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_action_controlAccess(self, method, url, body, headers): body = str(body) self.assertTrue(method == 'POST') self.assertTrue( 'false' in body) self.assertTrue( '' in body) self.assertTrue('FullControl' in body) body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6a_controlAccess.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413(self, method, url, body, headers): body = self.fixtures.load( 'api_admin_group_b8202c48_7151_4e61_9a6c_155474c7d413.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6d(self, method, url, body, headers): body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6d.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] class VCloud_5_5_MockHttp(VCloud_1_5_MockHttp): # TODO: Move 5.5 fixtures to their own folder def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_action_createSnapshot(self, method, url, body, headers): assert method == 'POST' body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_create_snapshot.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_task_fab4b26f_4f2e_4d49_ad01_ae9324bbfe48(self, method, url, body, headers): body = self.fixtures.load( 'api_task_b034df55_fe81_4798_bc81_1f0fd0ead450.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_action_removeAllSnapshots(self, method, url, body, headers): assert method == 'POST' body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_remove_snapshots.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_task_2518935e_b315_4d8e_9e99_9275f751877c(self, method, url, body, headers): body = self.fixtures.load( 'api_task_2518935e_b315_4d8e_9e99_9275f751877c.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_action_revertToCurrentSnapshot(self, method, url, body, headers): assert method == 'POST' body = self.fixtures.load( 'api_vApp_vapp_8c57a5b6_e61b_48ca_8a78_3b70ee65ef6b_revert_snapshot.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] def _api_task_fe75d3af_f5a3_44a5_b016_ae0bdadfc32b(self, method, url, body, headers): body = self.fixtures.load( 'api_task_fe75d3af_f5a3_44a5_b016_ae0bdadfc32b.xml') return httplib.OK, body, headers, httplib.responses[httplib.OK] if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_voxel.py0000664000175000017500000001376113577507766023460 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.base import Node, NodeSize, NodeImage, NodeLocation from libcloud.compute.drivers.voxel import VoxelNodeDriver as Voxel from libcloud.compute.types import InvalidCredsError from libcloud.test import MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import VOXEL_PARAMS class VoxelTest(unittest.TestCase): def setUp(self): Voxel.connectionCls.conn_class = VoxelMockHttp VoxelMockHttp.type = None self.driver = Voxel(*VOXEL_PARAMS) def test_auth_failed(self): VoxelMockHttp.type = 'UNAUTHORIZED' try: self.driver.list_nodes() except Exception as e: self.assertTrue(isinstance(e, InvalidCredsError)) else: self.fail('test should have thrown') def test_response_failure(self): VoxelMockHttp.type = 'FAILURE' try: self.driver.list_nodes() except Exception: pass else: self.fail('Invalid response, but exception was not thrown') def test_list_nodes(self): VoxelMockHttp.type = 'LIST_NODES' nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 1) self.assertEqual(nodes[0].name, 'www.voxel.net') def test_list_sizes(self): sizes = self.driver.list_sizes() self.assertEqual(len(sizes), 13) def test_list_images(self): VoxelMockHttp.type = 'LIST_IMAGES' images = self.driver.list_images() self.assertEqual(len(images), 1) def test_list_locations(self): VoxelMockHttp.type = 'LIST_LOCATIONS' locations = self.driver.list_locations() self.assertEqual(len(locations), 2) self.assertEqual(locations[0].name, 'Amsterdam') def test_create_node_invalid_disk_size(self): image = NodeImage( id=1, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', None, None, None, None, driver=self.driver) location = NodeLocation(id=1, name='Europe', country='England', driver=self.driver) try: self.driver.create_node(name='foo', image=image, size=size, location=location) except ValueError: pass else: self.fail('Invalid disk size provided but an exception was not' ' thrown') def test_create_node(self): VoxelMockHttp.type = 'CREATE_NODE' image = NodeImage( id=1, name='Ubuntu 8.10 (intrepid)', driver=self.driver) size = NodeSize( 1, '256 slice', 1024, 500, None, None, driver=self.driver) location = NodeLocation(id=1, name='Europe', country='England', driver=self.driver) node = self.driver.create_node(name='foo', image=image, size=size, location=location) self.assertEqual(node.id, '1234') node = self.driver.create_node(name='foo', image=image, size=size, location=location, ex_voxel_access=True) self.assertEqual(node.id, '1234') def test_reboot_node(self): VoxelMockHttp.type = 'REBOOT_NODE' node = Node( id=72258, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) self.assertTrue(node.reboot()) def test_destroy_node(self): VoxelMockHttp.type = 'DESTROY_NODE' node = Node( id=72258, name=None, state=None, public_ips=None, private_ips=None, driver=self.driver) self.assertTrue(node.destroy()) class VoxelMockHttp(MockHttp): fixtures = ComputeFileFixtures('voxel') def _UNAUTHORIZED(self, method, url, body, headers): body = self.fixtures.load('unauthorized.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _FAILURE(self, method, url, body, headers): body = self.fixtures.load('failure.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _LIST_NODES(self, method, url, body, headers): body = self.fixtures.load('nodes.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _LIST_IMAGES(self, method, url, body, headers): body = self.fixtures.load('images.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _LIST_LOCATIONS(self, method, url, body, headers): body = self.fixtures.load('locations.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CREATE_NODE(self, method, url, body, headers): body = self.fixtures.load('create_node.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _REBOOT_NODE(self, method, url, body, headers): body = self.fixtures.load('success.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DESTROY_NODE(self, method, url, body, headers): body = self.fixtures.load('success.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_vpsnet.py0000664000175000017500000002071013535474530023614 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.compute.drivers.vpsnet import VPSNetNodeDriver from libcloud.compute.base import Node from libcloud.compute.types import NodeState from libcloud.test import MockHttp from libcloud.test.compute import TestCaseMixin from libcloud.test.secrets import VPSNET_PARAMS from libcloud.test.file_fixtures import ComputeFileFixtures class VPSNetTests(unittest.TestCase, TestCaseMixin): def setUp(self): VPSNetNodeDriver.connectionCls.conn_class = VPSNetMockHttp self.driver = VPSNetNodeDriver(*VPSNET_PARAMS) def test_create_node(self): VPSNetMockHttp.type = 'create' image = self.driver.list_images()[0] size = self.driver.list_sizes()[0] node = self.driver.create_node('foo', image, size) self.assertEqual(node.name, 'foo') def test_list_nodes(self): VPSNetMockHttp.type = 'virtual_machines' node = self.driver.list_nodes()[0] self.assertEqual(node.id, '1384') self.assertEqual(node.state, NodeState.RUNNING) def test_reboot_node(self): VPSNetMockHttp.type = 'virtual_machines' node = self.driver.list_nodes()[0] VPSNetMockHttp.type = 'reboot' ret = self.driver.reboot_node(node) self.assertEqual(ret, True) def test_destroy_node(self): VPSNetMockHttp.type = 'delete' node = Node('2222', None, None, None, None, self.driver) ret = self.driver.destroy_node(node) self.assertTrue(ret) VPSNetMockHttp.type = 'delete_fail' node = Node('2223', None, None, None, None, self.driver) self.assertRaises(Exception, self.driver.destroy_node, node) def test_list_images(self): VPSNetMockHttp.type = 'templates' ret = self.driver.list_images() self.assertEqual(ret[0].id, '9') self.assertEqual(ret[-1].id, '160') def test_list_sizes(self): VPSNetMockHttp.type = 'sizes' ret = self.driver.list_sizes() self.assertEqual(len(ret), 1) self.assertEqual(ret[0].id, '1') self.assertEqual(ret[0].name, '1 Node') def test_destroy_node_response(self): # should return a node object node = Node('2222', None, None, None, None, self.driver) VPSNetMockHttp.type = 'delete' ret = self.driver.destroy_node(node) self.assertTrue(isinstance(ret, bool)) def test_reboot_node_response(self): # should return a node object VPSNetMockHttp.type = 'virtual_machines' node = self.driver.list_nodes()[0] VPSNetMockHttp.type = 'reboot' ret = self.driver.reboot_node(node) self.assertTrue(isinstance(ret, bool)) class VPSNetMockHttp(MockHttp): fixtures = ComputeFileFixtures('vpsnet') def _nodes_api10json_sizes(self, method, url, body, headers): body = """[{"slice":{"virtual_machine_id":8592,"id":12256,"consumer_id":0}}, {"slice":{"virtual_machine_id":null,"id":12258,"consumer_id":0}}, {"slice":{"virtual_machine_id":null,"id":12434,"consumer_id":0}}]""" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _nodes_api10json_create(self, method, url, body, headers): body = """[{"slice":{"virtual_machine_id":8592,"id":12256,"consumer_id":0}}, {"slice":{"virtual_machine_id":null,"id":12258,"consumer_id":0}}, {"slice":{"virtual_machine_id":null,"id":12434,"consumer_id":0}}]""" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _virtual_machines_2222_api10json_delete_fail(self, method, url, body, headers): return (httplib.FORBIDDEN, '', {}, httplib.responses[httplib.FORBIDDEN]) def _virtual_machines_2222_api10json_delete(self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _virtual_machines_1384_reboot_api10json_reboot(self, method, url, body, headers): body = """{ "virtual_machine": { "running": true, "updated_at": "2009-05-15T06:55:02-04:00", "power_action_pending": false, "system_template_id": 41, "id": 1384, "cloud_id": 3, "domain_name": "demodomain.com", "hostname": "web01", "consumer_id": 0, "backups_enabled": false, "password": "a8hjsjnbs91", "label": "foo", "slices_count": null, "created_at": "2009-04-16T08:17:39-04:00" } }""" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _virtual_machines_api10json_create(self, method, url, body, headers): body = """{ "virtual_machine": { "running": true, "updated_at": "2009-05-15T06:55:02-04:00", "power_action_pending": false, "system_template_id": 41, "id": 1384, "cloud_id": 3, "domain_name": "demodomain.com", "hostname": "web01", "consumer_id": 0, "backups_enabled": false, "password": "a8hjsjnbs91", "label": "foo", "slices_count": null, "created_at": "2009-04-16T08:17:39-04:00" } }""" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _virtual_machines_api10json_virtual_machines(self, method, url, body, headers): body = """ [{ "virtual_machine": { "running": true, "updated_at": "2009-05-15T06:55:02-04:00", "power_action_pending": false, "system_template_id": 41, "id": 1384, "cloud_id": 3, "domain_name": "demodomain.com", "hostname": "web01", "consumer_id": 0, "backups_enabled": false, "password": "a8hjsjnbs91", "label": "Web Server 01", "slices_count": null, "created_at": "2009-04-16T08:17:39-04:00" } }, { "virtual_machine": { "running": true, "updated_at": "2009-05-15T06:55:02-04:00", "power_action_pending": false, "system_template_id": 41, "id": 1385, "cloud_id": 3, "domain_name": "demodomain.com", "hostname": "mysql01", "consumer_id": 0, "backups_enabled": false, "password": "dsi8h38hd2s", "label": "MySQL Server 01", "slices_count": null, "created_at": "2009-04-16T08:17:39-04:00" } }]""" return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _available_clouds_api10json_templates(self, method, url, body, headers): body = self.fixtures.load('_available_clouds_api10json_templates.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _available_clouds_api10json_create(self, method, url, body, headers): body = """ [{"cloud":{"system_templates":[{"id":9,"label":"Ubuntu 8.04 x64"}],"id":2,"label":"USA VPS Cloud"}}] """ return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/compute/test_vultr.py0000664000175000017500000001466413535474530023464 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest try: import simplejson as json except ImportError: import json # NOQA from libcloud.utils.py3 import httplib from libcloud.common.types import ServiceUnavailableError from libcloud.compute.drivers.vultr import VultrNodeDriver from libcloud.test import LibcloudTestCase, MockHttp from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.test.secrets import VULTR_PARAMS # class VultrTests(unittest.TestCase, TestCaseMixin): class VultrTests(LibcloudTestCase): def setUp(self): VultrNodeDriver.connectionCls.conn_class = VultrMockHttp VultrMockHttp.type = None self.driver = VultrNodeDriver(*VULTR_PARAMS) def test_list_images_dont_require_api_key(self): self.driver.list_images() self.assertFalse(self.driver.connection.require_api_key()) def test_list_images_success(self): images = self.driver.list_images() self.assertTrue(len(images) >= 1) image = images[0] self.assertTrue(image.id is not None) self.assertTrue(image.name is not None) def test_list_sizes_success(self): sizes = self.driver.list_sizes() self.assertTrue(len(sizes) == 17) size = sizes[0] self.assertTrue(size.id is not None) self.assertEqual(size.name, '8192 MB RAM,110 GB SSD,10.00 TB BW') self.assertEqual(size.ram, 8192) size = sizes[16] self.assertTrue(size.id is not None) self.assertEqual(size.name, '4096 MB RAM,1000 GB SATA,5.00 TB BW') self.assertEqual(size.ram, 4096) def test_list_locations_success(self): locations = self.driver.list_locations() self.assertTrue(len(locations) >= 1) location = locations[0] self.assertEqual(location.id, '1') self.assertEqual(location.name, 'New Jersey') def test_list_nodes_require_api_key(self): self.driver.list_nodes() self.assertTrue(self.driver.connection.require_api_key()) def test_list_nodes_success(self): nodes = self.driver.list_nodes() self.assertEqual(len(nodes), 2) self.assertEqual(nodes[0].id, '1') self.assertEqual(nodes[0].public_ips, ['108.61.206.153']) def test_reboot_node_success(self): node = self.driver.list_nodes()[0] result = self.driver.reboot_node(node) self.assertTrue(result) def test_create_node_success(self): test_size = self.driver.list_sizes()[0] test_image = self.driver.list_images()[0] test_location = self.driver.list_locations()[0] created_node = self.driver.create_node('test-node', test_size, test_image, test_location) self.assertEqual(created_node.id, "1") def test_destroy_node_success(self): node = self.driver.list_nodes()[0] result = self.driver.destroy_node(node) self.assertTrue(result) def test_list_key_pairs_success(self): key_pairs = self.driver.list_key_pairs() self.assertEqual(len(key_pairs), 1) key_pair = key_pairs[0] self.assertEqual(key_pair.id, '5806a8ef2a0c6') self.assertEqual(key_pair.name, 'test-key-pair') def test_create_key_pair_success(self): res = self.driver.create_key_pair('test-key-pair') self.assertTrue(res) def test_delete_key_pair_success(self): key_pairs = self.driver.list_key_pairs() key_pair = key_pairs[0] res = self.driver.delete_key_pair(key_pair) self.assertTrue(res) def test_rate_limit(self): VultrMockHttp.type = 'SERVICE_UNAVAILABLE' self.assertRaises(ServiceUnavailableError, self.driver.list_nodes) class VultrMockHttp(MockHttp): fixtures = ComputeFileFixtures('vultr') def _v1_regions_list(self, method, url, body, headers): body = self.fixtures.load('list_locations.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_os_list(self, method, url, body, headers): body = self.fixtures.load('list_images.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_plans_list(self, method, url, body, headers): body = self.fixtures.load('list_sizes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_server_list(self, method, url, body, headers): body = self.fixtures.load('list_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_server_list_SERVICE_UNAVAILABLE(self, method, url, body, headers): body = self.fixtures.load('error_rate_limit.txt') return (httplib.SERVICE_UNAVAILABLE, body, {}, httplib.responses[httplib.SERVICE_UNAVAILABLE]) def _v1_server_create(self, method, url, body, headers): body = self.fixtures.load('create_node.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_server_destroy(self, method, url, body, headers): return (httplib.OK, "", {}, httplib.responses[httplib.OK]) def _v1_server_reboot(self, method, url, body, headers): return (httplib.OK, "", {}, httplib.responses[httplib.OK]) def _v1_sshkey_list(self, method, url, body, headers): body = self.fixtures.load('list_key_pairs.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_sshkey_create(self, method, url, body, headers): body = self.fixtures.load('create_key_pair.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_sshkey_destroy(self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/conftest.py0000664000175000017500000000316113570310635021402 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os.path import pytest def pytest_configure(config): """Check that secrets.py is valid""" this_dir = os.path.abspath(os.path.split(__file__)[0]) secrets_current = os.path.join(this_dir, 'secrets.py') secrets_dist = os.path.join(this_dir, 'secrets.py-dist') if not os.path.isfile(secrets_current): print("Missing " + secrets_current) print("Maybe you forgot to copy it from -dist:") print("cp libcloud/test/secrets.py-dist libcloud/test/secrets.py") pytest.exit('') mtime_current = os.path.getmtime(secrets_current) mtime_dist = os.path.getmtime(secrets_dist) if mtime_dist > mtime_current: print("It looks like test/secrets.py file is out of date.") print("Please copy the new secrets.py-dist file over otherwise" + " tests might fail") pytest.exit('') apache-libcloud-2.8.0/libcloud/test/container/0000775000175000017500000000000013600223624021157 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/__init__.py0000664000175000017500000000221113535474530023277 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.container.base import ContainerImage class TestCaseMixin(object): def test_list_images_response(self): images = self.driver.list_images() self.assertTrue(isinstance(images, list)) for image in images: self.assertTrue(isinstance(image, ContainerImage)) if __name__ == "__main__": import doctest doctest.testmod() apache-libcloud-2.8.0/libcloud/test/container/fixtures/0000775000175000017500000000000013600223624023030 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/0000775000175000017500000000000013600223624024277 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/0000775000175000017500000000000013600223624026024 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/container_a68.json0000664000175000017500000001017213535474530031373 0ustar kamikami00000000000000{ "Id": "a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303", "Created": "2015-12-23T01:05:40.56937184Z", "Path": "/entrypoint.sh", "Args": [ "None" ], "State": { "Status": "running", "Running": false, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 0, "ExitCode": 127, "Error": "", "StartedAt": "2015-12-23T01:06:29.018395755Z", "FinishedAt": "2015-12-23T01:06:30.144487212Z" }, "Image": "cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0", "ResolvConfPath": "/var/lib/docker/containers/a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303/resolv.conf", "HostnamePath": "/var/lib/docker/containers/a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303/hostname", "HostsPath": "/var/lib/docker/containers/a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303/hosts", "LogPath": "/var/lib/docker/containers/a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303/a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303-json.log", "Name": "/gigantic_goldberg", "RestartCount": 0, "Driver": "aufs", "ExecDriver": "native-0.2", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": null, "ContainerIDFile": "", "LxcConf": null, "Memory": 0, "MemoryReservation": 0, "MemorySwap": 0, "KernelMemory": 0, "CpuShares": 0, "CpuPeriod": 0, "CpusetCpus": "", "CpusetMems": "", "CpuQuota": 0, "BlkioWeight": 0, "OomKillDisable": false, "MemorySwappiness": null, "Privileged": false, "PortBindings": {}, "Links": null, "PublishAllPorts": true, "Dns": null, "DnsOptions": null, "DnsSearch": null, "ExtraHosts": null, "VolumesFrom": null, "Devices": null, "NetworkMode": "default", "IpcMode": "", "PidMode": "", "UTSMode": "", "CapAdd": null, "CapDrop": null, "GroupAdd": null, "RestartPolicy": { "Name": "", "MaximumRetryCount": 0 }, "SecurityOpt": null, "ReadonlyRootfs": false, "Ulimits": null, "LogConfig": { "Type": "json-file", "Config": {} }, "CgroupParent": "", "ConsoleSize": [ 0, 0 ], "VolumeDriver": "" }, "GraphDriver": { "Name": "aufs", "Data": null }, "Mounts": [ { "Name": "b1a70d8e1ebd7d5865e59ff91cf06357e3ef4d829af44c31675c2d0a24894444", "Source": "/var/lib/docker/volumes/b1a70d8e1ebd7d5865e59ff91cf06357e3ef4d829af44c31675c2d0a24894444/_data", "Destination": "/data/db", "Driver": "local", "Mode": "", "RW": true } ], "Config": { "Hostname": "a68c1872c746", "Domainname": "", "User": "", "AttachStdin": true, "AttachStdout": true, "AttachStderr": true, "ExposedPorts": { "27017/tcp": {} }, "Tty": true, "OpenStdin": true, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GPG_KEYS=DFFA3DCF326E302C4787673A01C4E7FAAAB2461C \t42F3E95A2C4F08279C4960ADD68FA50FEA312927", "MONGO_MAJOR=3.2", "MONGO_VERSION=3.2.0" ], "Cmd": [ "None" ], "Image": "mongo:latest", "Volumes": { "/data/db": {} }, "WorkingDir": "", "Entrypoint": [ "/entrypoint.sh" ], "OnBuild": null, "Labels": {} }, "NetworkSettings": { "Bridge": "", "SandboxID": "", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": null, "SandboxKey": "", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": { "bridge": { "EndpointID": "", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "" } } } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/containers.json0000664000175000017500000000647213535474530031110 0ustar kamikami00000000000000[ { "Id": "160936dc54fe8c332095676d9379003534b8cddd7565fa63018996e06dae1b6b", "Names": [ "/hubot" ], "Image": "stackstorm/hubot", "ImageID": "05c5761707b3970a9bf17c00886176add79ac087b4d6a500ac87985bf8ec07b1", "Command": "/app/bin/hubot", "Created": 1450130345, "Ports": [], "Labels": {}, "Status": "Exited (137) 11 minutes ago", "HostConfig": { "NetworkMode": "bridge" } }, { "Id": "f159072147ee7d253e21ec8fd2778a27ac29d7fc5f865641900d16665b46215a", "Names": [ "/mongo" ], "Image": "mongo", "ImageID": "cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0", "Command": "/entrypoint.sh mongod", "Created": 1450130332, "Ports": [], "Labels": {}, "Status": "Exited (14) 2 hours ago", "HostConfig": { "NetworkMode": "bridge" } }, { "Id": "e687b33f9ced0153104308e6ff7a2138b8cc026fa4085d31da831a02ed0dc03d", "Names": [ "/rabbitmq" ], "Image": "rabbitmq", "ImageID": "448afeda0388b18c6f3be18c7aaece29e0f8dbdfab30364e678c382bab1037c5", "Command": "/docker-entrypoint.sh rabbitmq-server", "Created": 1450130331, "Ports": [ { "IP": "0.0.0.0", "PrivatePort": 5672, "PublicPort": 5672, "Type": "tcp" }, { "PrivatePort": 25672, "Type": "tcp" }, { "PrivatePort": 4369, "Type": "tcp" }, { "PrivatePort": 5671, "Type": "tcp" } ], "Labels": {}, "Status": "Exited (137) 11 minutes ago", "HostConfig": { "NetworkMode": "bridge" } }, { "Id": "b82c16423c6dbb7cd1564f8fc413c822df45cc0c7aa35c24683a1329af6ec102", "Names": [ "/fervent_bhabha" ], "Image": "rabbitmq", "ImageID": "448afeda0388b18c6f3be18c7aaece29e0f8dbdfab30364e678c382bab1037c5", "Command": "/docker-entrypoint.sh rabbitmq-server", "Created": 1450059506, "Ports": [ { "PrivatePort": 4369, "Type": "tcp" }, { "PrivatePort": 5671, "Type": "tcp" }, { "IP": "0.0.0.0", "PrivatePort": 5672, "PublicPort": 5672, "Type": "tcp" }, { "PrivatePort": 25672, "Type": "tcp" } ], "Labels": {}, "Status": "Dead", "HostConfig": { "NetworkMode": "bridge" } }, { "Id": "8cc5481aa4621578f8dd2c942d74e27e75170c6899ea012db7a44ea5f1ba2069", "Names": [ "/suspicious_swirles" ], "Image": "mongo", "ImageID": "cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0", "Command": "/entrypoint.sh mongod", "Created": 1450059505, "Ports": [ { "IP": "0.0.0.0", "PrivatePort": 27017, "PublicPort": 27017, "Type": "tcp" } ], "Labels": {}, "Status": "Dead", "HostConfig": { "NetworkMode": "bridge" } }, { "Id": "598b3e4d15a406390baaa2947f910e7b52b810a4120028692ed309247f2e8346", "Names": [ "/mongodata" ], "Image": "mongo", "ImageID": "cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0", "Command": "/entrypoint.sh /bin/true", "Created": 1449637213, "Ports": [], "Labels": {}, "Status": "Created", "HostConfig": { "NetworkMode": "default" } } ]apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/create_container.json0000664000175000017500000000014213535474530032234 0ustar kamikami00000000000000{ "Id": "a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303", "Warnings": null }apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/create_image.txt0000664000175000017500000012202113535474530031203 0ustar kamikami00000000000000{"status":"Pulling from library/ubuntu","id":"12.04"} {"status":"Pulling fs layer","progressDetail":{},"id":"36cef014d5d4"} {"status":"Pulling fs layer","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Pulling fs layer","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Pulling fs layer","progressDetail":{},"id":"44710c456ffc"} {"status":"Pulling fs layer","progressDetail":{},"id":"56e70ac3b314"} {"status":"Waiting","progressDetail":{},"id":"44710c456ffc"} {"status":"Waiting","progressDetail":{},"id":"56e70ac3b314"} {"status":"Downloading","progressDetail":{"current":419,"total":419},"progress":"[==================================================\u003e] 419 B/419 B","id":"3e32dbf1ab94"} {"status":"Verifying Checksum","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Download complete","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Downloading","progressDetail":{"current":16384,"total":57935},"progress":"[==============\u003e ] 16.38 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Downloading","progressDetail":{"current":32768,"total":57935},"progress":"[============================\u003e ] 32.77 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Downloading","progressDetail":{"current":57935,"total":57935},"progress":"[==================================================\u003e] 57.94 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Verifying Checksum","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Download complete","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Downloading","progressDetail":{"current":162,"total":162},"progress":"[==================================================\u003e] 162 B/162 B","id":"56e70ac3b314"} {"status":"Verifying Checksum","progressDetail":{},"id":"56e70ac3b314"} {"status":"Download complete","progressDetail":{},"id":"56e70ac3b314"} {"status":"Downloading","progressDetail":{"current":682,"total":682},"progress":"[==================================================\u003e] 682 B/682 B","id":"44710c456ffc"} {"status":"Verifying Checksum","progressDetail":{},"id":"44710c456ffc"} {"status":"Download complete","progressDetail":{},"id":"44710c456ffc"} {"status":"Downloading","progressDetail":{"current":392563,"total":39081844},"progress":"[\u003e ] 392.6 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":783955,"total":39081844},"progress":"[=\u003e ] 784 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":1178995,"total":39081844},"progress":"[=\u003e ] 1.179 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":1572211,"total":39081844},"progress":"[==\u003e ] 1.572 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":1965427,"total":39081844},"progress":"[==\u003e ] 1.965 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":2358643,"total":39081844},"progress":"[===\u003e ] 2.359 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":2751859,"total":39081844},"progress":"[===\u003e ] 2.752 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":3145075,"total":39081844},"progress":"[====\u003e ] 3.145 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":3538291,"total":39081844},"progress":"[====\u003e ] 3.538 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":3931507,"total":39081844},"progress":"[=====\u003e ] 3.932 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":4324723,"total":39081844},"progress":"[=====\u003e ] 4.325 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":4717939,"total":39081844},"progress":"[======\u003e ] 4.718 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":5111155,"total":39081844},"progress":"[======\u003e ] 5.111 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":5504371,"total":39081844},"progress":"[=======\u003e ] 5.504 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":5897587,"total":39081844},"progress":"[=======\u003e ] 5.898 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":6290803,"total":39081844},"progress":"[========\u003e ] 6.291 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":6684019,"total":39081844},"progress":"[========\u003e ] 6.684 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":7077235,"total":39081844},"progress":"[=========\u003e ] 7.077 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":7470451,"total":39081844},"progress":"[=========\u003e ] 7.47 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":7863667,"total":39081844},"progress":"[==========\u003e ] 7.864 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":8256883,"total":39081844},"progress":"[==========\u003e ] 8.257 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":8650099,"total":39081844},"progress":"[===========\u003e ] 8.65 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":9043315,"total":39081844},"progress":"[===========\u003e ] 9.043 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":9436531,"total":39081844},"progress":"[============\u003e ] 9.437 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":9829747,"total":39081844},"progress":"[============\u003e ] 9.83 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":10222963,"total":39081844},"progress":"[=============\u003e ] 10.22 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":10616179,"total":39081844},"progress":"[=============\u003e ] 10.62 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":11009395,"total":39081844},"progress":"[==============\u003e ] 11.01 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":11402611,"total":39081844},"progress":"[==============\u003e ] 11.4 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":11795827,"total":39081844},"progress":"[===============\u003e ] 11.8 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":12189043,"total":39081844},"progress":"[===============\u003e ] 12.19 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":12582259,"total":39081844},"progress":"[================\u003e ] 12.58 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":12975475,"total":39081844},"progress":"[================\u003e ] 12.98 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":13368691,"total":39081844},"progress":"[=================\u003e ] 13.37 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":13761907,"total":39081844},"progress":"[=================\u003e ] 13.76 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":14155123,"total":39081844},"progress":"[==================\u003e ] 14.16 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":14548339,"total":39081844},"progress":"[==================\u003e ] 14.55 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":14941555,"total":39081844},"progress":"[===================\u003e ] 14.94 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":15334771,"total":39081844},"progress":"[===================\u003e ] 15.33 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":15727987,"total":39081844},"progress":"[====================\u003e ] 15.73 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":16121203,"total":39081844},"progress":"[====================\u003e ] 16.12 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":16514419,"total":39081844},"progress":"[=====================\u003e ] 16.51 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":16907635,"total":39081844},"progress":"[=====================\u003e ] 16.91 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":17300851,"total":39081844},"progress":"[======================\u003e ] 17.3 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":17694067,"total":39081844},"progress":"[======================\u003e ] 17.69 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":18087283,"total":39081844},"progress":"[=======================\u003e ] 18.09 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":18480499,"total":39081844},"progress":"[=======================\u003e ] 18.48 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":18873715,"total":39081844},"progress":"[========================\u003e ] 18.87 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":19266931,"total":39081844},"progress":"[========================\u003e ] 19.27 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":19660147,"total":39081844},"progress":"[=========================\u003e ] 19.66 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":20053363,"total":39081844},"progress":"[=========================\u003e ] 20.05 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":20446579,"total":39081844},"progress":"[==========================\u003e ] 20.45 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":20839795,"total":39081844},"progress":"[==========================\u003e ] 20.84 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":21233011,"total":39081844},"progress":"[===========================\u003e ] 21.23 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":21626227,"total":39081844},"progress":"[===========================\u003e ] 21.63 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":22019443,"total":39081844},"progress":"[============================\u003e ] 22.02 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":22412659,"total":39081844},"progress":"[============================\u003e ] 22.41 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":22805875,"total":39081844},"progress":"[=============================\u003e ] 22.81 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":23199091,"total":39081844},"progress":"[=============================\u003e ] 23.2 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":23592307,"total":39081844},"progress":"[==============================\u003e ] 23.59 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":23985523,"total":39081844},"progress":"[==============================\u003e ] 23.99 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":24378739,"total":39081844},"progress":"[===============================\u003e ] 24.38 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":24771955,"total":39081844},"progress":"[===============================\u003e ] 24.77 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":25165171,"total":39081844},"progress":"[================================\u003e ] 25.17 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":25558387,"total":39081844},"progress":"[================================\u003e ] 25.56 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":25951603,"total":39081844},"progress":"[=================================\u003e ] 25.95 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":26344819,"total":39081844},"progress":"[=================================\u003e ] 26.34 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":26738035,"total":39081844},"progress":"[==================================\u003e ] 26.74 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":27131251,"total":39081844},"progress":"[==================================\u003e ] 27.13 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":27524467,"total":39081844},"progress":"[===================================\u003e ] 27.52 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":27917683,"total":39081844},"progress":"[===================================\u003e ] 27.92 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":28310899,"total":39081844},"progress":"[====================================\u003e ] 28.31 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":28704115,"total":39081844},"progress":"[====================================\u003e ] 28.7 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":29097331,"total":39081844},"progress":"[=====================================\u003e ] 29.1 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":29490547,"total":39081844},"progress":"[=====================================\u003e ] 29.49 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":29883763,"total":39081844},"progress":"[======================================\u003e ] 29.88 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":30276979,"total":39081844},"progress":"[======================================\u003e ] 30.28 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":30670195,"total":39081844},"progress":"[=======================================\u003e ] 30.67 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":31063411,"total":39081844},"progress":"[=======================================\u003e ] 31.06 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":31456627,"total":39081844},"progress":"[========================================\u003e ] 31.46 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":31849843,"total":39081844},"progress":"[========================================\u003e ] 31.85 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":32243059,"total":39081844},"progress":"[=========================================\u003e ] 32.24 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":32636275,"total":39081844},"progress":"[=========================================\u003e ] 32.64 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":33029491,"total":39081844},"progress":"[==========================================\u003e ] 33.03 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":33422707,"total":39081844},"progress":"[==========================================\u003e ] 33.42 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":33815923,"total":39081844},"progress":"[===========================================\u003e ] 33.82 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":34209139,"total":39081844},"progress":"[===========================================\u003e ] 34.21 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":34602355,"total":39081844},"progress":"[============================================\u003e ] 34.6 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":34995571,"total":39081844},"progress":"[============================================\u003e ] 35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":35388787,"total":39081844},"progress":"[=============================================\u003e ] 35.39 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":35782003,"total":39081844},"progress":"[=============================================\u003e ] 35.78 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":36175219,"total":39081844},"progress":"[==============================================\u003e ] 36.18 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":36568435,"total":39081844},"progress":"[==============================================\u003e ] 36.57 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":36961651,"total":39081844},"progress":"[===============================================\u003e ] 36.96 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":37354867,"total":39081844},"progress":"[===============================================\u003e ] 37.35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":37748083,"total":39081844},"progress":"[================================================\u003e ] 37.75 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":38141299,"total":39081844},"progress":"[================================================\u003e ] 38.14 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":38534515,"total":39081844},"progress":"[=================================================\u003e ] 38.53 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":38927731,"total":39081844},"progress":"[=================================================\u003e ] 38.93 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Download complete","progressDetail":{},"id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":393216,"total":39081844},"progress":"[\u003e ] 393.2 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":786432,"total":39081844},"progress":"[=\u003e ] 786.4 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":1179648,"total":39081844},"progress":"[=\u003e ] 1.18 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":1572864,"total":39081844},"progress":"[==\u003e ] 1.573 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":1966080,"total":39081844},"progress":"[==\u003e ] 1.966 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":2359296,"total":39081844},"progress":"[===\u003e ] 2.359 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":2752512,"total":39081844},"progress":"[===\u003e ] 2.753 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":3145728,"total":39081844},"progress":"[====\u003e ] 3.146 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":3538944,"total":39081844},"progress":"[====\u003e ] 3.539 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":3932160,"total":39081844},"progress":"[=====\u003e ] 3.932 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":4325376,"total":39081844},"progress":"[=====\u003e ] 4.325 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":4718592,"total":39081844},"progress":"[======\u003e ] 4.719 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":5111808,"total":39081844},"progress":"[======\u003e ] 5.112 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":5505024,"total":39081844},"progress":"[=======\u003e ] 5.505 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":5898240,"total":39081844},"progress":"[=======\u003e ] 5.898 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":6291456,"total":39081844},"progress":"[========\u003e ] 6.291 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":6684672,"total":39081844},"progress":"[========\u003e ] 6.685 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":7077888,"total":39081844},"progress":"[=========\u003e ] 7.078 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":7471104,"total":39081844},"progress":"[=========\u003e ] 7.471 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":7864320,"total":39081844},"progress":"[==========\u003e ] 7.864 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":8257536,"total":39081844},"progress":"[==========\u003e ] 8.258 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":8650752,"total":39081844},"progress":"[===========\u003e ] 8.651 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":9043968,"total":39081844},"progress":"[===========\u003e ] 9.044 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":9437184,"total":39081844},"progress":"[============\u003e ] 9.437 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":9830400,"total":39081844},"progress":"[============\u003e ] 9.83 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":10223616,"total":39081844},"progress":"[=============\u003e ] 10.22 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":10616832,"total":39081844},"progress":"[=============\u003e ] 10.62 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":11010048,"total":39081844},"progress":"[==============\u003e ] 11.01 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":11403264,"total":39081844},"progress":"[==============\u003e ] 11.4 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":11796480,"total":39081844},"progress":"[===============\u003e ] 11.8 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":12189696,"total":39081844},"progress":"[===============\u003e ] 12.19 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":12582912,"total":39081844},"progress":"[================\u003e ] 12.58 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":12976128,"total":39081844},"progress":"[================\u003e ] 12.98 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":13369344,"total":39081844},"progress":"[=================\u003e ] 13.37 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":13762560,"total":39081844},"progress":"[=================\u003e ] 13.76 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":14155776,"total":39081844},"progress":"[==================\u003e ] 14.16 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":14548992,"total":39081844},"progress":"[==================\u003e ] 14.55 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":14942208,"total":39081844},"progress":"[===================\u003e ] 14.94 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":15335424,"total":39081844},"progress":"[===================\u003e ] 15.34 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":15728640,"total":39081844},"progress":"[====================\u003e ] 15.73 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":16121856,"total":39081844},"progress":"[====================\u003e ] 16.12 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":16515072,"total":39081844},"progress":"[=====================\u003e ] 16.52 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":16908288,"total":39081844},"progress":"[=====================\u003e ] 16.91 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":17301504,"total":39081844},"progress":"[======================\u003e ] 17.3 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":17694720,"total":39081844},"progress":"[======================\u003e ] 17.69 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":18087936,"total":39081844},"progress":"[=======================\u003e ] 18.09 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":18481152,"total":39081844},"progress":"[=======================\u003e ] 18.48 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":18874368,"total":39081844},"progress":"[========================\u003e ] 18.87 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":19267584,"total":39081844},"progress":"[========================\u003e ] 19.27 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":19660800,"total":39081844},"progress":"[=========================\u003e ] 19.66 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":20054016,"total":39081844},"progress":"[=========================\u003e ] 20.05 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":20447232,"total":39081844},"progress":"[==========================\u003e ] 20.45 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":20840448,"total":39081844},"progress":"[==========================\u003e ] 20.84 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":21233664,"total":39081844},"progress":"[===========================\u003e ] 21.23 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":21626880,"total":39081844},"progress":"[===========================\u003e ] 21.63 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":22020096,"total":39081844},"progress":"[============================\u003e ] 22.02 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":22413312,"total":39081844},"progress":"[============================\u003e ] 22.41 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":22806528,"total":39081844},"progress":"[=============================\u003e ] 22.81 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":23199744,"total":39081844},"progress":"[=============================\u003e ] 23.2 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":23592960,"total":39081844},"progress":"[==============================\u003e ] 23.59 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":23986176,"total":39081844},"progress":"[==============================\u003e ] 23.99 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":24379392,"total":39081844},"progress":"[===============================\u003e ] 24.38 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":24772608,"total":39081844},"progress":"[===============================\u003e ] 24.77 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":25165824,"total":39081844},"progress":"[================================\u003e ] 25.17 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":25559040,"total":39081844},"progress":"[================================\u003e ] 25.56 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":25952256,"total":39081844},"progress":"[=================================\u003e ] 25.95 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":26345472,"total":39081844},"progress":"[=================================\u003e ] 26.35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":26738688,"total":39081844},"progress":"[==================================\u003e ] 26.74 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":27131904,"total":39081844},"progress":"[==================================\u003e ] 27.13 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":27525120,"total":39081844},"progress":"[===================================\u003e ] 27.53 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":27918336,"total":39081844},"progress":"[===================================\u003e ] 27.92 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":28311552,"total":39081844},"progress":"[====================================\u003e ] 28.31 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":28704768,"total":39081844},"progress":"[====================================\u003e ] 28.7 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":29097984,"total":39081844},"progress":"[=====================================\u003e ] 29.1 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":29491200,"total":39081844},"progress":"[=====================================\u003e ] 29.49 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":29884416,"total":39081844},"progress":"[======================================\u003e ] 29.88 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":30277632,"total":39081844},"progress":"[======================================\u003e ] 30.28 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":30670848,"total":39081844},"progress":"[=======================================\u003e ] 30.67 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":31064064,"total":39081844},"progress":"[=======================================\u003e ] 31.06 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":31457280,"total":39081844},"progress":"[========================================\u003e ] 31.46 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":31850496,"total":39081844},"progress":"[========================================\u003e ] 31.85 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":32243712,"total":39081844},"progress":"[=========================================\u003e ] 32.24 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":32636928,"total":39081844},"progress":"[=========================================\u003e ] 32.64 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":33030144,"total":39081844},"progress":"[==========================================\u003e ] 33.03 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":33423360,"total":39081844},"progress":"[==========================================\u003e ] 33.42 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":33816576,"total":39081844},"progress":"[===========================================\u003e ] 33.82 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":34209792,"total":39081844},"progress":"[===========================================\u003e ] 34.21 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":34603008,"total":39081844},"progress":"[============================================\u003e ] 34.6 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":34996224,"total":39081844},"progress":"[============================================\u003e ] 35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":35389440,"total":39081844},"progress":"[=============================================\u003e ] 35.39 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":35782656,"total":39081844},"progress":"[=============================================\u003e ] 35.78 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":36175872,"total":39081844},"progress":"[==============================================\u003e ] 36.18 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":36569088,"total":39081844},"progress":"[==============================================\u003e ] 36.57 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":36962304,"total":39081844},"progress":"[===============================================\u003e ] 36.96 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":37355520,"total":39081844},"progress":"[===============================================\u003e ] 37.36 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":37748736,"total":39081844},"progress":"[================================================\u003e ] 37.75 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":38141952,"total":39081844},"progress":"[================================================\u003e ] 38.14 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":38535168,"total":39081844},"progress":"[=================================================\u003e ] 38.54 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":38928384,"total":39081844},"progress":"[=================================================\u003e ] 38.93 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":39081844,"total":39081844},"progress":"[==================================================\u003e] 39.08 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Pull complete","progressDetail":{},"id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":32768,"total":57935},"progress":"[============================\u003e ] 32.77 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Extracting","progressDetail":{"current":57935,"total":57935},"progress":"[==================================================\u003e] 57.94 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Extracting","progressDetail":{"current":57935,"total":57935},"progress":"[==================================================\u003e] 57.94 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Pull complete","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Extracting","progressDetail":{"current":419,"total":419},"progress":"[==================================================\u003e] 419 B/419 B","id":"3e32dbf1ab94"} {"status":"Extracting","progressDetail":{"current":419,"total":419},"progress":"[==================================================\u003e] 419 B/419 B","id":"3e32dbf1ab94"} {"status":"Pull complete","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Extracting","progressDetail":{"current":682,"total":682},"progress":"[==================================================\u003e] 682 B/682 B","id":"44710c456ffc"} {"status":"Extracting","progressDetail":{"current":682,"total":682},"progress":"[==================================================\u003e] 682 B/682 B","id":"44710c456ffc"} {"status":"Pull complete","progressDetail":{},"id":"44710c456ffc"} {"status":"Extracting","progressDetail":{"current":162,"total":162},"progress":"[==================================================\u003e] 162 B/162 B","id":"56e70ac3b314"} {"status":"Extracting","progressDetail":{"current":162,"total":162},"progress":"[==================================================\u003e] 162 B/162 B","id":"56e70ac3b314"} {"status":"Pull complete","progressDetail":{},"id":"56e70ac3b314"} {"status":"Digest: sha256:992069aee4016783df6345315302fa59681aae51a8eeb2f889dea59290f21787"} {"status":"Status: Downloaded newer image for ubuntu:12.04"}apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/images.json0000664000175000017500000000247213535474530030204 0ustar kamikami00000000000000[ { "Id": "cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0", "ParentId": "3e408cde1b7f6276b9ead7b8111d80a367f9223dfbbd4102ea89a5fc42947960", "RepoTags": [ "mongo:latest" ], "RepoDigests": [], "Created": 1449618009, "Size": 0, "VirtualSize": 316957672, "Labels": null }, { "Id": "05c5761707b3970a9bf17c00886176add79ac087b4d6a500ac87985bf8ec07b1", "ParentId": "be7965ce1bef5d2e3b27efb3f4fe2253683bc7144d2ebae614e9e7155066c833", "RepoTags": [ "stackstorm/hubot:latest" ], "RepoDigests": [], "Created": 1449466772, "Size": 0, "VirtualSize": 550102318, "Labels": {} }, { "Id": "448afeda0388b18c6f3be18c7aaece29e0f8dbdfab30364e678c382bab1037c5", "ParentId": "67edbf589f9af9b2c6f87e8481ec0299c50bfce5f9b98b95316c7235494c7bea", "RepoTags": [ "rabbitmq:latest" ], "RepoDigests": [], "Created": 1449312753, "Size": 0, "VirtualSize": 304310861, "Labels": null }, { "Id": "9da5438fedb2e9a1e11a3361c4a53e0801ed1f8f4c014d83a5a514f0c60892bf", "ParentId": "64ccc5e9d20c638849eadddab4f23204c3fcdd62d497cdbd0ecf44d863b086c8", "RepoTags": [ "mongo:2.4.14" ], "RepoDigests": [], "Created": 1449299455, "Size": 0, "VirtualSize": 344445131, "Labels": null } ]apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/logs.txt0000664000175000017500000000005713535474530027546 0ustar kamikami00000000000000/entrypoint.sh: line 19: exec: None: not found apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/search.json0000664000175000017500000001200113535474530030171 0ustar kamikami00000000000000[ { "star_count": 1502, "is_official": true, "name": "mysql", "is_trusted": false, "is_automated": false, "description": "MySQL is a widely used, open-source relational database management system (RDBMS)." }, { "star_count": 80, "is_official": false, "name": "mysql/mysql-server", "is_trusted": true, "is_automated": true, "description": "Optimized MySQL Server Docker images. Created, maintained and supported by the MySQL team at Oracle" }, { "star_count": 31, "is_official": false, "name": "centurylink/mysql", "is_trusted": true, "is_automated": true, "description": "Image containing mysql. Optimized to be linked to another image/container." }, { "star_count": 6, "is_official": false, "name": "appcontainers/mysql", "is_trusted": true, "is_automated": true, "description": "CentOS/Ubuntu/Debian based customizible MySQL 5.5 Container - 284MB/283MB/245MB - Updated 12/14/2015" }, { "star_count": 2, "is_official": false, "name": "alterway/mysql", "is_trusted": true, "is_automated": true, "description": "Docker Mysql" }, { "star_count": 0, "is_official": false, "name": "tozd/mysql", "is_trusted": true, "is_automated": true, "description": "MySQL (MariaDB fork) Docker image." }, { "star_count": 0, "is_official": false, "name": "wenzizone/mysql", "is_trusted": true, "is_automated": true, "description": "mysql" }, { "star_count": 0, "is_official": false, "name": "dockerizedrupal/mysql", "is_trusted": true, "is_automated": true, "description": "docker-mysql" }, { "star_count": 2, "is_official": false, "name": "azukiapp/mysql", "is_trusted": true, "is_automated": true, "description": "Docker image to run MySQL by Azuki - http://azk.io" }, { "star_count": 1, "is_official": false, "name": "phpmentors/mysql", "is_trusted": true, "is_automated": true, "description": "MySQL server image" }, { "star_count": 0, "is_official": false, "name": "lancehudson/docker-mysql", "is_trusted": true, "is_automated": true, "description": "MySQL is a widely used, open-source relational database management system (RDBMS)." }, { "star_count": 1, "is_official": false, "name": "bahmni/mysql", "is_trusted": true, "is_automated": true, "description": "Mysql container for bahmni. Contains the openmrs database" }, { "star_count": 2, "is_official": false, "name": "yfix/mysql", "is_trusted": true, "is_automated": true, "description": "Yfix docker built mysql" }, { "star_count": 23, "is_official": false, "name": "sameersbn/mysql", "is_trusted": true, "is_automated": true, "description": "" }, { "star_count": 0, "is_official": false, "name": "nanobox/mysql", "is_trusted": true, "is_automated": true, "description": "MySQL service for nanobox.io" }, { "star_count": 0, "is_official": false, "name": "withinboredom/mysql", "is_trusted": true, "is_automated": true, "description": "A MySQL container using s6 and Consul -- built on tatum/mysql" }, { "star_count": 4, "is_official": false, "name": "marvambass/mysql", "is_trusted": true, "is_automated": true, "description": "MySQL Server based on Ubuntu 14.04" }, { "star_count": 14, "is_official": false, "name": "google/mysql", "is_trusted": true, "is_automated": true, "description": "MySQL server for Google Compute Engine" }, { "star_count": 1, "is_official": false, "name": "frodenas/mysql", "is_trusted": true, "is_automated": true, "description": "A Docker Image for MySQL" }, { "star_count": 0, "is_official": false, "name": "ahmet2mir/mysql", "is_trusted": true, "is_automated": true, "description": "This is a Debian based image with MySQL server installed listening on port 3306. " }, { "star_count": 25, "is_official": false, "name": "wnameless/mysql-phpmyadmin", "is_trusted": true, "is_automated": true, "description": "MySQL + phpMyAdmin\nhttps://index.docker.io/u/wnameless/mysql-phpmyadmin/" }, { "star_count": 0, "is_official": false, "name": "drupaldocker/mysql", "is_trusted": true, "is_automated": true, "description": "MySQL for Drupal" }, { "star_count": 0, "is_official": false, "name": "tetraweb/mysql", "is_trusted": true, "is_automated": true, "description": "" }, { "star_count": 1, "is_official": false, "name": "boomtownroi/mysql-dev", "is_trusted": true, "is_automated": true, "description": "A mysql box with consul integration for development. Based on tatum box" }, { "star_count": 5, "is_official": false, "name": "ioggstream/mysql", "is_trusted": true, "is_automated": true, "description": "MySQL Image with Master-Slave replication" } ]apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/linux_124/version.json0000664000175000017500000000033713535474530030422 0ustar kamikami00000000000000{ "Version": "1.9.1", "ApiVersion": "1.21", "GitCommit": "a34a1d5", "GoVersion": "go1.4.3", "Os": "linux", "Arch": "amd64", "KernelVersion": "3.13.0-46-generic", "BuildTime": "Fri Nov 20 17:56:04 UTC 2015" }apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/mac_124/0000775000175000017500000000000013600223624025425 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/mac_124/containers.json0000664000175000017500000002100213535474530030473 0ustar kamikami00000000000000[{ "Id": "160936dc54fe8c332095676d9379003534b8cddd7565fa63018996e06dae1b6b", "Names": ["/hubot"], "Image": "stackstorm/hubot", "ImageID": "sha256:0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "Command": "nginx -g 'daemon off;'", "Created": 1466734872, "Ports": [{ "PrivatePort": 443, "Type": "tcp" }, { "PrivatePort": 80, "Type": "tcp" } ], "Labels": {}, "State": "running", "Status": "Up 4 seconds", "HostConfig": { "NetworkMode": "default" }, "NetworkSettings": { "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "beceac1c78e75bd5f8a13a60e3bf95b76aa45cac2d31978ae77934da17c16cc8", "EndpointID": "d0c614dcdd1c6a89765c989640239a27ab3a99a5ca3dbd1de7494b939f39652c", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.7", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:07" } } }, "Mounts": [] }, { "Id": "6089a78e3e938a6a693601ad8a3f416d39273f8d2b4d3d3971b82eaa05281d08", "Names": ["/fervent_noether"], "Image": "nginx", "ImageID": "sha256:0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "Command": "nginx -g 'daemon off;'", "Created": 1466734871, "Ports": [{ "PrivatePort": 443, "Type": "tcp" }, { "PrivatePort": 80, "Type": "tcp" } ], "Labels": {}, "State": "running", "Status": "Up 5 seconds", "HostConfig": { "NetworkMode": "default" }, "NetworkSettings": { "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "beceac1c78e75bd5f8a13a60e3bf95b76aa45cac2d31978ae77934da17c16cc8", "EndpointID": "1298dfe058795ed277e539e80e00cb88bbbcbb08051b1f43f979f878e959e9c4", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.6", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:06" } } }, "Mounts": [] }, { "Id": "1fa078bc0c56b94a81e62586aebab06042abc524df45fc3197eaff31dd61705f", "Names": ["/cranky_nobel"], "Image": "nginx", "ImageID": "sha256:0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "Command": "nginx -g 'daemon off;'", "Created": 1466734869, "Ports": [{ "PrivatePort": 443, "Type": "tcp" }, { "PrivatePort": 80, "Type": "tcp" } ], "Labels": {}, "State": "running", "Status": "Up 6 seconds", "HostConfig": { "NetworkMode": "default" }, "NetworkSettings": { "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "beceac1c78e75bd5f8a13a60e3bf95b76aa45cac2d31978ae77934da17c16cc8", "EndpointID": "4985fa8a74f2997ee0794c1866e6492dbc9124705d41596fa27bb4c2505739fb", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.5", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:05" } } }, "Mounts": [] }, { "Id": "15faa50fa2a41f417cee3f2013fc150d0f90d9ed3102d8533e65099d50476e4d", "Names": ["/sharp_kilby"], "Image": "nginx", "ImageID": "sha256:0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "Command": "nginx -g 'daemon off;'", "Created": 1466734868, "Ports": [{ "PrivatePort": 443, "Type": "tcp" }, { "PrivatePort": 80, "Type": "tcp" } ], "Labels": {}, "State": "running", "Status": "Up 7 seconds", "HostConfig": { "NetworkMode": "default" }, "NetworkSettings": { "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "beceac1c78e75bd5f8a13a60e3bf95b76aa45cac2d31978ae77934da17c16cc8", "EndpointID": "912a856ada2ab2e84a95ff2ca5236b9e84976e3daf4844623ba80228bb244660", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.4", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:04" } } }, "Mounts": [] }, { "Id": "c3bd5b03b4d5a636344b75271781c3402341db6be1e76168cb602c5d79439519", "Names": ["/agitated_lalande"], "Image": "nginx", "ImageID": "sha256:0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "Command": "nginx -g 'daemon off;'", "Created": 1466734867, "Ports": [{ "PrivatePort": 443, "Type": "tcp" }, { "PrivatePort": 80, "Type": "tcp" } ], "Labels": {}, "State": "running", "Status": "Up 9 seconds", "HostConfig": { "NetworkMode": "default" }, "NetworkSettings": { "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "beceac1c78e75bd5f8a13a60e3bf95b76aa45cac2d31978ae77934da17c16cc8", "EndpointID": "2856237f86f145817f3807996c3e89c9ad019d45a29c98cb0ab165abebe11ef9", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:03" } } }, "Mounts": [] }, { "Id": "5ad88cda3edccb5523ddd6831a399f406434ef0fc35dc24caa6cd09ee08b7826", "Names": ["/elated_euler"], "Image": "nginx", "ImageID": "sha256:0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "Command": "nginx -g 'daemon off;'", "Created": 1466734255, "Ports": [{ "PrivatePort": 443, "Type": "tcp" }, { "PrivatePort": 80, "Type": "tcp" } ], "Labels": {}, "State": "running", "Status": "Up 10 minutes", "HostConfig": { "NetworkMode": "default" }, "NetworkSettings": { "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "beceac1c78e75bd5f8a13a60e3bf95b76aa45cac2d31978ae77934da17c16cc8", "EndpointID": "80646c52b170bffbde82cffd0fff2c7096ecf55b47ec297481127b2a4e622416", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02" } } }, "Mounts": [] } ]apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/mac_124/create_container.json0000664000175000017500000000014213535474530031635 0ustar kamikami00000000000000{ "Id": "a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303", "Warnings": null }apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/mac_124/create_image.txt0000664000175000017500000012202113535474530030604 0ustar kamikami00000000000000{"status":"Pulling from library/ubuntu","id":"12.04"} {"status":"Pulling fs layer","progressDetail":{},"id":"36cef014d5d4"} {"status":"Pulling fs layer","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Pulling fs layer","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Pulling fs layer","progressDetail":{},"id":"44710c456ffc"} {"status":"Pulling fs layer","progressDetail":{},"id":"56e70ac3b314"} {"status":"Waiting","progressDetail":{},"id":"44710c456ffc"} {"status":"Waiting","progressDetail":{},"id":"56e70ac3b314"} {"status":"Downloading","progressDetail":{"current":419,"total":419},"progress":"[==================================================\u003e] 419 B/419 B","id":"3e32dbf1ab94"} {"status":"Verifying Checksum","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Download complete","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Downloading","progressDetail":{"current":16384,"total":57935},"progress":"[==============\u003e ] 16.38 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Downloading","progressDetail":{"current":32768,"total":57935},"progress":"[============================\u003e ] 32.77 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Downloading","progressDetail":{"current":57935,"total":57935},"progress":"[==================================================\u003e] 57.94 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Verifying Checksum","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Download complete","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Downloading","progressDetail":{"current":162,"total":162},"progress":"[==================================================\u003e] 162 B/162 B","id":"56e70ac3b314"} {"status":"Verifying Checksum","progressDetail":{},"id":"56e70ac3b314"} {"status":"Download complete","progressDetail":{},"id":"56e70ac3b314"} {"status":"Downloading","progressDetail":{"current":682,"total":682},"progress":"[==================================================\u003e] 682 B/682 B","id":"44710c456ffc"} {"status":"Verifying Checksum","progressDetail":{},"id":"44710c456ffc"} {"status":"Download complete","progressDetail":{},"id":"44710c456ffc"} {"status":"Downloading","progressDetail":{"current":392563,"total":39081844},"progress":"[\u003e ] 392.6 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":783955,"total":39081844},"progress":"[=\u003e ] 784 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":1178995,"total":39081844},"progress":"[=\u003e ] 1.179 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":1572211,"total":39081844},"progress":"[==\u003e ] 1.572 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":1965427,"total":39081844},"progress":"[==\u003e ] 1.965 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":2358643,"total":39081844},"progress":"[===\u003e ] 2.359 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":2751859,"total":39081844},"progress":"[===\u003e ] 2.752 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":3145075,"total":39081844},"progress":"[====\u003e ] 3.145 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":3538291,"total":39081844},"progress":"[====\u003e ] 3.538 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":3931507,"total":39081844},"progress":"[=====\u003e ] 3.932 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":4324723,"total":39081844},"progress":"[=====\u003e ] 4.325 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":4717939,"total":39081844},"progress":"[======\u003e ] 4.718 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":5111155,"total":39081844},"progress":"[======\u003e ] 5.111 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":5504371,"total":39081844},"progress":"[=======\u003e ] 5.504 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":5897587,"total":39081844},"progress":"[=======\u003e ] 5.898 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":6290803,"total":39081844},"progress":"[========\u003e ] 6.291 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":6684019,"total":39081844},"progress":"[========\u003e ] 6.684 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":7077235,"total":39081844},"progress":"[=========\u003e ] 7.077 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":7470451,"total":39081844},"progress":"[=========\u003e ] 7.47 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":7863667,"total":39081844},"progress":"[==========\u003e ] 7.864 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":8256883,"total":39081844},"progress":"[==========\u003e ] 8.257 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":8650099,"total":39081844},"progress":"[===========\u003e ] 8.65 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":9043315,"total":39081844},"progress":"[===========\u003e ] 9.043 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":9436531,"total":39081844},"progress":"[============\u003e ] 9.437 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":9829747,"total":39081844},"progress":"[============\u003e ] 9.83 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":10222963,"total":39081844},"progress":"[=============\u003e ] 10.22 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":10616179,"total":39081844},"progress":"[=============\u003e ] 10.62 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":11009395,"total":39081844},"progress":"[==============\u003e ] 11.01 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":11402611,"total":39081844},"progress":"[==============\u003e ] 11.4 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":11795827,"total":39081844},"progress":"[===============\u003e ] 11.8 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":12189043,"total":39081844},"progress":"[===============\u003e ] 12.19 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":12582259,"total":39081844},"progress":"[================\u003e ] 12.58 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":12975475,"total":39081844},"progress":"[================\u003e ] 12.98 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":13368691,"total":39081844},"progress":"[=================\u003e ] 13.37 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":13761907,"total":39081844},"progress":"[=================\u003e ] 13.76 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":14155123,"total":39081844},"progress":"[==================\u003e ] 14.16 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":14548339,"total":39081844},"progress":"[==================\u003e ] 14.55 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":14941555,"total":39081844},"progress":"[===================\u003e ] 14.94 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":15334771,"total":39081844},"progress":"[===================\u003e ] 15.33 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":15727987,"total":39081844},"progress":"[====================\u003e ] 15.73 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":16121203,"total":39081844},"progress":"[====================\u003e ] 16.12 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":16514419,"total":39081844},"progress":"[=====================\u003e ] 16.51 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":16907635,"total":39081844},"progress":"[=====================\u003e ] 16.91 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":17300851,"total":39081844},"progress":"[======================\u003e ] 17.3 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":17694067,"total":39081844},"progress":"[======================\u003e ] 17.69 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":18087283,"total":39081844},"progress":"[=======================\u003e ] 18.09 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":18480499,"total":39081844},"progress":"[=======================\u003e ] 18.48 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":18873715,"total":39081844},"progress":"[========================\u003e ] 18.87 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":19266931,"total":39081844},"progress":"[========================\u003e ] 19.27 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":19660147,"total":39081844},"progress":"[=========================\u003e ] 19.66 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":20053363,"total":39081844},"progress":"[=========================\u003e ] 20.05 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":20446579,"total":39081844},"progress":"[==========================\u003e ] 20.45 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":20839795,"total":39081844},"progress":"[==========================\u003e ] 20.84 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":21233011,"total":39081844},"progress":"[===========================\u003e ] 21.23 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":21626227,"total":39081844},"progress":"[===========================\u003e ] 21.63 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":22019443,"total":39081844},"progress":"[============================\u003e ] 22.02 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":22412659,"total":39081844},"progress":"[============================\u003e ] 22.41 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":22805875,"total":39081844},"progress":"[=============================\u003e ] 22.81 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":23199091,"total":39081844},"progress":"[=============================\u003e ] 23.2 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":23592307,"total":39081844},"progress":"[==============================\u003e ] 23.59 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":23985523,"total":39081844},"progress":"[==============================\u003e ] 23.99 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":24378739,"total":39081844},"progress":"[===============================\u003e ] 24.38 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":24771955,"total":39081844},"progress":"[===============================\u003e ] 24.77 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":25165171,"total":39081844},"progress":"[================================\u003e ] 25.17 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":25558387,"total":39081844},"progress":"[================================\u003e ] 25.56 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":25951603,"total":39081844},"progress":"[=================================\u003e ] 25.95 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":26344819,"total":39081844},"progress":"[=================================\u003e ] 26.34 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":26738035,"total":39081844},"progress":"[==================================\u003e ] 26.74 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":27131251,"total":39081844},"progress":"[==================================\u003e ] 27.13 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":27524467,"total":39081844},"progress":"[===================================\u003e ] 27.52 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":27917683,"total":39081844},"progress":"[===================================\u003e ] 27.92 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":28310899,"total":39081844},"progress":"[====================================\u003e ] 28.31 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":28704115,"total":39081844},"progress":"[====================================\u003e ] 28.7 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":29097331,"total":39081844},"progress":"[=====================================\u003e ] 29.1 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":29490547,"total":39081844},"progress":"[=====================================\u003e ] 29.49 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":29883763,"total":39081844},"progress":"[======================================\u003e ] 29.88 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":30276979,"total":39081844},"progress":"[======================================\u003e ] 30.28 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":30670195,"total":39081844},"progress":"[=======================================\u003e ] 30.67 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":31063411,"total":39081844},"progress":"[=======================================\u003e ] 31.06 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":31456627,"total":39081844},"progress":"[========================================\u003e ] 31.46 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":31849843,"total":39081844},"progress":"[========================================\u003e ] 31.85 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":32243059,"total":39081844},"progress":"[=========================================\u003e ] 32.24 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":32636275,"total":39081844},"progress":"[=========================================\u003e ] 32.64 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":33029491,"total":39081844},"progress":"[==========================================\u003e ] 33.03 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":33422707,"total":39081844},"progress":"[==========================================\u003e ] 33.42 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":33815923,"total":39081844},"progress":"[===========================================\u003e ] 33.82 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":34209139,"total":39081844},"progress":"[===========================================\u003e ] 34.21 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":34602355,"total":39081844},"progress":"[============================================\u003e ] 34.6 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":34995571,"total":39081844},"progress":"[============================================\u003e ] 35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":35388787,"total":39081844},"progress":"[=============================================\u003e ] 35.39 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":35782003,"total":39081844},"progress":"[=============================================\u003e ] 35.78 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":36175219,"total":39081844},"progress":"[==============================================\u003e ] 36.18 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":36568435,"total":39081844},"progress":"[==============================================\u003e ] 36.57 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":36961651,"total":39081844},"progress":"[===============================================\u003e ] 36.96 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":37354867,"total":39081844},"progress":"[===============================================\u003e ] 37.35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":37748083,"total":39081844},"progress":"[================================================\u003e ] 37.75 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":38141299,"total":39081844},"progress":"[================================================\u003e ] 38.14 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":38534515,"total":39081844},"progress":"[=================================================\u003e ] 38.53 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Downloading","progressDetail":{"current":38927731,"total":39081844},"progress":"[=================================================\u003e ] 38.93 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Download complete","progressDetail":{},"id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":393216,"total":39081844},"progress":"[\u003e ] 393.2 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":786432,"total":39081844},"progress":"[=\u003e ] 786.4 kB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":1179648,"total":39081844},"progress":"[=\u003e ] 1.18 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":1572864,"total":39081844},"progress":"[==\u003e ] 1.573 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":1966080,"total":39081844},"progress":"[==\u003e ] 1.966 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":2359296,"total":39081844},"progress":"[===\u003e ] 2.359 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":2752512,"total":39081844},"progress":"[===\u003e ] 2.753 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":3145728,"total":39081844},"progress":"[====\u003e ] 3.146 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":3538944,"total":39081844},"progress":"[====\u003e ] 3.539 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":3932160,"total":39081844},"progress":"[=====\u003e ] 3.932 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":4325376,"total":39081844},"progress":"[=====\u003e ] 4.325 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":4718592,"total":39081844},"progress":"[======\u003e ] 4.719 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":5111808,"total":39081844},"progress":"[======\u003e ] 5.112 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":5505024,"total":39081844},"progress":"[=======\u003e ] 5.505 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":5898240,"total":39081844},"progress":"[=======\u003e ] 5.898 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":6291456,"total":39081844},"progress":"[========\u003e ] 6.291 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":6684672,"total":39081844},"progress":"[========\u003e ] 6.685 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":7077888,"total":39081844},"progress":"[=========\u003e ] 7.078 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":7471104,"total":39081844},"progress":"[=========\u003e ] 7.471 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":7864320,"total":39081844},"progress":"[==========\u003e ] 7.864 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":8257536,"total":39081844},"progress":"[==========\u003e ] 8.258 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":8650752,"total":39081844},"progress":"[===========\u003e ] 8.651 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":9043968,"total":39081844},"progress":"[===========\u003e ] 9.044 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":9437184,"total":39081844},"progress":"[============\u003e ] 9.437 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":9830400,"total":39081844},"progress":"[============\u003e ] 9.83 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":10223616,"total":39081844},"progress":"[=============\u003e ] 10.22 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":10616832,"total":39081844},"progress":"[=============\u003e ] 10.62 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":11010048,"total":39081844},"progress":"[==============\u003e ] 11.01 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":11403264,"total":39081844},"progress":"[==============\u003e ] 11.4 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":11796480,"total":39081844},"progress":"[===============\u003e ] 11.8 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":12189696,"total":39081844},"progress":"[===============\u003e ] 12.19 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":12582912,"total":39081844},"progress":"[================\u003e ] 12.58 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":12976128,"total":39081844},"progress":"[================\u003e ] 12.98 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":13369344,"total":39081844},"progress":"[=================\u003e ] 13.37 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":13762560,"total":39081844},"progress":"[=================\u003e ] 13.76 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":14155776,"total":39081844},"progress":"[==================\u003e ] 14.16 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":14548992,"total":39081844},"progress":"[==================\u003e ] 14.55 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":14942208,"total":39081844},"progress":"[===================\u003e ] 14.94 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":15335424,"total":39081844},"progress":"[===================\u003e ] 15.34 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":15728640,"total":39081844},"progress":"[====================\u003e ] 15.73 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":16121856,"total":39081844},"progress":"[====================\u003e ] 16.12 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":16515072,"total":39081844},"progress":"[=====================\u003e ] 16.52 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":16908288,"total":39081844},"progress":"[=====================\u003e ] 16.91 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":17301504,"total":39081844},"progress":"[======================\u003e ] 17.3 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":17694720,"total":39081844},"progress":"[======================\u003e ] 17.69 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":18087936,"total":39081844},"progress":"[=======================\u003e ] 18.09 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":18481152,"total":39081844},"progress":"[=======================\u003e ] 18.48 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":18874368,"total":39081844},"progress":"[========================\u003e ] 18.87 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":19267584,"total":39081844},"progress":"[========================\u003e ] 19.27 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":19660800,"total":39081844},"progress":"[=========================\u003e ] 19.66 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":20054016,"total":39081844},"progress":"[=========================\u003e ] 20.05 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":20447232,"total":39081844},"progress":"[==========================\u003e ] 20.45 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":20840448,"total":39081844},"progress":"[==========================\u003e ] 20.84 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":21233664,"total":39081844},"progress":"[===========================\u003e ] 21.23 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":21626880,"total":39081844},"progress":"[===========================\u003e ] 21.63 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":22020096,"total":39081844},"progress":"[============================\u003e ] 22.02 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":22413312,"total":39081844},"progress":"[============================\u003e ] 22.41 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":22806528,"total":39081844},"progress":"[=============================\u003e ] 22.81 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":23199744,"total":39081844},"progress":"[=============================\u003e ] 23.2 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":23592960,"total":39081844},"progress":"[==============================\u003e ] 23.59 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":23986176,"total":39081844},"progress":"[==============================\u003e ] 23.99 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":24379392,"total":39081844},"progress":"[===============================\u003e ] 24.38 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":24772608,"total":39081844},"progress":"[===============================\u003e ] 24.77 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":25165824,"total":39081844},"progress":"[================================\u003e ] 25.17 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":25559040,"total":39081844},"progress":"[================================\u003e ] 25.56 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":25952256,"total":39081844},"progress":"[=================================\u003e ] 25.95 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":26345472,"total":39081844},"progress":"[=================================\u003e ] 26.35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":26738688,"total":39081844},"progress":"[==================================\u003e ] 26.74 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":27131904,"total":39081844},"progress":"[==================================\u003e ] 27.13 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":27525120,"total":39081844},"progress":"[===================================\u003e ] 27.53 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":27918336,"total":39081844},"progress":"[===================================\u003e ] 27.92 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":28311552,"total":39081844},"progress":"[====================================\u003e ] 28.31 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":28704768,"total":39081844},"progress":"[====================================\u003e ] 28.7 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":29097984,"total":39081844},"progress":"[=====================================\u003e ] 29.1 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":29491200,"total":39081844},"progress":"[=====================================\u003e ] 29.49 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":29884416,"total":39081844},"progress":"[======================================\u003e ] 29.88 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":30277632,"total":39081844},"progress":"[======================================\u003e ] 30.28 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":30670848,"total":39081844},"progress":"[=======================================\u003e ] 30.67 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":31064064,"total":39081844},"progress":"[=======================================\u003e ] 31.06 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":31457280,"total":39081844},"progress":"[========================================\u003e ] 31.46 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":31850496,"total":39081844},"progress":"[========================================\u003e ] 31.85 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":32243712,"total":39081844},"progress":"[=========================================\u003e ] 32.24 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":32636928,"total":39081844},"progress":"[=========================================\u003e ] 32.64 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":33030144,"total":39081844},"progress":"[==========================================\u003e ] 33.03 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":33423360,"total":39081844},"progress":"[==========================================\u003e ] 33.42 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":33816576,"total":39081844},"progress":"[===========================================\u003e ] 33.82 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":34209792,"total":39081844},"progress":"[===========================================\u003e ] 34.21 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":34603008,"total":39081844},"progress":"[============================================\u003e ] 34.6 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":34996224,"total":39081844},"progress":"[============================================\u003e ] 35 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":35389440,"total":39081844},"progress":"[=============================================\u003e ] 35.39 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":35782656,"total":39081844},"progress":"[=============================================\u003e ] 35.78 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":36175872,"total":39081844},"progress":"[==============================================\u003e ] 36.18 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":36569088,"total":39081844},"progress":"[==============================================\u003e ] 36.57 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":36962304,"total":39081844},"progress":"[===============================================\u003e ] 36.96 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":37355520,"total":39081844},"progress":"[===============================================\u003e ] 37.36 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":37748736,"total":39081844},"progress":"[================================================\u003e ] 37.75 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":38141952,"total":39081844},"progress":"[================================================\u003e ] 38.14 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":38535168,"total":39081844},"progress":"[=================================================\u003e ] 38.54 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":38928384,"total":39081844},"progress":"[=================================================\u003e ] 38.93 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":39081844,"total":39081844},"progress":"[==================================================\u003e] 39.08 MB/39.08 MB","id":"36cef014d5d4"} {"status":"Pull complete","progressDetail":{},"id":"36cef014d5d4"} {"status":"Extracting","progressDetail":{"current":32768,"total":57935},"progress":"[============================\u003e ] 32.77 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Extracting","progressDetail":{"current":57935,"total":57935},"progress":"[==================================================\u003e] 57.94 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Extracting","progressDetail":{"current":57935,"total":57935},"progress":"[==================================================\u003e] 57.94 kB/57.94 kB","id":"0d99ad4de1d2"} {"status":"Pull complete","progressDetail":{},"id":"0d99ad4de1d2"} {"status":"Extracting","progressDetail":{"current":419,"total":419},"progress":"[==================================================\u003e] 419 B/419 B","id":"3e32dbf1ab94"} {"status":"Extracting","progressDetail":{"current":419,"total":419},"progress":"[==================================================\u003e] 419 B/419 B","id":"3e32dbf1ab94"} {"status":"Pull complete","progressDetail":{},"id":"3e32dbf1ab94"} {"status":"Extracting","progressDetail":{"current":682,"total":682},"progress":"[==================================================\u003e] 682 B/682 B","id":"44710c456ffc"} {"status":"Extracting","progressDetail":{"current":682,"total":682},"progress":"[==================================================\u003e] 682 B/682 B","id":"44710c456ffc"} {"status":"Pull complete","progressDetail":{},"id":"44710c456ffc"} {"status":"Extracting","progressDetail":{"current":162,"total":162},"progress":"[==================================================\u003e] 162 B/162 B","id":"56e70ac3b314"} {"status":"Extracting","progressDetail":{"current":162,"total":162},"progress":"[==================================================\u003e] 162 B/162 B","id":"56e70ac3b314"} {"status":"Pull complete","progressDetail":{},"id":"56e70ac3b314"} {"status":"Digest: sha256:992069aee4016783df6345315302fa59681aae51a8eeb2f889dea59290f21787"} {"status":"Status: Downloaded newer image for ubuntu:12.04"}apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/mac_124/search.json0000664000175000017500000001150313535474530027600 0ustar kamikami00000000000000[{ "star_count": 2558, "is_official": true, "name": "mysql", "is_automated": false, "description": "MySQL is a widely used, open-source relational database management system (RDBMS)." }, { "star_count": 164, "is_official": false, "name": "mysql/mysql-server", "is_automated": true, "description": "Optimized MySQL Server Docker images. Created, maintained and supported by the MySQL team at Oracle" }, { "star_count": 0, "is_official": false, "name": "tozd/mysql", "is_automated": true, "description": "MySQL (MariaDB fork) Docker image." }, { "star_count": 45, "is_official": false, "name": "centurylink/mysql", "is_automated": true, "description": "Image containing mysql. Optimized to be linked to another image/container." }, { "star_count": 8, "is_official": false, "name": "appcontainers/mysql", "is_automated": true, "description": "Centos/Debian Based Customizable MySQL Container - Updated 06/16/2016" }, { "star_count": 2, "is_official": false, "name": "alterway/mysql", "is_automated": true, "description": "Docker Mysql" }, { "star_count": 2, "is_official": false, "name": "drupaldocker/mysql", "is_automated": true, "description": "MySQL for Drupal" }, { "star_count": 2, "is_official": false, "name": "yfix/mysql", "is_automated": true, "description": "Yfix docker built mysql" }, { "star_count": 1, "is_official": false, "name": "phpmentors/mysql", "is_automated": true, "description": "MySQL server image" }, { "star_count": 0, "is_official": false, "name": "cloudposse/mysql", "is_automated": true, "description": "Improved `mysql` service with support for `mysqld_safe` and `fixtures` loaded from `mysqldump.sql`" }, { "star_count": 0, "is_official": false, "name": "nanobox/mysql", "is_automated": true, "description": "MySQL service for nanobox.io" }, { "star_count": 36, "is_official": false, "name": "sameersbn/mysql", "is_automated": true, "description": "" }, { "star_count": 0, "is_official": false, "name": "vukor/mysql", "is_automated": true, "description": "Build for MySQL. Project available on https://github.com/vukor/docker-web-stack" }, { "star_count": 6, "is_official": false, "name": "marvambass/mysql", "is_automated": true, "description": "MySQL Server based on Ubuntu 14.04" }, { "star_count": 0, "is_official": false, "name": "lancehudson/docker-mysql", "is_automated": true, "description": "MySQL is a widely used, open-source relational database management system (RDBMS)." }, { "star_count": 1, "is_official": false, "name": "sin30/mysql", "is_automated": true, "description": "MySQL images with my own config files." }, { "star_count": 2, "is_official": false, "name": "azukiapp/mysql", "is_automated": true, "description": "Docker image to run MySQL by Azuki - http://azk.io" }, { "star_count": 1, "is_official": false, "name": "kaluzki/mysql", "is_automated": true, "description": "mysql" }, { "star_count": 0, "is_official": false, "name": "livingobjects/mysql", "is_automated": true, "description": "MySQL" }, { "star_count": 0, "is_official": false, "name": "akilli/mysql", "is_automated": true, "description": "akilli/base based MySQL image" }, { "star_count": 0, "is_official": false, "name": "projectomakase/mysql", "is_automated": true, "description": "Docker image for MySQL" }, { "star_count": 1, "is_official": false, "name": "tetraweb/mysql", "is_automated": true, "description": "" }, { "star_count": 0, "is_official": false, "name": "dockerizedrupal/mysql", "is_automated": true, "description": "docker-mysql" }, { "star_count": 1, "is_official": false, "name": "debezium/example-mysql", "is_automated": true, "description": "Example MySQL database server with a simple Inventory database, useful for demos and tutorials." }, { "star_count": 16, "is_official": false, "name": "google/mysql", "is_automated": true, "description": "MySQL server for Google Compute Engine" } ]apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker/mac_124/version.json0000664000175000017500000000041713535474530030022 0ustar kamikami00000000000000{ "Version": "1.12.0-rc2", "ApiVersion": "1.24", "GitCommit": "a7119de", "GoVersion": "go1.6.2", "Os": "linux", "Arch": "amd64", "KernelVersion": "4.4.13-moby", "Experimental": true, "BuildTime": "2016-06-17T22:09:20.440355664+00:00" }apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker_utils/0000775000175000017500000000000013600223624025517 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu.jsonapache-libcloud-2.8.0/libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu.j0000664000175000017500000001464713535474530034205 0ustar kamikami00000000000000{ "user": "library", "name": "ubuntu", "namespace": "library", "status": 1, "description": "Ubuntu is a Debian-based Linux operating system based on free software.", "is_private": false, "is_automated": false, "can_edit": false, "star_count": 2954, "pull_count": 37627788, "last_updated": "2016-01-04T19:00:53.547174Z", "has_starred": false, "full_description": "# Supported tags and respective `Dockerfile` links\n\n-\t[`12.04.5`, `12.04`, `precise-20151208`, `precise` (*precise/Dockerfile*)](https://github.com/tianon/docker-brew-ubuntu-core/blob/d7f2045ad9b08962d9728f6d9910fa252282b85f/precise/Dockerfile)\n-\t[`14.04.3`, `14.04`, `trusty-20151218`, `trusty`, `latest` (*trusty/Dockerfile*)](https://github.com/tianon/docker-brew-ubuntu-core/blob/d7f2045ad9b08962d9728f6d9910fa252282b85f/trusty/Dockerfile)\n-\t[`15.04`, `vivid-20151208`, `vivid` (*vivid/Dockerfile*)](https://github.com/tianon/docker-brew-ubuntu-core/blob/d7f2045ad9b08962d9728f6d9910fa252282b85f/vivid/Dockerfile)\n-\t[`15.10`, `wily-20151208`, `wily` (*wily/Dockerfile*)](https://github.com/tianon/docker-brew-ubuntu-core/blob/d7f2045ad9b08962d9728f6d9910fa252282b85f/wily/Dockerfile)\n-\t[`16.04`, `xenial-20151218.1`, `xenial` (*xenial/Dockerfile*)](https://github.com/tianon/docker-brew-ubuntu-core/blob/d7f2045ad9b08962d9728f6d9910fa252282b85f/xenial/Dockerfile)\n\nFor more information about this image and its history, please see [the relevant manifest file (`library/ubuntu`)](https://github.com/docker-library/official-images/blob/master/library/ubuntu). This image is updated via pull requests to [the `docker-library/official-images` GitHub repo](https://github.com/docker-library/official-images).\n\nFor detailed information about the virtual/transfer sizes and individual layers of each of the above supported tags, please see [the `ubuntu/tag-details.md` file](https://github.com/docker-library/docs/blob/master/ubuntu/tag-details.md) in [the `docker-library/docs` GitHub repo](https://github.com/docker-library/docs).\n\n# What is Ubuntu?\n\nUbuntu is a Debian-based Linux operating system, with Unity as its default desktop environment. It is based on free software and named after the Southern African philosophy of ubuntu (literally, \"human-ness\"), which often is translated as \"humanity towards others\" or \"the belief in a universal bond of sharing that connects all humanity\".\n\nDevelopment of Ubuntu is led by UK-based Canonical Ltd., a company owned by South African entrepreneur Mark Shuttleworth. Canonical generates revenue through the sale of technical support and other services related to Ubuntu. The Ubuntu project is publicly committed to the principles of open-source software development; people are encouraged to use free software, study how it works, improve upon it, and distribute it.\n\n> [wikipedia.org/wiki/Ubuntu_(operating_system)](https://en.wikipedia.org/wiki/Ubuntu_%28operating_system%29)\n\n![logo](https://raw.githubusercontent.com/docker-library/docs/01c12653951b2fe592c1f93a13b4e289ada0e3a1/ubuntu/logo.png)\n\n# What's in this image?\n\n## `/etc/apt/sources.list`\n\n### `ubuntu:14.04`\n\n```console\n$ docker run ubuntu:14.04 grep -v '^#' /etc/apt/sources.list\n\ndeb http://archive.ubuntu.com/ubuntu/ trusty main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ trusty universe\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty universe\ndeb http://archive.ubuntu.com/ubuntu/ trusty-updates universe\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty-updates universe\n\n\ndeb http://archive.ubuntu.com/ubuntu/ trusty-security main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty-security main restricted\ndeb http://archive.ubuntu.com/ubuntu/ trusty-security universe\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty-security universe\n```\n\n### `ubuntu:12.04`\n\n```console\n$ docker run ubuntu:12.04 cat /etc/apt/sources.list\n\ndeb http://archive.ubuntu.com/ubuntu/ precise main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ precise main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ precise-updates main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ precise-updates main restricted\n\ndeb http://archive.ubuntu.com/ubuntu/ precise universe\ndeb-src http://archive.ubuntu.com/ubuntu/ precise universe\ndeb http://archive.ubuntu.com/ubuntu/ precise-updates universe\ndeb-src http://archive.ubuntu.com/ubuntu/ precise-updates universe\n\n\ndeb http://archive.ubuntu.com/ubuntu/ precise-security main restricted\ndeb-src http://archive.ubuntu.com/ubuntu/ precise-security main restricted\ndeb http://archive.ubuntu.com/ubuntu/ precise-security universe\ndeb-src http://archive.ubuntu.com/ubuntu/ precise-security universe\n```\n\n# Supported Docker versions\n\nThis image is officially supported on Docker version 1.9.1.\n\nSupport for older versions (down to 1.6) is provided on a best-effort basis.\n\nPlease see [the Docker installation documentation](https://docs.docker.com/installation/) for details on how to upgrade your Docker daemon.\n\n# User Feedback\n\n## Documentation\n\nDocumentation for this image is stored in the [`ubuntu/` directory](https://github.com/docker-library/docs/tree/master/ubuntu) of the [`docker-library/docs` GitHub repo](https://github.com/docker-library/docs). Be sure to familiarize yourself with the [repository's `README.md` file](https://github.com/docker-library/docs/blob/master/README.md) before attempting a pull request.\n\n## Issues\n\nIf you have any problems with or questions about this image, please contact us through a [GitHub issue](https://github.com/tianon/docker-brew-ubuntu-core/issues).\n\nYou can also reach many of the official image maintainers via the `#docker-library` IRC channel on [Freenode](https://freenode.net).\n\n## Contributing\n\nYou are invited to contribute new features, fixes, or updates, large or small; we are always thrilled to receive pull requests, and do our best to process them as fast as we can.\n\nBefore you start to code, we recommend discussing your plans through a [GitHub issue](https://github.com/tianon/docker-brew-ubuntu-core/issues), especially for more ambitious contributions. This gives other contributors a chance to point you in the right direction, give you feedback on your design, and help you find out if someone else is working on the same thing." }././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu_tags.jsonapache-libcloud-2.8.0/libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu_t0000664000175000017500000005253713535474530034300 0ustar kamikami00000000000000{ "count": 88, "next": null, "previous": null, "results": [ { "name": "xenial", "full_size": 47439662, "id": 1589976, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T19:00:51.344198Z", "image_id": null, "v2": true }, { "name": "xenial-20151218.1", "full_size": 47439662, "id": 1589974, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T19:00:45.326998Z", "image_id": null, "v2": true }, { "name": "16.04", "full_size": 47439662, "id": 1589970, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T19:00:39.215205Z", "image_id": null, "v2": true }, { "name": "wily", "full_size": 50294202, "id": 2332, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T19:00:30.141301Z", "image_id": null, "v2": true }, { "name": "wily-20151208", "full_size": 50294202, "id": 1509180, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T19:00:24.324323Z", "image_id": null, "v2": true }, { "name": "15.10", "full_size": 50294202, "id": 2327, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T19:00:18.625895Z", "image_id": null, "v2": true }, { "name": "vivid", "full_size": 49334628, "id": 2329, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T19:00:12.764756Z", "image_id": null, "v2": true }, { "name": "vivid-20151208", "full_size": 49334628, "id": 1509158, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T19:00:07.282476Z", "image_id": null, "v2": true }, { "name": "15.04", "full_size": 49334628, "id": 2298, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T19:00:01.659187Z", "image_id": null, "v2": true }, { "name": "latest", "full_size": 65747044, "id": 2343, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T18:59:54.779484Z", "image_id": null, "v2": true }, { "name": "trusty", "full_size": 65747044, "id": 2305, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T18:59:49.102906Z", "image_id": null, "v2": true }, { "name": "trusty-20151218", "full_size": 65747044, "id": 1657173, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T18:59:43.103725Z", "image_id": null, "v2": true }, { "name": "14.04", "full_size": 65747044, "id": 2324, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T18:59:37.496154Z", "image_id": null, "v2": true }, { "name": "14.04.3", "full_size": 65747044, "id": 693829, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T18:58:46.261151Z", "image_id": null, "v2": true }, { "name": "precise", "full_size": 44194573, "id": 2292, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T18:57:33.494399Z", "image_id": null, "v2": true }, { "name": "precise-20151208", "full_size": 44194573, "id": 1509115, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2016-01-04T18:57:22.912930Z", "image_id": null, "v2": true }, { "name": "12.04", "full_size": 44194573, "id": 2310, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T18:57:14.495660Z", "image_id": null, "v2": true }, { "name": "12.04.5", "full_size": 44194573, "id": 2295, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T18:57:08.237857Z", "image_id": null, "v2": true }, { "name": "trusty-20151208", "full_size": 65742980, "id": 1509143, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-12-18T18:26:56.770757Z", "image_id": null, "v2": true }, { "name": "wily-20151019", "full_size": 49817335, "id": 1168566, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-12-08T09:04:03.336941Z", "image_id": null, "v2": true }, { "name": "vivid-20151111", "full_size": 49333876, "id": 1389462, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-12-08T09:02:56.243906Z", "image_id": null, "v2": true }, { "name": "trusty-20151028", "full_size": 65742789, "id": 1313714, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-12-08T09:02:32.340602Z", "image_id": null, "v2": true }, { "name": "precise-20151028", "full_size": 44096878, "id": 1313721, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-12-08T09:02:07.834932Z", "image_id": null, "v2": true }, { "name": "vivid-20151106", "full_size": 49329280, "id": 1313735, "repository": 130, "creator": 2215, "last_updater": 213249, "last_updated": "2015-11-21T01:14:52.126272Z", "image_id": null, "v2": true }, { "name": "12.10", "full_size": 58078433, "id": 2339, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:42:40.878495Z", "image_id": null, "v2": true }, { "name": "trusty-20150218.1", "full_size": 65832655, "id": 2325, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:42:29.777917Z", "image_id": null, "v2": true }, { "name": "utopic-20150211", "full_size": 68374766, "id": 2307, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:41:34.805100Z", "image_id": null, "v2": true }, { "name": "quantal", "full_size": 58078433, "id": 2341, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:40:29.962553Z", "image_id": null, "v2": true }, { "name": "14.04.1", "full_size": 65827193, "id": 2322, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:39:42.479726Z", "image_id": null, "v2": true }, { "name": "raring", "full_size": 57667348, "id": 2316, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:38:47.745980Z", "image_id": null, "v2": true }, { "name": "vivid-20150218", "full_size": 44122689, "id": 2320, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:38:37.964774Z", "image_id": null, "v2": true }, { "name": "vivid-20150309", "full_size": 49448856, "id": 2317, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:37:59.209284Z", "image_id": null, "v2": true }, { "name": "10.04", "full_size": 63533781, "id": 2299, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:37:16.010344Z", "image_id": null, "v2": true }, { "name": "saucy", "full_size": 60522580, "id": 2301, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:37:04.113916Z", "image_id": null, "v2": true }, { "name": "precise-20150228.11", "full_size": 43657047, "id": 2331, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:36:51.552688Z", "image_id": null, "v2": true }, { "name": "utopic-20150228.11", "full_size": 68379536, "id": 2318, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:36:02.986916Z", "image_id": null, "v2": true }, { "name": "13.10", "full_size": 60522580, "id": 2304, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:34:52.333445Z", "image_id": null, "v2": true }, { "name": "13.04", "full_size": 57667348, "id": 2294, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:33:49.391093Z", "image_id": null, "v2": true }, { "name": "precise-20150212", "full_size": 43616335, "id": 2340, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:32:59.135708Z", "image_id": null, "v2": true }, { "name": "trusty-20150228.11", "full_size": 65828716, "id": 2323, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:32:14.798440Z", "image_id": null, "v2": true }, { "name": "lucid", "full_size": 63533781, "id": 2321, "repository": 130, "creator": 7, "last_updater": 134455, "last_updated": "2015-11-14T14:31:11.758283Z", "image_id": null, "v2": true }, { "name": "vivid-20151021", "full_size": 49328003, "id": 1168551, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-10-28T12:21:31.210637Z", "image_id": null, "v2": true }, { "name": "trusty-20151021", "full_size": 65741561, "id": 1168539, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-10-28T12:21:07.780326Z", "image_id": null, "v2": true }, { "name": "precise-20151020", "full_size": 44096883, "id": 1168524, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": "2015-10-28T12:20:39.816211Z", "image_id": null, "v2": true }, { "name": "wily-20151009", "full_size": 49844614, "id": 1096696, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20151009", "full_size": 65861875, "id": 1096682, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "wily-20151006", "full_size": 49861095, "id": 1081815, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "vivid-20150930", "full_size": 49345386, "id": 1081804, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20151001", "full_size": 65757468, "id": 1081789, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "precise-20150924", "full_size": 44037965, "id": 1081772, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "wily-20150829", "full_size": 49614664, "id": 828778, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "wily-20150818", "full_size": 50298307, "id": 778618, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "precise-20150813", "full_size": 43977816, "id": 776393, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "vivid-20150813", "full_size": 49343696, "id": 776144, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20150814", "full_size": 65859249, "id": 775535, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "wily-20150807", "full_size": 50528668, "id": 693839, "repository": 130, "creator": 2215, "last_updater": 213249, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20150806", "full_size": 65857914, "id": 693834, "repository": 130, "creator": 2215, "last_updater": 213249, "last_updated": null, "image_id": null, "v2": true }, { "name": "wily-20150731", "full_size": 50488452, "id": 674054, "repository": 130, "creator": 2215, "last_updater": 213249, "last_updated": null, "image_id": null, "v2": true }, { "name": "vivid-20150802", "full_size": 49340063, "id": 674043, "repository": 130, "creator": 2215, "last_updater": 213249, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20150730", "full_size": 65860360, "id": 674034, "repository": 130, "creator": 2215, "last_updater": 213249, "last_updated": null, "image_id": null, "v2": true }, { "name": "precise-20150729", "full_size": 43967445, "id": 674016, "repository": 130, "creator": 2215, "last_updater": 213249, "last_updated": null, "image_id": null, "v2": true }, { "name": "wily-20150708", "full_size": 50494409, "id": 541269, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "utopic-20150625", "full_size": 68399747, "id": 541258, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20150630", "full_size": 65858138, "id": 541253, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "precise-20150626", "full_size": 43878461, "id": 541246, "repository": 130, "creator": 2215, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "vivid-20150528", "full_size": 131333439, "id": 2338, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "utopic-20150528", "full_size": 194454267, "id": 2337, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "utopic", "full_size": 68399747, "id": 2336, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "precise-20150528", "full_size": 133416464, "id": 2335, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "utopic-20150319", "full_size": 194424279, "id": 2334, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "utopic-20150418", "full_size": 194463410, "id": 2333, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "precise-20150427", "full_size": 132465012, "id": 2330, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "trusty-20150612", "full_size": 188284994, "id": 2328, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "wily-20150528.1", "full_size": 132392276, "id": 2326, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "vivid-20150319.1", "full_size": 131685773, "id": 2315, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "14.04.2", "full_size": 65860360, "id": 2314, "repository": 130, "creator": 7, "last_updater": 213249, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20150528", "full_size": 188281989, "id": 2313, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "precise-20150612", "full_size": 133706040, "id": 2312, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "trusty-20150320", "full_size": 188300556, "id": 2311, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "vivid-20150611", "full_size": 49338475, "id": 2309, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "trusty-20150427", "full_size": 188278440, "id": 2308, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "wily-20150611", "full_size": 133648792, "id": 2306, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "utopic-20150612", "full_size": 194462706, "id": 2303, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "utopic-20150427", "full_size": 194461653, "id": 2302, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "precise-20150320", "full_size": 131886863, "id": 2300, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "14.10", "full_size": 68399747, "id": 2297, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": null, "image_id": null, "v2": true }, { "name": "vivid-20150427", "full_size": 131302888, "id": 2296, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false }, { "name": "vivid-20150421", "full_size": 131279915, "id": 2293, "repository": 130, "creator": 7, "last_updater": 7, "last_updated": null, "image_id": null, "v2": false } ] }././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu_tags_latest.jsonapache-libcloud-2.8.0/libcloud/test/container/fixtures/docker_utils/v2_repositories_library_ubuntu_t0000664000175000017500000000031513535474530034263 0ustar kamikami00000000000000{ "name": "latest", "full_size": 65747044, "id": 2343, "repository": 130, "creator": 7, "last_updater": 2215, "last_updated": "2016-01-04T18:59:54.779484Z", "image_id": null, "v2": true }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/0000775000175000017500000000000013600223624023602 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/createcluster.json0000664000175000017500000000050013535474530027350 0ustar kamikami00000000000000{ "cluster": { "activeServicesCount": 0, "clusterArn": "arn:aws:ecs:ap-southeast-2:647433528374:cluster/my-cluster", "clusterName": "my-cluster", "pendingTasksCount": 0, "registeredContainerInstancesCount": 0, "runningTasksCount": 0, "status": "ACTIVE" } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/createservice.json0000664000175000017500000000156513535474530027343 0ustar kamikami00000000000000{ "service": { "clusterArn": "arn:aws:ecs:us-east-1:012345678910:cluster/default", "deploymentConfiguration": { "maximumPercent": 200, "minimumHealthyPercent": 100 }, "deployments": [ { "createdAt": 1430326887.362, "desiredCount": 10, "id": "ecs-svc/9223370606527888445", "pendingCount": 0, "runningCount": 0, "status": "PRIMARY", "taskDefinition": "arn:aws:ecs:us-east-1:012345678910:task-definition/ecs-demo:1", "updatedAt": 1430326887.362 } ], "desiredCount": 10, "events": [], "loadBalancers": [], "pendingCount": 0, "runningCount": 0, "serviceArn": "arn:aws:ecs:us-east-1:012345678910:service/test", "serviceName": "test", "status": "ACTIVE", "taskDefinition": "arn:aws:ecs:us-east-1:012345678910:task-definition/ecs-demo:1" } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/deletecluster.json0000664000175000017500000000050213535474530027351 0ustar kamikami00000000000000{ "cluster": { "activeServicesCount": 0, "clusterArn": "arn:aws:ecs:ap-southeast-2:647433528374:cluster/my-cluster", "clusterName": "my-cluster", "pendingTasksCount": 0, "registeredContainerInstancesCount": 0, "runningTasksCount": 0, "status": "INACTIVE" } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/deleteservice.json0000664000175000017500000000156713535474530027344 0ustar kamikami00000000000000{ "service": { "clusterArn": "arn:aws:ecs:us-east-1:012345678910:cluster/default", "deploymentConfiguration": { "maximumPercent": 200, "minimumHealthyPercent": 100 }, "deployments": [ { "createdAt": 1430320735.285, "desiredCount": 0, "id": "ecs-svc/9223370606534040511", "pendingCount": 0, "runningCount": 0, "status": "PRIMARY", "taskDefinition": "arn:aws:ecs:us-east-1:012345678910:task-definition/sleep360:27", "updatedAt": 1430320735.285 } ], "desiredCount": 0, "events": [], "loadBalancers": [], "pendingCount": 0, "runningCount": 0, "serviceArn": "arn:aws:ecs:us-east-1:012345678910:service/test", "serviceName": "test", "status": "DRAINING", "taskDefinition": "arn:aws:ecs:us-east-1:012345678910:task-definition/sleep360:27" } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/describeclusters.json0000664000175000017500000000050213535474530030052 0ustar kamikami00000000000000{ "clusters": [ { "activeServicesCount": 1, "clusterArn": "arn:aws:ecs:us-east-1:012345678910:cluster/default", "clusterName": "default", "pendingTasksCount": 0, "registeredContainerInstancesCount": 0, "runningTasksCount": 0, "status": "ACTIVE" } ], "failures": [] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/describerepositories.json0000664000175000017500000000032613535474530030741 0ustar kamikami00000000000000{ "repositories": [{ "registryId": "647433528374", "repositoryArn": "arn:aws:ecr:us-east-1:647433528374:repository/my-images", "repositoryName": "my-images" } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/describeservices.json0000664000175000017500000000173513535474530030042 0ustar kamikami00000000000000{ "failures": [], "services": [ { "clusterArn": "arn:aws:ecs:us-west-2:012345678910:cluster/telemetry", "deploymentConfiguration": { "maximumPercent": 200, "minimumHealthyPercent": 100 }, "deployments": [ { "createdAt": 1432829320.611, "desiredCount": 4, "id": "ecs-svc/9223370604025455196", "pendingCount": 0, "runningCount": 4, "status": "PRIMARY", "taskDefinition": "arn:aws:ecs:us-west-2:012345678910:task-definition/hpcc-t2-medium:1", "updatedAt": 1432829320.611 } ], "desiredCount": 4, "events": [], "loadBalancers": [], "pendingCount": 0, "runningCount": 4, "serviceArn": "arn:aws:ecs:us-west-2:012345678910:service/bunker-buster", "serviceName": "test", "status": "ACTIVE", "taskDefinition": "arn:aws:ecs:us-west-2:012345678910:task-definition/hpcc-t2-medium:1" } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/describetasks.json0000664000175000017500000000302513535474530027336 0ustar kamikami00000000000000{ "failures": [], "tasks": [{ "clusterArn": "arn:aws:ecs:ap-southeast-2:647433528374:cluster/default", "containerInstanceArn": "arn:aws:ecs:ap-southeast-2:647433528374:container-instance/13b83f4b-d557-48a6-a4d7-2b0e8068e62b", "containers": [{ "containerArn": "arn:aws:ecs:ap-southeast-2:647433528374:container/d56d4e2c-9804-42a7-9f2a-6029cb50d4a2", "lastStatus": "RUNNING", "name": "simple-app", "networkBindings": [{ "bindIP": "0.0.0.0", "containerPort": 80, "hostPort": 80, "protocol": "tcp" } ], "taskArn": "arn:aws:ecs:ap-southeast-2:647433528374:task/c15bcab8-39e6-4c28-a47d-27b433269e5c" } ], "createdAt": 1.451468104403E9, "desiredStatus": "RUNNING", "lastStatus": "RUNNING", "overrides": { "containerOverrides": [{ "name": "simple-app" } ] }, "startedAt": 1.45146812139E9, "startedBy": "ecs-svc/9223370585386692588", "taskArn": "arn:aws:ecs:ap-southeast-2:647433528374:task/c15bcab8-39e6-4c28-a47d-27b433269e5c", "taskDefinitionArn": "arn:aws:ecs:ap-southeast-2:647433528374:task-definition/console-sample-app-static:1" } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/getauthorizationtoken.json0000664000175000017500000000032713535474530031153 0ustar kamikami00000000000000{ "authorizationData": [ { "authorizationToken": "QVdTOkNpQzErSHF1ZXZPcUR...", "expiresAt": 1448878779.809, "proxyEndpoint": "https://012345678910.dkr.ecr.us-east-1.amazonaws.com" } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/listclusters.json0000664000175000017500000000021013535474530027241 0ustar kamikami00000000000000{"clusterArns":["arn:aws:ecs:ap-southeast-2:647433528374:cluster/my-cluster","arn:aws:ecs:ap-southeast-2:647433528374:cluster/default"]}apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/listimages.json0000664000175000017500000000025513535474530026653 0ustar kamikami00000000000000{ "imageIds": [{ "imageDigest": "sha256:9bacaf947ed397fcc9afb7359a1a8eaa1f6944ba8cd4ddca1c69bdcf4acf12a2", "imageTag": "latest" } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/listservices.json0000664000175000017500000000023413535474530027226 0ustar kamikami00000000000000{ "serviceArns": [ "arn:aws:ecs:us-east-1:012345678910:service/hello_world", "arn:aws:ecs:us-east-1:012345678910:service/ecs-simple-service" ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/listtasks.json0000664000175000017500000000054613535474530026536 0ustar kamikami00000000000000{ "taskArns": [ "arn:aws:ecs:us-east-1:012345678910:task/0b69d5c0-d655-4695-98cd-5d2d526d9d5a", "arn:aws:ecs:us-east-1:012345678910:task/51a01bdf-d00e-487e-ab14-7645330b6207", "arn:aws:ecs:us-east-1:012345678910:task/b0b28bb8-2be3-4810-b52b-88df129d893c", "arn:aws:ecs:us-east-1:012345678910:task/c09f0188-7f87-4b0f-bfc3-16296622b6fe" ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/registertaskdefinition.json0000664000175000017500000000115213535474530031267 0ustar kamikami00000000000000{ "taskDefinition": { "containerDefinitions": [{ "cpu": 10, "environment": [], "essential": true, "image": "simple-app", "memory": 500, "mountPoints": [], "name": "my-simple-app", "portMappings": [], "volumesFrom": [] } ], "family": "my-simple-app", "revision": 1, "status": "ACTIVE", "taskDefinitionArn": "arn:aws:ecs:ap-southeast-2:647433528374:task-definition/my-simple-app:1", "volumes": [] } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/runtask.json0000664000175000017500000000222513535474530026200 0ustar kamikami00000000000000{ "failures": [], "tasks": [{ "clusterArn": "arn:aws:ecs:ap-southeast-2:647433528374:cluster/default", "containerInstanceArn": "arn:aws:ecs:ap-southeast-2:647433528374:container-instance/13b83f4b-d557-48a6-a4d7-2b0e8068e62b", "containers": [{ "containerArn": "arn:aws:ecs:ap-southeast-2:647433528374:container/e443d10f-dea3-481e-8a1e-966b9ad4e498", "lastStatus": "PENDING", "name": "my-simple-app", "taskArn": "arn:aws:ecs:ap-southeast-2:647433528374:task/b7c76236-b96f-4de1-93c8-9da3c30ccc23" } ], "createdAt": 1.45181726008E9, "desiredStatus": "RUNNING", "lastStatus": "PENDING", "overrides": { "containerOverrides": [{ "name": "my-simple-app" } ] }, "taskArn": "arn:aws:ecs:ap-southeast-2:647433528374:task/b7c76236-b96f-4de1-93c8-9da3c30ccc23", "taskDefinitionArn": "arn:aws:ecs:ap-southeast-2:647433528374:task-definition/my-simple-app:1" } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/ecs/stoptask.json0000664000175000017500000000257613535474530026372 0ustar kamikami00000000000000{ "task": { "clusterArn": "arn:aws:ecs:us-east-1:012345678910:cluster/default", "containerInstanceArn": "arn:aws:ecs:us-east-1:012345678910:container-instance/8db248d6-16a7-42b5-b9f9-43d3b1ad9430", "containers": [ { "containerArn": "arn:aws:ecs:us-east-1:012345678910:container/05a5528c-77f6-4e5b-8f9a-2b0a1928a926", "lastStatus": "RUNNING", "name": "mysql", "networkBindings": [], "taskArn": "arn:aws:ecs:us-east-1:012345678910:task/a126249b-b7e4-4b06-9d8f-1b56e75a99b5" }, { "containerArn": "arn:aws:ecs:us-east-1:012345678910:container/37234a82-77f6-41d7-b54b-591f1e278093", "lastStatus": "RUNNING", "name": "wordpress", "networkBindings": [ { "bindIP": "0.0.0.0", "containerPort": 80, "hostPort": 80 } ], "taskArn": "arn:aws:ecs:us-east-1:012345678910:task/a126249b-b7e4-4b06-9d8f-1b56e75a99b5" } ], "desiredStatus": "STOPPED", "lastStatus": "RUNNING", "overrides": { "containerOverrides": [ { "name": "mysql" }, { "name": "wordpress" } ] }, "taskArn": "arn:aws:ecs:us-east-1:012345678910:task/a126249b-b7e4-4b06-9d8f-1b56e75a99b5", "taskDefinitionArn": "arn:aws:ecs:us-east-1:012345678910:task-definition/hello_world:11" } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/gke/0000775000175000017500000000000013600223624023576 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/gke/zones_us-central1-a_instance_serverconfig.jsonapache-libcloud-2.8.0/libcloud/test/container/fixtures/gke/zones_us-central1-a_instance_serverconfig0000664000175000017500000000033113535474530033763 0ustar kamikami00000000000000{"validImageTypes": ["CONTAINER_VM", "COS"], "validNodeVersions": ["1.6.4", "1.6.2", "1.5.7", "1.5.6", "1.4.9"], "defaultClusterVersion": "1.6.4", "validMasterVersions": ["1.6.4", "1.5.7"], "defaultImageType": "COS"} apache-libcloud-2.8.0/libcloud/test/container/fixtures/gke/zones_us-central1-a_list.json0000664000175000017500000000177513535474530031343 0ustar kamikami00000000000000{"clusters": [{ "currentMasterVersion": "1.6.4", "currentNodeCount": 3, "currentNodeVersion": "1.6.4", "initialClusterVersion": "1.6.4", "locations": ["us-central1-a"], "loggingService": "logging.googleapis.com", "name": "cluster-1", "network": "default", "nodeConfig": {"diskSizeGb": 100, "imageType": "COS", "machineType": "n1-standard-1", "oauthScopes": ["https://www.googleapis.com/auth/compute"], "serviceAccount": "default"}, "nodeIpv4CidrSize": 24, "nodePools": [{"autoscaling": {}, "config": {"diskSizeGb": 100, "serviceAccount": "default"}, "initialNodeCount": 3, "instanceGroupUrls": ["https://www.googleapis.com/compute/v1/projects/project_name"], "management": {}, "name": "default-pool", "status": "RUNNING", "version": "1.6.4"}], "selfLink": "https://container.googleapis.com/v1/projects/", "servicesIpv4Cidr": "XX.XX.XXX.X/20", "status": "RUNNING", "subnetwork": "default", "zone": "us-central1-a"}]} apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/0000775000175000017500000000000013600223624025177 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces.json0000664000175000017500000000165013535474530031624 0ustar kamikami00000000000000{ "kind": "NamespaceList", "apiVersion": "v1", "metadata": { "selfLink": "/api/v1/namespaces", "resourceVersion": "443" }, "items": [ { "metadata": { "name": "default", "selfLink": "/api/v1/namespaces/default", "uid": "43e99cf9-b99d-11e5-8d53-0050568157ec", "resourceVersion": "6", "creationTimestamp": "2016-01-13T02:28:00Z" }, "spec": { "finalizers": [ "kubernetes" ] }, "status": { "phase": "Active" } }, { "metadata": { "name": "test", "selfLink": "/api/v1/namespaces/test", "uid": "7cb89199-b9a6-11e5-8d53-0050568157ec", "resourceVersion": "419", "creationTimestamp": "2016-01-13T03:34:01Z" }, "spec": { "finalizers": [ "kubernetes" ] }, "status": { "phase": "Active" } } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default.json0000664000175000017500000000055713535474530033335 0ustar kamikami00000000000000{ "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "default", "selfLink": "/api/v1/namespaces/default", "uid": "43e99cf9-b99d-11e5-8d53-0050568157ec", "resourceVersion": "6", "creationTimestamp": "2016-01-13T02:28:00Z" }, "spec": { "finalizers": [ "kubernetes" ] }, "status": { "phase": "Active" } }././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default_DELETE.jsonapache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default_DELETE.0000664000175000017500000000064113535474530033457 0ustar kamikami00000000000000{ "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "test", "selfLink": "/api/v1/namespaces/test", "uid": "7cb89199-b9a6-11e5-8d53-0050568157ec", "resourceVersion": "447", "creationTimestamp": "2016-01-13T03:34:01Z", "deletionTimestamp": "2016-01-13T03:38:05Z" }, "spec": { "finalizers": [ "kubernetes" ] }, "status": { "phase": "Terminating" } }././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default_pods_POST.jsonapache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_default_pods_PO0000664000175000017500000000221213535474530033776 0ustar kamikami00000000000000{ "kind": "Pod", "apiVersion": "v1", "metadata": { "name": "hello-world", "namespace": "default", "selfLink": "/api/v1/namespaces/default/pods/hello-world", "uid": "1fad5411-b9af-11e5-8701-0050568157ec", "resourceVersion": "32", "creationTimestamp": "2016-01-13T04:35:50Z" }, "spec": { "volumes": [ { "name": "default-token-dpyh0", "secret": { "secretName": "default-token-dpyh0" } } ], "containers": [ { "name": "hello-world", "image": "ubuntu:14.04", "resources": {}, "volumeMounts": [ { "name": "default-token-dpyh0", "readOnly": true, "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" } ], "terminationMessagePath": "/dev/termination-log", "imagePullPolicy": "IfNotPresent" } ], "restartPolicy": "Always", "terminationGracePeriodSeconds": 30, "dnsPolicy": "ClusterFirst", "serviceAccountName": "default", "serviceAccount": "default", "securityContext": {} }, "status": { "phase": "Pending" } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_namespaces_test.json0000664000175000017500000000055313535474530032664 0ustar kamikami00000000000000{ "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "test", "selfLink": "/api/v1/namespaces/test", "uid": "7cb89199-b9a6-11e5-8d53-0050568157ec", "resourceVersion": "419", "creationTimestamp": "2016-01-13T03:34:01Z" }, "spec": { "finalizers": [ "kubernetes" ] }, "status": { "phase": "Active" } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_nodes.json0000664000175000017500000000436313535474530030621 0ustar kamikami00000000000000{ "kind": "NodeList", "apiVersion": "v1", "metadata": { "selfLink": "/api/v1/nodes", "resourceVersion": "24" }, "items": [ { "metadata": { "name": "127.0.0.1", "selfLink": "/api/v1/nodes/127.0.0.1", "uid": "45949cbb-b99d-11e5-8d53-0050568157ec", "resourceVersion": "24", "creationTimestamp": "2016-01-13T02:28:03Z", "labels": { "kubernetes.io/hostname": "127.0.0.1" } }, "spec": { "externalID": "127.0.0.1" }, "status": { "capacity": { "cpu": "2", "memory": "4048236Ki", "pods": "40" }, "allocatable": { "cpu": "2", "memory": "4048236Ki", "pods": "40" }, "conditions": [ { "type": "OutOfDisk", "status": "False", "lastHeartbeatTime": "2016-01-13T02:28:53Z", "lastTransitionTime": "2016-01-13T02:28:03Z", "reason": "KubeletHasSufficientDisk", "message": "kubelet has sufficient disk space available" }, { "type": "Ready", "status": "True", "lastHeartbeatTime": "2016-01-13T02:28:53Z", "lastTransitionTime": "2016-01-13T02:28:03Z", "reason": "KubeletReady", "message": "kubelet is posting ready status" } ], "addresses": [ { "type": "LegacyHostIP", "address": "127.0.0.1" }, { "type": "InternalIP", "address": "127.0.0.1" } ], "daemonEndpoints": { "kubeletEndpoint": { "Port": 10250 } }, "nodeInfo": { "machineID": "1d9faaba9168d4b4a3416e99000002a2", "systemUUID": "42015AA3-9AF2-D089-9105-63CEF89EFE35", "bootID": "c31fdd67-f995-4be5-942d-10df26b40501", "kernelVersion": "3.13.0-46-generic", "osImage": "Ubuntu 14.04.2 LTS", "containerRuntimeVersion": "docker://1.9.1", "kubeletVersion": "v1.2.0-alpha.5.848+3f2e99b7e7d6d8", "kubeProxyVersion": "v1.2.0-alpha.5.848+3f2e99b7e7d6d8" }, "images": null } } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_nodes_127_0_0_1.json0000664000175000017500000000355513535474530032072 0ustar kamikami00000000000000{ "kind": "Node", "apiVersion": "v1", "metadata": { "name": "127.0.0.1", "selfLink": "/api/v1/nodes/127.0.0.1", "uid": "45949cbb-b99d-11e5-8d53-0050568157ec", "resourceVersion": "184", "creationTimestamp": "2016-01-13T02:28:03Z", "labels": { "kubernetes.io/hostname": "127.0.0.1" } }, "spec": { "externalID": "127.0.0.1" }, "status": { "capacity": { "cpu": "2", "memory": "4048236Ki", "pods": "40" }, "allocatable": { "cpu": "2", "memory": "4048236Ki", "pods": "40" }, "conditions": [ { "type": "OutOfDisk", "status": "False", "lastHeartbeatTime": "2016-01-13T02:55:34Z", "lastTransitionTime": "2016-01-13T02:28:03Z", "reason": "KubeletHasSufficientDisk", "message": "kubelet has sufficient disk space available" }, { "type": "Ready", "status": "True", "lastHeartbeatTime": "2016-01-13T02:55:34Z", "lastTransitionTime": "2016-01-13T02:28:03Z", "reason": "KubeletReady", "message": "kubelet is posting ready status" } ], "addresses": [ { "type": "LegacyHostIP", "address": "127.0.0.1" }, { "type": "InternalIP", "address": "127.0.0.1" } ], "daemonEndpoints": { "kubeletEndpoint": { "Port": 10250 } }, "nodeInfo": { "machineID": "1d9faaba9168d4b4a3416e99000002a2", "systemUUID": "42015AA3-9AF2-D089-9105-63CEF89EFE35", "bootID": "c31fdd67-f995-4be5-942d-10df26b40501", "kernelVersion": "3.13.0-46-generic", "osImage": "Ubuntu 14.04.2 LTS", "containerRuntimeVersion": "docker://1.9.1", "kubeletVersion": "v1.2.0-alpha.5.848+3f2e99b7e7d6d8", "kubeProxyVersion": "v1.2.0-alpha.5.848+3f2e99b7e7d6d8" }, "images": null } }apache-libcloud-2.8.0/libcloud/test/container/fixtures/kubernetes/_api_v1_pods.json0000664000175000017500000000561613535474530030460 0ustar kamikami00000000000000{ "kind": "PodList", "apiVersion": "v1", "metadata": { "selfLink": "/api/v1/pods", "resourceVersion": "63" }, "items": [ { "metadata": { "name": "hello-world", "namespace": "default", "selfLink": "/api/v1/namespaces/default/pods/hello-world", "uid": "1fad5411-b9af-11e5-8701-0050568157ec", "resourceVersion": "62", "creationTimestamp": "2016-01-13T04:35:50Z" }, "spec": { "volumes": [ { "name": "default-token-dpyh0", "secret": { "secretName": "default-token-dpyh0" } } ], "containers": [ { "name": "hello-world", "image": "ubuntu:14.04", "resources": {}, "volumeMounts": [ { "name": "default-token-dpyh0", "readOnly": true, "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" } ], "terminationMessagePath": "/dev/termination-log", "imagePullPolicy": "IfNotPresent" } ], "restartPolicy": "Always", "terminationGracePeriodSeconds": 30, "dnsPolicy": "ClusterFirst", "serviceAccountName": "default", "serviceAccount": "default", "nodeName": "127.0.0.1", "securityContext": {} }, "status": { "phase": "Running", "conditions": [ { "type": "Ready", "status": "False", "lastProbeTime": null, "lastTransitionTime": "2016-01-13T04:37:09Z", "reason": "ContainersNotReady", "message": "containers with unready status: [hello-world]" } ], "hostIP": "127.0.0.1", "podIP": "172.17.0.2", "startTime": "2016-01-13T04:35:50Z", "containerStatuses": [ { "name": "hello-world", "state": { "waiting": { "reason": "CrashLoopBackOff", "message": "Back-off 20s restarting failed container=hello-world pod=hello-world_default(1fad5411-b9af-11e5-8701-0050568157ec)" } }, "lastState": { "terminated": { "exitCode": 0, "reason": "Completed", "startedAt": "2016-01-13T04:37:07Z", "finishedAt": "2016-01-13T04:37:07Z", "containerID": "docker://3c48b5cda79bce4c8866f02a3b96a024edb8f660d10e7d1755e9ced49ef47b36" } }, "ready": false, "restartCount": 2, "image": "ubuntu:14.04", "imageID": "docker://c4bea91afef3764163fd506f5c1090be1d34a9b63ece81867cb863455937048e", "containerID": "docker://3c48b5cda79bce4c8866f02a3b96a024edb8f660d10e7d1755e9ced49ef47b36" } ] } } ] }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/0000775000175000017500000000000013600223624024452 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/deploy_container.json0000664000175000017500000000734213535474530030724 0ustar kamikami00000000000000{ "id": "1i31", "type": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers/1i31", "account": "http://172.30.0.100:8080/v1/containers/1i31/account", "credentials": "http://172.30.0.100:8080/v1/containers/1i31/credentials", "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i31/healthcheckinstancehostmaps", "hosts": "http://172.30.0.100:8080/v1/containers/1i31/hosts", "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i31/instancelabels", "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/instancelinks", "instances": "http://172.30.0.100:8080/v1/containers/1i31/instances", "mounts": "http://172.30.0.100:8080/v1/containers/1i31/mounts", "ports": "http://172.30.0.100:8080/v1/containers/1i31/ports", "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i31/serviceevents", "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i31/serviceexposemaps", "services": "http://172.30.0.100:8080/v1/containers/1i31/services", "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/targetinstancelinks", "volumes": "http://172.30.0.100:8080/v1/containers/1i31/volumes", "stats": "http://172.30.0.100:8080/v1/containers/1i31/stats", "containerStats": "http://172.30.0.100:8080/v1/containers/1i31/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/containers/1i31/?action=update", "error": "http://172.30.0.100:8080/v1/containers/1i31/?action=error", "remove": "http://172.30.0.100:8080/v1/containers/1i31/?action=remove", "start": "http://172.30.0.100:8080/v1/containers/1i31/?action=start", "logs": "http://172.30.0.100:8080/v1/containers/1i31/?action=logs", "setlabels": "http://172.30.0.100:8080/v1/containers/1i31/?action=setlabels" }, "name": "newcontainer", "state": "running", "accountId": "1a5", "blkioDeviceOptions": null, "build": null, "capAdd": null, "capDrop": null, "command": null, "cpuSet": null, "cpuShares": null, "createIndex": null, "created": "2016-10-06T15:55:58Z", "createdTS": 1475769358000, "dataVolumeMounts": {}, "dataVolumes": [], "dataVolumesFrom": null, "deploymentUnitUuid": null, "description": null, "devices": null, "dns": [ "169.254.169.250" ], "dnsSearch": [ "rancher.internal" ], "dockerPorts": [], "domainName": null, "entryPoint": null, "environment": { "STORAGE_TYPE": "file" }, "expose": null, "externalId": "ab334bd25d25db7b94fdcead8f5c023b05bed424f56243187aa90f5ef7f07b09", "extraHosts": null, "firstRunning": "2016-10-06T15:56:00Z", "firstRunningTS": 1475769360000, "healthCheck": null, "healthState": null, "hostId": "1h1", "hostname": null, "imageUuid": "docker:rlister/hastebin:latest", "kind": "container", "labels": { "io.rancher.container.uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805", "io.rancher.container.name": "newcontainer", "io.rancher.container.ip": "10.42.204.104/16" }, "logConfig": null, "lxcConf": null, "memory": null, "memorySwap": null, "nativeContainer": false, "networkContainerId": null, "networkMode": "managed", "pidMode": null, "ports": null, "primaryIpAddress": "10.42.204.104", "privileged": false, "publishAllPorts": false, "readOnly": false, "registryCredentialId": null, "removed": null, "requestedHostId": null, "restartPolicy": null, "securityOpt": null, "startCount": 1, "startOnCreate": true, "stdinOpen": false, "systemContainer": null, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "tty": false, "user": null, "uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805", "version": "0", "volumeDriver": null, "workingDir": null }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_activate_service.json0000664000175000017500000001322313535474530031375 0ustar kamikami00000000000000{ "id": "1s6", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s6", "account": "http://172.30.0.100:8080/v1/services/1s6/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s6/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s6/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s6/environment", "instances": "http://172.30.0.100:8080/v1/services/1s6/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s6/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s6/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/services/1s6/?action=update", "restart": "http://172.30.0.100:8080/v1/services/1s6/?action=restart", "remove": "http://172.30.0.100:8080/v1/services/1s6/?action=remove", "setservicelinks": "http://172.30.0.100:8080/v1/services/1s6/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=removeservicelink", "upgrade": "http://172.30.0.100:8080/v1/services/1s6/?action=upgrade", "addservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=addservicelink", "deactivate": "http://172.30.0.100:8080/v1/services/1s6/?action=deactivate" }, "name": "123", "state": "active", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-09-22T18:28:04Z", "createdTS": 1474568884000, "currentScale": 1, "description": null, "environmentId": "1e2", "externalId": null, "fqdn": null, "healthState": "healthy", "kind": "service", "launchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0bdea468-c3e9-4562-951c-d543958e966a", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "metadata": null, "publicEndpoints": null, "removed": null, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": { "inServiceStrategy": { "batchSize": 1, "intervalMillis": 2000, "launchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0bdea468-c3e9-4562-951c-d543958e966a", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "previousLaunchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "previousSecondaryLaunchConfigs": [], "secondaryLaunchConfigs": [], "startFirst": true }, "toServiceStrategy": null }, "uuid": "c0ae4d08-e20a-45ef-9fb9-ad9f7cdeeb15", "vip": null }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_activate_stack.json0000664000175000017500000001453313535474530031047 0ustar kamikami00000000000000{ "id": "1e1", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e1", "account": "http://172.30.0.100:8080/v1/environments/1e1/account", "services": "http://172.30.0.100:8080/v1/environments/1e1/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e1/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e1/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e1/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e1/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e1/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e1/?action=exportconfig" }, "name": "Concrete5", "state": "active", "accountId": "1a5", "created": "2016-09-22T17:58:53Z", "createdTS": 1474567133000, "description": null, "dockerCompose": "CMSMysql:\r\n environment:\r\n MYSQL_ROOT_PASSWORD: ${root_password}\r\n MYSQL_DATABASE: ${db_name}\r\n MYSQL_USER: ${db_username}\r\n MYSQL_PASSWORD: ${db_password}\r\n labels:\r\n io.rancher.container.pull_image: always\r\n tty: true\r\n image: mysql\r\n volumes:\r\n - ${db_data_location}:/var/lib/mysql\r\n stdin_open: true\r\n volume_driver: ${volume_driver}\r\n\r\nCMSConfig:\r\n image: opensaas/concrete5\r\n tty: true\r\n stdin_open: true\r\n links:\r\n - CMSMysql:mysql\r\n volumes:\r\n - ${cms_application_data}:/var/www/html/application\r\n - ${cms_packages_data}:/var/www/html/packages\r\n labels:\r\n io.rancher.container.hostname_override: container_name\r\n io.rancher.container.start_once: true\r\n volume_driver: ${volume_driver}\r\n command: bash -c \"chown -R www-data. application; chown -R www-data. packages; sleep 2m; php -f concrete/bin/concrete5.php c5:install --db-server=mysql --db-username=${db_username} --db-password=${db_password} --db-database=${db_name} --site=${cms_sitename} --admin-email=${cms_admin_email} --admin-password=${cms_admin_password} -n -vvv\"\r\n\r\nConcrete5App:\r\n labels:\r\n io.rancher.container.pull_image: always\r\n io.rancher.sidekicks: CMSConfig\r\n tty: true\r\n links:\r\n - CMSMysql:mysql\r\n image: opensaas/concrete5\r\n volumes:\r\n - ${cms_application_data}:/var/www/html/application\r\n - ${cms_packages_data}:/var/www/html/packages\r\n volume_driver: ${volume_driver}\r\n stdin_open: true", "environment": { "root_password": "password", "db_name": "CMS_DB", "db_username": "CMS_USER", "db_password": "password", "db_data_location": "CMS_DB_DATA", "volume_driver": "", "cms_application_data": "CMS_APP_DATA", "cms_packages_data": "CMS_PACK_DATA", "cms_admin_email": "admin@example.com", "cms_admin_password": "password", "cms_sitename": "MySite" }, "externalId": "catalog://community:Concrete5:1", "healthState": "unhealthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": ".catalog:\r\n name: \"Concrete5\"\r\n version: \"v0.2\"\r\n description: \"Concrete5 CMS\"\r\n uuid: Concrete5-1\r\n minimum_rancher_version: v0.51.0\r\n questions:\r\n - variable: root_password\r\n description: \"MySQL root password - keep this password complex and secure\"\r\n label: \"MySQL Root Password\"\r\n required: true\r\n default: \"password\"\r\n type: \"string\"\r\n - variable: db_name\r\n description: \"MySQL Database Name - to use in the Concrete5 setup\"\r\n label: \"MySQL Database Name\"\r\n required: true\r\n default: \"CMS_DB\"\r\n type: \"string\"\r\n - variable: db_username\r\n description: \"MySQL Username - to use in the Concrete5 setup\"\r\n label: \"MySQL Username\"\r\n required: true\r\n default: \"CMS_USER\"\r\n type: \"string\"\r\n - variable: db_password\r\n description: \"MySQL password for the above user - to use in the Concrete5 setup\"\r\n label: \"MySQL Password\"\r\n required: true\r\n default: \"password\"\r\n type: \"string\"\r\n - variable: db_data_location\r\n description: \"Location on the host for the database files\"\r\n label: \"DB Data Location\"\r\n required: true\r\n default: \"CMS_DB_DATA\"\r\n type: \"string\"\r\n - variable: volume_driver\r\n description: \"Volume Driver for the persistant data locations requires docker 1.7\"\r\n label: \"Volume Driver\"\r\n type: \"string\"\r\n - variable: cms_application_data\r\n description: \"Concrcte5 application folder for persistant data storage\"\r\n label: \"Application Folder\"\r\n required: true\r\n default: \"CMS_APP_DATA\"\r\n type: \"string\"\r\n - variable: cms_packages_data\r\n description: \"Concrcte5 packages folder for persistant data storage\"\r\n label: \"Packages Folder\"\r\n required: true\r\n default: \"CMS_PACK_DATA\"\r\n type: \"string\"\r\n - variable: cms_admin_email\r\n description: \"Concrcete5 admin email address\"\r\n label: \"Admin Email\"\r\n required: true\r\n default: \"admin@example.com\"\r\n type: \"string\"\r\n - variable: cms_admin_password\r\n description: \"Concrcete5 admin password\"\r\n label: \"Admin Password\"\r\n required: true\r\n default: \"password\"\r\n type: \"string\"\r\n - variable: cms_sitename\r\n description: \"Concrcete5 Sitename\"\r\n label: \"Sitename\"\r\n required: true\r\n default: \"MySite\"\r\n type: \"string\"\r\nCMSMysql:\r\n scale: 1\r\nConcrete5App:\r\n scale: 1\r\n\r\n", "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "e129ed27-3823-4e2e-af62-4565d68995d4" }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_deploy_service.json0000664000175000017500000000414513535474530031074 0ustar kamikami00000000000000{ "id": "1s13", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s13", "account": "http://172.30.0.100:8080/v1/services/1s13/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s13/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s13/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s13/environment", "instances": "http://172.30.0.100:8080/v1/services/1s13/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s13/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s13/containerstats" }, "actions": { "setservicelinks": "http://172.30.0.100:8080/v1/services/1s13/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=removeservicelink", "addservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=addservicelink" }, "name": "newservice", "state": "active", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-10-06T15:31:35Z", "createdTS": 1475767895000, "currentScale": 1, "description": null, "environmentId": "1e6", "externalId": null, "fqdn": null, "healthState": "unhealthy", "kind": "service", "launchConfig": { "environment": { "root_password": "password" }, "imageUuid": "docker:rlister/hastebin:latest", "kind": "container", "networkMode": "managed", "privileged": false, "publishAllPorts": false, "readOnly": false, "startOnCreate": true, "stdinOpen": false, "tty": false, "version": "0", "vcpu": 1 }, "metadata": null, "publicEndpoints": null, "removed": "2016-10-06T15:45:03Z", "removedTS": 1475768703000, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": null, "uuid": "de2cd54f-9936-49fb-a41a-35653c4510f7", "vip": null }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_deploy_stack.json0000664000175000017500000000303313535474530030534 0ustar kamikami00000000000000{ "id": "1e9", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e9", "account": "http://172.30.0.100:8080/v1/environments/1e9/account", "services": "http://172.30.0.100:8080/v1/environments/1e9/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e9/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e9/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e9/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e9/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e9/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e9/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e9/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e9/?action=exportconfig" }, "name": "newstack", "state": "active", "accountId": "1a5", "created": "2016-10-06T14:12:34Z", "createdTS": 1475763154000, "description": null, "dockerCompose": null, "environment": {"root_password": "password"}, "externalId": null, "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": null, "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "7f8b1836-5619-4e19-adfe-6967fe55bda7" }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_destroy_service.json0000664000175000017500000000414713535474530031273 0ustar kamikami00000000000000{ "id": "1s13", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s13", "account": "http://172.30.0.100:8080/v1/services/1s13/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s13/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s13/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s13/environment", "instances": "http://172.30.0.100:8080/v1/services/1s13/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s13/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s13/containerstats" }, "actions": { "setservicelinks": "http://172.30.0.100:8080/v1/services/1s13/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=removeservicelink", "addservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=addservicelink" }, "name": "newservice", "state": "removing", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-10-06T15:31:35Z", "createdTS": 1475767895000, "currentScale": 1, "description": null, "environmentId": "1e6", "externalId": null, "fqdn": null, "healthState": "unhealthy", "kind": "service", "launchConfig": { "environment": { "root_password": "password" }, "imageUuid": "docker:rlister/hastebin:latest", "kind": "container", "networkMode": "managed", "privileged": false, "publishAllPorts": false, "readOnly": false, "startOnCreate": true, "stdinOpen": false, "tty": false, "version": "0", "vcpu": 1 }, "metadata": null, "publicEndpoints": null, "removed": "2016-10-06T15:45:03Z", "removedTS": 1475768703000, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": null, "uuid": "de2cd54f-9936-49fb-a41a-35653c4510f7", "vip": null }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_destroy_stack.json0000664000175000017500000000256613535474530030743 0ustar kamikami00000000000000{ "id": "1e10", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e10", "account": "http://172.30.0.100:8080/v1/environments/1e10/account", "services": "http://172.30.0.100:8080/v1/environments/1e10/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e10/composeconfig" }, "actions": { "addoutputs": "http://172.30.0.100:8080/v1/environments/1e10/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e10/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e10/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e10/?action=exportconfig" }, "name": "newstack1", "state": "removing", "accountId": "1a5", "created": "2016-10-06T14:15:41Z", "createdTS": 1475763341000, "description": null, "dockerCompose": null, "environment": { "root_password": "password" }, "externalId": null, "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": null, "removed": "2016-10-06T14:56:16Z", "removedTS": 1475765776000, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "289f380f-d00a-4faf-b69f-53a559dbfd05" }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_list_services.json0000664000175000017500000004576613535474530030754 0ustar kamikami00000000000000{ "type": "collection", "resourceType": "service", "links": { "self": "http://172.30.0.100:8080/v1/services" }, "createTypes": { "dnsService": "http://172.30.0.100:8080/v1/dnsservices", "externalService": "http://172.30.0.100:8080/v1/externalservices", "loadBalancerService": "http://172.30.0.100:8080/v1/loadbalancerservices", "service": "http://172.30.0.100:8080/v1/services" }, "actions": {}, "data": [ { "id": "1s1", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s1", "account": "http://172.30.0.100:8080/v1/services/1s1/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s1/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s1/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s1/environment", "instances": "http://172.30.0.100:8080/v1/services/1s1/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s1/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s1/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/services/1s1/?action=update", "remove": "http://172.30.0.100:8080/v1/services/1s1/?action=remove", "setservicelinks": "http://172.30.0.100:8080/v1/services/1s1/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s1/?action=removeservicelink", "activate": "http://172.30.0.100:8080/v1/services/1s1/?action=activate", "upgrade": "http://172.30.0.100:8080/v1/services/1s1/?action=upgrade", "addservicelink": "http://172.30.0.100:8080/v1/services/1s1/?action=addservicelink" }, "name": "CMSMysql", "state": "inactive", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-09-22T17:58:54Z", "createdTS": 1474567134000, "currentScale": 1, "description": null, "environmentId": "1e1", "externalId": null, "fqdn": null, "healthState": "unhealthy", "kind": "service", "launchConfig": { "dataVolumes": [ "CMS_DB_DATA:/var/lib/mysql" ], "environment": { "MYSQL_DATABASE": "CMS_DB", "MYSQL_PASSWORD": "password", "MYSQL_ROOT_PASSWORD": "password", "MYSQL_USER": "CMS_USER" }, "imageUuid": "docker:mysql", "kind": "container", "labels": { "io.rancher.container.pull_image": "always", "io.rancher.service.hash": "c5d6bacef4be47a5ca5d1517a1d33319d024cdde" }, "logConfig": {}, "networkMode": "managed", "privileged": false, "publishAllPorts": false, "readOnly": false, "startOnCreate": true, "stdinOpen": true, "tty": true, "version": "0", "vcpu": 1 }, "metadata": { "io.rancher.service.hash": "41ccfd7f8023f2efcc758a925a9f461d607c990d" }, "publicEndpoints": null, "removed": null, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": false, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": null, "uuid": "85f4e9fc-c311-45a0-9a1a-a9da229aaa2a", "vip": null }, { "id": "1s2", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s2", "account": "http://172.30.0.100:8080/v1/services/1s2/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s2/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s2/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s2/environment", "instances": "http://172.30.0.100:8080/v1/services/1s2/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s2/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s2/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/services/1s2/?action=update", "remove": "http://172.30.0.100:8080/v1/services/1s2/?action=remove", "setservicelinks": "http://172.30.0.100:8080/v1/services/1s2/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s2/?action=removeservicelink", "activate": "http://172.30.0.100:8080/v1/services/1s2/?action=activate", "upgrade": "http://172.30.0.100:8080/v1/services/1s2/?action=upgrade", "addservicelink": "http://172.30.0.100:8080/v1/services/1s2/?action=addservicelink" }, "name": "Concrete5App", "state": "inactive", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 2, "created": "2016-09-22T17:58:54Z", "createdTS": 1474567134000, "currentScale": 1, "description": null, "environmentId": "1e1", "externalId": null, "fqdn": null, "healthState": "degraded", "kind": "service", "launchConfig": { "dataVolumes": [ "CMS_APP_DATA:/var/www/html/application", "CMS_PACK_DATA:/var/www/html/packages" ], "imageUuid": "docker:opensaas/concrete5", "kind": "container", "labels": { "io.rancher.container.pull_image": "always", "io.rancher.service.hash": "6033469e7596fd16896eb87b3a99f50af2dbf522", "io.rancher.sidekicks": "CMSConfig" }, "logConfig": {}, "networkMode": "managed", "privileged": false, "publishAllPorts": false, "readOnly": false, "startOnCreate": true, "stdinOpen": true, "tty": true, "version": "0", "vcpu": 1 }, "metadata": { "io.rancher.service.hash": "037726f2f6d389022953a652a5d3e5775415d0b0" }, "publicEndpoints": null, "removed": null, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [ { "command": [ "bash", "-c", "chown -R www-data. application; chown -R www-data. packages; sleep 2m; php -f concrete/bin/concrete5.php c5:install --db-server=mysql --db-username=CMS_USER --db-password=password --db-database=CMS_DB --site=MySite --admin-email=admin@example.com --admin-password=password -n -vvv" ], "dataVolumes": [ "CMS_APP_DATA:/var/www/html/application", "CMS_PACK_DATA:/var/www/html/packages" ], "imageUuid": "docker:opensaas/concrete5", "labels": { "io.rancher.container.hostname_override": "container_name", "io.rancher.container.start_once": "true", "io.rancher.service.hash": "db08c70dbb11ff2955a5cac93c2c6e5e1ac95e7e" }, "logConfig": {}, "name": "CMSConfig", "networkMode": "managed", "startOnCreate": true, "stdinOpen": true, "tty": true, "kind": "container", "privileged": false, "publishAllPorts": false, "readOnly": false, "vcpu": 1, "version": "0" } ], "selectorContainer": null, "selectorLink": null, "startOnCreate": false, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": null, "uuid": "1d824bd6-e18b-4ac4-8ea1-5cd0a3c7e234", "vip": null }, { "id": "1s3", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s3", "account": "http://172.30.0.100:8080/v1/services/1s3/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s3/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s3/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s3/environment", "instances": "http://172.30.0.100:8080/v1/services/1s3/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s3/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s3/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/services/1s3/?action=update", "restart": "http://172.30.0.100:8080/v1/services/1s3/?action=restart", "remove": "http://172.30.0.100:8080/v1/services/1s3/?action=remove", "setservicelinks": "http://172.30.0.100:8080/v1/services/1s3/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=removeservicelink", "upgrade": "http://172.30.0.100:8080/v1/services/1s3/?action=upgrade", "addservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=addservicelink", "deactivate": "http://172.30.0.100:8080/v1/services/1s3/?action=deactivate" }, "name": "ghost", "state": "active", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-09-22T18:00:26Z", "createdTS": 1474567226000, "currentScale": 1, "description": null, "environmentId": "1e2", "externalId": null, "fqdn": null, "healthState": "healthy", "kind": "service", "launchConfig": { "imageUuid": "docker:ghost", "kind": "container", "labels": { "io.rancher.service.hash": "af9b5ddd2891271b12a88129e2bc37ff57998182" }, "logConfig": {}, "networkMode": "managed", "ports": [ "80:2368/tcp" ], "privileged": false, "publishAllPorts": false, "readOnly": false, "startOnCreate": true, "stdinOpen": false, "tty": false, "version": "0", "vcpu": 1 }, "metadata": { "io.rancher.service.hash": "f49280e1f709117b76693b638834791e4f4ef0fd" }, "publicEndpoints": [ { "ipAddress": "172.30.0.101", "port": 80, "serviceId": "1s3", "hostId": "1h1", "instanceId": "1i5" } ], "removed": null, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": false, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": null, "uuid": "c2ce7050-e5b5-42c7-a9fb-8ed8d33a4884", "vip": null }, { "id": "1s6", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s6", "account": "http://172.30.0.100:8080/v1/services/1s6/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s6/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s6/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s6/environment", "instances": "http://172.30.0.100:8080/v1/services/1s6/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s6/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s6/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/services/1s6/?action=update", "restart": "http://172.30.0.100:8080/v1/services/1s6/?action=restart", "remove": "http://172.30.0.100:8080/v1/services/1s6/?action=remove", "setservicelinks": "http://172.30.0.100:8080/v1/services/1s6/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=removeservicelink", "upgrade": "http://172.30.0.100:8080/v1/services/1s6/?action=upgrade", "addservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=addservicelink", "deactivate": "http://172.30.0.100:8080/v1/services/1s6/?action=deactivate" }, "name": "123", "state": "active", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-09-22T18:28:04Z", "createdTS": 1474568884000, "currentScale": 1, "description": null, "environmentId": "1e2", "externalId": null, "fqdn": null, "healthState": "healthy", "kind": "service", "launchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0bdea468-c3e9-4562-951c-d543958e966a", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "metadata": null, "publicEndpoints": null, "removed": null, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": { "inServiceStrategy": { "batchSize": 1, "intervalMillis": 2000, "launchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0bdea468-c3e9-4562-951c-d543958e966a", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "previousLaunchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "previousSecondaryLaunchConfigs": [], "secondaryLaunchConfigs": [], "startFirst": true }, "toServiceStrategy": null }, "uuid": "c0ae4d08-e20a-45ef-9fb9-ad9f7cdeeb15", "vip": null } ], "sortLinks": { "accountId": "http://172.30.0.100:8080/v1/services?limit=4&sort=accountId", "createIndex": "http://172.30.0.100:8080/v1/services?limit=4&sort=createIndex", "created": "http://172.30.0.100:8080/v1/services?limit=4&sort=created", "description": "http://172.30.0.100:8080/v1/services?limit=4&sort=description", "environmentId": "http://172.30.0.100:8080/v1/services?limit=4&sort=environmentId", "externalId": "http://172.30.0.100:8080/v1/services?limit=4&sort=externalId", "healthState": "http://172.30.0.100:8080/v1/services?limit=4&sort=healthState", "id": "http://172.30.0.100:8080/v1/services?limit=4&sort=id", "kind": "http://172.30.0.100:8080/v1/services?limit=4&sort=kind", "name": "http://172.30.0.100:8080/v1/services?limit=4&sort=name", "removeTime": "http://172.30.0.100:8080/v1/services?limit=4&sort=removeTime", "removed": "http://172.30.0.100:8080/v1/services?limit=4&sort=removed", "selectorContainer": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorContainer", "selectorLink": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorLink", "state": "http://172.30.0.100:8080/v1/services?limit=4&sort=state", "uuid": "http://172.30.0.100:8080/v1/services?limit=4&sort=uuid", "vip": "http://172.30.0.100:8080/v1/services?limit=4&sort=vip" }, "pagination": { "first": null, "previous": null, "next": "http://172.30.0.100:8080/v1/services?limit=4&marker=m4", "limit": 4, "total": null, "partial": true }, "sort": null, "filters": { "accountId": null, "createIndex": null, "created": null, "description": null, "environmentId": null, "externalId": null, "healthState": null, "id": null, "kind": null, "name": null, "removeTime": null, "removed": null, "selectorContainer": null, "selectorLink": null, "state": null, "uuid": null, "vip": null }, "createDefaults": {} }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_list_stacks.json0000664000175000017500000004224213535474530030403 0ustar kamikami00000000000000{ "type": "collection", "resourceType": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments" }, "createTypes": { "composeProject": "http://172.30.0.100:8080/v1/composeprojects", "environment": "http://172.30.0.100:8080/v1/environments" }, "actions": {}, "data": [ { "id": "1e1", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e1", "account": "http://172.30.0.100:8080/v1/environments/1e1/account", "services": "http://172.30.0.100:8080/v1/environments/1e1/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e1/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e1/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e1/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e1/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e1/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e1/?action=exportconfig" }, "name": "Concrete5", "state": "active", "accountId": "1a5", "created": "2016-09-22T17:58:53Z", "createdTS": 1474567133000, "description": null, "dockerCompose": "CMSMysql:\r\n environment:\r\n MYSQL_ROOT_PASSWORD: ${root_password}\r\n MYSQL_DATABASE: ${db_name}\r\n MYSQL_USER: ${db_username}\r\n MYSQL_PASSWORD: ${db_password}\r\n labels:\r\n io.rancher.container.pull_image: always\r\n tty: true\r\n image: mysql\r\n volumes:\r\n - ${db_data_location}:/var/lib/mysql\r\n stdin_open: true\r\n volume_driver: ${volume_driver}\r\n\r\nCMSConfig:\r\n image: opensaas/concrete5\r\n tty: true\r\n stdin_open: true\r\n links:\r\n - CMSMysql:mysql\r\n volumes:\r\n - ${cms_application_data}:/var/www/html/application\r\n - ${cms_packages_data}:/var/www/html/packages\r\n labels:\r\n io.rancher.container.hostname_override: container_name\r\n io.rancher.container.start_once: true\r\n volume_driver: ${volume_driver}\r\n command: bash -c \"chown -R www-data. application; chown -R www-data. packages; sleep 2m; php -f concrete/bin/concrete5.php c5:install --db-server=mysql --db-username=${db_username} --db-password=${db_password} --db-database=${db_name} --site=${cms_sitename} --admin-email=${cms_admin_email} --admin-password=${cms_admin_password} -n -vvv\"\r\n\r\nConcrete5App:\r\n labels:\r\n io.rancher.container.pull_image: always\r\n io.rancher.sidekicks: CMSConfig\r\n tty: true\r\n links:\r\n - CMSMysql:mysql\r\n image: opensaas/concrete5\r\n volumes:\r\n - ${cms_application_data}:/var/www/html/application\r\n - ${cms_packages_data}:/var/www/html/packages\r\n volume_driver: ${volume_driver}\r\n stdin_open: true", "environment": { "root_password": "password", "db_name": "CMS_DB", "db_username": "CMS_USER", "db_password": "password", "db_data_location": "CMS_DB_DATA", "volume_driver": "", "cms_application_data": "CMS_APP_DATA", "cms_packages_data": "CMS_PACK_DATA", "cms_admin_email": "admin@example.com", "cms_admin_password": "password", "cms_sitename": "MySite" }, "externalId": "catalog://community:Concrete5:1", "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": ".catalog:\r\n name: \"Concrete5\"\r\n version: \"v0.2\"\r\n description: \"Concrete5 CMS\"\r\n uuid: Concrete5-1\r\n minimum_rancher_version: v0.51.0\r\n questions:\r\n - variable: root_password\r\n description: \"MySQL root password - keep this password complex and secure\"\r\n label: \"MySQL Root Password\"\r\n required: true\r\n default: \"password\"\r\n type: \"string\"\r\n - variable: db_name\r\n description: \"MySQL Database Name - to use in the Concrete5 setup\"\r\n label: \"MySQL Database Name\"\r\n required: true\r\n default: \"CMS_DB\"\r\n type: \"string\"\r\n - variable: db_username\r\n description: \"MySQL Username - to use in the Concrete5 setup\"\r\n label: \"MySQL Username\"\r\n required: true\r\n default: \"CMS_USER\"\r\n type: \"string\"\r\n - variable: db_password\r\n description: \"MySQL password for the above user - to use in the Concrete5 setup\"\r\n label: \"MySQL Password\"\r\n required: true\r\n default: \"password\"\r\n type: \"string\"\r\n - variable: db_data_location\r\n description: \"Location on the host for the database files\"\r\n label: \"DB Data Location\"\r\n required: true\r\n default: \"CMS_DB_DATA\"\r\n type: \"string\"\r\n - variable: volume_driver\r\n description: \"Volume Driver for the persistant data locations requires docker 1.7\"\r\n label: \"Volume Driver\"\r\n type: \"string\"\r\n - variable: cms_application_data\r\n description: \"Concrcte5 application folder for persistant data storage\"\r\n label: \"Application Folder\"\r\n required: true\r\n default: \"CMS_APP_DATA\"\r\n type: \"string\"\r\n - variable: cms_packages_data\r\n description: \"Concrcte5 packages folder for persistant data storage\"\r\n label: \"Packages Folder\"\r\n required: true\r\n default: \"CMS_PACK_DATA\"\r\n type: \"string\"\r\n - variable: cms_admin_email\r\n description: \"Concrcete5 admin email address\"\r\n label: \"Admin Email\"\r\n required: true\r\n default: \"admin@example.com\"\r\n type: \"string\"\r\n - variable: cms_admin_password\r\n description: \"Concrcete5 admin password\"\r\n label: \"Admin Password\"\r\n required: true\r\n default: \"password\"\r\n type: \"string\"\r\n - variable: cms_sitename\r\n description: \"Concrcete5 Sitename\"\r\n label: \"Sitename\"\r\n required: true\r\n default: \"MySite\"\r\n type: \"string\"\r\nCMSMysql:\r\n scale: 1\r\nConcrete5App:\r\n scale: 1\r\n\r\n", "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "e129ed27-3823-4e2e-af62-4565d68995d4" }, { "id": "1e2", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e2", "account": "http://172.30.0.100:8080/v1/environments/1e2/account", "services": "http://172.30.0.100:8080/v1/environments/1e2/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e2/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e2/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e2/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e2/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e2/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e2/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e2/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e2/?action=exportconfig" }, "name": "ghost", "state": "active", "accountId": "1a5", "created": "2016-09-22T18:00:25Z", "createdTS": 1474567225000, "description": null, "dockerCompose": "ghost:\n image: ghost\n ports:\n - ${public_port}:2368\n", "environment": { "public_port": "80" }, "externalId": "catalog://community:ghost:0", "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": ".catalog:\n name: \"Ghost\"\n version: \"v0.1-educaas\"\n description: \"Blog powered by Ghost. Requires no database\"\n uuid: ghost-0\n minimum_rancher_version: v0.51.0\n questions:\n - variable: public_port\n description: \"public port to access the blog\"\n label: \"Public Port\"\n required: true\n default: \"80\"\n type: \"int\"\nghost:\n", "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "4c335202-2ca7-41f1-8702-4984518566ec" }, { "id": "1e5", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e5", "account": "http://172.30.0.100:8080/v1/environments/1e5/account", "services": "http://172.30.0.100:8080/v1/environments/1e5/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e5/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e5/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e5/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e5/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e5/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e5/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e5/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e5/?action=exportconfig" }, "name": "heyk", "state": "active", "accountId": "1a5", "created": "2016-09-29T20:40:14Z", "createdTS": 1475181614000, "description": null, "dockerCompose": null, "environment": null, "externalId": null, "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": null, "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "d5a39304-9247-4a31-8662-7dba98238105" }, { "id": "1e6", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e6", "account": "http://172.30.0.100:8080/v1/environments/1e6/account", "services": "http://172.30.0.100:8080/v1/environments/1e6/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e6/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e6/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e6/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e6/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e6/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e6/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e6/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e6/?action=exportconfig" }, "name": "ilikegurls", "state": "active", "accountId": "1a5", "created": "2016-10-06T00:40:23Z", "createdTS": 1475714423000, "description": null, "dockerCompose": null, "environment": null, "externalId": null, "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": null, "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "19101511-6dcb-49f7-a8e1-063bcded1956" }, { "id": "1e7", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e7", "account": "http://172.30.0.100:8080/v1/environments/1e7/account", "services": "http://172.30.0.100:8080/v1/environments/1e7/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e7/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e7/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e7/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e7/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e7/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e7/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e7/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e7/?action=exportconfig" }, "name": "maybethisyear", "state": "active", "accountId": "1a5", "created": "2016-10-06T00:41:17Z", "createdTS": 1475714477000, "description": null, "dockerCompose": null, "environment": null, "externalId": null, "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": null, "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "250c66f6-cd36-4c12-8767-deb5c35d0a05" }, { "id": "1e8", "type": "environment", "links": { "self": "http://172.30.0.100:8080/v1/environments/1e8", "account": "http://172.30.0.100:8080/v1/environments/1e8/account", "services": "http://172.30.0.100:8080/v1/environments/1e8/services", "composeConfig": "http://172.30.0.100:8080/v1/environments/1e8/composeconfig" }, "actions": { "upgrade": "http://172.30.0.100:8080/v1/environments/1e8/?action=upgrade", "update": "http://172.30.0.100:8080/v1/environments/1e8/?action=update", "remove": "http://172.30.0.100:8080/v1/environments/1e8/?action=remove", "addoutputs": "http://172.30.0.100:8080/v1/environments/1e8/?action=addoutputs", "activateservices": "http://172.30.0.100:8080/v1/environments/1e8/?action=activateservices", "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e8/?action=deactivateservices", "exportconfig": "http://172.30.0.100:8080/v1/environments/1e8/?action=exportconfig" }, "name": "oh-another", "state": "active", "accountId": "1a5", "created": "2016-10-06T00:51:34Z", "createdTS": 1475715094000, "description": null, "dockerCompose": null, "environment": null, "externalId": null, "healthState": "healthy", "kind": "environment", "outputs": null, "previousEnvironment": null, "previousExternalId": null, "rancherCompose": null, "removed": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "uuid": "a777dd5e-e524-43c8-8783-d7bb14bcffb6" } ], "sortLinks": { "accountId": "http://172.30.0.100:8080/v1/environments?limit=6&sort=accountId", "created": "http://172.30.0.100:8080/v1/environments?limit=6&sort=created", "description": "http://172.30.0.100:8080/v1/environments?limit=6&sort=description", "externalId": "http://172.30.0.100:8080/v1/environments?limit=6&sort=externalId", "healthState": "http://172.30.0.100:8080/v1/environments?limit=6&sort=healthState", "id": "http://172.30.0.100:8080/v1/environments?limit=6&sort=id", "kind": "http://172.30.0.100:8080/v1/environments?limit=6&sort=kind", "name": "http://172.30.0.100:8080/v1/environments?limit=6&sort=name", "removeTime": "http://172.30.0.100:8080/v1/environments?limit=6&sort=removeTime", "removed": "http://172.30.0.100:8080/v1/environments?limit=6&sort=removed", "state": "http://172.30.0.100:8080/v1/environments?limit=6&sort=state", "uuid": "http://172.30.0.100:8080/v1/environments?limit=6&sort=uuid" }, "pagination": { "first": null, "previous": null, "next": "http://172.30.0.100:8080/v1/environments?limit=6&marker=m6", "limit": 6, "total": null, "partial": true }, "sort": null, "filters": { "accountId": null, "created": null, "description": null, "externalId": null, "healthState": [ { "modifier": "eq", "value": "healthy" } ], "id": null, "kind": null, "name": null, "removeTime": null, "removed": null, "state": null, "uuid": null }, "createDefaults": {} }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_search_containers.json0000664000175000017500000002163213535474530031552 0ustar kamikami00000000000000{ "type": "collection", "resourceType": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers" }, "createTypes": { "container": "http://172.30.0.100:8080/v1/containers", "launchConfig": "http://172.30.0.100:8080/v1/launchconfigs", "virtualMachine": "http://172.30.0.100:8080/v1/virtualmachines" }, "actions": {}, "data": [ { "id": "1i2", "type": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers/1i2", "account": "http://172.30.0.100:8080/v1/containers/1i2/account", "credentials": "http://172.30.0.100:8080/v1/containers/1i2/credentials", "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i2/healthcheckinstancehostmaps", "hosts": "http://172.30.0.100:8080/v1/containers/1i2/hosts", "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i2/instancelabels", "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/instancelinks", "instances": "http://172.30.0.100:8080/v1/containers/1i2/instances", "mounts": "http://172.30.0.100:8080/v1/containers/1i2/mounts", "ports": "http://172.30.0.100:8080/v1/containers/1i2/ports", "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i2/serviceevents", "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i2/serviceexposemaps", "services": "http://172.30.0.100:8080/v1/containers/1i2/services", "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/targetinstancelinks", "volumes": "http://172.30.0.100:8080/v1/containers/1i2/volumes", "stats": "http://172.30.0.100:8080/v1/containers/1i2/stats", "containerStats": "http://172.30.0.100:8080/v1/containers/1i2/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/containers/1i2/?action=update", "stop": "http://172.30.0.100:8080/v1/containers/1i2/?action=stop", "restart": "http://172.30.0.100:8080/v1/containers/1i2/?action=restart", "migrate": "http://172.30.0.100:8080/v1/containers/1i2/?action=migrate", "logs": "http://172.30.0.100:8080/v1/containers/1i2/?action=logs", "setlabels": "http://172.30.0.100:8080/v1/containers/1i2/?action=setlabels", "execute": "http://172.30.0.100:8080/v1/containers/1i2/?action=execute", "proxy": "http://172.30.0.100:8080/v1/containers/1i2/?action=proxy" }, "name": "Network Agent", "state": "running", "accountId": "1a5", "blkioDeviceOptions": null, "build": null, "capAdd": null, "capDrop": null, "command": null, "cpuSet": null, "cpuShares": null, "createIndex": null, "created": "2016-09-22T17:58:57Z", "createdTS": 1474567137000, "dataVolumeMounts": {}, "dataVolumes": [ "/var/lib/rancher/etc:/var/lib/rancher/etc:ro" ], "dataVolumesFrom": null, "deploymentUnitUuid": null, "description": null, "devices": null, "dns": null, "dnsSearch": null, "domainName": null, "entryPoint": null, "environment": null, "expose": null, "externalId": "129c67adc9fa084fbc8e1f963db0180896b88af3dca69c7e8fe0493284e4651c", "extraHosts": null, "firstRunning": "2016-09-22T17:59:11Z", "firstRunningTS": 1474567151000, "healthCheck": null, "healthState": null, "hostId": "1h1", "hostname": null, "imageUuid": "docker:rancher/agent-instance:v0.8.3", "kind": "container", "labels": { "io.rancher.container.system": "NetworkAgent", "io.rancher.container.uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb", "io.rancher.container.name": "Network Agent", "io.rancher.container.agent_id": "2", "io.rancher.container.ip": "10.42.247.188/16" }, "logConfig": null, "lxcConf": null, "memory": null, "memorySwap": null, "nativeContainer": false, "networkContainerId": null, "networkIds": [], "networkMode": null, "pidMode": null, "ports": null, "primaryIpAddress": "10.42.247.188", "privileged": true, "publishAllPorts": false, "readOnly": false, "registryCredentialId": null, "removed": null, "requestedHostId": null, "restartPolicy": null, "securityOpt": null, "startCount": 3, "startOnCreate": true, "stdinOpen": false, "systemContainer": "NetworkAgent", "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "tty": false, "user": null, "uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb", "version": "0", "volumeDriver": null, "workingDir": null } ], "sortLinks": { "accountId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=accountId", "agentId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=agentId", "allocationState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=allocationState", "compute": "http://172.30.0.100:8080/v1/containers?limit=2&sort=compute", "createIndex": "http://172.30.0.100:8080/v1/containers?limit=2&sort=createIndex", "created": "http://172.30.0.100:8080/v1/containers?limit=2&sort=created", "deploymentUnitUuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=deploymentUnitUuid", "description": "http://172.30.0.100:8080/v1/containers?limit=2&sort=description", "dnsInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsInternal", "dnsSearchInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsSearchInternal", "domain": "http://172.30.0.100:8080/v1/containers?limit=2&sort=domain", "externalId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=externalId", "firstRunning": "http://172.30.0.100:8080/v1/containers?limit=2&sort=firstRunning", "healthState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthState", "healthUpdated": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthUpdated", "hostname": "http://172.30.0.100:8080/v1/containers?limit=2&sort=hostname", "id": "http://172.30.0.100:8080/v1/containers?limit=2&sort=id", "imageId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=imageId", "instanceTriggeredStop": "http://172.30.0.100:8080/v1/containers?limit=2&sort=instanceTriggeredStop", "kind": "http://172.30.0.100:8080/v1/containers?limit=2&sort=kind", "memoryMb": "http://172.30.0.100:8080/v1/containers?limit=2&sort=memoryMb", "name": "http://172.30.0.100:8080/v1/containers?limit=2&sort=name", "nativeContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=nativeContainer", "networkContainerId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=networkContainerId", "offeringId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=offeringId", "registryCredentialId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=registryCredentialId", "removeTime": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removeTime", "removed": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removed", "serviceIndexId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=serviceIndexId", "startCount": "http://172.30.0.100:8080/v1/containers?limit=2&sort=startCount", "state": "http://172.30.0.100:8080/v1/containers?limit=2&sort=state", "systemContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=systemContainer", "token": "http://172.30.0.100:8080/v1/containers?limit=2&sort=token", "userdata": "http://172.30.0.100:8080/v1/containers?limit=2&sort=userdata", "uuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=uuid", "version": "http://172.30.0.100:8080/v1/containers?limit=2&sort=version", "zoneId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=zoneId" }, "pagination": { "first": null, "previous": null, "next": "http://172.30.0.100:8080/v1/containers?limit=2&marker=m2", "limit": 2, "total": null, "partial": true }, "sort": null, "filters": { "accountId": null, "agentId": null, "allocationState": null, "compute": null, "createIndex": null, "created": null, "deploymentUnitUuid": null, "description": null, "dnsInternal": null, "dnsSearchInternal": null, "domain": null, "externalId": null, "firstRunning": null, "healthState": null, "healthUpdated": null, "hostname": null, "id": null, "imageId": null, "instanceTriggeredStop": null, "kind": null, "memoryMb": null, "name": null, "nativeContainer": null, "networkContainerId": null, "offeringId": null, "registryCredentialId": null, "removeTime": null, "removed": null, "serviceIndexId": null, "startCount": null, "state": null, "systemContainer": null, "token": null, "userdata": null, "uuid": null, "version": null, "zoneId": null }, "createDefaults": {} }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/ex_search_services.json0000664000175000017500000002750013535474530031230 0ustar kamikami00000000000000{ "type": "collection", "resourceType": "service", "links": { "self": "http://172.30.0.100:8080/v1/services" }, "createTypes": { "dnsService": "http://172.30.0.100:8080/v1/dnsservices", "externalService": "http://172.30.0.100:8080/v1/externalservices", "loadBalancerService": "http://172.30.0.100:8080/v1/loadbalancerservices", "service": "http://172.30.0.100:8080/v1/services" }, "actions": {}, "data": [ { "id": "1s3", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s3", "account": "http://172.30.0.100:8080/v1/services/1s3/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s3/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s3/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s3/environment", "instances": "http://172.30.0.100:8080/v1/services/1s3/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s3/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s3/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/services/1s3/?action=update", "restart": "http://172.30.0.100:8080/v1/services/1s3/?action=restart", "remove": "http://172.30.0.100:8080/v1/services/1s3/?action=remove", "setservicelinks": "http://172.30.0.100:8080/v1/services/1s3/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=removeservicelink", "upgrade": "http://172.30.0.100:8080/v1/services/1s3/?action=upgrade", "addservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=addservicelink", "deactivate": "http://172.30.0.100:8080/v1/services/1s3/?action=deactivate" }, "name": "ghost", "state": "active", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-09-22T18:00:26Z", "createdTS": 1474567226000, "currentScale": 1, "description": null, "environmentId": "1e2", "externalId": null, "fqdn": null, "healthState": "healthy", "kind": "service", "launchConfig": { "imageUuid": "docker:ghost", "kind": "container", "labels": { "io.rancher.service.hash": "af9b5ddd2891271b12a88129e2bc37ff57998182" }, "logConfig": {}, "networkMode": "managed", "ports": [ "80:2368/tcp" ], "privileged": false, "publishAllPorts": false, "readOnly": false, "startOnCreate": true, "stdinOpen": false, "tty": false, "version": "0", "vcpu": 1 }, "metadata": { "io.rancher.service.hash": "f49280e1f709117b76693b638834791e4f4ef0fd" }, "publicEndpoints": [ { "ipAddress": "172.30.0.101", "port": 80, "serviceId": "1s3", "hostId": "1h1", "instanceId": "1i5" } ], "removed": null, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": false, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": null, "uuid": "c2ce7050-e5b5-42c7-a9fb-8ed8d33a4884", "vip": null }, { "id": "1s6", "type": "service", "links": { "self": "http://172.30.0.100:8080/v1/services/1s6", "account": "http://172.30.0.100:8080/v1/services/1s6/account", "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s6/consumedbyservices", "consumedservices": "http://172.30.0.100:8080/v1/services/1s6/consumedservices", "environment": "http://172.30.0.100:8080/v1/services/1s6/environment", "instances": "http://172.30.0.100:8080/v1/services/1s6/instances", "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s6/serviceexposemaps", "containerStats": "http://172.30.0.100:8080/v1/services/1s6/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/services/1s6/?action=update", "restart": "http://172.30.0.100:8080/v1/services/1s6/?action=restart", "remove": "http://172.30.0.100:8080/v1/services/1s6/?action=remove", "setservicelinks": "http://172.30.0.100:8080/v1/services/1s6/?action=setservicelinks", "removeservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=removeservicelink", "upgrade": "http://172.30.0.100:8080/v1/services/1s6/?action=upgrade", "addservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=addservicelink", "deactivate": "http://172.30.0.100:8080/v1/services/1s6/?action=deactivate" }, "name": "123", "state": "active", "accountId": "1a5", "assignServiceIpAddress": false, "createIndex": 1, "created": "2016-09-22T18:28:04Z", "createdTS": 1474568884000, "currentScale": 1, "description": null, "environmentId": "1e2", "externalId": null, "fqdn": null, "healthState": "healthy", "kind": "service", "launchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0bdea468-c3e9-4562-951c-d543958e966a", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "metadata": null, "publicEndpoints": null, "removed": null, "retainIp": null, "scale": 1, "scalePolicy": null, "secondaryLaunchConfigs": [], "selectorContainer": null, "selectorLink": null, "startOnCreate": true, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "upgrade": { "inServiceStrategy": { "batchSize": 1, "intervalMillis": 2000, "launchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0bdea468-c3e9-4562-951c-d543958e966a", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "previousLaunchConfig": { "capAdd": [], "capDrop": [], "count": null, "cpuSet": null, "cpuShares": null, "dataVolumes": [], "dataVolumesFrom": [], "description": null, "devices": [], "dns": [], "dnsSearch": [], "domainName": null, "hostname": null, "imageUuid": "docker:ubuntu:trusty", "kind": "container", "labels": { "io.rancher.container.pull_image": "always" }, "logConfig": { "config": {}, "driver": "" }, "memory": null, "memoryMb": null, "memorySwap": null, "networkMode": "managed", "pidMode": null, "ports": [], "privileged": false, "publishAllPorts": false, "readOnly": false, "requestedIpAddress": null, "startOnCreate": true, "stdinOpen": true, "tty": true, "user": null, "userdata": null, "version": "0", "volumeDriver": null, "workingDir": null, "dataVolumesFromLaunchConfigs": [], "networkLaunchConfig": null, "vcpu": 1 }, "previousSecondaryLaunchConfigs": [], "secondaryLaunchConfigs": [], "startFirst": true }, "toServiceStrategy": null }, "uuid": "c0ae4d08-e20a-45ef-9fb9-ad9f7cdeeb15", "vip": null } ], "sortLinks": { "accountId": "http://172.30.0.100:8080/v1/services?limit=4&sort=accountId", "createIndex": "http://172.30.0.100:8080/v1/services?limit=4&sort=createIndex", "created": "http://172.30.0.100:8080/v1/services?limit=4&sort=created", "description": "http://172.30.0.100:8080/v1/services?limit=4&sort=description", "environmentId": "http://172.30.0.100:8080/v1/services?limit=4&sort=environmentId", "externalId": "http://172.30.0.100:8080/v1/services?limit=4&sort=externalId", "healthState": "http://172.30.0.100:8080/v1/services?limit=4&sort=healthState", "id": "http://172.30.0.100:8080/v1/services?limit=4&sort=id", "kind": "http://172.30.0.100:8080/v1/services?limit=4&sort=kind", "name": "http://172.30.0.100:8080/v1/services?limit=4&sort=name", "removeTime": "http://172.30.0.100:8080/v1/services?limit=4&sort=removeTime", "removed": "http://172.30.0.100:8080/v1/services?limit=4&sort=removed", "selectorContainer": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorContainer", "selectorLink": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorLink", "state": "http://172.30.0.100:8080/v1/services?limit=4&sort=state", "uuid": "http://172.30.0.100:8080/v1/services?limit=4&sort=uuid", "vip": "http://172.30.0.100:8080/v1/services?limit=4&sort=vip" }, "pagination": { "first": null, "previous": null, "next": "http://172.30.0.100:8080/v1/services?limit=4&marker=m4", "limit": 4, "total": null, "partial": true }, "sort": null, "filters": { "accountId": null, "createIndex": null, "created": null, "description": null, "environmentId": null, "externalId": null, "healthState": null, "id": null, "kind": null, "name": null, "removeTime": null, "removed": null, "selectorContainer": null, "selectorLink": null, "state": null, "uuid": null, "vip": null }, "createDefaults": {} }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/list_containers.json0000664000175000017500000003346713535474530030575 0ustar kamikami00000000000000{ "type": "collection", "resourceType": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers" }, "createTypes": { "container": "http://172.30.0.100:8080/v1/containers", "launchConfig": "http://172.30.0.100:8080/v1/launchconfigs", "virtualMachine": "http://172.30.0.100:8080/v1/virtualmachines" }, "actions": {}, "data": [ { "id": "1i1", "type": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers/1i1", "account": "http://172.30.0.100:8080/v1/containers/1i1/account", "credentials": "http://172.30.0.100:8080/v1/containers/1i1/credentials", "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i1/healthcheckinstancehostmaps", "hosts": "http://172.30.0.100:8080/v1/containers/1i1/hosts", "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i1/instancelabels", "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i1/instancelinks", "instances": "http://172.30.0.100:8080/v1/containers/1i1/instances", "mounts": "http://172.30.0.100:8080/v1/containers/1i1/mounts", "ports": "http://172.30.0.100:8080/v1/containers/1i1/ports", "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i1/serviceevents", "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i1/serviceexposemaps", "services": "http://172.30.0.100:8080/v1/containers/1i1/services", "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i1/targetinstancelinks", "volumes": "http://172.30.0.100:8080/v1/containers/1i1/volumes", "stats": "http://172.30.0.100:8080/v1/containers/1i1/stats", "containerStats": "http://172.30.0.100:8080/v1/containers/1i1/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/containers/1i1/?action=update", "error": "http://172.30.0.100:8080/v1/containers/1i1/?action=error", "remove": "http://172.30.0.100:8080/v1/containers/1i1/?action=remove", "start": "http://172.30.0.100:8080/v1/containers/1i1/?action=start", "logs": "http://172.30.0.100:8080/v1/containers/1i1/?action=logs", "setlabels": "http://172.30.0.100:8080/v1/containers/1i1/?action=setlabels" }, "name": "Concrete5_CMSMysql_1", "state": "stopped", "accountId": "1a5", "blkioDeviceOptions": null, "build": null, "capAdd": null, "capDrop": null, "command": null, "cpuSet": null, "cpuShares": null, "createIndex": 1, "created": "2016-09-22T17:58:55Z", "createdTS": 1474567135000, "dataVolumeMounts": {}, "dataVolumes": [ "CMS_DB_DATA:/var/lib/mysql" ], "dataVolumesFrom": null, "deploymentUnitUuid": "761675e2-7fc7-4fbf-a825-132429a44349", "description": null, "devices": null, "dns": [ "169.254.169.250" ], "dnsSearch": [ "concrete5.rancher.internal", "cmsmysql.concrete5.rancher.internal", "rancher.internal" ], "dockerPorts": [], "domainName": null, "entryPoint": null, "environment": { "MYSQL_DATABASE": "CMS_DB", "MYSQL_PASSWORD": "password", "MYSQL_ROOT_PASSWORD": "password", "MYSQL_USER": "CMS_USER" }, "expose": null, "externalId": "957136960bd1b51acf5a6c0079d0e35b8d5c14f54722a3063ceb868e85fd3758", "extraHosts": null, "firstRunning": "2016-09-22T17:59:40Z", "firstRunningTS": 1474567180000, "healthCheck": null, "healthState": null, "hostId": "1h1", "hostname": null, "imageUuid": "docker:mysql", "kind": "container", "labels": { "io.rancher.project.name": "Concrete5", "io.rancher.container.pull_image": "always", "io.rancher.service.deployment.unit": "761675e2-7fc7-4fbf-a825-132429a44349", "io.rancher.service.launch.config": "io.rancher.service.primary.launch.config", "io.rancher.project_service.name": "Concrete5/CMSMysql", "io.rancher.stack.name": "Concrete5", "io.rancher.stack_service.name": "Concrete5/CMSMysql", "io.rancher.service.hash": "c5d6bacef4be47a5ca5d1517a1d33319d024cdde", "io.rancher.container.uuid": "a1140e7c-9260-423e-a7d0-8f5f7bb8e946", "io.rancher.container.name": "Concrete5_CMSMysql_1", "io.rancher.container.ip": "10.42.80.96/16" }, "logConfig": {}, "lxcConf": null, "memory": null, "memorySwap": null, "nativeContainer": false, "networkContainerId": null, "networkMode": "managed", "pidMode": null, "ports": null, "primaryIpAddress": "10.42.80.96", "privileged": false, "publishAllPorts": false, "readOnly": false, "registryCredentialId": null, "removed": null, "requestedHostId": null, "restartPolicy": null, "securityOpt": null, "startCount": 4, "startOnCreate": true, "stdinOpen": true, "systemContainer": null, "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "tty": true, "user": null, "uuid": "a1140e7c-9260-423e-a7d0-8f5f7bb8e946", "version": "0", "volumeDriver": null, "workingDir": null }, { "id": "1i2", "type": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers/1i2", "account": "http://172.30.0.100:8080/v1/containers/1i2/account", "credentials": "http://172.30.0.100:8080/v1/containers/1i2/credentials", "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i2/healthcheckinstancehostmaps", "hosts": "http://172.30.0.100:8080/v1/containers/1i2/hosts", "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i2/instancelabels", "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/instancelinks", "instances": "http://172.30.0.100:8080/v1/containers/1i2/instances", "mounts": "http://172.30.0.100:8080/v1/containers/1i2/mounts", "ports": "http://172.30.0.100:8080/v1/containers/1i2/ports", "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i2/serviceevents", "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i2/serviceexposemaps", "services": "http://172.30.0.100:8080/v1/containers/1i2/services", "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/targetinstancelinks", "volumes": "http://172.30.0.100:8080/v1/containers/1i2/volumes", "stats": "http://172.30.0.100:8080/v1/containers/1i2/stats", "containerStats": "http://172.30.0.100:8080/v1/containers/1i2/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/containers/1i2/?action=update", "stop": "http://172.30.0.100:8080/v1/containers/1i2/?action=stop", "restart": "http://172.30.0.100:8080/v1/containers/1i2/?action=restart", "migrate": "http://172.30.0.100:8080/v1/containers/1i2/?action=migrate", "logs": "http://172.30.0.100:8080/v1/containers/1i2/?action=logs", "setlabels": "http://172.30.0.100:8080/v1/containers/1i2/?action=setlabels", "execute": "http://172.30.0.100:8080/v1/containers/1i2/?action=execute", "proxy": "http://172.30.0.100:8080/v1/containers/1i2/?action=proxy" }, "name": "Network Agent", "state": "running", "accountId": "1a5", "blkioDeviceOptions": null, "build": null, "capAdd": null, "capDrop": null, "command": null, "cpuSet": null, "cpuShares": null, "createIndex": null, "created": "2016-09-22T17:58:57Z", "createdTS": 1474567137000, "dataVolumeMounts": {}, "dataVolumes": [ "/var/lib/rancher/etc:/var/lib/rancher/etc:ro" ], "dataVolumesFrom": null, "deploymentUnitUuid": null, "description": null, "devices": null, "dns": null, "dnsSearch": null, "domainName": null, "entryPoint": null, "environment": null, "expose": null, "externalId": "129c67adc9fa084fbc8e1f963db0180896b88af3dca69c7e8fe0493284e4651c", "extraHosts": null, "firstRunning": "2016-09-22T17:59:11Z", "firstRunningTS": 1474567151000, "healthCheck": null, "healthState": null, "hostId": "1h1", "hostname": null, "imageUuid": "docker:rancher/agent-instance:v0.8.3", "kind": "container", "labels": { "io.rancher.container.system": "NetworkAgent", "io.rancher.container.uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb", "io.rancher.container.name": "Network Agent", "io.rancher.container.agent_id": "2", "io.rancher.container.ip": "10.42.247.188/16" }, "logConfig": null, "lxcConf": null, "memory": null, "memorySwap": null, "nativeContainer": false, "networkContainerId": null, "networkIds": [], "networkMode": null, "pidMode": null, "ports": null, "primaryIpAddress": "10.42.247.188", "privileged": true, "publishAllPorts": false, "readOnly": false, "registryCredentialId": null, "removed": null, "requestedHostId": null, "restartPolicy": null, "securityOpt": null, "startCount": 3, "startOnCreate": true, "stdinOpen": false, "systemContainer": "NetworkAgent", "transitioning": "no", "transitioningMessage": null, "transitioningProgress": null, "tty": false, "user": null, "uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb", "version": "0", "volumeDriver": null, "workingDir": null } ], "sortLinks": { "accountId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=accountId", "agentId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=agentId", "allocationState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=allocationState", "compute": "http://172.30.0.100:8080/v1/containers?limit=2&sort=compute", "createIndex": "http://172.30.0.100:8080/v1/containers?limit=2&sort=createIndex", "created": "http://172.30.0.100:8080/v1/containers?limit=2&sort=created", "deploymentUnitUuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=deploymentUnitUuid", "description": "http://172.30.0.100:8080/v1/containers?limit=2&sort=description", "dnsInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsInternal", "dnsSearchInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsSearchInternal", "domain": "http://172.30.0.100:8080/v1/containers?limit=2&sort=domain", "externalId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=externalId", "firstRunning": "http://172.30.0.100:8080/v1/containers?limit=2&sort=firstRunning", "healthState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthState", "healthUpdated": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthUpdated", "hostname": "http://172.30.0.100:8080/v1/containers?limit=2&sort=hostname", "id": "http://172.30.0.100:8080/v1/containers?limit=2&sort=id", "imageId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=imageId", "instanceTriggeredStop": "http://172.30.0.100:8080/v1/containers?limit=2&sort=instanceTriggeredStop", "kind": "http://172.30.0.100:8080/v1/containers?limit=2&sort=kind", "memoryMb": "http://172.30.0.100:8080/v1/containers?limit=2&sort=memoryMb", "name": "http://172.30.0.100:8080/v1/containers?limit=2&sort=name", "nativeContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=nativeContainer", "networkContainerId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=networkContainerId", "offeringId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=offeringId", "registryCredentialId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=registryCredentialId", "removeTime": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removeTime", "removed": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removed", "serviceIndexId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=serviceIndexId", "startCount": "http://172.30.0.100:8080/v1/containers?limit=2&sort=startCount", "state": "http://172.30.0.100:8080/v1/containers?limit=2&sort=state", "systemContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=systemContainer", "token": "http://172.30.0.100:8080/v1/containers?limit=2&sort=token", "userdata": "http://172.30.0.100:8080/v1/containers?limit=2&sort=userdata", "uuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=uuid", "version": "http://172.30.0.100:8080/v1/containers?limit=2&sort=version", "zoneId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=zoneId" }, "pagination": { "first": null, "previous": null, "next": "http://172.30.0.100:8080/v1/containers?limit=2&marker=m2", "limit": 2, "total": null, "partial": true }, "sort": null, "filters": { "accountId": null, "agentId": null, "allocationState": null, "compute": null, "createIndex": null, "created": null, "deploymentUnitUuid": null, "description": null, "dnsInternal": null, "dnsSearchInternal": null, "domain": null, "externalId": null, "firstRunning": null, "healthState": null, "healthUpdated": null, "hostname": null, "id": null, "imageId": null, "instanceTriggeredStop": null, "kind": null, "memoryMb": null, "name": null, "nativeContainer": null, "networkContainerId": null, "offeringId": null, "registryCredentialId": null, "removeTime": null, "removed": null, "serviceIndexId": null, "startCount": null, "state": null, "systemContainer": null, "token": null, "userdata": null, "uuid": null, "version": null, "zoneId": null }, "createDefaults": {} }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/start_container.json0000664000175000017500000000734413535474530030567 0ustar kamikami00000000000000{ "id": "1i31", "type": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers/1i31", "account": "http://172.30.0.100:8080/v1/containers/1i31/account", "credentials": "http://172.30.0.100:8080/v1/containers/1i31/credentials", "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i31/healthcheckinstancehostmaps", "hosts": "http://172.30.0.100:8080/v1/containers/1i31/hosts", "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i31/instancelabels", "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/instancelinks", "instances": "http://172.30.0.100:8080/v1/containers/1i31/instances", "mounts": "http://172.30.0.100:8080/v1/containers/1i31/mounts", "ports": "http://172.30.0.100:8080/v1/containers/1i31/ports", "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i31/serviceevents", "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i31/serviceexposemaps", "services": "http://172.30.0.100:8080/v1/containers/1i31/services", "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/targetinstancelinks", "volumes": "http://172.30.0.100:8080/v1/containers/1i31/volumes", "stats": "http://172.30.0.100:8080/v1/containers/1i31/stats", "containerStats": "http://172.30.0.100:8080/v1/containers/1i31/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/containers/1i31/?action=update", "error": "http://172.30.0.100:8080/v1/containers/1i31/?action=error", "remove": "http://172.30.0.100:8080/v1/containers/1i31/?action=remove", "start": "http://172.30.0.100:8080/v1/containers/1i31/?action=start", "logs": "http://172.30.0.100:8080/v1/containers/1i31/?action=logs", "setlabels": "http://172.30.0.100:8080/v1/containers/1i31/?action=setlabels" }, "name": "newcontainer", "state": "starting", "accountId": "1a5", "blkioDeviceOptions": null, "build": null, "capAdd": null, "capDrop": null, "command": null, "cpuSet": null, "cpuShares": null, "createIndex": null, "created": "2016-10-06T15:55:58Z", "createdTS": 1475769358000, "dataVolumeMounts": {}, "dataVolumes": [], "dataVolumesFrom": null, "deploymentUnitUuid": null, "description": null, "devices": null, "dns": [ "169.254.169.250" ], "dnsSearch": [ "rancher.internal" ], "dockerPorts": [], "domainName": null, "entryPoint": null, "environment": { "STORAGE_TYPE": "file" }, "expose": null, "externalId": "ab334bd25d25db7b94fdcead8f5c023b05bed424f56243187aa90f5ef7f07b09", "extraHosts": null, "firstRunning": "2016-10-06T15:56:00Z", "firstRunningTS": 1475769360000, "healthCheck": null, "healthState": null, "hostId": "1h1", "hostname": null, "imageUuid": "docker:rlister/hastebin:latest", "kind": "container", "labels": { "io.rancher.container.uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805", "io.rancher.container.name": "newcontainer", "io.rancher.container.ip": "10.42.204.104/16" }, "logConfig": null, "lxcConf": null, "memory": null, "memorySwap": null, "nativeContainer": false, "networkContainerId": null, "networkMode": "managed", "pidMode": null, "ports": null, "primaryIpAddress": "10.42.204.104", "privileged": false, "publishAllPorts": false, "readOnly": false, "registryCredentialId": null, "removed": null, "requestedHostId": null, "restartPolicy": null, "securityOpt": null, "startCount": 1, "startOnCreate": true, "stdinOpen": false, "systemContainer": null, "transitioning": "yes", "transitioningMessage": null, "transitioningProgress": null, "tty": false, "user": null, "uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805", "version": "0", "volumeDriver": null, "workingDir": null }apache-libcloud-2.8.0/libcloud/test/container/fixtures/rancher/stop_container.json0000664000175000017500000000734413535474530030417 0ustar kamikami00000000000000{ "id": "1i31", "type": "container", "links": { "self": "http://172.30.0.100:8080/v1/containers/1i31", "account": "http://172.30.0.100:8080/v1/containers/1i31/account", "credentials": "http://172.30.0.100:8080/v1/containers/1i31/credentials", "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i31/healthcheckinstancehostmaps", "hosts": "http://172.30.0.100:8080/v1/containers/1i31/hosts", "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i31/instancelabels", "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/instancelinks", "instances": "http://172.30.0.100:8080/v1/containers/1i31/instances", "mounts": "http://172.30.0.100:8080/v1/containers/1i31/mounts", "ports": "http://172.30.0.100:8080/v1/containers/1i31/ports", "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i31/serviceevents", "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i31/serviceexposemaps", "services": "http://172.30.0.100:8080/v1/containers/1i31/services", "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/targetinstancelinks", "volumes": "http://172.30.0.100:8080/v1/containers/1i31/volumes", "stats": "http://172.30.0.100:8080/v1/containers/1i31/stats", "containerStats": "http://172.30.0.100:8080/v1/containers/1i31/containerstats" }, "actions": { "update": "http://172.30.0.100:8080/v1/containers/1i31/?action=update", "error": "http://172.30.0.100:8080/v1/containers/1i31/?action=error", "remove": "http://172.30.0.100:8080/v1/containers/1i31/?action=remove", "start": "http://172.30.0.100:8080/v1/containers/1i31/?action=start", "logs": "http://172.30.0.100:8080/v1/containers/1i31/?action=logs", "setlabels": "http://172.30.0.100:8080/v1/containers/1i31/?action=setlabels" }, "name": "newcontainer", "state": "stopping", "accountId": "1a5", "blkioDeviceOptions": null, "build": null, "capAdd": null, "capDrop": null, "command": null, "cpuSet": null, "cpuShares": null, "createIndex": null, "created": "2016-10-06T15:55:58Z", "createdTS": 1475769358000, "dataVolumeMounts": {}, "dataVolumes": [], "dataVolumesFrom": null, "deploymentUnitUuid": null, "description": null, "devices": null, "dns": [ "169.254.169.250" ], "dnsSearch": [ "rancher.internal" ], "dockerPorts": [], "domainName": null, "entryPoint": null, "environment": { "STORAGE_TYPE": "file" }, "expose": null, "externalId": "ab334bd25d25db7b94fdcead8f5c023b05bed424f56243187aa90f5ef7f07b09", "extraHosts": null, "firstRunning": "2016-10-06T15:56:00Z", "firstRunningTS": 1475769360000, "healthCheck": null, "healthState": null, "hostId": "1h1", "hostname": null, "imageUuid": "docker:rlister/hastebin:latest", "kind": "container", "labels": { "io.rancher.container.uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805", "io.rancher.container.name": "newcontainer", "io.rancher.container.ip": "10.42.204.104/16" }, "logConfig": null, "lxcConf": null, "memory": null, "memorySwap": null, "nativeContainer": false, "networkContainerId": null, "networkMode": "managed", "pidMode": null, "ports": null, "primaryIpAddress": "10.42.204.104", "privileged": false, "publishAllPorts": false, "readOnly": false, "registryCredentialId": null, "removed": null, "requestedHostId": null, "restartPolicy": null, "securityOpt": null, "startCount": 1, "startOnCreate": true, "stdinOpen": false, "systemContainer": null, "transitioning": "yes", "transitioningMessage": null, "transitioningProgress": null, "tty": false, "user": null, "uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805", "version": "0", "volumeDriver": null, "workingDir": null }apache-libcloud-2.8.0/libcloud/test/container/test_docker.py0000664000175000017500000002562113535474530024060 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.test import unittest from libcloud.container.base import ContainerImage from libcloud.container.drivers.docker import DockerContainerDriver from libcloud.utils.py3 import httplib from libcloud.test.secrets import CONTAINER_PARAMS_DOCKER from libcloud.test.file_fixtures import ContainerFileFixtures from libcloud.test import MockHttp class DockerContainerDriverTestCase(unittest.TestCase): def setUp(self): # Create a test driver for each version versions = ('linux_124', 'mac_124') self.drivers = [] for version in versions: DockerContainerDriver.connectionCls.conn_class = \ DockerMockHttp DockerMockHttp.type = None DockerMockHttp.use_param = 'a' driver = DockerContainerDriver(*CONTAINER_PARAMS_DOCKER) driver.version = version self.drivers.append(driver) def test_list_images(self): for driver in self.drivers: images = driver.list_images() self.assertEqual(len(images), 4) self.assertIsInstance(images[0], ContainerImage) self.assertEqual(images[0].id, 'cf55d61f5307b7a18a45980971d6cfd40b737dd661879c4a6b3f2aecc3bc37b0') self.assertEqual(images[0].name, 'mongo:latest') def test_install_image(self): for driver in self.drivers: image = driver.install_image('ubuntu:12.04') self.assertTrue(image is not None) self.assertEqual(image.id, '992069aee4016783df6345315302fa59681aae51a8eeb2f889dea59290f21787') def test_list_containers(self): for driver in self.drivers: containers = driver.list_containers(all=True) self.assertEqual(len(containers), 6) self.assertEqual(containers[0].id, '160936dc54fe8c332095676d9379003534b8cddd7565fa63018996e06dae1b6b') self.assertEqual(containers[0].name, 'hubot') self.assertEqual(containers[0].image.name, 'stackstorm/hubot') def test_deploy_container(self): for driver in self.drivers: image = driver.list_images()[0] container = driver.deploy_container(image=image, name='test') self.assertEqual(container.id, 'a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') self.assertEqual(container.name, 'gigantic_goldberg') def test_get_container(self): for driver in self.drivers: container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') self.assertEqual(container.id, 'a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') self.assertEqual(container.name, 'gigantic_goldberg') self.assertEqual(container.state, 'running') def test_start_container(self): for driver in self.drivers: container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') container.start() def test_stop_container(self): for driver in self.drivers: container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') container.stop() def test_restart_container(self): for driver in self.drivers: container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') container.restart() def test_delete_container(self): for driver in self.drivers: container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') container.destroy() def test_ex_rename_container(self): for driver in self.drivers: container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') driver.ex_rename_container(container, 'bob') def test_ex_get_logs(self): for driver in self.drivers: container = driver.get_container('a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303') logs = driver.ex_get_logs(container) self.assertTrue(logs is not None) def test_ex_search_images(self): for driver in self.drivers: images = driver.ex_search_images('mysql') self.assertEqual(len(images), 25) self.assertEqual(images[0].name, 'mysql') class DockerMockHttp(MockHttp): fixtures = ContainerFileFixtures('docker') version = None def _version( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('linux_124/version.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _vlinux_124_images_search( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/search.json'), {}, httplib.responses[httplib.OK]) def _vmac_124_images_search( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('mac_124/search.json'), {}, httplib.responses[httplib.OK]) def _vlinux_124_images_json( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/images.json'), {}, httplib.responses[httplib.OK]) def _vmac_124_images_json( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/images.json'), {}, httplib.responses[httplib.OK]) def _vlinux_124_images_create( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/create_image.txt'), {'Content-Type': 'application/json', 'transfer-encoding': 'chunked'}, httplib.responses[httplib.OK]) def _vmac_124_images_create( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('mac_124/create_image.txt'), {'Content-Type': 'application/json', 'transfer-encoding': 'chunked'}, httplib.responses[httplib.OK]) def _vlinux_124_containers_json( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/containers.json'), {}, httplib.responses[httplib.OK]) def _vmac_124_containers_json( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('mac_124/containers.json'), {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_create( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/create_container.json'), {}, httplib.responses[httplib.OK]) def _vmac_124_containers_create( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('mac_124/create_container.json'), {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vmac_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_start( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vmac_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_start( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_restart( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vmac_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_restart( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_rename( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vmac_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_rename( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_stop( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vmac_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_stop( self, method, url, body, headers): return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_json( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/container_a68.json'), {}, httplib.responses[httplib.OK]) def _vmac_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_json( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/container_a68.json'), {}, httplib.responses[httplib.OK]) def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_logs( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/logs.txt'), {'content-type': 'text/plain'}, httplib.responses[httplib.OK]) def _vmac_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_logs( self, method, url, body, headers): return (httplib.OK, self.fixtures.load('linux_124/logs.txt'), {'content-type': 'text/plain'}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/container/test_docker_utils.py0000664000175000017500000000600413535474530025272 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.test import unittest from libcloud.container.utils.docker import HubClient from libcloud.utils.py3 import httplib from libcloud.test.file_fixtures import ContainerFileFixtures from libcloud.test import MockHttp class DockerUtilitiesTestCase(unittest.TestCase): def setUp(self): HubClient.connectionCls.conn_class = DockerMockHttp DockerMockHttp.type = None DockerMockHttp.use_param = 'a' self.driver = HubClient() def test_list_tags(self): tags = self.driver.list_images('ubuntu', max_count=100) self.assertEqual(len(tags), 88) self.assertEqual(tags[0].name, 'registry.hub.docker.com/ubuntu:xenial') def test_get_repository(self): repo = self.driver.get_repository('ubuntu') self.assertEqual(repo['name'], 'ubuntu') def test_get_image(self): image = self.driver.get_image('ubuntu', 'latest') self.assertEqual(image.id, '2343') self.assertEqual(image.name, 'registry.hub.docker.com/ubuntu:latest') self.assertEqual(image.path, 'registry.hub.docker.com/ubuntu:latest') class DockerMockHttp(MockHttp): fixtures = ContainerFileFixtures('docker_utils') def _v2_repositories_library_ubuntu_tags_latest( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v2_repositories_library_ubuntu_tags_latest.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_repositories_library_ubuntu_tags( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v2_repositories_library_ubuntu_tags.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v2_repositories_library_ubuntu( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('v2_repositories_library_ubuntu.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/container/test_ecs.py0000664000175000017500000001733213535474530023363 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.test import unittest from libcloud.container.base import ContainerCluster, ContainerImage, Container from libcloud.container.drivers.ecs import ElasticContainerDriver from libcloud.container.utils.docker import RegistryClient from libcloud.utils.py3 import httplib from libcloud.test.secrets import CONTAINER_PARAMS_ECS from libcloud.test.file_fixtures import ContainerFileFixtures from libcloud.test import MockHttp class ElasticContainerDriverTestCase(unittest.TestCase): def setUp(self): ElasticContainerDriver.connectionCls.conn_class = ECSMockHttp ECSMockHttp.type = None ECSMockHttp.use_param = 'a' ElasticContainerDriver.ecrConnectionClass.conn_class = ECSMockHttp self.driver = ElasticContainerDriver(*CONTAINER_PARAMS_ECS) def test_list_clusters(self): clusters = self.driver.list_clusters() self.assertEqual(len(clusters), 1) self.assertEqual(clusters[0].id, 'arn:aws:ecs:us-east-1:012345678910:cluster/default') self.assertEqual(clusters[0].name, 'default') def test_create_cluster(self): cluster = self.driver.create_cluster('my-cluster') self.assertEqual(cluster.name, 'my-cluster') def test_destroy_cluster(self): self.assertTrue( self.driver.destroy_cluster( ContainerCluster( id='arn:aws:ecs:us-east-1:012345678910:cluster/jim', name='jim', driver=self.driver))) def test_list_containers(self): containers = self.driver.list_containers() self.assertEqual(len(containers), 1) def test_list_containers_for_cluster(self): cluster = self.driver.list_clusters()[0] containers = self.driver.list_containers(cluster=cluster) self.assertEqual(len(containers), 1) def test_deploy_container(self): container = self.driver.deploy_container( name='jim', image=ContainerImage( id=None, name='mysql', path='mysql', version=None, driver=self.driver ) ) self.assertEqual(container.id, 'arn:aws:ecs:ap-southeast-2:647433528374:container/e443d10f-dea3-481e-8a1e-966b9ad4e498') def test_get_container(self): container = self.driver.get_container( 'arn:aws:ecs:us-east-1:012345678910:container/76c980a8-2454-4a9c-acc4-9eb103117273' ) self.assertEqual(container.id, 'arn:aws:ecs:ap-southeast-2:647433528374:container/d56d4e2c-9804-42a7-9f2a-6029cb50d4a2') self.assertEqual(container.name, 'simple-app') self.assertEqual(container.image.name, 'simple-app') def test_start_container(self): container = self.driver.start_container( Container( id=None, name=None, image=None, state=None, ip_addresses=None, driver=self.driver, extra={ 'taskDefinitionArn': '' } ) ) self.assertFalse(container is None) def test_stop_container(self): container = self.driver.stop_container( Container( id=None, name=None, image=None, state=None, ip_addresses=None, driver=self.driver, extra={ 'taskArn': '12345', 'taskDefinitionArn': '123556' } ) ) self.assertFalse(container is None) def test_restart_container(self): container = self.driver.restart_container( Container( id=None, name=None, image=None, state=None, ip_addresses=None, driver=self.driver, extra={ 'taskArn': '12345', 'taskDefinitionArn': '123556' } ) ) self.assertFalse(container is None) def test_list_images(self): images = self.driver.list_images('my-images') self.assertEqual(len(images), 1) self.assertEqual(images[0].name, '647433528374.dkr.ecr.region.amazonaws.com/my-images:latest') def test_ex_create_service(self): cluster = self.driver.list_clusters()[0] task_definition = self.driver.list_containers()[0].extra['taskDefinitionArn'] service = self.driver.ex_create_service(cluster=cluster, name='jim', task_definition=task_definition) self.assertEqual(service['serviceName'], 'test') def test_ex_list_service_arns(self): arns = self.driver.ex_list_service_arns() self.assertEqual(len(arns), 2) def test_ex_describe_service(self): arn = self.driver.ex_list_service_arns()[0] service = self.driver.ex_describe_service(arn) self.assertEqual(service['serviceName'], 'test') def test_ex_destroy_service(self): arn = self.driver.ex_list_service_arns()[0] service = self.driver.ex_destroy_service(arn) self.assertEqual(service['status'], 'DRAINING') def test_ex_get_registry_client(self): client = self.driver.ex_get_registry_client('my-images') self.assertIsInstance(client, RegistryClient) class ECSMockHttp(MockHttp): fixtures = ContainerFileFixtures('ecs') fixture_map = { 'DescribeClusters': 'describeclusters.json', 'CreateCluster': 'createcluster.json', 'DeleteCluster': 'deletecluster.json', 'DescribeTasks': 'describetasks.json', 'ListTasks': 'listtasks.json', 'ListClusters': 'listclusters.json', 'RegisterTaskDefinition': 'registertaskdefinition.json', 'RunTask': 'runtask.json', 'StopTask': 'stoptask.json', 'ListImages': 'listimages.json', 'DescribeRepositories': 'describerepositories.json', 'CreateService': 'createservice.json', 'ListServices': 'listservices.json', 'DescribeServices': 'describeservices.json', 'DeleteService': 'deleteservice.json', 'GetAuthorizationToken': 'getauthorizationtoken.json' } def root(self, method, url, body, headers): target = headers['x-amz-target'] # Workaround for host not being correctly set for the tests if '%s' in self.host: self.host = self.host % ('region') if target is not None: type = target.split('.')[-1] if type is None or self.fixture_map.get(type) is None: raise AssertionError('Unsupported request type %s' % (target)) body = self.fixtures.load(self.fixture_map.get(type)) else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/container/test_gke.py0000664000175000017500000000711313535474530023353 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Tests for Google Container Engine Driver """ import sys import unittest from libcloud.utils.py3 import httplib from libcloud.container.drivers.gke import GKEContainerDriver, API_VERSION from libcloud.common.google import (GoogleBaseAuthConnection) from libcloud.test.common.test_google import GoogleAuthMockHttp, GoogleTestCase from libcloud.test import MockHttp from libcloud.test.container import TestCaseMixin from libcloud.test.file_fixtures import ContainerFileFixtures from libcloud.test.secrets import GKE_PARAMS, GKE_KEYWORD_PARAMS class GKEContainerDriverTestCase(GoogleTestCase, TestCaseMixin): """ Google Compute Engine Test Class. """ # Mock out a few specific calls that interact with the user, system or # environment. datacenter = 'us-central1-a' def setUp(self): GKEMockHttp.test = self GKEContainerDriver.connectionCls.conn_class = GKEMockHttp GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp GKEMockHttp.type = None kwargs = GKE_KEYWORD_PARAMS.copy() kwargs['auth_type'] = 'IA' kwargs['datacenter'] = self.datacenter self.driver = GKEContainerDriver(*GKE_PARAMS, **kwargs) def test_list_images_response(self): config = self.driver.list_clusters(ex_zone="us-central1-a") assert "clusters" in config assert config["clusters"][0]["zone"] == "us-central1-a" def test_server_config(self): config = self.driver.get_server_config() assert "validImageTypes" in config class GKEMockHttp(MockHttp): fixtures = ContainerFileFixtures('gke') json_hdr = {'content-type': 'application/json; charset=UTF-8'} def _get_method_name(self, type, use_param, qs, path): api_path = '/%s' % API_VERSION project_path = '/projects/%s' % GKE_KEYWORD_PARAMS['project'] path = path.replace(api_path, '') # This replace is separate, since there is a call with a different # project name path = path.replace(project_path, '') # The path to get project information is the base path, so use a fake # '/project' path instead if not path: path = '/project' method_name = super(GKEMockHttp, self)._get_method_name( type, use_param, qs, path) return method_name def _zones_us_central1_a_serverconfig(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_instance_serverconfig.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) def _zones_us_central1_a_clusters(self, method, url, body, headers): body = self.fixtures.load( 'zones_us-central1-a_list.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/container/test_joyent.py0000664000175000017500000000313013535474530024110 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.test import unittest from libcloud.container.drivers.joyent import JoyentContainerDriver from libcloud.test.secrets import CONTAINER_PARAMS_DOCKER from libcloud.test.container.test_docker import DockerContainerDriverTestCase, DockerMockHttp class JoyentContainerDriverTestCase(DockerContainerDriverTestCase, unittest.TestCase): def setUp(self): # Create a test driver for each version versions = ('linux_124', 'mac_124') self.drivers = [] for version in versions: JoyentContainerDriver.connectionCls.conn_class = \ DockerMockHttp DockerMockHttp.type = None DockerMockHttp.use_param = 'a' driver = JoyentContainerDriver(*CONTAINER_PARAMS_DOCKER) driver.version = version self.drivers.append(driver) apache-libcloud-2.8.0/libcloud/test/container/test_kubernetes.py0000664000175000017500000001162213535474530024754 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.test import unittest from libcloud.container.base import ContainerImage from libcloud.container.drivers.kubernetes import KubernetesContainerDriver from libcloud.utils.py3 import httplib from libcloud.test.secrets import CONTAINER_PARAMS_KUBERNETES from libcloud.test.file_fixtures import ContainerFileFixtures from libcloud.test import MockHttp class KubernetesContainerDriverTestCase(unittest.TestCase): def setUp(self): KubernetesContainerDriver.connectionCls.conn_class = KubernetesMockHttp KubernetesMockHttp.type = None KubernetesMockHttp.use_param = 'a' self.driver = KubernetesContainerDriver(*CONTAINER_PARAMS_KUBERNETES) def test_list_containers(self): containers = self.driver.list_containers() self.assertEqual(len(containers), 1) self.assertEqual(containers[0].id, 'docker://3c48b5cda79bce4c8866f02a3b96a024edb8f660d10e7d1755e9ced49ef47b36') self.assertEqual(containers[0].name, 'hello-world') def test_list_clusters(self): clusters = self.driver.list_clusters() self.assertEqual(len(clusters), 2) self.assertEqual(clusters[0].id, 'default') self.assertEqual(clusters[0].name, 'default') def test_get_cluster(self): cluster = self.driver.get_cluster('default') self.assertEqual(cluster.id, 'default') self.assertEqual(cluster.name, 'default') def test_create_cluster(self): cluster = self.driver.create_cluster('test') self.assertEqual(cluster.id, 'test') self.assertEqual(cluster.name, 'test') def test_destroy_cluster(self): cluster = self.driver.get_cluster('default') result = self.driver.destroy_cluster(cluster) self.assertTrue(result) def test_deploy_container(self): image = ContainerImage( id=None, name='hello-world', path=None, driver=self.driver, version=None ) container = self.driver.deploy_container('hello-world', image=image) self.assertEqual(container.name, 'hello-world') def test_get_container(self): container = self.driver.get_container('docker://3c48b5cda79bce4c8866f02a3b96a024edb8f660d10e7d1755e9ced49ef47b36') assert container.id == 'docker://3c48b5cda79bce4c8866f02a3b96a024edb8f660d10e7d1755e9ced49ef47b36' class KubernetesMockHttp(MockHttp): fixtures = ContainerFileFixtures('kubernetes') def _api_v1_pods( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_api_v1_pods.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_v1_namespaces( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_api_v1_namespaces.json') elif method == 'POST': body = self.fixtures.load('_api_v1_namespaces_test.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_v1_namespaces_default( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_api_v1_namespaces_default.json') elif method == 'DELETE': body = self.fixtures.load('_api_v1_namespaces_default_DELETE.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_v1_namespaces_default_pods( self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('_api_v1_namespaces_default_pods.json') elif method == 'POST': body = self.fixtures.load('_api_v1_namespaces_default_pods_POST.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/container/test_rancher.py0000664000175000017500000003202013535474530024222 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.test import unittest from libcloud.container.base import ContainerImage from libcloud.container.drivers.rancher import RancherContainerDriver from libcloud.utils.py3 import httplib from libcloud.test.secrets import CONTAINER_PARAMS_RANCHER from libcloud.test.file_fixtures import ContainerFileFixtures from libcloud.test import MockHttp # --------------------------------------------------------------------------- # # Mock Classes class RancherMockHttp(MockHttp): fixtures = ContainerFileFixtures('rancher') def _v1_environments(self, method, url, body, headers): if method == 'GET': return (httplib.OK, self.fixtures.load('ex_list_stacks.json'), {}, httplib.responses[httplib.OK]) else: return (httplib.OK, self.fixtures.load('ex_deploy_stack.json'), {}, httplib.responses[httplib.OK]) def _v1_environments_1e9(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('ex_deploy_stack.json'), {}, httplib.responses[httplib.OK]) def _v1_environments_1e10(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('ex_destroy_stack.json'), {}, httplib.responses[httplib.OK]) def _v1_environments_1e1(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('ex_activate_stack.json'), {}, httplib.responses[httplib.OK]) def _v1_services(self, method, url, body, headers): if '?healthState=healthy' in url: return (httplib.OK, self.fixtures.load('ex_search_services.json'), {}, httplib.responses[httplib.OK]) elif method == 'GET': return (httplib.OK, self.fixtures.load('ex_list_services.json'), {}, httplib.responses[httplib.OK]) else: return (httplib.OK, self.fixtures.load('ex_deploy_service.json'), {}, httplib.responses[httplib.OK]) def _v1_services_1s13(self, method, url, body, headers): if method == 'GET': return (httplib.OK, self.fixtures.load('ex_deploy_service.json'), {}, httplib.responses[httplib.OK]) elif method == 'DELETE': return (httplib.OK, self.fixtures.load('ex_destroy_service.json'), {}, httplib.responses[httplib.OK]) def _v1_services_1s6(self, method, url, body, headers): return (httplib.OK, self.fixtures.load('ex_activate_service.json'), {}, httplib.responses[httplib.OK]) def _v1_containers(self, method, url, body, headers): if '?state=running' in url: return (httplib.OK, self.fixtures.load('ex_search_containers.json'), {}, httplib.responses[httplib.OK]) elif method == 'POST': return (httplib.OK, self.fixtures.load('deploy_container.json'), {}, httplib.responses[httplib.OK]) return (httplib.OK, self.fixtures.load('list_containers.json'), {}, httplib.responses[httplib.OK]) def _v1_containers_1i31(self, method, url, body, headers): if method == 'GET': return (httplib.OK, self.fixtures.load('deploy_container.json'), {}, httplib.responses[httplib.OK]) elif method == 'DELETE' or '?action=stop' in url: return (httplib.OK, self.fixtures.load('stop_container.json'), {}, httplib.responses[httplib.OK]) elif '?action=start' in url: return (httplib.OK, self.fixtures.load('start_container.json'), {}, httplib.responses[httplib.OK]) else: return (httplib.OK, self.fixtures.load('deploy_container.json'), {}, httplib.responses[httplib.OK]) RancherContainerDriver.connectionCls.conn_class = RancherMockHttp RancherMockHttp.type = None RancherMockHttp.use_param = 'a' # --------------------------------------------------------------------------- # # Test Cases class RancherContainerDriverInitTestCase(unittest.TestCase): """ Tests for testing the different permutations of the driver initialization string. """ def test_full_url_string(self): """ Test a 'full' URL string, which contains a scheme, port, and base path. """ path = "http://myhostname:1234/base" driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path) self.assertEqual(driver.secure, False) self.assertEqual(driver.connection.host, "myhostname") self.assertEqual(driver.connection.port, 1234) self.assertEqual(driver.baseuri, "/base") def test_url_string_no_port(self): """ Test a partial URL string, which contains a scheme, and base path. """ path = "http://myhostname/base" driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path, port=1234) self.assertEqual(driver.secure, False) self.assertEqual(driver.connection.host, "myhostname") self.assertEqual(driver.connection.port, 1234) self.assertEqual(driver.baseuri, "/base") def test_url_string_no_scheme(self): """ Test a partial URL string, which contains a port, and base path. """ path = "myhostname:1234/base" driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path) self.assertEqual(driver.secure, True) self.assertEqual(driver.connection.host, "myhostname") self.assertEqual(driver.connection.port, 1234) self.assertEqual(driver.baseuri, "/base") def test_url_string_no_base_path(self): """ Test a partial URL string, which contains a scheme, and a port. """ path = "http://myhostname:1234" driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path) self.assertEqual(driver.secure, False) self.assertEqual(driver.connection.host, "myhostname") self.assertEqual(driver.connection.port, 1234) self.assertEqual(driver.baseuri, "/v%s" % driver.version) class RancherContainerDriverTestCase(unittest.TestCase): def setUp(self): self.driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER) # Stacks def test_ex_list_stacks(self): stacks = self.driver.ex_list_stacks() self.assertEqual(len(stacks), 6) self.assertEqual(stacks[0]['id'], "1e1") def test_ex_deploy_stack(self): stack = self.driver.ex_deploy_stack(name="newstack", environment={ "root_password": "password" }) self.assertEqual(stack['id'], "1e9") self.assertEqual(stack['environment']['root_password'], "password") def test_ex_get_stack(self): # also uses ex_deploy_stack.json stack = self.driver.ex_get_stack("1e9") self.assertEqual(stack['id'], "1e9") self.assertEqual(stack['environment']['root_password'], "password") def test_ex_search_stacks(self): stacks = self.driver.ex_search_stacks({"healthState": "healthy"}) self.assertEqual(len(stacks), 6) self.assertEqual(stacks[0]['healthState'], "healthy") def test_ex_destroy_stack(self): response = self.driver.ex_destroy_stack("1e10") self.assertEqual(response, True) def test_ex_activate_stack(self): response = self.driver.ex_activate_stack("1e1") self.assertEqual(response, True) def test_ex_deactivate_stack(self): # also uses ex_activate_stack.json response = self.driver.ex_activate_stack("1e1") self.assertEqual(response, True) def test_ex_list_services(self): services = self.driver.ex_list_services() self.assertEqual(len(services), 4) self.assertEqual(services[0]['id'], "1s1") def test_ex_deploy_service(self): image = ContainerImage( id="hastebin", name="hastebin", path="rlister/hastebin", version="latest", driver=None ) service = self.driver.ex_deploy_service(name="newservice", environment_id="1e1", image=image, environment={ "root_password": "password" }) self.assertEqual(service['id'], "1s13") self.assertEqual(service['environmentId'], "1e6") self.assertEqual(service['launchConfig']['environment'] ['root_password'], "password") self.assertEqual(service['launchConfig']['imageUuid'], "docker:rlister/hastebin:latest") def test_ex_get_service(self): # also uses ex_deploy_service.json service = self.driver.ex_get_service("1s13") self.assertEqual(service['id'], "1s13") self.assertEqual(service['environmentId'], "1e6") self.assertEqual(service['launchConfig']['environment'] ['root_password'], "password") def test_ex_search_services(self): services = self.driver.ex_search_services({"healthState": "healthy"}) self.assertEqual(len(services), 2) self.assertEqual(services[0]['healthState'], "healthy") def test_ex_destroy_service(self): # Not sure how to do these with returns in mockhttp response = self.driver.ex_destroy_service("1s13") self.assertEqual(response, True) def test_ex_activate_service(self): response = self.driver.ex_activate_service("1s6") self.assertEqual(response, True) def test_ex_deactivate_service(self): # also uses ex_activate_service.json response = self.driver.ex_activate_service("1s6") self.assertEqual(response, True) def test_list_containers(self): containers = self.driver.list_containers() self.assertEqual(len(containers), 2) self.assertEqual(containers[0].id, "1i1") def test_deploy_container(self): container = self.driver.deploy_container( name='newcontainer', image=ContainerImage( id="hastebin", name="hastebin", path="rlister/hastebin", version="latest", driver=None ), environment={"STORAGE_TYPE": "file"}, networkMode="managed" ) self.assertEqual(container.id, '1i31') self.assertEqual(container.name, 'newcontainer') self.assertEqual(container.extra['environment'], {'STORAGE_TYPE': 'file'}) def test_get_container(self): # also uses ex_deploy_container.json container = self.driver.get_container("1i31") self.assertEqual(container.id, '1i31') self.assertEqual(container.name, 'newcontainer') self.assertEqual(container.extra['environment'], {'STORAGE_TYPE': 'file'}) def test_start_container(self): container = self.driver.get_container("1i31") started = container.start() self.assertEqual(started.id, "1i31") self.assertEqual(started.name, "newcontainer") self.assertEqual(started.state, "pending") self.assertEqual(started.extra['state'], "starting") def test_stop_container(self): container = self.driver.get_container("1i31") stopped = container.stop() self.assertEqual(stopped.id, "1i31") self.assertEqual(stopped.name, "newcontainer") self.assertEqual(stopped.state, "pending") self.assertEqual(stopped.extra['state'], "stopping") def test_ex_search_containers(self): containers = self.driver.ex_search_containers({"state": "running"}) self.assertEqual(len(containers), 1) def test_destroy_container(self): container = self.driver.get_container("1i31") destroyed = container.destroy() self.assertEqual(destroyed.id, "1i31") self.assertEqual(destroyed.name, "newcontainer") self.assertEqual(destroyed.state, "pending") self.assertEqual(destroyed.extra['state'], "stopping") if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/dns/0000775000175000017500000000000013600223624017761 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/__init__.py0000664000175000017500000000000013535474530022073 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/0000775000175000017500000000000013600223624021632 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/0000775000175000017500000000000013600223624023630 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/zone_create.json0000664000175000017500000000051613535474530027036 0ustar kamikami00000000000000 { "created":"2015-05-21T13:51:12Z", "id":"ffb62570-8414-4578-a346-526b44e320b7", "account_id": "7be65324-6e97-4b73-9427-0f4abcf7d216", "cluster_id": "734f21f4-765e-4fea-b571-eedef73b20c5", "name":"example.com", "servers":[ "ns1.auroradns.eu", "ns2.auroradns.info" ] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/zone_example_com.json0000664000175000017500000000051613535474530030064 0ustar kamikami00000000000000 { "created":"2015-05-21T13:51:12Z", "id":"ffb62570-8414-4578-a346-526b44e320b7", "account_id": "7be65324-6e97-4b73-9427-0f4abcf7d216", "cluster_id": "734f21f4-765e-4fea-b571-eedef73b20c5", "name":"example.com", "servers":[ "ns1.auroradns.eu", "ns2.auroradns.info" ] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/zone_example_com_health_check.json0000664000175000017500000000047113535474530032546 0ustar kamikami00000000000000{ "created": "2015-08-07T13:56:59Z", "enabled": true, "health": true, "hostname": "www.pcextreme.nl", "id": "9990ec60-d592-4673-9e7e-9220ed42ee0b", "interval": 10, "ipaddress": "109.72.87.252", "next_run": "2015-08-10T14:22:32Z", "path": "/", "port": 8080, "threshold": 3, "type": "HTTP" }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/zone_example_com_health_checks.json0000664000175000017500000000177413535474530032740 0ustar kamikami00000000000000[ { "created": "2015-08-07T13:56:59Z", "enabled": true, "health": true, "hostname": "www.pcextreme.nl", "id": "9990ec60-d592-4673-9e7e-9220ed42ee0b", "interval": 60, "ipaddress": "109.72.87.252", "next_run": "2015-08-10T14:22:32Z", "path": "/", "port": 80, "threshold": 3, "type": "HTTP" }, { "created": "2015-08-07T13:56:59Z", "enabled": true, "health": true, "hostname": "www.pcextreme.nl", "id": "3f29a813-6a25-41c5-a45e-f771347de526", "interval": 60, "ipaddress": "2a00:f10:101::3eb:1", "next_run": "2015-08-10T14:22:32Z", "path": "/", "port": 80, "threshold": 3, "type": "HTTP" }, { "created": "2015-08-07T13:56:59Z", "enabled": true, "health": true, "hostname": "www.pcextreme.nl", "id": "7719a4c5-b319-46e7-a917-3dc57bdab1d4", "interval": 60, "ipaddress": null, "next_run": "2015-08-10T14:22:32Z", "path": "/", "port": 80, "threshold": 3, "type": "HTTP" } ]apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/zone_example_com_record_localhost.json0000664000175000017500000000036013535474530033467 0ustar kamikami00000000000000{ "id": "5592f1ff", "content": "127.0.0.1", "disabled": false, "health_check_id": null, "name": "localhost", "prio": null, "ttl": 900, "type": "A", "created": "2015-08-07T13:56:51Z", "modified": "2015-08-07T14:11:40Z" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/zone_example_com_records.json0000664000175000017500000000165413535474530031611 0ustar kamikami00000000000000[ { "content":"ns1.auroradns.eu admin.auroradns.eu 2015021901 86400 7200 604800 300", "created":"2015-08-07T13:56:51Z", "disabled":false, "health_check_id":null, "id":"8f4a27b2-0b15-4ed7-b652-813b23c2027f", "modified":"2015-08-07T14:11:40Z", "name":"", "prio":null, "ttl":3600, "type":"SOA" }, { "content":"ns1.auroradns.eu", "created":"2015-08-07T13:56:50Z", "disabled":false, "health_check_id":null, "id":"4d8aaffc-2e43-49c6-82cc-a26d01a159bc", "modified":"2015-08-07T14:11:40Z", "name":"", "prio":null, "ttl":3600, "type":"NS" }, { "content":"109.72.87.137", "created":"2015-08-07T13:56:50Z", "disabled":false, "health_check_id":"aecad772-9234-4722-9a05-66ad5ff6a5b0", "id":"30245a1a-5569-4136-900f-864f088c60ee", "modified":"2015-08-10T14:10:17Z", "name":"smtp", "prio":null, "ttl":3600, "type":"A" } ] apache-libcloud-2.8.0/libcloud/test/dns/fixtures/auroradns/zone_list.json0000664000175000017500000000125413535474530026546 0ustar kamikami00000000000000[ { "created":"2015-05-21T13:51:12Z", "id":"ffb62570-8414-4578-a346-526b44e320b7", "account_id": "7be65324-6e97-4b73-9427-0f4abcf7d216", "cluster_id": "734f21f4-765e-4fea-b571-eedef73b20c5", "name":"auroradns1.eu", "servers":[ "ns1.auroradns.eu", "ns2.auroradns.info" ] }, { "created":"2015-07-07T08:15:14Z", "id":"e3c012266-72e5-48a1-ad3d-ffa7daa06dc5", "account_id": "78971987-f0a0-4714-8926-5d9206601aa9", "cluster_id": "d842505b-8dd9-4597-a34d-93fde6b61818", "name":"auroradns2.nl", "servers":[ "ns1.auroradns.eu", "ns2.auroradns.info" ] } ] apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/0000775000175000017500000000000013600223624023302 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/create_zone_success.json0000664000175000017500000000043013535474530030233 0ustar kamikami00000000000000{ "name": "microsoft.com", "name_idn": "microsoft.com", "serial": null, "master": "65.55.37.62", "creation_ts": null, "status": "https://www.buddyns.com/api/v2/zone/anexample.com/status/", "delegation": "https://www.buddyns.com/api/v2/zone/anexample.com/delegation/" }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/delete_zone_success.json0000664000175000017500000000000013535474530030223 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/empty_zones_list.json0000664000175000017500000000000313535474530027610 0ustar kamikami00000000000000[] apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/get_zone_success.json0000664000175000017500000000045413535474530027555 0ustar kamikami00000000000000{ "name": "myexample.com", "name_idn": "myexample.com", "serial": null, "master": "65.55.37.62", "creation_ts": "2016-04-09T06:20:05.140", "status": "https://www.buddyns.com/api/v2/zone/myexample.com/status/", "delegation": "https://www.buddyns.com/api/v2/zone/myexample.com/delegation/"}apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/list_zones.json0000664000175000017500000000103713535474530026402 0ustar kamikami00000000000000[ { "name" : "microsoft.com", "name_idn" : "microsoft.com", "creation_ts" : "2013-11-06T19:39:38.205", "master" : "65.55.37.62", "serial" : 2013110601, "status": "/api/v2/zone/microsoft.com/status/", "delegation": "/api/v2/zone/microsoft.com/delegation/" }, { "name" : "google.de", "name_idn" : "google.de", "creation_ts" : "2012-06-06T19:53:07.269", "master" : "154.15.200.6", "serial" : 1383743519, "status": "google.de/status/", "delegation": "/api/v2/zone/b?cher.de/delegation/" } ]apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/zone_already_exists.json0000664000175000017500000000017113535474530030262 0ustar kamikami00000000000000 {"errors": {"name": ["Zone with this Domain already exists."]}, "detail": "Invalid zone submitted for addition."} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/buddyns/zone_does_not_exist.json0000664000175000017500000000003013535474530030262 0ustar kamikami00000000000000{"detail": "Not found"} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/0000775000175000017500000000000013600223624023752 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/memberships_GET.json0000664000175000017500000000416413570310635027674 0ustar kamikami00000000000000{ "result": [ { "id": "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "status": "accepted", "permissions": { "access": { "read": true, "edit": true }, "analytics": { "read": true, "edit": false }, "app": { "read": false, "edit": true }, "auditlogs": { "read": true, "edit": false }, "billing": { "read": true, "edit": true }, "cache_purge": { "read": false, "edit": true }, "dns_records": { "read": true, "edit": true }, "lb": { "read": true, "edit": true }, "legal": { "read": true, "edit": true }, "logs": { "read": true, "edit": true }, "member": { "read": true, "edit": true }, "organization": { "read": true, "edit": true }, "ssl": { "read": true, "edit": true }, "stream": { "read": true, "edit": true }, "subscription": { "read": true, "edit": true }, "waf": { "read": true, "edit": true }, "webhooks": { "read": true, "edit": true }, "worker": { "read": true, "edit": true }, "zone": { "read": true, "edit": true }, "zone_settings": { "read": true, "edit": true } }, "roles": [ "Super Administrator - All Privileges" ], "account": { "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "name": "cloudflare@test.com's Account", "settings": { "enforce_twofactor": false } } } ], "result_info": { "page": 1, "per_page": 20, "total_pages": 1, "count": 1, "total_count": 1 }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/record_DELETE.json0000664000175000017500000000014113570310635027146 0ustar kamikami00000000000000{ "result": { "id": "364797364" }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/record_GET.json0000664000175000017500000000101513570310635026624 0ustar kamikami00000000000000{ "result": { "id": "364797364", "type": "A", "name": "example.com", "content": "192.30.252.153", "proxiable": true, "proxied": true, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T21:28:00.801892Z", "created_on": "2018-12-22T21:28:00.801892Z", "meta": { "auto_added": false, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/record_GET_400.json0000664000175000017500000000045213570310635027213 0ustar kamikami00000000000000{ "success": false, "errors": [ { "code": 7003, "message": "Could not route to /zones/1234/dns_records/invalid, perhaps your object identifier is invalid?" }, { "code": 7000, "message": "No route for that URI" } ], "messages": [], "result": null } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/record_GET_404.json0000664000175000017500000000023713570310635027220 0ustar kamikami00000000000000{ "success": false, "errors": [ { "code": 1002, "message": "Invalid dns record identifier" } ], "messages": [], "result": null } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/record_PUT.json0000664000175000017500000000101613570310635026656 0ustar kamikami00000000000000{ "result": { "id": "412561327", "type": "A", "name": "test6.example.com", "content": "127.0.0.4", "proxiable": true, "proxied": true, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T21:28:00.801892Z", "created_on": "2018-12-22T21:28:00.801892Z", "meta": { "auto_added": false, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/records_GET_1.json0000664000175000017500000000530213570310635027232 0ustar kamikami00000000000000{ "result": [ { "id": "364797364", "type": "A", "name": "example.com", "content": "192.30.252.153", "proxiable": true, "proxied": true, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T21:28:00.801892Z", "created_on": "2018-12-22T21:28:00.801892Z", "meta": { "auto_added": false, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, { "id": "r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1", "type": "A", "name": "example.com", "content": "192.30.252.154", "proxiable": true, "proxied": true, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T21:28:03.346998Z", "created_on": "2018-12-22T21:28:03.346998Z", "meta": { "auto_added": false, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, { "id": "r2r2r2r2r2r2r2r2r2r2r2r2r2r2r2r2", "type": "CNAME", "name": "email.example.com", "content": "mailgun.org", "proxiable": true, "proxied": false, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T20:29:48.453923Z", "created_on": "2018-12-22T20:29:48.453923Z", "meta": { "auto_added": true, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, { "id": "r3r3r3r3r3r3r3r3r3r3r3r3r3r3r3r3", "type": "CNAME", "name": "foo.example.com", "content": "foo.com", "proxiable": true, "proxied": false, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2019-05-30T01:43:01.509188Z", "created_on": "2019-05-30T01:43:01.509188Z", "meta": { "auto_added": false, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, { "id": "364982413", "type": "CNAME", "name": "yesyes", "content": "verify.bing.com", "proxiable": true, "proxied": true, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T21:29:46.874918Z", "created_on": "2018-12-22T21:29:46.874918Z", "meta": { "auto_added": false, "managed_by_apps": false, "managed_by_argo_tunnel": false } } ], "result_info": { "page": 1, "per_page": 5, "total_pages": 2, "count": 5, "total_count": 9 }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/records_GET_2.json0000664000175000017500000000446113570310635027240 0ustar kamikami00000000000000{ "result": [ { "id": "r4r4r4r4r4r4r4r4r4r4r4r4r4r4r4r4", "type": "MX", "name": "example.com", "content": "mxa.mailgun.org", "proxiable": false, "proxied": false, "ttl": 1, "priority": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T20:29:48.532399Z", "created_on": "2018-12-22T20:29:48.532399Z", "meta": { "auto_added": true, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, { "id": "r5r5r5r5r5r5r5r5r5r5r5r5r5r5r5r5", "type": "MX", "name": "example.com", "content": "mxb.mailgun.org", "proxiable": false, "proxied": false, "ttl": 1, "priority": 2, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T20:29:48.540671Z", "created_on": "2018-12-22T20:29:48.540671Z", "meta": { "auto_added": true, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, { "id": "r6r6r6r6r6r6r6r6r6r6r6r6r6r6r6r6", "type": "TXT", "name": "example.com", "content": "v=spf1 include:mailgun.org ~all", "proxiable": false, "proxied": false, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T20:29:48.512931Z", "created_on": "2018-12-22T20:29:48.512931Z", "meta": { "auto_added": true, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, { "id": "r7r7r7r7r7r7r7r7r7r7r7r7r7r7r7r7", "type": "TXT", "name": "pic._domainkey.example.com", "content": "k=rsa; ...", "proxiable": false, "proxied": false, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T20:29:48.523230Z", "created_on": "2018-12-22T20:29:48.523230Z", "meta": { "auto_added": true, "managed_by_apps": false, "managed_by_argo_tunnel": false } } ], "result_info": { "page": 2, "per_page": 5, "total_pages": 2, "count": 4, "total_count": 9 }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/records_POST.json0000664000175000017500000000101613570310635027156 0ustar kamikami00000000000000{ "result": { "id": "412561327", "type": "A", "name": "test5.example.com", "content": "127.0.0.3", "proxiable": true, "proxied": true, "ttl": 1, "locked": false, "zone_id": "1234", "zone_name": "example.com", "modified_on": "2018-12-22T21:28:00.801892Z", "created_on": "2018-12-22T21:28:00.801892Z", "meta": { "auto_added": false, "managed_by_apps": false, "managed_by_argo_tunnel": false } }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/zone_DELETE.json0000664000175000017500000000013413570310635026645 0ustar kamikami00000000000000{ "result": { "id": "1234" }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/zone_GET.json0000664000175000017500000000427113570310635026330 0ustar kamikami00000000000000{ "result": { "id": "1234", "name": "example.com", "status": "active", "paused": false, "type": "full", "development_mode": 0, "name_servers": [ "anna.ns.cloudflare.com", "john.ns.cloudflare.com" ], "original_name_servers": [ "amir.ns.cloudflare.com", "dee.ns.cloudflare.com" ], "original_registrar": null, "original_dnshost": null, "modified_on": "2019-05-30T01:43:01.509188Z", "created_on": "2018-12-22T20:29:41.313041Z", "activated_on": "2018-12-22T21:14:27.799913Z", "meta": { "step": 3, "wildcard_proxiable": false, "custom_certificate_quota": 0, "page_rule_quota": 3, "phishing_detected": false, "multiple_railguns_allowed": false }, "owner": { "id": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu", "type": "user", "email": "cloudflare@test.com" }, "account": { "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "name": "cloudflare@test.com" }, "permissions": [ "#access:edit", "#access:read", "#analytics:read", "#app:edit", "#auditlogs:read", "#billing:edit", "#billing:read", "#cache_purge:edit", "#dns_records:edit", "#dns_records:read", "#lb:edit", "#lb:read", "#legal:edit", "#legal:read", "#logs:edit", "#logs:read", "#member:edit", "#member:read", "#organization:edit", "#organization:read", "#ssl:edit", "#ssl:read", "#stream:edit", "#stream:read", "#subscription:edit", "#subscription:read", "#waf:edit", "#waf:read", "#webhooks:edit", "#webhooks:read", "#worker:edit", "#worker:read", "#zone:edit", "#zone:read", "#zone_settings:edit", "#zone_settings:read" ], "plan": { "id": "0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "name": "Free Website", "price": 0, "currency": "USD", "frequency": "", "is_subscribed": true, "can_subscribe": false, "legacy_id": "free", "legacy_discount": false, "externally_managed": false } }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/zone_GET_400.json0000664000175000017500000000043113570310635026705 0ustar kamikami00000000000000{ "success": false, "errors": [ { "code": 7003, "message": "Could not route to /zones/invalid, perhaps your object identifier is invalid?" }, { "code": 7000, "message": "No route for that URI" } ], "messages": [], "result": null } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/zone_GET_404.json0000664000175000017500000000023113570310635026707 0ustar kamikami00000000000000{ "success": false, "errors": [ { "code": 1001, "message": "Invalid zone identifier" } ], "messages": [], "result": null } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/zone_PATCH.json0000664000175000017500000000427013570310635026547 0ustar kamikami00000000000000{ "result": { "id": "1234", "name": "example.com", "status": "active", "paused": true, "type": "full", "development_mode": 0, "name_servers": [ "anna.ns.cloudflare.com", "john.ns.cloudflare.com" ], "original_name_servers": [ "amir.ns.cloudflare.com", "dee.ns.cloudflare.com" ], "original_registrar": null, "original_dnshost": null, "modified_on": "2019-05-30T01:43:02.509188Z", "created_on": "2018-12-22T20:29:41.313041Z", "activated_on": "2018-12-22T21:14:27.799913Z", "meta": { "step": 3, "wildcard_proxiable": false, "custom_certificate_quota": 0, "page_rule_quota": 3, "phishing_detected": false, "multiple_railguns_allowed": false }, "owner": { "id": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu", "type": "user", "email": "cloudflare@test.com" }, "account": { "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "name": "cloudflare@test.com" }, "permissions": [ "#access:edit", "#access:read", "#analytics:read", "#app:edit", "#auditlogs:read", "#billing:edit", "#billing:read", "#cache_purge:edit", "#dns_records:edit", "#dns_records:read", "#lb:edit", "#lb:read", "#legal:edit", "#legal:read", "#logs:edit", "#logs:read", "#member:edit", "#member:read", "#organization:edit", "#organization:read", "#ssl:edit", "#ssl:read", "#stream:edit", "#stream:read", "#subscription:edit", "#subscription:read", "#waf:edit", "#waf:read", "#webhooks:edit", "#webhooks:read", "#worker:edit", "#worker:read", "#zone:edit", "#zone:read", "#zone_settings:edit", "#zone_settings:read" ], "plan": { "id": "0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "name": "Free Website", "price": 0, "currency": "USD", "frequency": "", "is_subscribed": true, "can_subscribe": false, "legacy_id": "free", "legacy_discount": false, "externally_managed": false } }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/zones_GET.json0000664000175000017500000000474713570310635026523 0ustar kamikami00000000000000{ "result": [ { "id": "1234", "name": "example.com", "status": "active", "paused": false, "type": "full", "development_mode": 0, "name_servers": [ "anna.ns.cloudflare.com", "john.ns.cloudflare.com" ], "original_name_servers": [ "amir.ns.cloudflare.com", "dee.ns.cloudflare.com" ], "original_registrar": null, "original_dnshost": null, "modified_on": "2019-05-30T01:43:01.509188Z", "created_on": "2018-12-22T20:29:41.313041Z", "activated_on": "2018-12-22T21:14:27.799913Z", "meta": { "step": 3, "wildcard_proxiable": false, "custom_certificate_quota": 0, "page_rule_quota": 3, "phishing_detected": false, "multiple_railguns_allowed": false }, "owner": { "id": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu", "type": "user", "email": "cloudflare@test.com" }, "account": { "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "name": "cloudflare@test.com" }, "permissions": [ "#access:edit", "#access:read", "#analytics:read", "#app:edit", "#auditlogs:read", "#billing:edit", "#billing:read", "#cache_purge:edit", "#dns_records:edit", "#dns_records:read", "#lb:edit", "#lb:read", "#legal:edit", "#legal:read", "#logs:edit", "#logs:read", "#member:edit", "#member:read", "#organization:edit", "#organization:read", "#ssl:edit", "#ssl:read", "#stream:edit", "#stream:read", "#subscription:edit", "#subscription:read", "#waf:edit", "#waf:read", "#webhooks:edit", "#webhooks:read", "#worker:edit", "#worker:read", "#zone:edit", "#zone:read", "#zone_settings:edit", "#zone_settings:read" ], "plan": { "id": "0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "name": "Free Website", "price": 0, "currency": "USD", "frequency": "", "is_subscribed": true, "can_subscribe": false, "legacy_id": "free", "legacy_discount": false, "externally_managed": false } } ], "result_info": { "page": 1, "per_page": 20, "total_pages": 1, "count": 1, "total_count": 1 }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/cloudflare/zones_POST.json0000664000175000017500000000424213570310635026657 0ustar kamikami00000000000000{ "result": { "id": "6789", "name": "example2.com", "status": "pending", "paused": false, "type": "full", "development_mode": 0, "name_servers": [ "anna.ns.cloudflare.com", "john.ns.cloudflare.com" ], "original_name_servers": [ "amir.ns.cloudflare.com", "dee.ns.cloudflare.com" ], "original_registrar": null, "original_dnshost": null, "modified_on": "2019-05-30T02:09:25.975712Z", "created_on": "2019-05-30T02:09:25.975712Z", "activated_on": null, "meta": { "step": 4, "wildcard_proxiable": false, "custom_certificate_quota": 0, "page_rule_quota": 3, "phishing_detected": false, "multiple_railguns_allowed": false }, "owner": { "id": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu", "type": "user", "email": "cloudflare@test.com" }, "account": { "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "name": "cloudflare@test.com" }, "permissions": [ "#access:edit", "#access:read", "#analytics:read", "#app:edit", "#auditlogs:read", "#billing:edit", "#billing:read", "#cache_purge:edit", "#dns_records:edit", "#dns_records:read", "#lb:edit", "#lb:read", "#legal:edit", "#legal:read", "#logs:edit", "#logs:read", "#member:edit", "#member:read", "#organization:edit", "#organization:read", "#ssl:edit", "#ssl:read", "#stream:edit", "#stream:read", "#subscription:edit", "#subscription:read", "#waf:edit", "#waf:read", "#webhooks:edit", "#webhooks:read", "#worker:edit", "#worker:read", "#zone:edit", "#zone:read", "#zone_settings:edit", "#zone_settings:read" ], "plan": { "id": "0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "name": "Free Website", "price": 0, "currency": "USD", "frequency": "", "is_subscribed": true, "can_subscribe": false, "legacy_id": "free", "legacy_discount": false, "externally_managed": false } }, "success": true, "errors": [], "messages": [] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/0000775000175000017500000000000013600223624024255 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains.json0000664000175000017500000000061513535474530027365 0ustar kamikami00000000000000{"domains":[{"name":"testdomain","ttl":1800,"zone_file":"$ORIGIN testdomain.\n$TTL 1800\ntestdomain. IN SOA ns1.digitalocean.com. hostmaster.testdomain. 1428768671 10800 3600 604800 1800\ntestdomain. 1800 IN NS ns1.digitalocean.com.\ntestdomain. 1800 IN NS ns2.digitalocean.com.\ntestdomain. 1800 IN NS ns3.digitalocean.com.\ntestdomain. 1800 IN A 123.45.67.89\n"}],"links":{},"meta":{"total":1}} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_CREATE.json0000664000175000017500000000007513535474530030410 0ustar kamikami00000000000000{"domain":{"name":"testdomain","ttl":null,"zone_file":null}} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_EMPTY.json0000664000175000017500000000005513535474530030341 0ustar kamikami00000000000000{"domains":[],"links":{},"meta":{"total":0}} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_UNAUTHORIZED.json0000664000175000017500000000007613535474530031367 0ustar kamikami00000000000000{"id":"unauthorized","message":"Unable to authenticate you."} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain.json0000664000175000017500000000055413535474530031616 0ustar kamikami00000000000000{"domain":{"name":"testdomain","ttl":1800,"zone_file":"$ORIGIN testdomain.\n$TTL 1800\ntestdomain. IN SOA ns1.digitalocean.com. hostmaster.testdomain. 1428768671 10800 3600 604800 1800\ntestdomain. 1800 IN NS ns1.digitalocean.com.\ntestdomain. 1800 IN NS ns2.digitalocean.com.\ntestdomain. 1800 IN NS ns3.digitalocean.com.\ntestdomain. 1800 IN A 123.45.67.89\n"}} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_NOT_FOUND.json0000664000175000017500000000012313535474530033261 0ustar kamikami00000000000000{"id":"not_found","message":"The resource you were accessing could not be found."} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records.json0000664000175000017500000000132613535474530033335 0ustar kamikami00000000000000{ "domain_records": [ { "id": 1234560, "type": "NS", "name": "@", "data": "ns1.digitalocean.com", "priority": null, "port": null, "ttl": 1800, "weight": null }, { "id": 1234561, "type": "NS", "name": "@", "data": "ns2.digitalocean.com", "priority": null, "port": null, "ttl": 1800, "weight": null }, { "id": 1234562, "type": "NS", "name": "@", "data": "ns3.digitalocean.com", "priority": null, "port": null, "ttl": 1800, "weight": null }, { "id": 1234564, "type": "A", "name": "@", "data": "123.45.67.89", "priority": null, "port": null, "ttl": 1800, "weight": null }, { "id": 1234567, "type": "A", "name": "@", "data": "123.45.67.99", "priority": null, "port": null, "weight": null } ], "links": {}, "meta": { "total": 5 } } ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234560.jsonapache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_12345600000664000175000017500000000021413535474530033264 0ustar kamikami00000000000000{"domain_record":{"id":1234560,"type":"NS","name":"@","data":"ns1.digitalocean.com","priority":null,"port":null,"ttl": 1800,"weight":null}} ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234561.jsonapache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_12345610000664000175000017500000000021413535474530033265 0ustar kamikami00000000000000{"domain_record":{"id":1234561,"type":"NS","name":"@","data":"ns2.digitalocean.com","priority":null,"port":null,"ttl": 1800,"weight":null}} ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234562.jsonapache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_12345620000664000175000017500000000021413535474530033266 0ustar kamikami00000000000000{"domain_record":{"id":1234563,"type":"NS","name":"@","data":"ns3.digitalocean.com","priority":null,"port":null,"ttl": 1800,"weight":null}} ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564.jsonapache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_12345640000664000175000017500000000020313535474530033266 0ustar kamikami00000000000000{"domain_record":{"id":1234564,"type":"A","name":"@","data":"123.45.67.89","priority":null,"port":null,"ttl": 1800,"weight":null}} ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_NOT_FOUND.jsonapache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_12345640000664000175000017500000000012313535474530033267 0ustar kamikami00000000000000{"id":"not_found","message":"The resource you were accessing could not be found."} ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_UPDATE.jsonapache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_12345640000664000175000017500000000020113535474530033264 0ustar kamikami00000000000000{"domain_record":{"id":1234564,"type":"A","name":"@","data":"234.56.78.90","priority":null,"port":null,"ttl": 60,"weight":null}} ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_CREATE.jsonapache-libcloud-2.8.0/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_CREATE.0000664000175000017500000000020313535474530033457 0ustar kamikami00000000000000{"domain_record":{"id":1234565,"type":"A","name":"sub","data":"234.56.78.90","priority":null,"port":null,"ttl": 60,"weight":null}} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/0000775000175000017500000000000013600223624023445 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/create_domain.json0000664000175000017500000000070613535474530027150 0ustar kamikami00000000000000{ "domain": { "id": 1, "user_id": 21, "registrant_id": 321, "name": "example.com", "unicode_name": "example.com", "token": "domain-token", "state": "hosted", "language": null, "lockable": false, "auto_renew": true, "whois_protected": false, "record_count": 5, "service_count": 1, "expires_on": null, "created_at": "2012-09-27T14:25:57.646Z", "updated_at": "2014-12-15T20:27:04.552Z" } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/create_domain_record.json0000664000175000017500000000037113535474530030504 0ustar kamikami00000000000000{ "record": { "content": "mail.example.com", "created_at": "2013-01-29T14:25:38Z", "domain_id": 28, "id": 172, "name": "", "prio": 10, "record_type": "MX", "ttl": 3600, "updated_at": "2013-01-29T14:25:38Z" } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/get_domain.json0000664000175000017500000000072213535474530026462 0ustar kamikami00000000000000{ "domain": { "id": 1, "user_id": 21, "registrant_id": 321, "name": "example.com", "unicode_name": "example.com", "token": "domain-token", "state": "registered", "language": null, "lockable": false, "auto_renew": true, "whois_protected": false, "record_count": 5, "service_count": 1, "expires_on": "2015-09-27", "created_at": "2012-09-27T14:25:57.646Z", "updated_at": "2014-12-15T20:27:04.552Z" } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/get_domain_record.json0000664000175000017500000000037313535474530030022 0ustar kamikami00000000000000{ "record": { "name": "www", "ttl": 3600, "created_at": "2010-07-01T08:01:18Z", "updated_at": "2010-10-21T15:47:47Z", "domain_id": 1, "id": 123, "content": "example.com", "record_type": "CNAME", "prio": null } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/list_domain_records.json0000664000175000017500000000152413535474530030400 0ustar kamikami00000000000000[ { "record": { "name": "", "ttl": 3600, "created_at": "2010-07-04T04:41:31Z", "updated_at": "2010-10-21T15:47:47Z", "domain_id": 1, "id": 31, "content": "1.2.3.4", "record_type": "A", "prio": null } }, { "record": { "name": "www", "ttl": 3600, "created_at": "2010-07-01T08:01:18Z", "updated_at": "2010-10-21T15:47:47Z", "domain_id": 1, "id": 2, "content": "example.com", "record_type": "CNAME", "prio": null } }, { "record": { "name": "", "ttl": 3600, "created_at": "2010-07-04T04:42:11Z", "updated_at": "2010-10-21T15:47:47Z", "pdns_identifier": "40", "domain_id": 1, "id": 32, "content": "mail.example.com", "record_type": "MX", "prio": 10 } } ]apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/list_domains.json0000664000175000017500000000175513535474530027050 0ustar kamikami00000000000000[ { "domain": { "id": 1, "user_id": 21, "registrant_id": 321, "name": "example.com", "unicode_name": "example.com", "token": "domain-token", "state": "registered", "language": null, "lockable": false, "auto_renew": true, "whois_protected": false, "record_count": 5, "service_count": 1, "expires_on": "2015-09-27", "created_at": "2012-09-27T14:25:57.646Z", "updated_at": "2014-12-15T20:27:04.552Z" } }, { "domain": { "id": 2, "user_id": 22, "registrant_id": 322, "name": "example.com", "unicode_name": "example.it", "token": "domain-token", "state": "hosted", "language": null, "lockable": false, "auto_renew": true, "whois_protected": false, "record_count": 5, "service_count": 1, "expires_on": null, "created_at": "2012-09-27T14:25:57.646Z", "updated_at": "2014-12-15T20:27:04.552Z" } } ]apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnsimple/update_domain_record.json0000664000175000017500000000037313535474530030525 0ustar kamikami00000000000000{ "record": { "name": "www", "ttl": 4500, "created_at": "2010-07-01T08:01:18Z", "updated_at": "2010-10-21T15:47:47Z", "domain_id": 1, "id": 123, "content": "updated.com", "record_type": "CNAME", "prio": null } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/0000775000175000017500000000000013600223624023121 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/create_zone_success.json0000664000175000017500000000035513535474530030060 0ustar kamikami00000000000000{ "status": { "code":"1", "message":"Action completed successful", "created_at":"2012-08-29 22:12:35" }, "domain": { "id":"3", "punycode":"api2.com", "domain":"api2.com" } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/delete_record_record_does_not_exist.json0000664000175000017500000000013613535474530033273 0ustar kamikami00000000000000{"status": {"message": "Record id invalid", "code": "8", "created_at": "2016-05-13 15:05:46"}}apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/delete_record_success.json0000664000175000017500000000000013535474530030345 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/delete_zone_success.json0000664000175000017500000000000013535474530030042 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/empty_zones_list.json0000664000175000017500000000012213535474530027431 0ustar kamikami00000000000000{"status":{"code":"9","message":"No domains","created_at":"2016-04-24 19:02:23"}} apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/get_record.json0000664000175000017500000000113113535474530026140 0ustar kamikami00000000000000{ "status": { "code": "1", "message": "Action completed successful", "created_at": "2014-06-05 10:07:05" }, "domain": { "id": "9", "domain": "dnspod.com", "domain_grade": "DP_Free" }, "record": { "id": "50", "sub_domain": "@", "record_type": "A", "record_line": "Default", "value": "96.126.115.73", "mx": "0", "ttl": "600", "enabled": "1", "monitor_status": "", "remark": "", "updated_on": "2014-06-05 09:47:59", "domain_id": "9" } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/get_zone_success.json0000664000175000017500000000132313535474530027370 0ustar kamikami00000000000000{ "status": { "code": "1", "message": "Action completed successful", "created_at": "2014-06-04 21:25:21" }, "domain": { "id": "6", "name": "dnspod.com", "punycode": "dnspod.com", "grade": "DP_Free", "grade_title": "Free", "status": "enable", "ext_status": "notexist", "records": "3", "group_id": "1", "is_mark": "no", "remark": false, "is_vip": "no", "searchengine_push": "yes", "beian": "no", "user_id": "730060", "created_on": "2014-06-04 16:19:31", "updated_on": "2014-06-04 16:20:05", "ttl": "600", "owner": "yizero@qq.com" } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/list_records.json0000664000175000017500000000470613535474530026532 0ustar kamikami00000000000000{ "status": { "code": "1", "message": "Action completed successful", "created_at": "2014-06-05 09:58:40" }, "domain": { "id": "9", "name": "dnspod.com", "punycode": "dnspod.com", "grade": "DP_Free", "owner": "yizerowu@dnspod.com" }, "info": { "sub_domains": "5", "record_total": "5" }, "records": [ { "id": "50", "name": "@", "line": "Default", "type": "A", "ttl": "600", "value": "96.126.115.73", "mx": "0", "enabled": "1", "status": "enabled", "monitor_status": "", "remark": "", "updated_on": "2014-06-05 09:47:59" }, { "id": "49", "name": "@", "line": "Default", "type": "MX", "ttl": "600", "value": "cloudmx.qq.com.", "mx": "5", "enabled": "1", "status": "enabled", "monitor_status": "", "remark": "", "updated_on": "2014-06-05 09:47:59" }, { "id": "46", "name": "@", "line": "Default", "type": "NS", "ttl": "600", "value": "a.dnspod.com.", "mx": "0", "enabled": "1", "status": "enabled", "monitor_status": "", "remark": "", "updated_on": "2014-06-05 09:47:40", "hold": "hold" }, { "id": "47", "name": "@", "line": "Default", "type": "NS", "ttl": "600", "value": "b.dnspod.com.", "mx": "0", "enabled": "1", "status": "enabled", "monitor_status": "", "remark": "", "updated_on": "2014-06-05 09:47:40", "hold": "hold" }, { "id": "48", "name": "@", "line": "Default", "type": "NS", "ttl": "600", "value": "c.dnspod.com.", "mx": "0", "enabled": "1", "status": "enabled", "monitor_status": "", "remark": "", "updated_on": "2014-06-05 09:47:40", "hold": "hold" } ] }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/list_zones.json0000664000175000017500000000206213535474530026220 0ustar kamikami00000000000000{ "status": { "code": "1", "message": "Action completed successful", "created_at": "2014-06-04 21:22:08" }, "info": { "domain_total": 1, "all_total": 1, "mine_total": 1, "share_total": 0, "vip_total": 0, "ismark_total": 0, "pause_total": 0, "error_total": 1, "lock_total": 0, "spam_total": 0, "vip_expire": 0, "share_out_total": 0 }, "domains": [ { "id": 6, "name": "dnspod.com", "grade": "DP_Free", "grade_title": "Free", "status": "enable", "ext_status": "notexist", "records": "3", "group_id": "1", "is_mark": "no", "remark": "", "is_vip": "no", "searchengine_push": "yes", "beian": "no", "created_on": "2014-06-04 16:19:31", "updated_on": "2014-06-04 16:20:05", "ttl": "600", "owner": "yizero@qq.com" } ] }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/record_already_exists.json0000664000175000017500000000023713535474530030407 0ustar kamikami00000000000000{ "status": { "message": "Record impacted, same record exists or CNAME/URL impacted", "code": "31", "created_at": "2016-05-15 16:16:41" } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/zone_already_exists.json0000664000175000017500000000013513535474530030101 0ustar kamikami00000000000000{"status": {"message": "Domain is exists", "code": "7", "created_at": "2016-05-08 20:24:50"}}apache-libcloud-2.8.0/libcloud/test/dns/fixtures/dnspod/zone_does_not_exist.json0000664000175000017500000000013613535474530030110 0ustar kamikami00000000000000{"status": {"message": "Domain id invalid", "code": "6", "created_at": "2016-05-08 18:50:57"}}apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/0000775000175000017500000000000013600223624023755 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/create_record_NO_EXTRA_PARAMS.xml0000664000175000017500000000073613535474530031723 0ustar kamikami00000000000000 353367855 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/create_record_WITH_EXTRA_PARAMS.xml0000664000175000017500000000073613535474530032162 0ustar kamikami00000000000000 353367855 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/create_record_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000124413535474530032455 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/create_zone.xml0000664000175000017500000000072713535474530027016 0ustar kamikami00000000000000 302811 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/create_zone_ZONE_ALREADY_EXIST.xml0000664000175000017500000000124413535474530031761 0ustar kamikami00000000000000 SERVER Zone Already Exists apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/delete_record.xml0000664000175000017500000000073413535474530027316 0ustar kamikami00000000000000 Success apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/delete_record_RECORD_DOES_NOT_EXIST.xml0000664000175000017500000000075313535474530032663 0ustar kamikami00000000000000 Record does not exists apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/delete_record_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000127713535474530032462 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/delete_zone.xml0000664000175000017500000000073013535474530027007 0ustar kamikami00000000000000 Success apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/delete_zone_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000124413535474530032151 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_record.xml0000664000175000017500000000124213535474530026626 0ustar kamikami00000000000000 353286987 record1 A 192.168.0.1 1 3600 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_record_RECORD_DOES_NOT_EXIST.xml0000664000175000017500000000132513535474530032174 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_record_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000124413535474530031771 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_zone.xml0000664000175000017500000000170713535474530026331 0ustar kamikami00000000000000 myzone.com. ns1.durabledns.com. mail.myzone.com 1437473456 13000 7200 1300 13 1300 127.0.0.1/32 127.0.0.1/32,127.0.0.100/32 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_zone_NO_EXTRA_PARAMS.xml0000664000175000017500000000165413535474530030734 0ustar kamikami00000000000000 myzone.com. ns1.durabledns.com. support.durabledns.com 1437473456 28800 7200 604800 82000 3600 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_zone_UPDATE_ZONE.xml0000664000175000017500000000166413535474530030230 0ustar kamikami00000000000000 myzone.com. ns1.durabledns.com. mail.myzone.com 1437475078 13000 7200 8000 5000 4000 127.0.0.1 127.0.0.1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_zone_WITH_EXTRA_PARAMS.xml0000664000175000017500000000164513535474530031173 0ustar kamikami00000000000000 myzone.com. ns1.durabledns.com. mail.myzone.com 1437473456 28800 7200 604800 50000 4000 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/get_zone_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000124413535474530031466 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/list_records.xml0000664000175000017500000000210413535474530027203 0ustar kamikami00000000000000 353286987 record1 A 192.168.0.1 353286997 record2 A 127.0.0.1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/list_records_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000124413535474530032350 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/list_zones.xml0000664000175000017500000000142713535474530026707 0ustar kamikami00000000000000 myzone.com. myzone2.com. apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/update_record.xml0000664000175000017500000000073413535474530027336 0ustar kamikami00000000000000 Success apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/update_record_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000124413535474530032474 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/update_record_success.xml0000664000175000017500000000100513535474530031056 0ustar kamikami00000000000000\n \n \n \n \n Success\n \n \n \n apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/update_zone_UPDATE_ZONE.xml0000664000175000017500000000073013535474530030724 0ustar kamikami00000000000000 Success apache-libcloud-2.8.0/libcloud/test/dns/fixtures/durabledns/update_zone_ZONE_DOES_NOT_EXIST.xml0000664000175000017500000000124413535474530032171 0ustar kamikami00000000000000 SERVER Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/0000775000175000017500000000000013600223624022714 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/create_record.xml0000664000175000017500000000157313535474530026260 0ustar kamikami00000000000000 id 47234 name www ttl 0 type A value 127.0.0.1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/create_zone.xml0000664000175000017500000000253213535474530025751 0ustar kamikami00000000000000 date_updated 20101028T12:38:17 domains 0 id 47234 name t.com owner AB3917-GANDI public 0 version 1 versions apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/delete_record.xml0000664000175000017500000000024513535474530026252 0ustar kamikami00000000000000 1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/delete_record_doesnotexist.xml0000664000175000017500000000024513535474530031062 0ustar kamikami00000000000000 0 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/delete_zone.xml0000664000175000017500000000025513535474530025750 0ustar kamikami00000000000000 1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/delete_zone_fail.xml0000664000175000017500000000025513535474530026743 0ustar kamikami00000000000000 0 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/get_zone.xml0000664000175000017500000000253213535474530025265 0ustar kamikami00000000000000 date_updated 20101028T12:38:17 domains 0 id 47234 name t.com owner AB3917-GANDI public 0 version 1 versions apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/list_records.xml0000664000175000017500000001016513535474530026150 0ustar kamikami00000000000000 id 47234 name wibble ttl 86400 type CNAME value t.com id 47234 name www ttl 86400 type A value 208.111.35.173 id 47234 name blahblah ttl 86400 type A value 208.111.35.173 id 47234 name ttl 86400 type MX value 15 aspmx.l.google.com apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/list_records_empty.xml0000664000175000017500000000037213535474530027365 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/list_zones.xml0000664000175000017500000001242513535474530025646 0ustar kamikami00000000000000 date_updated 20101028T12:38:17 id 47234 name t.com public 0 version 1 date_updated 20101028T12:38:17 id 48170 name newbug.net public 0 version 1 date_updated 20101028T12:38:17 id 48017 name newblah.com public 0 version 1 date_updated 20101028T12:38:17 id 47288 name fromapi.com public 0 version 1 date_updated 20101028T12:38:17 id 48008 name blahnew.com public 0 version 1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/new_version.xml0000664000175000017500000000024513535474530026010 0ustar kamikami00000000000000 1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi/zone_doesnt_exist.xml0000664000175000017500000000057113535474530027217 0ustar kamikami00000000000000 faultCode 581042 faultString Zone does not exist apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/0000775000175000017500000000000013600223624023733 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/create_bad_zone.json0000664000175000017500000000017713570310635027744 0ustar kamikami00000000000000{ "code": 409, "message": "Zone badexample.com already exists", "object": "HTTPConflict", "cause": "Duplicate Entry" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/create_domain.json0000664000175000017500000000004413570310635027423 0ustar kamikami00000000000000{ "message": "Domain Created" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/create_existing_record.json0000664000175000017500000000017613570310635031352 0ustar kamikami00000000000000{ "code": 409, "message": "Record bob already exists", "object": "HTTPConflict", "cause": "Duplicate Entry" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/create_record.json0000664000175000017500000000005113570310635027430 0ustar kamikami00000000000000{ "message": "Zone Record Created" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/create_zone.json0000664000175000017500000000004213570310635027125 0ustar kamikami00000000000000{ "message": "Zone Created" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/delete_gandi_zone.json0000664000175000017500000000004213570310635030266 0ustar kamikami00000000000000{ "message": "Zone deleted" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/delete_record.json0000664000175000017500000000005113570310635027427 0ustar kamikami00000000000000{ "message": "Zone Record Deleted" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/get_bad_zone.json0000664000175000017500000000072013570310635027252 0ustar kamikami00000000000000{ "zone_uuid": "12346" "domain_keys_href": "https://dns.api.gandi.net/api/v5/domains/badexample.com/keys", "fqdn": "badexample.com", "zone_href": "https://dns.api.gandi.net/api/v5/zones/12346", "zone_records_href": "https://dns.api.gandi.net/api/v5/zones/12346/records", "domain_records_href": "https://dns.api.gandi.net/api/v5/domains/badexample.com/records", "domain_href": "https://dns.api.gandi.net/api/v5/domains/badexample.com" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/get_mx_record.json0000664000175000017500000000022113570310635027447 0ustar kamikami00000000000000{ "rrset_type": "MX", "rrset_ttl": 10800, "rrset_name": "lists", "rrset_values": [ "10 mail", "20 mail2" ] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/get_nonexistent_record.json0000664000175000017500000000016613570310635031411 0ustar kamikami00000000000000{ "code": 404, "message": "Unknown record", "object": "LocalizedHTTPNotFound", "cause": "Not Found" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/get_nonexistent_zone.json0000664000175000017500000000016413570310635031104 0ustar kamikami00000000000000{ "code": 404, "message": "Unknown zone", "object": "LocalizedHTTPNotFound", "cause": "Not Found" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/get_record.json0000664000175000017500000000017313570310635026751 0ustar kamikami00000000000000{ "rrset_type": "A", "rrset_ttl": 9600, "rrset_name": "bob", "rrset_values": [ "127.0.1.1" ] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/get_zone.json0000664000175000017500000000070513570310635026447 0ustar kamikami00000000000000{ "zone_uuid": "12345", "domain_keys_href": "https://dns.api.gandi.net/api/v5/domains/example.com/keys", "fqdn": "example.com", "zone_href": "https://dns.api.gandi.net/api/v5/zones/12345", "zone_records_href": "https://dns.api.gandi.net/api/v5/zones/12345/records", "domain_records_href": "https://dns.api.gandi.net/api/v5/domains/example.com/records", "domain_href": "https://dns.api.gandi.net/api/v5/domains/example.com" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/list_records.json0000664000175000017500000000074113570310635027331 0ustar kamikami00000000000000[ { "rrset_type": "A", "rrset_ttl": 10800, "rrset_name": "@", "rrset_values": [ "127.0.0.1" ] }, { "rrset_type": "CNAME", "rrset_ttl": 3600, "rrset_name": "www", "rrset_values": [ "bob.example.com." ] }, { "rrset_type": "A", "rrset_ttl": 9600, "rrset_name": "bob", "rrset_values": [ "127.0.1.1" ] } ] apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/list_records_bind.txt0000664000175000017500000000012213570310635030164 0ustar kamikami00000000000000@ 10800 IN A 127.0.0.1 www 3600 IN CNAME bob.example.com. bob 9600 IN A 127.0.1.1 apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/list_zones.json0000664000175000017500000000066513570310635027033 0ustar kamikami00000000000000[ { "fqdn": "example.com", "domain_href": "https://dns.api.gandi.net/api/v5/domains/example.com", "domain_records_href": "https://dns.api.gandi.net/api/v5/domains/example.com/records" }, { "fqdn": "example.net", "domain_href": "https://dns.api.gandi.net/api/v5/domains/example.net", "domain_records_href": "https://dns.api.gandi.net/api/v5/domains/example.net/records" } ] apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/update_bad_record.json0000664000175000017500000000035113570310635030260 0ustar kamikami00000000000000{ "code": 400, "message": "foo must be set", "object": "HTTPBadRequest", "cause": "No foo set.", "errors": [ { "location": "body", "name": "foo", "description": "'' is not a foo" } ] } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/update_gandi_zone.json0000664000175000017500000000004613570310635030312 0ustar kamikami00000000000000{ "message": "Request Accepted" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/update_mx_record.json0000664000175000017500000000005113570310635030153 0ustar kamikami00000000000000{ "message": "Zone Record Updated" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/gandi_live/update_record.json0000664000175000017500000000005113570310635027447 0ustar kamikami00000000000000{ "message": "Zone Record Updated" } apache-libcloud-2.8.0/libcloud/test/dns/fixtures/godaddy/0000775000175000017500000000000013600223624023245 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/dns/fixtures/godaddy/purchase_request.json0000664000175000017500000000312213535474530027533 0ustar kamikami00000000000000{ "domain": " ", "consent": { "agreementKeys": [ " " ], "agreedBy": " ", "agreedAt": " " }, "period": 1, "nameServers": [ " " ], "renewAuto": true, "privacy": false, "contactRegistrant": { "nameFirst": " ", "nameMiddle": " ", "nameLast": " ", "organization": " ", "jobTitle": " ", "email": " ", "phone": " ", "fax": " ", "addressMailing": { "address1": " ", "address2": " ", "city": " ", "state": " ", "postalCode": " ", "country": "US" } }, "contactAdmin": { "nameFirst": " ", "nameMiddle": " ", "nameLast": " ", "organization": " ", "jobTitle": " ", "email": " ", "phone": " ", "fax": " ", "addressMailing": { "address1": " ", "address2": " ", "city": " ", "state": " ", "postalCode": " ", "country": "US" } }, "contactTech": { "nameFirst": " ", "nameMiddle": " ", "nameLast": " ", "organization": " ", "jobTitle": " ", "email": " ", "phone": " ", "fax": " ", "addressMailing": { "address1": " ", "address2": " ", "city": " ", "state": " ", "postalCode": " ", "country": "US" } }, "contactBilling": { "nameFirst": " ", "nameMiddle": " ", "nameLast": " ", "organization": " ", "jobTitle": " ", "email": " ", "phone": " ", "fax": " ", "addressMailing": { "address1": " ", "address2": " ", "city": " ", "state": " ", "postalCode": " ", "country": "US" } } }apache-libcloud-2.8.0/libcloud/test/dns/fixtures/godaddy/v1_domains.json0000664000175000017500000000340013535474530026210 0ustar kamikami00000000000000[ { "domainId": 177184419, "domain": "aperture-platform.com", "status": "ACTIVE", "expires": "2016-09-25T19:29:32Z", "expirationProtected": false, "holdRegistrar": false, "limited": false, "locked": true, "privacy": false, "renewAuto": true, "renewable": true, "smart": false, "transferProtected": false }, { "domainId": 203342445, "domain": "dd-innovation-days.com", "status": "ACTIVE", "expires": "2016-11-15T20:10:17Z", "expirationProtected": false, "holdRegistrar": false, "limited": false, "locked": true, "privacy": false, "renewAuto": true, "renewable": true, "smart": false, "transferProtected": false }, { "domainId": 183117834, "domain": "givesourcing.com", "status": "ACTIVE", "expires": "2017-01-01T19:00:40Z", "expirationProtected": false, "holdRegistrar": false, "limited": false, "locked": true, "privacy": false, "renewAuto": true, "renewable": true, "smart": false, "transferProtected": false }, { "domainId": 200411864, "domain": "service-layer.com", "status": "ACTIVE", "expires": "2018-09-30T18:22:00Z", "expirationProtected": false, "holdRegistrar": false, "limited": false, "locked": true, "privacy": false, "renewAuto": true, "renewable": true, "smart": false, "transferProtected": false }, { "domainId": 183221633, "domain": "sourcewise.org", "status": "ACTIVE", "expires": "2017-01-04T04:02:07Z", "expirationProtected": false, "holdRegistrar": false, "limited": false, "locked": true, "privacy": false, "renewAuto": true, "renewable": true, "smart": false, "transferProtected": false } ]apache-libcloud-2.8.0/libcloud/test/dns/fixtures/godaddy/v1_domains_agreements.json0000664000175000017500000000044613535474530030431 0ustar kamikami00000000000000[ { "agreementKey": "DNRA", "title": "Domain Name Registration Agreement", "url": "http://www.secureserver.net/agreements/ShowDoc.aspx?pageid=7959&pl_id=1", "content": "\n\nDomain Name Registration and Customer Service Agreement\n

Service Unavailable

The service is temporarily unavailable. Please try again later.

"}}././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_0_slug_loadbalancers_8290_usage_current.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_0_slug_loadbalancers_8290_usa0000664000175000017500000000207613535474530033357 0ustar kamikami00000000000000{ "links": [], "loadBalancerUsageRecords": [ { "id": 1234, "startTime": "2013-04-22T22:00:00Z", "endTime": "2013-04-22T23:00:00Z", "numVips": 1, "incomingTransfer": 0, "outgoingTransfer": 0, "incomingTransferSsl": 6182163, "outgoingTransferSsl": 9702071, "vipType": "PUBLIC", "averageNumConnections": 0, "averageNumConnectionsSsl": 14.9166666666666, "numPolls": 12, "sslMode": "ON" }, { "id": 12345, "startTime": "2013-04-22T23:00:00Z", "endTime": "2013-04-23T00:00:00Z", "numVips": 1, "incomingTransfer": 0, "outgoingTransfer": 0, "incomingTransferSsl": 6815503, "outgoingTransferSsl": 10474092, "vipType": "PUBLIC", "averageNumConnections": 0, "averageNumConnectionsSsl": 19.9166666666667, "numPolls": 12, "sslMode": "ON" } ] } apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers.json0000664000175000017500000000237213535474530032555 0ustar kamikami00000000000000{ "loadBalancers": [ { "algorithm": "RANDOM", "created": { "time": "2011-04-06T21:25:19+0000" }, "id": 8155, "name": "test0", "port": 80, "protocol": "HTTP", "status": "ACTIVE", "updated": { "time": "2011-04-06T21:25:31+0000" }, "virtualIps": [ { "address": "1.1.1.25", "id": 965, "ipVersion": "IPV4", "type": "PUBLIC" } ] }, { "algorithm": "RANDOM", "created": { "time": "2011-04-06T21:26:22+0000" }, "id": 8156, "name": "test1", "port": 80, "protocol": "HTTP", "status": "ACTIVE", "updated": { "time": "2011-04-06T21:26:33+0000" }, "virtualIps": [ { "address": "1.1.1.83", "id": 1279, "ipVersion": "IPV4", "type": "PUBLIC" } ] } ] } ././@LongLink0000000000000000000000000000016000000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_accesslist.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_acce0000664000175000017500000000017413535474530033323 0ustar kamikami00000000000000{"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"}]}././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_errorpage.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_erro0000664000175000017500000000065513535474530033403 0ustar kamikami00000000000000{"errorpage":{"content":"Service Unavailable

Service Unavailable

The service is temporarily unavailable. Please try again later.

"}}././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_ex_public_ips.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18940_ex_p0000664000175000017500000000113513535474530033361 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"RANDOM","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED"}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T13:32:05Z"},"connectionLogging":{"enabled":false}}} ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18941_ex_private_ips.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18941_ex_p0000664000175000017500000000113113535474530033356 0ustar kamikami00000000000000{"loadBalancer":{"name":"servicenet","id":18941,"protocol":"HTTP","port":80,"algorithm":"RANDOM","status":"BUILD","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.183.32.247","id":94693,"port":80,"status":"ONLINE","condition":"ENABLED"}],"created":{"time":"2011-12-09T13:33:28Z"},"virtualIps":[{"address":"10.183.252.175","id":572,"type":"SERVICENET","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T13:33:28Z"},"connectionLogging":{"enabled":false}}}././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18945_ex_public_ips.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_18945_ex_p0000664000175000017500000000113513535474530033366 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"RANDOM","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED"}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T13:32:05Z"},"connectionLogging":{"enabled":false}}} apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_3xxx.json0000664000175000017500000000220313535474530033540 0ustar kamikami00000000000000{ "loadBalancer": { "algorithm": "UUUUUUUUUU", "cluster": { "name": "ztm-n05.lbaas.ord1.rackspace.net" }, "connectionLogging": { "enabled": false }, "created": { "time": "2011-04-07T16:27:50Z" }, "id": 9999999, "name": "test2", "nodes": [ { "address": "10.1.0.11", "condition": "ENABLED", "id": 30944, "port": 80, "status": "ONLINE" }, { "address": "10.1.0.10", "condition": "ENABLED", "id": 30945, "port": 80, "status": "ONLINE" } ], "port": 88888, "protocol": "XXXXX", "status": "ACTIVE", "updated": { "time": "2011-04-07T16:28:12Z" }, "virtualIps": [ { "address": "1.1.1.1", "id": 1151, "ipVersion": "IPV4", "type": "PUBLIC" } ] } } apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290.json0000664000175000017500000000264413535474530033241 0ustar kamikami00000000000000{ "loadBalancer": { "algorithm": "RANDOM", "cluster": { "name": "ztm-n05.lbaas.ord1.rackspace.net" }, "connectionLogging": { "enabled": false }, "created": { "time": "2011-04-07T16:27:50Z" }, "id": 8290, "name": "test2", "nodes": [ { "address": "10.1.0.11", "condition": "ENABLED", "id": 30944, "port": 80, "status": "ONLINE", "weight": 12 }, { "address": "10.1.0.10", "condition": "DISABLED", "id": 30945, "port": 80, "status": "OFFLINE", "weight": 8 }, { "address": "10.1.0.9", "condition": "DRAINING", "id": 30946, "port": 8080, "status": "DRAINING", "weight": 20 } ], "port": 80, "protocol": "HTTP", "status": "ACTIVE", "updated": { "time": "2011-04-07T16:28:12Z" }, "virtualIps": [ { "address": "1.1.1.1", "id": 1151, "ipVersion": "IPV4", "type": "PUBLIC" } ] } } ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_errorpage.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_error0000664000175000017500000000007313535474530033474 0ustar kamikami00000000000000{"errorpage":{"content":"Generic Error Page"}}././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes0000664000175000017500000000117713535474530033461 0ustar kamikami00000000000000{ "nodes": [ { "address": "10.1.0.11", "condition": "ENABLED", "id": 30944, "port": 80, "status": "ONLINE", "weight": 12 }, { "address": "10.1.0.10", "condition": "DISABLED", "id": 30945, "port": 80, "status": "OFFLINE", "weight": 8 }, { "address": "10.1.0.9", "condition": "DRAINING", "id": 30946, "port": 8080, "status": "DRAINING", "weight": 20 } ] } ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes_post.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8290_nodes0000664000175000017500000000034313535474530033453 0ustar kamikami00000000000000{ "nodes": [ { "address": "10.1.0.12", "condition": "ENABLED", "id": 30972, "port": 80, "status": "ONLINE", "weight": 1 } ] } apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8291.json0000664000175000017500000000261413535474530033237 0ustar kamikami00000000000000{ "loadBalancer": { "algorithm": "RANDOM", "cluster": { "name": "ztm-n05.lbaas.ord1.rackspace.net" }, "connectionLogging": { "enabled": false }, "created": { "time": "2011-04-07T16:27:50Z" }, "id": 8291, "name": "test8291", "nodes": [ { "address": "10.1.0.11", "condition": "ENABLED", "id": 30944, "port": 80, "status": "ONLINE", "weight": 12 }, { "address": "10.1.0.10", "condition": "DISABLED", "id": 30945, "port": 80, "status": "OFFLINE", "weight": 8 }, { "address": "10.1.0.9", "condition": "DRAINING", "id": 30946, "port": 8080, "status": "DRAINING", "weight": 20 } ], "port": 80, "protocol": "HTTP", "status": "ACTIVE", "updated": { "time": "2011-04-07T16:28:12Z" }, "virtualIps": [ { "address": "1.1.1.1", "id": 1151, "ipVersion": "IPV4", "type": "PUBLIC" } ] } } apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292.json0000664000175000017500000000261413535474530033240 0ustar kamikami00000000000000{ "loadBalancer": { "algorithm": "RANDOM", "cluster": { "name": "ztm-n05.lbaas.ord1.rackspace.net" }, "connectionLogging": { "enabled": false }, "created": { "time": "2011-04-07T16:27:50Z" }, "id": 8292, "name": "test8292", "nodes": [ { "address": "10.1.0.11", "condition": "ENABLED", "id": 30944, "port": 80, "status": "ONLINE", "weight": 12 }, { "address": "10.1.0.10", "condition": "DISABLED", "id": 30945, "port": 80, "status": "OFFLINE", "weight": 8 }, { "address": "10.1.0.9", "condition": "DRAINING", "id": 30946, "port": 8080, "status": "DRAINING", "weight": 20 } ], "port": 80, "protocol": "HTTP", "status": "ACTIVE", "updated": { "time": "2011-04-07T16:28:12Z" }, "virtualIps": [ { "address": "1.1.1.2", "id": 1151, "ipVersion": "IPV4", "type": "PUBLIC" } ] } } ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292_nodes_post.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_8292_nodes0000664000175000017500000000064413535474530033461 0ustar kamikami00000000000000{ "nodes": [ { "address": "10.1.0.12", "condition": "ENABLED", "id": 30972, "port": 80, "status": "ONLINE", "weight": 1 }, { "address": "10.1.0.13", "condition": "ENABLED", "id": 30973, "port": 80, "status": "ONLINE", "weight": 1 } ] } ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94692_weighted_round_robin.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94692_weig0000664000175000017500000000116513535474530033374 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_ROUND_ROBIN","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T14:39:40Z"},"connectionLogging":{"enabled":false}}}././@LongLink0000000000000000000000000000020000000000000011205 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94693_weighted_least_connections.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94693_weig0000664000175000017500000000120413535474530033367 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"PENDING_UPDATE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T15:18:38Z"},"connectionLogging":{"enabled":false}}} ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94694_unknown_algorithm.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94694_unkn0000664000175000017500000000120613535474530033412 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":18940,"protocol":"HTTP","port":80,"algorithm":"UNSPECIFIED_FUTURE_ALGORITHM","status":"PENDING_UPDATE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T15:18:38Z"},"connectionLogging":{"enabled":false}}} ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94695_full_details.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94695_full0000664000175000017500000000156413535474530033411 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":94695,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"OFFLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"CONNECT","delay":10,"timeout":5,"attemptsBeforeDeactivation":2},"sessionPersistence":{"persistenceType":"HTTP_COOKIE"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T16:01:36Z"},"connectionThrottle":{"maxConnections":200,"minConnections":50,"maxConnectionRate":50,"rateInterval":10},"connectionLogging":{"enabled":true}}}././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94696_http_health_monitor.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94696_http0000664000175000017500000000166713535474530033433 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":94696,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"HTTP","path":"/","delay":10,"timeout":5,"attemptsBeforeDeactivation":2,"statusRegex":"^[234][0-9][0-9]$","bodyRegex":"Hello World!"},"sessionPersistence":{"persistenceType":"HTTP_COOKIE"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T16:51:32Z"},"connectionThrottle":{"maxConnections":100,"minConnections":25,"maxConnectionRate":25,"rateInterval":5},"connectionLogging":{"enabled":true}}}././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94697_https_health_monitor.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94697_http0000664000175000017500000000200713535474530033421 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":94697,"protocol":"HTTPS","port":443,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"PENDING_UPDATE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"OFFLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"HTTPS","path":"/test","delay":15,"timeout":12,"attemptsBeforeDeactivation":5,"statusRegex":"^[234][0-9][0-9]$","bodyRegex":"abcdef"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T19:34:34Z"},"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"}],"connectionThrottle":{"maxConnections":100,"minConnections":25,"maxConnectionRate":25,"rateInterval":5},"connectionLogging":{"enabled":true}}} ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_access_list.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_acce0000664000175000017500000000025413535474530033340 0ustar kamikami00000000000000{"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"},{"address":"8.8.8.8/0","id":3006,"type":"DENY"}]}././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_with_access_list.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94698_with0000664000175000017500000000212213535474530033414 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":94698,"protocol":"HTTPS","port":443,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"OFFLINE","condition":"DRAINING","weight":25},{"address":"10.181.238.11","id":97683,"port":443,"status":"OFFLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"CONNECT","delay":5,"timeout":10,"attemptsBeforeDeactivation":4},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2012-01-05T19:31:38Z"},"accessList":[{"address":"0.0.0.0/0","id":2883,"type":"DENY"},{"address":"2001:4801:7901::6/64","id":2884,"type":"ALLOW"},{"address":"8.8.8.8/0","id":3006,"type":"DENY"}],"connectionThrottle":{"maxConnections":200,"minConnections":50,"maxConnectionRate":50,"rateInterval":10},"connectionLogging":{"enabled":true}}}././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94700_http_health_monitor_no_body_regex.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_94700_http0000664000175000017500000000163413535474530033407 0ustar kamikami00000000000000{"loadBalancer":{"name":"new ord balancer","id":94700,"protocol":"HTTP","port":80,"algorithm":"WEIGHTED_LEAST_CONNECTIONS","status":"ACTIVE","cluster":{"name":"ztm-n06.lbaas.ord1.rackspace.net"},"nodes":[{"address":"10.181.231.202","id":94692,"port":80,"status":"ONLINE","condition":"ENABLED","weight":1}],"created":{"time":"2011-12-09T13:30:40Z"},"healthMonitor":{"type":"HTTP","path":"/","delay":10,"timeout":5,"attemptsBeforeDeactivation":2,"statusRegex":"^[234][0-9][0-9]$"},"sessionPersistence":{"persistenceType":"HTTP_COOKIE"},"virtualIps":[{"address":"50.56.49.149","id":2359,"type":"PUBLIC","ipVersion":"IPV4"}],"sourceAddresses":{"ipv6Public":"2001:4801:7901::6/64","ipv4Servicenet":"10.183.252.25","ipv4Public":"184.106.100.25"},"updated":{"time":"2011-12-09T16:51:32Z"},"connectionThrottle":{"maxConnections":100,"minConnections":25,"maxConnectionRate":25,"rateInterval":5},"connectionLogging":{"enabled":true}}}././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_algorithms.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_algorithms0000664000175000017500000000023513535474530034032 0ustar kamikami00000000000000{"algorithms":[{"name":"LEAST_CONNECTIONS"},{"name":"RANDOM"},{"name":"ROUND_ROBIN"},{"name":"WEIGHTED_LEAST_CONNECTIONS"},{"name":"WEIGHTED_ROUND_ROBIN"}]} ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_nodeaddress.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_nodeaddres0000664000175000017500000000057413535474530033777 0ustar kamikami00000000000000{"loadBalancers": [ { "name": "First Loadbalancer", "id": 1, "status": "ACTIVE" }, { "name": "Second Loadbalancer", "id": 2, "status": "PENDING_UPDATE" }, { "name": "Third Loadbalancer", "id": 8, "status": "ERROR" } ] } apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_post.json0000664000175000017500000000227313535474530033622 0ustar kamikami00000000000000{ "loadBalancer": { "algorithm": "RANDOM", "cluster": { "name": "ztm-n05.lbaas.ord1.rackspace.net" }, "connectionLogging": { "enabled": false }, "created": { "time": "2011-04-07T16:27:50+0000" }, "id": 8290, "name": "test2", "nodes": [ { "address": "10.1.0.11", "condition": "ENABLED", "id": 30944, "port": 80, "status": "ONLINE", "weight": 1 }, { "address": "10.1.0.10", "condition": "ENABLED", "id": 30945, "port": 80, "status": "ONLINE", "weight": 1 } ], "port": 80, "protocol": "HTTP", "status": "BUILD", "updated": { "time": "2011-04-07T16:27:50+0000" }, "virtualIps": [ { "address": "1.1.1.1", "id": 1151, "ipVersion": "IPV4", "type": "PUBLIC" } ] } } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_protocols.jsonapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/rackspace/v1_slug_loadbalancers_protocols.0000664000175000017500000000140713535474530033765 0ustar kamikami00000000000000{"protocols": [ { "name": "HTTP", "port": "80" }, { "name": "FTP", "port": "21" }, { "name": "IMAPv4", "port": "143" }, { "name": "POP3", "port": "110" }, { "name": "SMTP", "port": "25" }, { "name": "LDAP", "port": "389" }, { "name": "HTTPS", "port": "443" }, { "name": "IMAPS", "port": "993" }, { "name": "POP3S", "port": "995" }, { "name": "LDAPS", "port": "636" } ] } apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/0000775000175000017500000000000013600223624024235 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/add_backend_servers.xml0000664000175000017500000000061113535474530030740 0ustar kamikami00000000000000 365F4154-92F6-4AE4-92F8-7FF34B540710 139a00604ad-cn-east-hangzhou-01 node1 100 apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/create_load_balancer.xml0000664000175000017500000000070013535474530031060 0ustar kamikami00000000000000 365F4154-92F6-4AE4-92F8-7FF34B540710 139a00604ad-cn-east-hangzhou-01
42.250.6.36
classic cn-hangzhou-d cn-hangzhou-b balancer1
apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/create_load_balancer_http_listener.xml0000664000175000017500000000027213535474530034030 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/delete_load_balancer.xml0000664000175000017500000000023713535474530031064 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/delete_server_certificate.xml0000664000175000017500000000025613535474530032167 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/describe_load_balancer_attribute.xml0000664000175000017500000000247613535474530033474 0ustar kamikami00000000000000 1452403099000 cn-hangzhou i-23tshnsdq 100 15229f88562-cn-hangzhou-dg-a01 80 paybytraffic cn-hangzhou-b classic cn-hangzhou-d http 80 2016-01-10 13:18:19
120.27.186.149
cn-hangzhou-dg-a01 D67B80CD-C359-4352-AE3C-4F286CC3782D internet http 80 active 1
apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/describe_load_balancers.xml0000664000175000017500000000142413535474530031564 0ustar kamikami00000000000000 1452403099000 cn-hangzhou-b classic cn-hangzhou-d cn-hangzhou 2016-01-10T13:18Z cn-hangzhou-dg-a01
120.27.186.149
internet 15229f88562-cn-hangzhou-dg-a01 abc active
A0DAF856-B181-4098-B507-6CE9E40420E8
apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/describe_server_certificates.xml0000664000175000017500000000130613535474530032665 0ustar kamikami00000000000000 365F4154-92F6-4AE4-92F8-7FF34B540710 139a00604ad-cn-east-hangzhou-01 abe A:B:E 139a00604ad-cn-east-hangzhou-02 abf A:B:F apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/remove_backend_servers.xml0000664000175000017500000000061713535474530031513 0ustar kamikami00000000000000 365F4154-92F6-4AE4-92F8-7FF34B540710 139a00604ad-cn-east-hangzhou-01 node1 100 apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/set_server_certificate_name.xml0000664000175000017500000000026013535474530032513 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/start_load_balancer_listener.xml0000664000175000017500000000027013535474530032661 0ustar kamikami00000000000000 CEF72CEB-54B6-4AE8-B225-F876FF7BA984 apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/slb/upload_server_certificate.xml0000664000175000017500000000051313535474530032205 0ustar kamikami00000000000000 365F4154-92F6-4AE4-92F8-7FF34B540710 idkp-123-cn-test-01 cert1 01:DF:AB:CD apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/0000775000175000017500000000000013600223624025465 5ustar kamikami00000000000000././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Account_getAdcLoadBalancers.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Account_getAdcLoad0000664000175000017500000005451613535474530033640 0ustar kamikami00000000000000 accountId 411826 connectionLimit 50 connectionLimitUnits connections/second dedicatedFlag 0 id 76185 ipAddressId 7303289 securityCertificateId sslActiveFlag 0 sslEnabledFlag 0 highAvailabilityFlag 0 ipAddress id 7303289 ipAddress 108.168.157.130 isBroadcast 0 isGateway 0 isNetwork 0 isReserved 1 note Load balancer VIP subnetId 406030 loadBalancerHardware accountId 1 bareMetalInstanceFlag 0 domain softlayer.com fullyQualifiedDomainName lb04.dal05.softlayer.com hardwareStatusId 5 hostname lb04.dal05 id 178860 notes provisionDate serviceProviderId 1 serviceProviderResourceId 178860 datacenter id 138124 longName Dallas 5 name dal05 statusId 2 virtualServers allocation 100 id 132193 port 80 routingMethodId virtualIpAddressId 76185 serviceGroups id 131113 routingMethodId 10 routingTypeId 2 timeout routingMethod id 10 keyname ROUND_ROBIN name Round Robin routingType id 2 keyname HTTP name HTTP services enabled 1 id 221145 ipAddressId 33499201 notes inst-test-276a.example.com port 8080 status DOWN ipAddress id 33499201 ipAddress 75.126.161.106 isBroadcast 0 isGateway 0 isNetwork 0 isReserved 0 subnetId 22958 subnet broadcastAddress 75.126.161.111 cidr 29 gateway 75.126.161.105 id 22958 isCustomerOwned 0 isCustomerRoutable 0 modifyDate 2015-04-19T03:04:09+02:00 netmask 255.255.255.248 networkIdentifier 75.126.161.104 networkVlanId 815621 sortOrder 4 subnetType PRIMARY totalIpAddresses 8 usableIpAddressCount 5 version 4 accountId 411826 connectionLimit 50 connectionLimitUnits connections/second dedicatedFlag 0 id 76265 ipAddressId 25808370 securityCertificateId sslActiveFlag 0 sslEnabledFlag 0 highAvailabilityFlag 0 ipAddress id 25808370 ipAddress 159.8.117.72 isBroadcast 0 isGateway 0 isNetwork 0 isReserved 1 note Load balancer VIP subnetId 717366 loadBalancerHardware accountId 1 bareMetalInstanceFlag 0 domain softlayer.com fullyQualifiedDomainName lb01.par01.softlayer.com hardwareStatusId 5 hostname lb01.par01 id 390016 notes provisionDate serviceProviderId 1 serviceProviderResourceId 390016 datacenter id 449500 longName Paris 1 name par01 statusId 2 virtualServers ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Billing_Item_cancelService.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Billing_Item_cance0000664000175000017500000000016413535474530033652 0ustar kamikami00000000000000 1 ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Location_Datacenter_getDatacenters.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Location_Datacente0000664000175000017500000003053113535474530033704 0ustar kamikami00000000000000 id 265592 longName Amsterdam 1 name ams01 statusId 2 id 814994 longName Amsterdam 3 name ams03 statusId 2 id 3 longName Dallas 1 name dal01 statusId 2 id 154770 longName Dallas 2 name dal02 statusId 2 id 167092 longName Dallas 4 name dal04 statusId 2 id 138124 longName Dallas 5 name dal05 statusId 2 id 154820 longName Dallas 6 name dal06 statusId 2 id 142776 longName Dallas 7 name dal07 statusId 2 id 449494 longName Dallas 9 name dal09 statusId 2 id 449506 longName Frankfurt 2 name fra02 statusId 2 id 352494 longName Hong Kong 2 name hkg02 statusId 2 id 142775 longName Houston 2 name hou02 statusId 2 id 358694 longName London 2 name lon02 statusId 2 id 449596 longName Melbourne 1 name mel01 statusId 2 id 449600 longName Mexico 1 name mex01 statusId 2 id 449610 longName Montreal 1 name mon01 statusId 2 id 449500 longName Paris 1 name par01 statusId 2 id 168642 longName San Jose 1 name sjc01 statusId 2 id 18171 longName Seattle name sea01 statusId 2 id 224092 longName Singapore 1 name sng01 statusId 2 id 449612 longName Sydney 1 name syd01 statusId 2 id 449604 longName Tokyo 2 name tok02 statusId 2 id 448994 longName Toronto 1 name tor01 statusId 2 id 37473 longName Washington 1 name wdc01 statusId 2 ././@LongLink0000000000000000000000000000024000000000000011211 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_Service_deleteObject.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Applicatio0000664000175000017500000000016513535474530033762 0ustar kamikami00000000000000 1 ././@LongLink0000000000000000000000000000024700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_editObject.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Applicatio0000664000175000017500000000016513535474530033762 0ustar kamikami00000000000000 1 ././@LongLink0000000000000000000000000000025300000000000011215 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_getBillingItem.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Applicatio0000664000175000017500000000513213535474530033761 0ustar kamikami00000000000000 allowCancellationFlag 1 cancellationDate categoryCode proxy_load_balancer createDate 2015-04-24T15:19:21+02:00 cycleStartDate 2015-04-24T15:19:21+02:00 description Load Balancer 50 connections id 50844215 laborFee 0 laborFeeTaxRate 0 lastBillDate 2015-04-24T15:19:21+02:00 modifyDate 2015-04-24T15:19:23+02:00 nextBillDate 2015-05-01T07:00:00+02:00 notes 1.2.3.4 oneTimeFee 0 oneTimeFeeTaxRate 0 orderItemId 65021573 parentId recurringFee 29 recurringFeeTaxRate 0 recurringMonths 1 serviceProviderId 1 setupFee 0 setupFeeTaxRate 0 ././@LongLink0000000000000000000000000000024600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_getObject.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Applicatio0000664000175000017500000006660113535474530033771 0ustar kamikami00000000000000 accountId 411826 connectionLimit 50 connectionLimitUnits connections/second dedicatedFlag 0 id 76185 ipAddressId 7303289 securityCertificateId sslActiveFlag 0 sslEnabledFlag 0 highAvailabilityFlag 0 managedResourceFlag 0 virtualServers allocation 100 id 132193 port 80 routingMethodId virtualIpAddressId 76185 serviceGroups id 131113 routingMethodId 10 routingTypeId 2 timeout services enabled 1 id 226227 ipAddressId 29341260 port 8000 status UP groupReferences serviceGroupId 131113 serviceId 226227 weight 1 ipAddress id 29341260 ipAddress 10.126.5.34 isBroadcast 0 isGateway 0 isNetwork 0 isReserved 0 subnetId 730826 subnet broadcastAddress 10.126.5.63 cidr 26 gateway 10.126.5.1 id 730826 isCustomerOwned 0 isCustomerRoutable 0 modifyDate 2015-04-19T03:14:26+02:00 netmask 255.255.255.192 networkIdentifier 10.126.5.0 networkVlanId 728518 sortOrder 4 subnetType PRIMARY totalIpAddresses 64 usableIpAddressCount 61 version 4 enabled 1 id 226229 ipAddressId 29341262 port 8080 status UP groupReferences serviceGroupId 131113 serviceId 226229 weight 1 ipAddress id 29341262 ipAddress 10.126.5.35 isBroadcast 0 isGateway 0 isNetwork 0 isReserved 0 subnetId 730826 subnet broadcastAddress 10.126.5.63 cidr 26 gateway 10.126.5.1 id 730826 isCustomerOwned 0 isCustomerRoutable 0 modifyDate 2015-04-19T03:14:26+02:00 netmask 255.255.255.192 networkIdentifier 10.126.5.0 networkVlanId 728518 sortOrder 4 subnetType PRIMARY totalIpAddresses 64 usableIpAddressCount 61 version 4 enabled 1 id 221145 ipAddressId 33499201 notes inst-test-276a.example.com port 8080 status UP groupReferences serviceGroupId 131113 serviceId 221145 weight 1 ipAddress id 33499201 ipAddress 75.75.75.75 isBroadcast 0 isGateway 0 isNetwork 0 isReserved 0 subnetId 22958 subnet broadcastAddress 75.75.75.75 cidr 29 gateway 75.75.75.75 id 22958 isCustomerOwned 0 isCustomerRoutable 0 modifyDate 2015-04-19T03:04:09+02:00 netmask 255.255.255.248 networkIdentifier 75.75.75.75 networkVlanId 815621 sortOrder 4 subnetType PRIMARY totalIpAddresses 8 usableIpAddressCount 5 version 4 ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Subnet_IpAddress_getByIpAddress.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Network_Subnet_IpA0000664000175000017500000000537613535474530033677 0ustar kamikami00000000000000 id 29341260 ipAddress 10.126.5.34 isBroadcast 0 isGateway 0 isNetwork 0 isReserved 0 subnetId 730826 subnet broadcastAddress 10.126.5.63 cidr 26 gateway 10.126.5.1 id 730826 isCustomerOwned 0 isCustomerRoutable 0 modifyDate 2015-04-19T03:14:26+02:00 netmask 255.255.255.192 networkIdentifier 10.126.5.0 networkVlanId 728518 sortOrder 4 subnetType PRIMARY totalIpAddresses 64 usableIpAddressCount 61 version 4 ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Product_Order_placeOrder.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Product_Order_plac0000664000175000017500000003675113535474530033750 0ustar kamikami00000000000000 orderDate 2015-04-24T15:19:20+02:00 orderId 4320271 orderDetails bigDataOrderFlag 0 billingOrderItemId containerSplHash 00000000 currencyShortName USD extendedHardwareTesting imageTemplateId isManagedOrder 0 location 265592 message packageId 0 paymentType ADD_TO_BALANCE postTaxRecurring 29 postTaxRecurringHourly 0 postTaxRecurringMonthly 29 postTaxSetup 0 preTaxRecurring 29 preTaxRecurringHourly 0 preTaxRecurringMonthly 29 preTaxSetup 0 presetId primaryDiskPartitionId privateCloudOrderFlag 0 proratedInitialCharge 6.77 proratedOrderTotal 6.77 quantity 1 resourceGroupId resourceGroupTemplateId sendQuoteEmailFlag serverCoreCount sourceVirtualGuestId stepId taxCacheHash b94c43e22aeaedb3dc4 taxCompletedFlag 1 totalRecurringTax 0 totalSetupTax 0 useHourlyPricing 0 billingInformation billingAddressLine1 University billingCity Haifa billingCountryCode IL billingEmail someone@com billingNameCompany IBM billingNameFirst Foo billingNameLast Bar billingPhoneVoice 972-4-44444 billingPostalCode 0000 billingState OT cardExpirationMonth cardExpirationYear taxExempt 0 itemCategoryQuestionAnswers locationObject id 265592 longName Amsterdam 1 name ams01 prices id 33021 itemId 565 laborFee 0 oneTimeFee 0 recurringFee 29 setupFee 0 categories categoryCode proxy_load_balancer id 55 name Proxy Load Balancer item capacity 50 description Load Balancer 50 connections id 565 keyName LOAD_BALANCER_50_CONNECTIONS units Connections/Second bundle properties sshKeys storageGroups placedOrder accountId 411826 id 4320271 orderQuoteId orderTypeId 4 presaleEventId status PENDING_AUTO_APPROVAL userRecordId 315282 account brandId 30130 companyName IBM id 411826 items categoryCode proxy_load_balancer description Load Balancer 50 connections id 65021573 itemId 565 itemPriceId 33021 laborFee 0 oneTimeFee 0 parentId promoCodeId recurringFee 29 setupFee 0 children userRecord accountId 00000 firstName Foo id 00000 lastName Foo username foo ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Product_Package_getItems.xmlapache-libcloud-2.8.0/libcloud/test/loadbalancer/fixtures/softlayer/v3__SoftLayer_Product_Package_ge0000664000175000017500000036173713535474530033711 0ustar kamikami00000000000000 capacity 0 description Citrix VDC id 1148 itemTaxCategoryId 166 keyName CITRIX_VDC softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 24912 itemId 1148 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 0 sort 0 capacity 65000 description Load Balancer (Dedicated, with SSL offload) - 15,000 Connections id 4136 itemTaxCategoryId 166 keyName LOAD_BALANCER_DEDICATED_WITH_SSL_OFFLOAD_15000_CONNECTIONS softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 25314 itemId 4136 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 849 setupFee 0 sort 0 capacity 200 description Citrix NetScaler VPX 10.5 200Mbps Platinum id 5916 itemTaxCategoryId 166 keyName CITRIX_NETSCALER_VPX_10_5_200MBPS_PLATINUM softwareDescriptionId 1378 units Mbps upgradeItemId prices currentPriceFlag id 44970 itemId 5916 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 899 setupFee 0 sort 0 capacity 64 description /64 Block Static Public IPv6 Addresses id 784 itemTaxCategoryId 166 keyName 64_BLOCK_STATIC_PUBLIC_IPV6_ADDRESSES softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag hourlyRecurringFee .007 id 26340 itemId 784 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 0 sort 10 capacity 4 description .info - 4 year id 4007 itemTaxCategoryId 166 keyName DOMAIN_INFO_4_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 26584 itemId 4007 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 38.48 sort 3 capacity 50 description Load Balancer 50 connections id 565 itemTaxCategoryId 166 keyName LOAD_BALANCER_50_CONNECTIONS softwareDescriptionId units Connections/Second upgradeItemId 567 prices currentPriceFlag id 33021 itemId 565 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 29 setupFee 0 sort 0 capacity 0 description Reseller Domain Credit id 4065 itemTaxCategoryId 162 keyName RESELLER_DOMAIN_CREDIT softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 27728 itemId 4065 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 0 sort 10 capacity 250 description CDN 250 GB Bandwidth id 892 itemTaxCategoryId 166 keyName CDN_250_GB_BANDWIDTH softwareDescriptionId units GB upgradeItemId prices currentPriceFlag id 27770 itemId 892 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 20 setupFee 0 sort 10 capacity 3 description .biz - 3 year id 3995 itemTaxCategoryId 166 keyName DOMAIN_BIZ_3_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 29940 itemId 3995 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 33 sort 2 capacity 0 description Dedicated Rack (Half) id 1302 itemTaxCategoryId 166 keyName DEDICATED_RACK_HALF softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 31299 itemId 1302 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 1100 setupFee 0 sort 0 capacity 1000 description Load Balancer 1,000 connections id 566 itemTaxCategoryId 166 keyName LOAD_BALANCER_1000_CONNECTIONS softwareDescriptionId units Connections/Second upgradeItemId 571 prices currentPriceFlag id 31322 itemId 566 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 499 setupFee 0 sort 0 capacity 5 description .info - 5 year id 4023 itemTaxCategoryId 166 keyName DOMAIN_INFO_5_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 31340 itemId 4023 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 48.1 sort 4 capacity 7 description .us - 7 year id 3999 itemTaxCategoryId 166 keyName DOMAIN_US_7_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 32381 itemId 3999 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 57.33 sort 6 capacity 0 description Windows 2008 Datacenter w/ Unlimited Virtuals (2 Proc License) id 791 itemTaxCategoryId 166 keyName VIRTUAL_OS_WINDOWS_2008_DATACENTER_W_UNLIMITED_VIRTUALS_2_PROC_LICENSE softwareDescriptionId 723 units N/A upgradeItemId prices currentPriceFlag id 32695 itemId 791 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 127.5 setupFee 0 sort 0 capacity 250 description Load Balancer 250 VIP Connections id 1106 itemTaxCategoryId 166 keyName LOAD_BALANCER_250_VIP_CONNECTIONS softwareDescriptionId units Connections/Second upgradeItemId 1105 prices currentPriceFlag id 33908 itemId 1106 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 29 setupFee 0 sort 0 capacity 1500 description 1500GB EVault Disk to Disk Enterprise Backup id 4185 itemTaxCategoryId 166 keyName EVAULT_1500_GB softwareDescriptionId 159 units GIGABYTE upgradeItemId 955 prices currentPriceFlag id 34594 itemId 4185 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 543.75 setupFee 0 sort 0 capacity 65000 description Dedicated Load Balancer with High Availability and SSL - 15,000 Connections id 4512 itemTaxCategoryId 166 keyName DEDICATED_LOAD_BALANCER_WITH_HIGH_AVAILABILITY_AND_SSL_15000_CONNECTIONS softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 36019 itemId 4512 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 1698 setupFee 0 sort 0 capacity 10 description Citrix NetScaler VPX 10.5 10Mbps Platinum id 5912 itemTaxCategoryId 166 keyName CITRIX_NETSCALER_VPX_10_5_10MBPS_PLATINUM softwareDescriptionId 1374 units Mbps upgradeItemId prices currentPriceFlag id 44950 itemId 5912 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 459 setupFee 0 sort 0 capacity 0 description EVault Plugin - VMWare ESX id 1087 itemTaxCategoryId 166 keyName EVAULT_PLUGIN_VMWARE_ESX softwareDescriptionId 635 upgradeItemId prices currentPriceFlag id 23040 itemId 1087 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 8.5 setupFee 0 sort 0 capacity 8 description 8 Static Public IP Addresses id 583 itemTaxCategoryId 166 keyName 8_STATIC_PUBLIC_IP_ADDRESSES softwareDescriptionId upgradeItemId prices currentPriceFlag hourlyRecurringFee 0 id 36692 itemId 583 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 0 sort 0 currentPriceFlag id 29583 itemId 583 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 8 setupFee 0 sort 0 currentPriceFlag id 31207 itemId 583 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 8 setupFee 0 sort 0 currentPriceFlag hourlyRecurringFee .007 id 23392 itemId 583 laborFee 0 onSaleFlag oneTimeFee 0 quantity setupFee 0 sort 0 capacity 2000 description Load Balancer 2,000 connections id 617 itemTaxCategoryId 166 keyName LOAD_BALANCER_2000_CONNECTIONS softwareDescriptionId units Connections/Second upgradeItemId 618 prices currentPriceFlag id 23794 itemId 617 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 999 setupFee 0 sort 0 capacity 3 description .us - 3 year id 4011 itemTaxCategoryId 166 keyName DOMAIN_US_3_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 24083 itemId 4011 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 24.57 sort 2 capacity 2 description FortiGate Security Appliance (High Availability) id 4338 itemTaxCategoryId 166 keyName FORTIGATE_SECURITY_APPLIANCE_HIGH_AVAILABILITY softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 24741 itemId 4338 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 1699 setupFee 0 sort 1 capacity 100000 description Advanced Package id 3859 itemTaxCategoryId 166 keyName NETWORK_MESSAGE_DELIVERY_ADVANCED_PACKAGE longDescription <ul> <li>Overage - $0.00085</li> <li>Bounce Tracking</li> <li>Unsub Tracking</li> <li>Click Tracking</li> <li>Open Tracking</li> <li>Dedicated IP</li> </ul> softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 24995 itemId 3859 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 36 setupFee 0 sort 0 capacity 0 description Global IPv6 id 4187 itemTaxCategoryId 166 keyName GLOBAL_IPV6 softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 25282 itemId 4187 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 20 setupFee 0 sort 10 capacity 0 description CDN Pay as You Go Bandwidth id 891 itemTaxCategoryId 166 keyName CDN_PAY_AS_YOU_GO_BANDWIDTH softwareDescriptionId units GB upgradeItemId prices currentPriceFlag id 25482 itemId 891 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 0 sort 5 capacity 2 description .net - 2 year id 4001 itemTaxCategoryId 166 keyName DOMAIN_NET_2_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 25495 itemId 4001 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 22 sort 1 capacity 1 description QuickSSL Premium - 1 year id 1293 itemTaxCategoryId 166 keyName SSL_CERTIFICATE_QUICKSSL_PREMIUM_1_YEAR longDescription <h3>GeoTrust QuickSSL&reg; Premium SSL</h3> <p> GeoTrust QuickSSL Premium Certificates are convenient and economical entry-level SSL Certificates. These certificates enable up to 256-bit encryption (depending on your client's browser capability and the cipher suite installed on your Web server) and are issued through an automated process that usually results in certificates being issued within minutes of being ordered. This process verifies that a certificate purchaser has appropriate administrative rights to a Web server's domain. </p> <h3>Features and Benefits</h3> <ul> <li>Domain-level authentication</li> <li>Up to 256-bit encryption</li> <li>True Site Seal embedded with a date/time stamp</li> <li>Issuance, often within minutes</li> <li>Unlimited, free self-service reissues</li> </ul> softwareDescriptionId units DV upgradeItemId prices currentPriceFlag id 25847 itemId 1293 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 79 sort 3 capacity 2 description Hardware Firewall (High Availability) id 3896 itemTaxCategoryId 166 keyName HARDWARE_FIREWALL_HIGH_AVAILABILITY softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 26005 itemId 3896 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 1398 setupFee 0 sort 0 capacity 3 description .org - 3 year id 4002 itemTaxCategoryId 166 keyName DOMAIN_ORG_3_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 26323 itemId 4002 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 30 sort 2 capacity 64 description /64 Block Portable Public IPv6 Addresses id 785 itemTaxCategoryId 166 keyName 64_BLOCK_PORTABLE_PUBLIC_IPV6_ADDRESSES softwareDescriptionId upgradeItemId prices currentPriceFlag id 28502 itemId 785 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 10 setupFee 0 sort 0 capacity 2500 description Load Balancer 2,500 VIP Connections id 1103 itemTaxCategoryId 166 keyName LOAD_BALANCER_2500_VIP_CONNECTIONS softwareDescriptionId units Connections/Second upgradeItemId 1102 prices currentPriceFlag id 30681 itemId 1103 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 299 setupFee 0 sort 0 capacity 500 description Load Balancer 500 VIP Connections id 1105 itemTaxCategoryId 166 keyName LOAD_BALANCER_500_VIP_CONNECTIONS softwareDescriptionId units Connections/Second upgradeItemId 1104 prices currentPriceFlag id 33416 itemId 1105 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 49 setupFee 0 sort 0 capacity 0 description Windows 2008 Datacenter w/ Unlimited Virtuals (4 Proc License) id 792 itemTaxCategoryId 166 keyName VIRTUAL_OS_WINDOWS_2008_DATACENTER_W_UNLIMITED_VIRTUALS_4_PROC_LICENSE softwareDescriptionId 723 units N/A upgradeItemId prices currentPriceFlag id 34006 itemId 792 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 255 setupFee 0 sort 0 capacity 1500 description Load Balancer 1,500 connections id 616 itemTaxCategoryId 166 keyName LOAD_BALANCER_1500_CONNECTIONS softwareDescriptionId upgradeItemId prices currentPriceFlag id 30815 itemId 616 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 749 setupFee 0 sort 0 capacity 2 description .com - 2 year id 4013 itemTaxCategoryId 166 keyName DOMAIN_COM_2_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 31127 itemId 4013 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 19.88 sort 1 capacity 10 description .net - 10 year id 4032 itemTaxCategoryId 166 keyName DOMAIN_NET_10_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 31647 itemId 4032 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 110 sort 9 description Hardware Firewall (Dedicated) id 1329 itemTaxCategoryId 166 keyName HARDWARE_FIREWALL_DEDICATED softwareDescriptionId units dedicated upgradeItemId prices currentPriceFlag id 33373 itemId 1329 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 699 setupFee 0 sort 0 capacity 2 description .org - 2 year id 3993 itemTaxCategoryId 166 keyName DOMAIN_ORG_2_YEAR softwareDescriptionId units N/A upgradeItemId prices currentPriceFlag id 22693 itemId 3993 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 20 sort 1 capacity 8 description 8 Portable Private IP Addresses id 3903 itemTaxCategoryId 166 keyName 8_PORTABLE_PRIVATE_IP_ADDRESSES softwareDescriptionId units IPs upgradeItemId prices currentPriceFlag id 23104 itemId 3903 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 0 setupFee 0 sort 0 capacity 1000 description 1000GB EVault Disk to Disk Enterprise Backup id 563 itemTaxCategoryId 166 keyName EVAULT_1000_GB softwareDescriptionId 159 units GIGABYTE upgradeItemId 4185 prices currentPriceFlag id 28124 itemId 563 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 362.5 setupFee 0 sort 0 capacity 1000 description Citrix NetScaler VPX 10.5 1000Mbps Standard id 5910 itemTaxCategoryId 166 keyName CITRIX_NETSCALER_VPX_10_5_1000MBPS_STANDARD softwareDescriptionId 1380 units Mbps upgradeItemId prices currentPriceFlag id 44938 itemId 5910 laborFee 0 onSaleFlag oneTimeFee 0 quantity recurringFee 999 setupFee 0 sort 0 apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_alb.py0000664000175000017500000004110413576514553023773 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.loadbalancer.drivers.alb import ApplicationLBDriver from libcloud.loadbalancer.types import State from libcloud.loadbalancer.base import Member from libcloud.test import MockHttp from libcloud.test.secrets import LB_ALB_PARAMS from libcloud.test.file_fixtures import LoadBalancerFileFixtures class ApplicationLBTests(unittest.TestCase): # defaults from fixtures balancer_id = 'arn:aws:elasticloadbalancing:us-east-1:111111111111:loadbalancer/app/Test-ALB/1111111111111111' target_group_id = 'arn:aws:elasticloadbalancing:us-east-1:111111111111:targetgroup/Test-ALB-tg/1111111111111111' listener_id = \ 'arn:aws:elasticloadbalancing:us-east-1:111111111111:listener/app/Test-ALB/1111111111111111/1111111111111111' rule_id = 'arn:aws:elasticloadbalancing:us-east-1:111111111111:listener-rule/app/Test-Develop-App-LB/1111111111111111/' \ '1111111111111111/1111111111111111' ssl_cert_id = 'arn:aws:iam::111111111111:server-certificate/test.certificate' def setUp(self): ApplicationLBMockHttp.test = self ApplicationLBDriver.connectionCls.conn_class = ApplicationLBMockHttp ApplicationLBMockHttp.type = None ApplicationLBMockHttp.use_param = 'Action' self.driver = ApplicationLBDriver(*LB_ALB_PARAMS) def test_instantiate_driver_with_token(self): token = 'temporary_credentials_token' driver = ApplicationLBDriver(*LB_ALB_PARAMS, **{'token': token}) self.assertTrue(hasattr(driver, 'token'), 'Driver has no attribute token') self.assertEqual(token, driver.token, "Driver token does not match with provided token") def test_driver_with_token_signature_version(self): token = 'temporary_credentials_token' driver = ApplicationLBDriver(*LB_ALB_PARAMS, **{'token': token}) kwargs = driver._ex_connection_class_kwargs() self.assertTrue(('signature_version' in kwargs), 'Driver has no attribute signature_version') self.assertEqual('4', kwargs['signature_version'], 'Signature version is not 4 with temporary credentials') def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertEqual(len(protocols), 2) self.assertTrue('http' in protocols) self.assertTrue('https' in protocols) def test_list_balancers(self): balancers = self.driver.list_balancers() self.assertEqual(len(balancers), 1) self.assertEqual(balancers[0].id, self.balancer_id) self.assertEqual(balancers[0].name, 'Test-ALB') def test_get_balancer(self): balancer = self.driver.get_balancer(balancer_id=self.balancer_id) self.assertEqual(balancer.id, self.balancer_id) self.assertEqual(balancer.extra['listeners'][0].balancer.id, self.balancer_id) self.assertEqual(balancer.name, 'Test-ALB') self.assertEqual(balancer.state, State.UNKNOWN) def test_create_balancer(self): balancer = self.driver.create_balancer(name='Test-ALB', port=443, protocol='HTTPS', algorithm=None, members=[Member(id='i-01111111111111111', ip=None, port=443)], ex_scheme="internet-facing", ex_security_groups=['sg-11111111'], ex_subnets=['subnet-11111111', 'subnet-22222222'], ex_tags={}, ex_ssl_cert_arn=self.ssl_cert_id) self.assertEqual(balancer.id, self.balancer_id) self.assertEqual(balancer.name, 'Test-ALB') self.assertEqual(balancer.state, State.UNKNOWN) self.assertEqual(balancer.port, 443) def test_ex_create_balancer(self): balancer = self.driver.ex_create_balancer(name='Test-ALB', addr_type='ipv4', scheme='internet-facing', security_groups=['sg-11111111'], subnets=['subnet-11111111', 'subnet-22222222']) self.assertEqual(balancer.id, self.balancer_id) self.assertEqual(balancer.name, 'Test-ALB') self.assertEqual(balancer.state, State.UNKNOWN) def test_ex_create_target_group(self): target_group = self.driver.ex_create_target_group(name='Test-ALB-tg', port=443, proto="HTTPS", vpc='vpc-11111111', health_check_interval=30, health_check_path="/", health_check_port="traffic-port", health_check_proto="HTTP", health_check_timeout=5, health_check_matcher="200", healthy_threshold=5, unhealthy_threshold=2 ) self.assertTrue(hasattr(target_group, 'id'), 'Target group is missing "id" field') self.assertTrue(hasattr(target_group, 'members'), 'Target group is missing "members" field') self.assertEqual(target_group.name, 'Test-ALB-tg') self.assertEqual(target_group.port, 443) self.assertEqual(target_group.protocol, 'HTTPS') self.assertEqual(target_group.vpc, 'vpc-11111111') self.assertEqual(target_group.health_check_timeout, 5) self.assertEqual(target_group.health_check_port, 'traffic-port') self.assertEqual(target_group.health_check_path, '/') self.assertEqual(target_group.health_check_matcher, "200") self.assertEqual(target_group.health_check_proto, 'HTTPS') self.assertEqual(target_group.health_check_interval, 30) self.assertEqual(target_group.healthy_threshold, 5) self.assertEqual(target_group.unhealthy_threshold, 2) def test_ex_register_targets(self): balancer = self.driver.get_balancer(self.balancer_id) target_group = self.driver.ex_get_target_group(self.target_group_id) members = [Member('i-01111111111111111', '10.0.0.0', 443)] targets_not_registered = self.driver.ex_register_targets(target_group=target_group, members=members) self.assertTrue(targets_not_registered, 'ex_register_targets is expected to return True on success') def test_ex_create_listener(self): balancer = self.driver.get_balancer(self.balancer_id) target_group = self.driver.ex_get_target_group(self.target_group_id) listener = self.driver.ex_create_listener(balancer=balancer, port=443, proto='HTTPS', target_group=target_group, action="forward", ssl_cert_arn=self.ssl_cert_id, ssl_policy="ELBSecurityPolicy-2016-08") self.assertTrue(hasattr(listener, 'id'), 'Listener is missing "id" field') self.assertTrue(hasattr(listener, 'rules'), 'Listener is missing "rules" field') self.assertTrue(hasattr(listener, 'balancer'), 'Listener is missing "balancer" field') self.assertEqual(listener.balancer.id, balancer.id) self.assertEqual(listener.rules[0].target_group.id, target_group.id) self.assertEqual(listener.port, 443) self.assertEqual(listener.protocol, 'HTTPS') self.assertEqual(listener.action, 'forward') self.assertEqual(listener.ssl_certificate, self.ssl_cert_id) self.assertEqual(listener.ssl_policy, 'ELBSecurityPolicy-2016-08') def test_ex_create_rule(self): balancer = self.driver.get_balancer(self.balancer_id) listener = balancer.extra.get('listeners')[0] target_group = self.driver.ex_get_target_group(self.target_group_id) rule = self.driver.ex_create_listener_rule(listener=listener, priority=10, target_group=target_group, action="forward", condition_field="path-pattern", condition_value="/img/*") self.assertTrue(hasattr(rule, 'id'), 'Rule is missing "id" field') self.assertTrue(hasattr(rule, 'conditions'), 'Rule is missing "conditions" field') self.assertEqual(rule.is_default, False) self.assertEqual(rule.priority, '10') self.assertEqual(rule.target_group.id, self.target_group_id) self.assertTrue(('/img/*' in rule.conditions['path-pattern']), 'Rule is missing test condition') def test_ex_get_balancer_tags(self): balancer = self.driver.get_balancer(balancer_id=self.balancer_id) self.assertTrue(('tags' in balancer.extra), 'No tags dict found in balancer.extra') tags = self.driver._ex_get_balancer_tags(balancer) self.assertEqual(tags['project'], 'lima') def test_ex_get_target_group(self): target_group = self.driver.ex_get_target_group(self.target_group_id) target_group_fields = ('id', 'name', 'protocol', 'port', 'vpc', 'health_check_timeout', 'health_check_port', 'health_check_path', 'health_check_proto', 'health_check_matcher', 'health_check_interval', 'healthy_threshold', 'unhealthy_threshold', '_balancers', '_balancers_arns', '_members', '_driver',) for field in target_group_fields: self.assertTrue((field in target_group.__dict__), 'Field [%s] is missing in ALBTargetGroup object' % field) self.assertEqual(target_group.id, self.target_group_id) def test_ex_get_listener(self): listener = self.driver.ex_get_listener(self.listener_id) listener_fields = ('id', 'protocol', 'port', 'action', 'ssl_policy', 'ssl_certificate', '_balancer', '_balancer_arn', '_rules', '_driver',) for field in listener_fields: self.assertTrue((field in listener.__dict__), 'Field [%s] is missing in ALBListener object' % field) self.assertEqual(listener.id, self.listener_id) def test_ex_get_rule(self): rule = self.driver.ex_get_rule(self.rule_id) rule_fields = ('id', 'is_default', 'priority', 'conditions', '_listener', '_listener_arn', '_target_group', '_target_group_arn', '_driver',) for field in rule_fields: self.assertTrue((field in rule.__dict__), 'Field [%s] is missing in ALBRule object' % field) self.assertEqual(rule.id, self.rule_id) def test_ex_get_target_group_members(self): target_group = self.driver.ex_get_target_group(self.target_group_id) target_group_members = self.driver._ex_get_target_group_members(target_group) self.assertEqual(len(target_group_members), 1) self.assertTrue(hasattr(target_group_members[0], 'id'), 'Target group member is missing "id" field') self.assertTrue(hasattr(target_group_members[0], 'port'), 'Target group member is missing "port" field') self.assertTrue(('health' in target_group_members[0].extra), 'Target group member is missing "health" field') def test_ex_get_balancer_listeners(self): balancer = self.driver.get_balancer(balancer_id=self.balancer_id) listeners = self.driver._ex_get_balancer_listeners(balancer) self.assertEqual(len(listeners), 1) self.assertTrue(hasattr(listeners[0], 'id'), 'Listener is missing "id" field') self.assertTrue(hasattr(listeners[0], 'port'), 'Listener is missing "port" field') self.assertTrue(hasattr(listeners[0], 'protocol'), 'Listener is missing "protocol" field') self.assertTrue(hasattr(listeners[0], 'rules'), 'Listener is missing "rules" field') def test_ex_get_rules_for_listener(self): listener = self.driver.ex_get_listener(self.listener_id) listener_rules = self.driver._ex_get_rules_for_listener(listener) self.assertEqual(len(listener_rules), 1) self.assertTrue(hasattr(listener_rules[0], 'id'), 'Rule is missing "id" field') self.assertTrue(hasattr(listener_rules[0], 'is_default'), 'Rule is missing "port" field') self.assertTrue(hasattr(listener_rules[0], 'priority'), 'Rule is missing "priority" field') self.assertTrue(hasattr(listener_rules[0], 'target_group'), 'Rule is missing "target_group" field') self.assertTrue(hasattr(listener_rules[0], 'conditions'), 'Rule is missing "conditions" field') # Commented out to avoid confusion. In AWS ALB relation between load balancer # and target group/members is indirect. So it's better to go through full chain # to obtain required object(s). # Chain is: balancer->listener->rule->target group->member # # def test_balancer_list_members(self): # balancer = self.driver.get_balancer(balancer_id=self.balancer_id) # members = balancer.list_members() # self.assertEqual(len(members), 1) # self.assertEqual(members[0].balancer, balancer) # self.assertEqual('i-01111111111111111', members[0].id) # # def test_ex_get_balancer_target_groups(self): # balancer = self.driver.get_balancer(balancer_id=self.balancer_id) # target_groups = self.driver._ex_get_balancer_target_groups(balancer) # self.assertEqual(len(target_groups), 1) # self.assertTrue(hasattr(target_groups[0], 'id'), 'Target group is missing "id" field') # self.assertTrue(hasattr(target_groups[0], 'name'), 'Target group is missing "port" field') # self.assertTrue(hasattr(target_groups[0], 'members'), 'Target group is missing "members" field') class ApplicationLBMockHttp(MockHttp): fixtures = LoadBalancerFileFixtures('alb') def _2015_12_01_DescribeLoadBalancers(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_DescribeListeners(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancer_listeters.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_DescribeRules(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancer_rules.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_DescribeTargetGroups(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancer_target_groups.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_DescribeTargetHealth(self, method, url, body, headers): body = self.fixtures.load('describe_target_health.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_DescribeTags(self, method, url, body, headers): body = self.fixtures.load('describe_tags.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_CreateLoadBalancer(self, method, url, body, headers): body = self.fixtures.load('create_balancer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_CreateTargetGroup(self, method, url, body, headers): body = self.fixtures.load('create_target_group.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_CreateListener(self, method, url, body, headers): body = self.fixtures.load('create_listener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_CreateRule(self, method, url, body, headers): body = self.fixtures.load('create_rule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2015_12_01_RegisterTargets(self, method, url, body, headers): body = self.fixtures.load('register_targets.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_brightbox.py0000664000175000017500000001271713535474530025230 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.loadbalancer.base import Member, Algorithm from libcloud.loadbalancer.drivers.brightbox import BrightboxLBDriver from libcloud.loadbalancer.types import State from libcloud.test import MockHttp from libcloud.test.secrets import LB_BRIGHTBOX_PARAMS from libcloud.test.file_fixtures import LoadBalancerFileFixtures class BrightboxLBTests(unittest.TestCase): def setUp(self): BrightboxLBDriver.connectionCls.conn_class = BrightboxLBMockHttp BrightboxLBMockHttp.type = None self.driver = BrightboxLBDriver(*LB_BRIGHTBOX_PARAMS) def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertEqual(len(protocols), 2) self.assertTrue('tcp' in protocols) self.assertTrue('http' in protocols) def test_list_balancers(self): balancers = self.driver.list_balancers() self.assertEqual(len(balancers), 1) self.assertEqual(balancers[0].id, 'lba-1235f') self.assertEqual(balancers[0].name, 'lb1') def test_get_balancer(self): balancer = self.driver.get_balancer(balancer_id='lba-1235f') self.assertEqual(balancer.id, 'lba-1235f') self.assertEqual(balancer.name, 'lb1') self.assertEqual(balancer.state, State.RUNNING) def test_destroy_balancer(self): balancer = self.driver.get_balancer(balancer_id='lba-1235f') self.assertTrue(self.driver.destroy_balancer(balancer)) def test_create_balancer(self): members = [Member('srv-lv426', None, None)] balancer = self.driver.create_balancer(name='lb2', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) self.assertEqual(balancer.name, 'lb2') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.state, State.PENDING) def test_balancer_list_members(self): balancer = self.driver.get_balancer(balancer_id='lba-1235f') members = balancer.list_members() self.assertEqual(len(members), 1) self.assertEqual(members[0].balancer, balancer) self.assertEqual('srv-lv426', members[0].id) def test_balancer_attach_member(self): balancer = self.driver.get_balancer(balancer_id='lba-1235f') member = balancer.attach_member(Member('srv-kg983', ip=None, port=None)) self.assertEqual(member.id, 'srv-kg983') def test_balancer_detach_member(self): balancer = self.driver.get_balancer(balancer_id='lba-1235f') member = Member('srv-lv426', None, None) self.assertTrue(balancer.detach_member(member)) class BrightboxLBMockHttp(MockHttp): fixtures = LoadBalancerFileFixtures('brightbox') def _token(self, method, url, body, headers): if method == 'POST': return (httplib.OK, self.fixtures.load('token.json'), {'content-type': 'application/json'}, httplib.responses[httplib.OK]) def _1_0_load_balancers(self, method, url, body, headers): if method == 'GET': return (httplib.OK, self.fixtures.load('load_balancers.json'), {'content-type': 'application/json'}, httplib.responses[httplib.OK]) elif method == 'POST': body = self.fixtures.load('load_balancers_post.json') return (httplib.ACCEPTED, body, {'content-type': 'application/json'}, httplib.responses[httplib.ACCEPTED]) def _1_0_load_balancers_lba_1235f(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('load_balancers_lba_1235f.json') return (httplib.OK, body, {'content-type': 'application/json'}, httplib.responses[httplib.OK]) elif method == 'DELETE': return (httplib.ACCEPTED, '', {'content-type': 'application/json'}, httplib.responses[httplib.ACCEPTED]) def _1_0_load_balancers_lba_1235f_add_nodes(self, method, url, body, headers): if method == 'POST': return (httplib.ACCEPTED, '', {'content-type': 'application/json'}, httplib.responses[httplib.ACCEPTED]) def _1_0_load_balancers_lba_1235f_remove_nodes(self, method, url, body, headers): if method == 'POST': return (httplib.ACCEPTED, '', {'content-type': 'application/json'}, httplib.responses[httplib.ACCEPTED]) if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_cloudstack.py0000664000175000017500000001234413570310635025362 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qsl from libcloud.utils.py3 import assertRaisesRegex from libcloud.loadbalancer.types import Provider from libcloud.loadbalancer.providers import get_driver from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm from libcloud.loadbalancer.drivers.cloudstack import CloudStackLBDriver from libcloud.test import unittest from libcloud.test import MockHttp from libcloud.test.file_fixtures import LoadBalancerFileFixtures class CloudStackLBTests(unittest.TestCase): def setUp(self): CloudStackLBDriver.connectionCls.conn_class = CloudStackMockHttp CloudStackLBDriver.path = '/test/path' CloudStackLBDriver.type = -1 CloudStackLBDriver.name = 'CloudStack' self.driver = CloudStackLBDriver('apikey', 'secret') CloudStackMockHttp.fixture_tag = 'default' self.driver.connection.poll_interval = 0.0 def test_user_must_provide_host_and_path(self): CloudStackLBDriver.path = None CloudStackLBDriver.type = Provider.CLOUDSTACK expected_msg = 'When instantiating CloudStack driver directly ' + \ 'you also need to provide host and path argument' cls = get_driver(Provider.CLOUDSTACK) assertRaisesRegex(self, Exception, expected_msg, cls, 'key', 'secret') try: cls('key', 'secret', True, 'localhost', '/path') except Exception: self.fail('host and path provided but driver raised an exception') def test_list_supported_algorithms(self): algorithms = self.driver.list_supported_algorithms() self.assertTrue(Algorithm.ROUND_ROBIN in algorithms) self.assertTrue(Algorithm.LEAST_CONNECTIONS in algorithms) def test_list_balancers(self): balancers = self.driver.list_balancers() for balancer in balancers: self.assertTrue(isinstance(balancer, LoadBalancer)) def test_create_balancer(self): members = [Member(1, '1.1.1.1', 80), Member(2, '1.1.1.2', 80)] balancer = self.driver.create_balancer( name='test', algorithm=Algorithm.ROUND_ROBIN, members=members) self.assertTrue(isinstance(balancer, LoadBalancer)) def test_destroy_balancer(self): balancer = self.driver.list_balancers()[0] self.driver.destroy_balancer(balancer) def test_balancer_attach_member(self): balancer = self.driver.list_balancers()[0] member = Member(id=1234, ip='1.1.1.1', port=80) balancer.attach_member(member) def test_balancer_detach_member(self): balancer = self.driver.list_balancers()[0] member = balancer.list_members()[0] balancer.detach_member(member) def test_balancer_list_members(self): balancer = self.driver.list_balancers()[0] members = balancer.list_members() for member in members: self.assertTrue(isinstance(member, Member)) self.assertEqual(member.balancer, balancer) class CloudStackMockHttp(MockHttp, unittest.TestCase): fixtures = LoadBalancerFileFixtures('cloudstack') fixture_tag = 'default' def _load_fixture(self, fixture): body = self.fixtures.load(fixture) return body, json.loads(body) def _test_path(self, method, url, body, headers): url = urlparse.urlparse(url) query = dict(parse_qsl(url.query)) self.assertTrue('apiKey' in query) self.assertTrue('command' in query) self.assertTrue('response' in query) self.assertTrue('signature' in query) self.assertTrue(query['response'] == 'json') del query['apiKey'] del query['response'] del query['signature'] command = query.pop('command') if hasattr(self, '_cmd_' + command): return getattr(self, '_cmd_' + command)(**query) else: fixture = command + '_' + self.fixture_tag + '.json' body, obj = self._load_fixture(fixture) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _cmd_queryAsyncJobResult(self, jobid): fixture = 'queryAsyncJobResult' + '_' + str(jobid) + '.json' body, obj = self._load_fixture(fixture) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py0000664000175000017500000006406713535474530026715 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.utils.py3 import httplib from libcloud.common.types import InvalidCredsError from libcloud.common.dimensiondata import DimensionDataVIPNode, DimensionDataPool from libcloud.common.dimensiondata import DimensionDataPoolMember from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm from libcloud.loadbalancer.drivers.dimensiondata \ import DimensionDataLBDriver as DimensionData from libcloud.loadbalancer.types import State from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import LoadBalancerFileFixtures from libcloud.test.secrets import DIMENSIONDATA_PARAMS class DimensionData_v2_3_Tests(unittest.TestCase): def setUp(self): DimensionData.connectionCls.active_api_version = '2.3' DimensionData.connectionCls.conn_class = DimensionDataMockHttp DimensionDataMockHttp.type = None self.driver = DimensionData(*DIMENSIONDATA_PARAMS) def test_invalid_region(self): with self.assertRaises(ValueError): self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah') def test_invalid_creds(self): DimensionDataMockHttp.type = 'UNAUTHORIZED' with self.assertRaises(InvalidCredsError): self.driver.list_balancers() def test_create_balancer(self): self.driver.ex_set_current_network_domain('1234') members = [] members.append(Member( id=None, ip='1.2.3.4', port=80)) balancer = self.driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members, ex_listener_ip_address='5.6.7.8') self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') self.assertEqual(balancer.extra['listener_ip_address'], '5.6.7.8') def test_create_balancer_with_defaults(self): self.driver.ex_set_current_network_domain('1234') balancer = self.driver.create_balancer( name='test', port=None, protocol=None, algorithm=None, members=None) self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertIsNone(balancer.port) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') def test_create_balancer_no_members(self): self.driver.ex_set_current_network_domain('1234') members = None balancer = self.driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') def test_create_balancer_empty_members(self): self.driver.ex_set_current_network_domain('1234') members = [] balancer = self.driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') def test_list_balancers(self): bal = self.driver.list_balancers() self.assertEqual(bal[0].name, 'myProduction.Virtual.Listener') self.assertEqual(bal[0].id, '6115469d-a8bb-445b-bb23-d23b5283f2b9') self.assertEqual(bal[0].port, '8899') self.assertEqual(bal[0].ip, '165.180.12.22') self.assertEqual(bal[0].state, State.RUNNING) def test_balancer_list_members(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) members = self.driver.balancer_list_members(balancer) self.assertEqual(2, len(members)) self.assertEqual(members[0].ip, '10.0.3.13') self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(members[0].port, 9889) def test_balancer_attach_member(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) member = Member( id=None, ip='112.12.2.2', port=80, balancer=balancer, extra=None) member = self.driver.balancer_attach_member(balancer, member) self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') def test_balancer_attach_member_without_port(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) member = Member( id=None, ip='112.12.2.2', port=None, balancer=balancer, extra=None) member = self.driver.balancer_attach_member(balancer, member) self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertIsNone(member.port) def test_balancer_detach_member(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) member = Member( id='3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0', ip='112.12.2.2', port=80, balancer=balancer, extra=None) result = self.driver.balancer_detach_member(balancer, member) self.assertEqual(result, True) def test_destroy_balancer(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) response = self.driver.destroy_balancer(balancer) self.assertEqual(response, True) def test_set_get_network_domain_id(self): self.driver.ex_set_current_network_domain('1234') nwd = self.driver.ex_get_current_network_domain() self.assertEqual(nwd, '1234') def test_ex_create_pool_member(self): pool = DimensionDataPool( id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None ) node = DimensionDataVIPNode( id='2344', name='test', status=State.RUNNING, ip='123.23.3.2' ) member = self.driver.ex_create_pool_member( pool=pool, node=node, port=80 ) self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(member.name, '10.0.3.13') self.assertEqual(member.ip, '123.23.3.2') def test_ex_create_node(self): node = self.driver.ex_create_node( network_domain_id='12345', name='test', ip='123.12.32.2', ex_description='', connection_limit=25000, connection_rate_limit=2000) self.assertEqual(node.name, 'myProductionNode.1') self.assertEqual(node.id, '9e6b496d-5261-4542-91aa-b50c7f569c54') def test_ex_create_pool(self, ): pool = self.driver.ex_create_pool( network_domain_id='1234', name='test', balancer_method='ROUND_ROBIN', ex_description='test', service_down_action='NONE', slow_ramp_time=30) self.assertEqual(pool.id, '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(pool.name, 'test') self.assertEqual(pool.status, State.RUNNING) def test_ex_create_virtual_listener(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', port=80, pool=DimensionDataPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_ex_create_virtual_listener_unusual_port(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', port=8900, pool=DimensionDataPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_ex_create_virtual_listener_without_port(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', pool=DimensionDataPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_ex_create_virtual_listener_without_pool(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test') self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_get_balancer(self): bal = self.driver.get_balancer('6115469d-a8bb-445b-bb23-d23b5283f2b9') self.assertEqual(bal.name, 'myProduction.Virtual.Listener') self.assertEqual(bal.id, '6115469d-a8bb-445b-bb23-d23b5283f2b9') self.assertEqual(bal.port, '8899') self.assertEqual(bal.ip, '165.180.12.22') self.assertEqual(bal.state, State.RUNNING) def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertNotEqual(0, len(protocols)) def test_ex_get_nodes(self): nodes = self.driver.ex_get_nodes() self.assertEqual(2, len(nodes)) self.assertEqual(nodes[0].name, 'ProductionNode.1') self.assertEqual(nodes[0].id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertEqual(nodes[0].ip, '10.10.10.101') def test_ex_get_node(self): node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertEqual(node.name, 'ProductionNode.2') self.assertEqual(node.id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertEqual(node.ip, '10.10.10.101') def test_ex_update_node(self): node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') node.connection_limit = '100' result = self.driver.ex_update_node(node) self.assertEqual(result.connection_limit, '100') def test_ex_destroy_node(self): result = self.driver.ex_destroy_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertTrue(result) def test_ex_set_node_state(self): node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') result = self.driver.ex_set_node_state(node, False) self.assertEqual(result.connection_limit, '10000') def test_ex_get_pools(self): pools = self.driver.ex_get_pools() self.assertNotEqual(0, len(pools)) self.assertEqual(pools[0].name, 'myDevelopmentPool.1') self.assertEqual(pools[0].id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') def test_ex_get_pool(self): pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') self.assertEqual(pool.name, 'myDevelopmentPool.1') self.assertEqual(pool.id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') def test_ex_update_pool(self): pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') pool.slow_ramp_time = '120' result = self.driver.ex_update_pool(pool) self.assertTrue(result) def test_ex_destroy_pool(self): response = self.driver.ex_destroy_pool( pool=DimensionDataPool( id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None)) self.assertTrue(response) def test_get_pool_members(self): members = self.driver.ex_get_pool_members('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') self.assertEqual(2, len(members)) self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(members[0].name, '10.0.3.13') self.assertEqual(members[0].status, 'NORMAL') self.assertEqual(members[0].ip, '10.0.3.13') self.assertEqual(members[0].port, 9889) self.assertEqual(members[0].node_id, '3c207269-e75e-11e4-811f-005056806999') def test_get_pool_member(self): member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(member.name, '10.0.3.13') self.assertEqual(member.status, 'NORMAL') self.assertEqual(member.ip, '10.0.3.13') self.assertEqual(member.port, 9889) def test_set_pool_member_state(self): member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') result = self.driver.ex_set_pool_member_state(member, True) self.assertTrue(result) def test_ex_destroy_pool_member(self): response = self.driver.ex_destroy_pool_member( member=DimensionDataPoolMember( id='', name='test', status=State.RUNNING, ip='1.2.3.4', port=80, node_id='3c207269-e75e-11e4-811f-005056806999'), destroy_node=False) self.assertTrue(response) def test_ex_destroy_pool_member_with_node(self): response = self.driver.ex_destroy_pool_member( member=DimensionDataPoolMember( id='', name='test', status=State.RUNNING, ip='1.2.3.4', port=80, node_id='34de6ed6-46a4-4dae-a753-2f8d3840c6f9'), destroy_node=True) self.assertTrue(response) def test_ex_get_default_health_monitors(self): monitors = self.driver.ex_get_default_health_monitors( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) self.assertEqual(len(monitors), 6) self.assertEqual(monitors[0].id, '01683574-d487-11e4-811f-005056806999') self.assertEqual(monitors[0].name, 'CCDEFAULT.Http') self.assertFalse(monitors[0].node_compatible) self.assertTrue(monitors[0].pool_compatible) def test_ex_get_default_persistence_profiles(self): profiles = self.driver.ex_get_default_persistence_profiles( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) self.assertEqual(len(profiles), 4) self.assertEqual(profiles[0].id, 'a34ca024-f3db-11e4-b010-005056806999') self.assertEqual(profiles[0].name, 'CCDEFAULT.Cookie') self.assertEqual(profiles[0].fallback_compatible, False) self.assertEqual(len(profiles[0].compatible_listeners), 1) self.assertEqual(profiles[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4') def test_ex_get_default_irules(self): irules = self.driver.ex_get_default_irules( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) self.assertEqual(len(irules), 4) self.assertEqual(irules[0].id, '2b20cb2c-ffdc-11e4-b010-005056806999') self.assertEqual(irules[0].name, 'CCDEFAULT.HttpsRedirect') self.assertEqual(len(irules[0].compatible_listeners), 1) self.assertEqual(irules[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4') class DimensionDataMockHttp(MockHttp): fixtures = LoadBalancerFileFixtures('dimensiondata') def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_virtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_pool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_poolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createPool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_addPoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createVirtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_removePoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deleteVirtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deletePool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deleteNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_node.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editPool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editPoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultHealthMonitor.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultPersistenceProfile.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultIrule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py0000664000175000017500000006406713535474530026716 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from libcloud.utils.py3 import httplib from libcloud.common.types import InvalidCredsError from libcloud.common.dimensiondata import DimensionDataVIPNode, DimensionDataPool from libcloud.common.dimensiondata import DimensionDataPoolMember from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm from libcloud.loadbalancer.drivers.dimensiondata \ import DimensionDataLBDriver as DimensionData from libcloud.loadbalancer.types import State from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import LoadBalancerFileFixtures from libcloud.test.secrets import DIMENSIONDATA_PARAMS class DimensionData_v2_4_Tests(unittest.TestCase): def setUp(self): DimensionData.connectionCls.active_api_version = '2.4' DimensionData.connectionCls.conn_class = DimensionDataMockHttp DimensionDataMockHttp.type = None self.driver = DimensionData(*DIMENSIONDATA_PARAMS) def test_invalid_region(self): with self.assertRaises(ValueError): self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah') def test_invalid_creds(self): DimensionDataMockHttp.type = 'UNAUTHORIZED' with self.assertRaises(InvalidCredsError): self.driver.list_balancers() def test_create_balancer(self): self.driver.ex_set_current_network_domain('1234') members = [] members.append(Member( id=None, ip='1.2.3.4', port=80)) balancer = self.driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members, ex_listener_ip_address='5.6.7.8') self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') self.assertEqual(balancer.extra['listener_ip_address'], '5.6.7.8') def test_create_balancer_with_defaults(self): self.driver.ex_set_current_network_domain('1234') balancer = self.driver.create_balancer( name='test', port=None, protocol=None, algorithm=None, members=None) self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertIsNone(balancer.port) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') def test_create_balancer_no_members(self): self.driver.ex_set_current_network_domain('1234') members = None balancer = self.driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') def test_create_balancer_empty_members(self): self.driver.ex_set_current_network_domain('1234') members = [] balancer = self.driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) self.assertEqual(balancer.name, 'test') self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(balancer.ip, '165.180.12.22') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(balancer.extra['network_domain_id'], '1234') def test_list_balancers(self): bal = self.driver.list_balancers() self.assertEqual(bal[0].name, 'myProduction.Virtual.Listener') self.assertEqual(bal[0].id, '6115469d-a8bb-445b-bb23-d23b5283f2b9') self.assertEqual(bal[0].port, '8899') self.assertEqual(bal[0].ip, '165.180.12.22') self.assertEqual(bal[0].state, State.RUNNING) def test_balancer_list_members(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) members = self.driver.balancer_list_members(balancer) self.assertEqual(2, len(members)) self.assertEqual(members[0].ip, '10.0.3.13') self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(members[0].port, 9889) def test_balancer_attach_member(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) member = Member( id=None, ip='112.12.2.2', port=80, balancer=balancer, extra=None) member = self.driver.balancer_attach_member(balancer, member) self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') def test_balancer_attach_member_without_port(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) member = Member( id=None, ip='112.12.2.2', port=None, balancer=balancer, extra=None) member = self.driver.balancer_attach_member(balancer, member) self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertIsNone(member.port) def test_balancer_detach_member(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) member = Member( id='3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0', ip='112.12.2.2', port=80, balancer=balancer, extra=None) result = self.driver.balancer_detach_member(balancer, member) self.assertEqual(result, True) def test_destroy_balancer(self): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=self.driver, extra=extra ) response = self.driver.destroy_balancer(balancer) self.assertEqual(response, True) def test_set_get_network_domain_id(self): self.driver.ex_set_current_network_domain('1234') nwd = self.driver.ex_get_current_network_domain() self.assertEqual(nwd, '1234') def test_ex_create_pool_member(self): pool = DimensionDataPool( id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None ) node = DimensionDataVIPNode( id='2344', name='test', status=State.RUNNING, ip='123.23.3.2' ) member = self.driver.ex_create_pool_member( pool=pool, node=node, port=80 ) self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(member.name, '10.0.3.13') self.assertEqual(member.ip, '123.23.3.2') def test_ex_create_node(self): node = self.driver.ex_create_node( network_domain_id='12345', name='test', ip='123.12.32.2', ex_description='', connection_limit=25000, connection_rate_limit=2000) self.assertEqual(node.name, 'myProductionNode.1') self.assertEqual(node.id, '9e6b496d-5261-4542-91aa-b50c7f569c54') def test_ex_create_pool(self, ): pool = self.driver.ex_create_pool( network_domain_id='1234', name='test', balancer_method='ROUND_ROBIN', ex_description='test', service_down_action='NONE', slow_ramp_time=30) self.assertEqual(pool.id, '9e6b496d-5261-4542-91aa-b50c7f569c54') self.assertEqual(pool.name, 'test') self.assertEqual(pool.status, State.RUNNING) def test_ex_create_virtual_listener(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', port=80, pool=DimensionDataPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_ex_create_virtual_listener_unusual_port(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', port=8900, pool=DimensionDataPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_ex_create_virtual_listener_without_port(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', pool=DimensionDataPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_ex_create_virtual_listener_without_pool(self): listener = self.driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test') self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea') self.assertEqual(listener.name, 'test') def test_get_balancer(self): bal = self.driver.get_balancer('6115469d-a8bb-445b-bb23-d23b5283f2b9') self.assertEqual(bal.name, 'myProduction.Virtual.Listener') self.assertEqual(bal.id, '6115469d-a8bb-445b-bb23-d23b5283f2b9') self.assertEqual(bal.port, '8899') self.assertEqual(bal.ip, '165.180.12.22') self.assertEqual(bal.state, State.RUNNING) def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertNotEqual(0, len(protocols)) def test_ex_get_nodes(self): nodes = self.driver.ex_get_nodes() self.assertEqual(2, len(nodes)) self.assertEqual(nodes[0].name, 'ProductionNode.1') self.assertEqual(nodes[0].id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertEqual(nodes[0].ip, '10.10.10.101') def test_ex_get_node(self): node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertEqual(node.name, 'ProductionNode.2') self.assertEqual(node.id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertEqual(node.ip, '10.10.10.101') def test_ex_update_node(self): node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') node.connection_limit = '100' result = self.driver.ex_update_node(node) self.assertEqual(result.connection_limit, '100') def test_ex_destroy_node(self): result = self.driver.ex_destroy_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') self.assertTrue(result) def test_ex_set_node_state(self): node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') result = self.driver.ex_set_node_state(node, False) self.assertEqual(result.connection_limit, '10000') def test_ex_get_pools(self): pools = self.driver.ex_get_pools() self.assertNotEqual(0, len(pools)) self.assertEqual(pools[0].name, 'myDevelopmentPool.1') self.assertEqual(pools[0].id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') def test_ex_get_pool(self): pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') self.assertEqual(pool.name, 'myDevelopmentPool.1') self.assertEqual(pool.id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') def test_ex_update_pool(self): pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') pool.slow_ramp_time = '120' result = self.driver.ex_update_pool(pool) self.assertTrue(result) def test_ex_destroy_pool(self): response = self.driver.ex_destroy_pool( pool=DimensionDataPool( id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None)) self.assertTrue(response) def test_get_pool_members(self): members = self.driver.ex_get_pool_members('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') self.assertEqual(2, len(members)) self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(members[0].name, '10.0.3.13') self.assertEqual(members[0].status, 'NORMAL') self.assertEqual(members[0].ip, '10.0.3.13') self.assertEqual(members[0].port, 9889) self.assertEqual(members[0].node_id, '3c207269-e75e-11e4-811f-005056806999') def test_get_pool_member(self): member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') self.assertEqual(member.name, '10.0.3.13') self.assertEqual(member.status, 'NORMAL') self.assertEqual(member.ip, '10.0.3.13') self.assertEqual(member.port, 9889) def test_set_pool_member_state(self): member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') result = self.driver.ex_set_pool_member_state(member, True) self.assertTrue(result) def test_ex_destroy_pool_member(self): response = self.driver.ex_destroy_pool_member( member=DimensionDataPoolMember( id='', name='test', status=State.RUNNING, ip='1.2.3.4', port=80, node_id='3c207269-e75e-11e4-811f-005056806999'), destroy_node=False) self.assertTrue(response) def test_ex_destroy_pool_member_with_node(self): response = self.driver.ex_destroy_pool_member( member=DimensionDataPoolMember( id='', name='test', status=State.RUNNING, ip='1.2.3.4', port=80, node_id='34de6ed6-46a4-4dae-a753-2f8d3840c6f9'), destroy_node=True) self.assertTrue(response) def test_ex_get_default_health_monitors(self): monitors = self.driver.ex_get_default_health_monitors( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) self.assertEqual(len(monitors), 6) self.assertEqual(monitors[0].id, '01683574-d487-11e4-811f-005056806999') self.assertEqual(monitors[0].name, 'CCDEFAULT.Http') self.assertFalse(monitors[0].node_compatible) self.assertTrue(monitors[0].pool_compatible) def test_ex_get_default_persistence_profiles(self): profiles = self.driver.ex_get_default_persistence_profiles( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) self.assertEqual(len(profiles), 4) self.assertEqual(profiles[0].id, 'a34ca024-f3db-11e4-b010-005056806999') self.assertEqual(profiles[0].name, 'CCDEFAULT.Cookie') self.assertEqual(profiles[0].fallback_compatible, False) self.assertEqual(len(profiles[0].compatible_listeners), 1) self.assertEqual(profiles[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4') def test_ex_get_default_irules(self): irules = self.driver.ex_get_default_irules( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) self.assertEqual(len(irules), 4) self.assertEqual(irules[0].id, '2b20cb2c-ffdc-11e4-b010-005056806999') self.assertEqual(irules[0].name, 'CCDEFAULT.HttpsRedirect') self.assertEqual(len(irules[0].compatible_listeners), 1) self.assertEqual(irules[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4') class DimensionDataMockHttp(MockHttp): fixtures = LoadBalancerFileFixtures('dimensiondata') def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_virtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_pool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_poolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createPool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_addPoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createVirtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_removePoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deleteVirtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deletePool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deleteNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_node.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editPool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editPoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultHealthMonitor.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultPersistenceProfile.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultIrule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_elb.py0000664000175000017500000002346013535474530023777 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.loadbalancer.base import Member, Algorithm from libcloud.loadbalancer.drivers.elb import ElasticLBDriver from libcloud.loadbalancer.types import State from libcloud.test import MockHttp from libcloud.test.secrets import LB_ELB_PARAMS from libcloud.test.file_fixtures import LoadBalancerFileFixtures class ElasticLBTests(unittest.TestCase): def setUp(self): ElasticLBMockHttp.test = self ElasticLBDriver.connectionCls.conn_class = ElasticLBMockHttp ElasticLBMockHttp.type = None ElasticLBMockHttp.use_param = 'Action' self.driver = ElasticLBDriver(*LB_ELB_PARAMS) def test_instantiate_driver_with_token(self): token = 'temporary_credentials_token' driver = ElasticLBDriver(*LB_ELB_PARAMS, **{'token': token}) self.assertTrue(hasattr(driver, 'token'), 'Driver has no attribute token') self.assertEqual(token, driver.token, "Driver token does not match with provided token") def test_driver_with_token_signature_version(self): token = 'temporary_credentials_token' driver = ElasticLBDriver(*LB_ELB_PARAMS, **{'token': token}) kwargs = driver._ex_connection_class_kwargs() self.assertTrue(('signature_version' in kwargs), 'Driver has no attribute signature_version') self.assertEqual('4', kwargs['signature_version'], 'Signature version is not 4 with temporary credentials') def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertEqual(len(protocols), 4) self.assertTrue('tcp' in protocols) self.assertTrue('http' in protocols) def test_list_balancers(self): balancers = self.driver.list_balancers() self.assertEqual(len(balancers), 1) self.assertEqual(balancers[0].id, 'tests') self.assertEqual(balancers[0].name, 'tests') def test_list_balancers_with_tags(self): balancers = self.driver.list_balancers(ex_fetch_tags=True) self.assertEqual(len(balancers), 1) self.assertEqual(balancers[0].id, 'tests') self.assertEqual(balancers[0].name, 'tests') self.assertTrue(('tags' in balancers[0].extra), 'No tags dict found in balancer.extra') self.assertEqual(balancers[0].extra['tags']['project'], 'lima') def test_list_balancer_tags(self): tags = self.driver._ex_list_balancer_tags('tests') self.assertEqual(len(tags), 1) self.assertEqual(tags['project'], 'lima') def test_get_balancer(self): balancer = self.driver.get_balancer(balancer_id='tests') self.assertEqual(balancer.id, 'tests') self.assertEqual(balancer.name, 'tests') self.assertEqual(balancer.state, State.UNKNOWN) def test_get_balancer_with_tags(self): balancer = self.driver.get_balancer(balancer_id='tests', ex_fetch_tags=True) self.assertEqual(balancer.id, 'tests') self.assertEqual(balancer.name, 'tests') self.assertTrue(('tags' in balancer.extra), 'No tags dict found in balancer.extra') self.assertEqual(balancer.extra['tags']['project'], 'lima') def test_populate_balancer_tags(self): balancer = self.driver.get_balancer(balancer_id='tests') balancer = self.driver._ex_populate_balancer_tags(balancer) self.assertEqual(balancer.id, 'tests') self.assertEqual(balancer.name, 'tests') self.assertTrue(('tags' in balancer.extra), 'No tags dict found in balancer.extra') self.assertEqual(balancer.extra['tags']['project'], 'lima') def test_destroy_balancer(self): balancer = self.driver.get_balancer(balancer_id='tests') self.assertTrue(self.driver.destroy_balancer(balancer)) def test_create_balancer(self): members = [Member('srv-lv426', None, None)] balancer = self.driver.create_balancer(name='lb2', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) self.assertEqual(balancer.name, 'lb2') self.assertEqual(balancer.port, 80) self.assertEqual(balancer.state, State.PENDING) def test_balancer_list_members(self): balancer = self.driver.get_balancer(balancer_id='tests') members = balancer.list_members() self.assertEqual(len(members), 1) self.assertEqual(members[0].balancer, balancer) self.assertEqual('i-64bd081c', members[0].id) def test_balancer_detach_member(self): balancer = self.driver.get_balancer(balancer_id='lba-1235f') member = Member('i-64bd081c', None, None) self.assertTrue(balancer.detach_member(member)) def test_ex_list_balancer_policies(self): balancer = self.driver.get_balancer(balancer_id='tests') policies = self.driver.ex_list_balancer_policies(balancer) self.assertTrue('MyDurationStickyPolicy' in policies) def test_ex_list_balancer_policy_types(self): policy_types = self.driver.ex_list_balancer_policy_types() self.assertTrue('ProxyProtocolPolicyType' in policy_types) def test_ex_create_balancer_policy(self): self.assertTrue( self.driver.ex_create_balancer_policy( name='tests', policy_name='MyDurationProxyPolicy', policy_type='ProxyProtocolPolicyType')) def test_ex_delete_balancer_policy(self): self.assertTrue( self.driver.ex_delete_balancer_policy( name='tests', policy_name='MyDurationProxyPolicy')) def test_ex_set_balancer_policies_listener(self): self.assertTrue( self.driver.ex_set_balancer_policies_listener( name='tests', port=80, policies=['MyDurationStickyPolicy'])) def test_ex_set_balancer_policies_backend_server(self): self.assertTrue( self.driver.ex_set_balancer_policies_backend_server( name='tests', instance_port=80, policies=['MyDurationProxyPolicy'])) def text_ex_create_balancer_listeners(self): self.assertTrue( self.driver.ex_create_balancer_listeners( name='tests', listeners=[[1024, 65533, 'HTTP']])) class ElasticLBMockHttp(MockHttp): fixtures = LoadBalancerFileFixtures('elb') def _2012_06_01_DescribeLoadBalancers(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_DescribeTags(self, method, url, body, headers): body = self.fixtures.load('describe_tags.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_CreateLoadBalancer(self, method, url, body, headers): body = self.fixtures.load('create_load_balancer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_DeregisterInstancesFromLoadBalancer(self, method, url, body, headers): body = self.fixtures.load( 'deregister_instances_from_load_balancer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_CreateLoadBalancerPolicy(self, method, url, body, headers): body = self.fixtures.load('create_load_balancer_policy.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_DeleteLoadBalancer(self, method, url, body, headers): body = '' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_DescribeLoadBalancerPolicies(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancer_policies.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_DescribeLoadBalancerPolicyTypes(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancers_policy_types.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_DeleteLoadBalancerPolicy(self, method, url, body, headers): body = '' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_SetLoadBalancerPoliciesOfListener(self, method, url, body, headers): body = self.fixtures.load('set_load_balancer_policies_of_listener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _2012_06_01_SetLoadBalancerPoliciesForBackendServer(self, method, url, body, headers): body = self.fixtures.load( 'set_load_balancer_policies_for_backend_server.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_gce.py0000664000175000017500000002133513535474530023772 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Tests for Google Compute Engine Load Balancer Driver """ import sys import unittest from libcloud.common.google import GoogleBaseAuthConnection from libcloud.compute.drivers.gce import (GCENodeDriver) from libcloud.loadbalancer.drivers.gce import (GCELBDriver) from libcloud.test.common.test_google import GoogleAuthMockHttp, GoogleTestCase from libcloud.test.compute.test_gce import GCEMockHttp from libcloud.test.secrets import GCE_PARAMS, GCE_KEYWORD_PARAMS class GCELoadBalancerTest(GoogleTestCase): datacenter = 'us-central1-a' def setUp(self): GCEMockHttp.test = self GCELBDriver.connectionCls.conn_class = GCEMockHttp GCENodeDriver.connectionCls.conn_class = GCEMockHttp GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp GCEMockHttp.type = None kwargs = GCE_KEYWORD_PARAMS.copy() kwargs['auth_type'] = 'IA' kwargs['datacenter'] = self.datacenter self.driver = GCELBDriver(*GCE_PARAMS, **kwargs) def test_get_node_from_ip(self): ip = '23.236.58.15' expected_name = 'node-name' node = self.driver._get_node_from_ip(ip) self.assertEqual(node.name, expected_name) dummy_ip = '8.8.8.8' node = self.driver._get_node_from_ip(dummy_ip) self.assertTrue(node is None) def test_list_protocols(self): expected_protocols = ['TCP', 'UDP'] protocols = self.driver.list_protocols() self.assertEqual(protocols, expected_protocols) def test_list_balancers(self): balancers = self.driver.list_balancers() balancers_all = self.driver.list_balancers(ex_region='all') balancer_name = 'lcforwardingrule' self.assertEqual(len(balancers), 2) self.assertEqual(len(balancers_all), 2) self.assertEqual(balancers[0].name, balancer_name) def test_create_balancer(self): balancer_name = 'libcloud-lb-demo-lb' tp_name = '%s-tp' % (balancer_name) port = '80' protocol = 'tcp' algorithm = None node0 = self.driver.gce.ex_get_node('libcloud-lb-demo-www-000', 'us-central1-b') node1 = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', 'us-central1-b') members = [node0, node1] balancer = self.driver.create_balancer(balancer_name, port, protocol, algorithm, members) self.assertEqual(balancer.name, balancer_name) self.assertEqual(balancer.extra['targetpool'].name, tp_name) self.assertEqual(len(balancer.list_members()), 3) def test_destory_balancer(self): balancer_name = 'lcforwardingrule' balancer = self.driver.get_balancer(balancer_name) destroyed = balancer.destroy() self.assertTrue(destroyed) def test_get_balancer(self): balancer_name = 'lcforwardingrule' tp_name = 'lctargetpool' balancer_ip = '173.255.119.224' balancer = self.driver.get_balancer(balancer_name) self.assertEqual(balancer.name, balancer_name) self.assertEqual(balancer.extra['forwarding_rule'].name, balancer_name) self.assertEqual(balancer.ip, balancer_ip) self.assertEqual(balancer.extra['targetpool'].name, tp_name) def test_attach_compute_node(self): node = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', 'us-central1-b') balancer = self.driver.get_balancer('lcforwardingrule') member = self.driver._node_to_member(node, balancer) # Detach member first balancer.detach_member(member) self.assertEqual(len(balancer.list_members()), 1) # Attach Node balancer.attach_compute_node(node) self.assertEqual(len(balancer.list_members()), 2) def test_detach_attach_member(self): node = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', 'us-central1-b') balancer = self.driver.get_balancer('lcforwardingrule') member = self.driver._node_to_member(node, balancer) # Check that balancer has 2 members self.assertEqual(len(balancer.list_members()), 2) # Remove a member and check that it now has 1 member balancer.detach_member(member) self.assertEqual(len(balancer.list_members()), 1) # Reattach member and check that it has 2 members again balancer.attach_member(member) self.assertEqual(len(balancer.list_members()), 2) def test_balancer_list_members(self): balancer = self.driver.get_balancer('lcforwardingrule') members = balancer.list_members() self.assertEqual(len(members), 2) member_ips = [m.ip for m in members] self.assertTrue('23.236.58.15' in member_ips) def test_ex_create_healthcheck(self): healthcheck_name = 'lchealthcheck' kwargs = {'host': 'lchost', 'path': '/lc', 'port': 8000, 'interval': 10, 'timeout': 10, 'unhealthy_threshold': 4, 'healthy_threshold': 3} hc = self.driver.ex_create_healthcheck(healthcheck_name, **kwargs) self.assertEqual(hc.name, healthcheck_name) self.assertEqual(hc.path, '/lc') self.assertEqual(hc.port, 8000) self.assertEqual(hc.interval, 10) def test_ex_list_healthchecks(self): healthchecks = self.driver.ex_list_healthchecks() self.assertEqual(len(healthchecks), 3) self.assertEqual(healthchecks[0].name, 'basic-check') def test_ex_balancer_detach_attach_healthcheck(self): healthcheck = self.driver.gce.ex_get_healthcheck( 'libcloud-lb-demo-healthcheck') balancer = self.driver.get_balancer('lcforwardingrule') healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) self.assertEqual(len(healthchecks), 1) # Detach Healthcheck detach_healthcheck = self.driver.ex_balancer_detach_healthcheck( balancer, healthcheck) self.assertTrue(detach_healthcheck) healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) self.assertEqual(len(healthchecks), 0) # Reattach Healthcheck attach_healthcheck = self.driver.ex_balancer_attach_healthcheck( balancer, healthcheck) self.assertTrue(attach_healthcheck) healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) self.assertEqual(len(healthchecks), 1) def test_ex_balancer_list_healthchecks(self): balancer = self.driver.get_balancer('lcforwardingrule') healthchecks = self.driver.ex_balancer_list_healthchecks(balancer) self.assertEqual(healthchecks[0].name, 'libcloud-lb-demo-healthcheck') def test_node_to_member(self): node = self.driver.gce.ex_get_node('libcloud-lb-demo-www-001', 'us-central1-b') balancer = self.driver.get_balancer('lcforwardingrule') member = self.driver._node_to_member(node, balancer) self.assertEqual(member.ip, node.public_ips[0]) self.assertEqual(member.id, node.name) self.assertEqual(member.port, balancer.port) def test_node_to_member_no_pub_ip(self): node = self.driver.gce.ex_get_node('libcloud-lb-nopubip-001', 'us-central1-b') balancer = self.driver.get_balancer('lcforwardingrule') member = self.driver._node_to_member(node, balancer) self.assertIsNone(member.ip) def test_forwarding_rule_to_loadbalancer(self): fwr = self.driver.gce.ex_get_forwarding_rule('lcforwardingrule') balancer = self.driver._forwarding_rule_to_loadbalancer(fwr) self.assertEqual(fwr.name, balancer.name) self.assertEqual(fwr.address, balancer.ip) self.assertEqual(fwr.extra['portRange'], balancer.port) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_gogrid.py0000664000175000017500000001775113570310635024510 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.common.types import LibcloudError from libcloud.compute.base import Node from libcloud.compute.drivers.dummy import DummyNodeDriver from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm from libcloud.loadbalancer.drivers.gogrid import GoGridLBDriver from libcloud.test import MockHttp from libcloud.test.file_fixtures import LoadBalancerFileFixtures class GoGridTests(unittest.TestCase): def setUp(self): GoGridLBDriver.connectionCls.conn_class = GoGridLBMockHttp GoGridLBMockHttp.type = None self.driver = GoGridLBDriver('user', 'key') def test_list_supported_algorithms(self): algorithms = self.driver.list_supported_algorithms() self.assertTrue(Algorithm.ROUND_ROBIN in algorithms) self.assertTrue(Algorithm.LEAST_CONNECTIONS in algorithms) def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertEqual(len(protocols), 1) self.assertEqual(protocols[0], 'http') def test_list_balancers(self): balancers = self.driver.list_balancers() self.assertEqual(len(balancers), 2) self.assertEqual(balancers[0].name, "foo") self.assertEqual(balancers[0].id, "23517") self.assertEqual(balancers[1].name, "bar") self.assertEqual(balancers[1].id, "23526") def test_create_balancer(self): balancer = self.driver.create_balancer(name='test2', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=( Member( None, '10.1.0.10', 80), Member(None, '10.1.0.11', 80)) ) self.assertEqual(balancer.name, 'test2') self.assertEqual(balancer.id, '123') def test_create_balancer_UNEXPECTED_ERROR(self): # Try to create new balancer and attach members with an IP address which # does not belong to this account GoGridLBMockHttp.type = 'UNEXPECTED_ERROR' try: self.driver.create_balancer(name='test2', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=(Member(None, '10.1.0.10', 80), Member(None, '10.1.0.11', 80)) ) except LibcloudError as e: self.assertTrue( str(e).find('tried to add a member with an IP address not assigned to your account') != -1) else: self.fail('Exception was not thrown') def test_destroy_balancer(self): balancer = self.driver.list_balancers()[0] ret1 = self.driver.destroy_balancer(balancer) ret2 = balancer.destroy() self.assertTrue(ret1) self.assertTrue(ret2) def test_get_balancer(self): balancer = self.driver.get_balancer(balancer_id='23530') self.assertEqual(balancer.name, 'test2') self.assertEqual(balancer.id, '23530') def test_balancer_list_members(self): balancer = self.driver.get_balancer(balancer_id='23530') members1 = self.driver.balancer_list_members(balancer=balancer) members2 = balancer.list_members() expected_members = {'10.0.0.78:80', '10.0.0.77:80', '10.0.0.76:80'} self.assertEqual(len(members1), 3) self.assertEqual(len(members2), 3) self.assertEqual(expected_members, set(["%s:%s" % (member.ip, member.port) for member in members1])) self.assertEqual(members1[0].balancer, balancer) def test_balancer_attach_compute_node(self): balancer = LoadBalancer(23530, None, None, None, None, self.driver) node = Node(id='1', name='test', state=None, public_ips=['10.0.0.75'], private_ips=[], driver=DummyNodeDriver) member1 = self.driver.balancer_attach_compute_node(balancer, node) member2 = balancer.attach_compute_node(node) self.assertEqual(member1.ip, '10.0.0.75') self.assertEqual(member1.port, 80) self.assertEqual(member2.ip, '10.0.0.75') self.assertEqual(member2.port, 80) def test_balancer_attach_member(self): balancer = LoadBalancer(23530, None, None, None, None, self.driver) member = Member(None, ip='10.0.0.75', port='80') member1 = self.driver.balancer_attach_member(balancer, member=member) member2 = balancer.attach_member(member=member) self.assertEqual(member1.ip, '10.0.0.75') self.assertEqual(member1.port, 80) self.assertEqual(member2.ip, '10.0.0.75') self.assertEqual(member2.port, 80) def test_balancer_detach_member(self): balancer = LoadBalancer(23530, None, None, None, None, self.driver) member = self.driver.balancer_list_members(balancer)[0] ret1 = self.driver.balancer_detach_member(balancer, member) ret2 = balancer.detach_member(member) self.assertTrue(ret1) self.assertTrue(ret2) class GoGridLBMockHttp(MockHttp, unittest.TestCase): fixtures = LoadBalancerFileFixtures('gogrid') def _api_grid_loadbalancer_list(self, method, url, body, headers): body = self.fixtures.load('loadbalancer_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_ip_list(self, method, url, body, headers): body = self.fixtures.load('ip_list.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_loadbalancer_add(self, method, url, body, headers): query = urlparse.urlparse(url).query self.assertTrue(query.find('loadbalancer.type=round+robin') != -1) body = self.fixtures.load('loadbalancer_add.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_ip_list_UNEXPECTED_ERROR(self, method, url, body, headers): return self._api_grid_ip_list(method, url, body, headers) def _api_grid_loadbalancer_add_UNEXPECTED_ERROR(self, method, url, body, headers): body = self.fixtures.load('unexpected_error.json') return (httplib.INTERNAL_SERVER_ERROR, body, {}, httplib.responses[httplib.OK]) def _api_grid_loadbalancer_delete(self, method, url, body, headers): body = self.fixtures.load('loadbalancer_add.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_loadbalancer_get(self, method, url, body, headers): body = self.fixtures.load('loadbalancer_get.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _api_grid_loadbalancer_edit(self, method, url, body, headers): body = self.fixtures.load('loadbalancer_edit.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_ninefold.py0000664000175000017500000000216013570310635025017 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.loadbalancer.types import Provider from libcloud.loadbalancer.providers import get_driver class NinefoldLbTestCase(unittest.TestCase): def test_driver_instantiation(self): cls = get_driver(Provider.NINEFOLD) cls('username', 'key') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_nttcis.py0000664000175000017500000012615213535474530024543 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import os import pytest from libcloud.utils.py3 import httplib from libcloud.common.types import InvalidCredsError from libcloud.common.nttcis import NttCisVIPNode, NttCisPool from libcloud.common.nttcis import NttCisPoolMember from libcloud.common.nttcis import NttCisAPIException from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm from libcloud.loadbalancer.drivers.nttcis import NttCisLBDriver from libcloud.loadbalancer.types import State from libcloud.test import MockHttp, unittest from libcloud.test.file_fixtures import LoadBalancerFileFixtures from libcloud.test.secrets import NTTCIS_PARAMS @pytest.fixture() def driver(): NttCisLBDriver.connectionCls.active_api_version = "2.7" NttCisLBDriver.connectionCls.conn_class = NttCisMockHttp NttCisMockHttp.type = None driver = NttCisLBDriver(*NTTCIS_PARAMS) return driver def test_invalid_region(driver): with pytest.raises(ValueError): driver = NttCisLBDriver(*NTTCIS_PARAMS, region='blah') def test_invalid_creds(driver): NttCisMockHttp.type = 'UNAUTHORIZED' with pytest.raises(InvalidCredsError): driver.list_balancers() def test_create_balancer(driver, capsys): print(Algorithm.ROUND_ROBIN) driver.ex_set_current_network_domain('1234') members = [] members.append(Member(id=None, ip='1.2.3.4', port=80)) balancer = driver.create_balancer( name='test', port=80, protocol='http', optimization_profile='TCP', algorithm=Algorithm.ROUND_ROBIN, members=members, ex_listener_ip_address='5.6.7.8') assert balancer.name == 'test' assert balancer.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert balancer.ip == '165.180.12.22' assert balancer.port == 80 assert balancer.extra['pool_id'] == '9e6b496d-5261-4542-91aa-b50c7f569c54' assert balancer.extra['network_domain_id'] == '1234' assert balancer.extra['listener_ip_address'] == '5.6.7.8' def test_create_balancer_with_defaults(driver): driver.ex_set_current_network_domain('1234') balancer = driver.create_balancer(name='test', port=None, protocol=None, algorithm=None, members=None) assert balancer.name == 'test' assert balancer.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert balancer.ip == '165.180.12.22' assert balancer.port is None assert balancer.extra['pool_id'] == '9e6b496d-5261-4542-91aa-b50c7f569c54' assert balancer.extra['network_domain_id'] == '1234' def test_create_balancer_no_members(driver): driver.ex_set_current_network_domain('1234') members = None balancer = driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) assert balancer.name == 'test' assert balancer.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert balancer.ip == '165.180.12.22' assert balancer.port == 80 assert balancer.extra['pool_id'] == '9e6b496d-5261-4542-91aa-b50c7f569c54' assert balancer.extra['network_domain_id'] == '1234' def test_create_balancer_empty_members(driver): driver.ex_set_current_network_domain('1234') members = [] balancer = driver.create_balancer( name='test', port=80, protocol='http', algorithm=Algorithm.ROUND_ROBIN, members=members) assert balancer.name == 'test' assert balancer.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert balancer.ip == '165.180.12.22' assert balancer.port == 80 assert balancer.extra['pool_id'] == '9e6b496d-5261-4542-91aa-b50c7f569c54' assert balancer.extra['network_domain_id'] == '1234' def test_list_balancers(driver): bal = driver.list_balancers() assert bal[0].name == 'myProduction.Virtual.Listener' assert bal[0].id == '6115469d-a8bb-445b-bb23-d23b5283f2b9' assert bal[0].port == '8899' assert bal[0].ip == '165.180.12.22' assert bal[0].state == State.RUNNING def test_balancer_list_members(driver): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=driver, extra=extra ) members = driver.balancer_list_members(balancer) assert 2 == len(members) assert members[0].ip == '10.0.3.13' assert members[0].id == '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0' assert members[0].port == 9889 def test_balancer_attach_member(driver): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=driver, extra=extra ) member = Member(id=None, ip='112.12.2.2', port=80, balancer=balancer, extra=None) member = driver.balancer_attach_member(balancer, member) assert member.id == '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0' def test_balancer_attach_member_without_port(driver): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=driver, extra=extra ) member = Member(id=None, ip='112.12.2.2', port=None, balancer=balancer, extra=None) member = driver.balancer_attach_member(balancer, member) assert member.id == '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0' assert member.port == None def test_balancer_detach_member(driver): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=driver, extra=extra ) member = Member( id='3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0', ip='112.12.2.2', port=80, balancer=balancer, extra=None ) result = driver.balancer_detach_member(balancer, member) assert result, True def test_destroy_balancer(driver): extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', 'network_domain_id': '1234'} balancer = LoadBalancer( id='234', name='test', state=State.RUNNING, ip='1.2.3.4', port=1234, driver=driver, extra=extra ) response = driver.destroy_balancer(balancer) assert response is True def test_set_get_network_domain_id(driver): driver.ex_set_current_network_domain('1234') nwd = driver.ex_get_current_network_domain() assert nwd == '1234' def test_ex_create_pool_member(driver): pool = NttCisPool( id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None ) node = NttCisVIPNode( id='2344', name='test', status=State.RUNNING, ip='123.23.3.2' ) member = driver.ex_create_pool_member(pool=pool, node=node, port=80) assert member.id == '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0' assert member.name == '10.0.3.13' assert member.ip == '123.23.3.2' def test_ex_create_node(driver): node = driver.ex_create_node( network_domain_id='12345', name='test', ip='123.12.32.2', ex_description='', connection_limit=25000, connection_rate_limit=2000) assert node.name == 'myProductionNode.1' assert node.id == '9e6b496d-5261-4542-91aa-b50c7f569c54' def test_ex_create_pool(driver, ): pool = driver.ex_create_pool( network_domain_id='1234', name='test', balancer_method='ROUND_ROBIN', ex_description='test', service_down_action='NONE', slow_ramp_time=30) assert pool.id == '9e6b496d-5261-4542-91aa-b50c7f569c54' assert pool.name == 'test' assert pool.status == State.RUNNING def test_ex_create_virtual_listener(driver): listener = driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', port=80, pool=NttCisPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) assert listener.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert listener.name == 'test' def test_ex_create_virtual_listener_unusual_port(driver): listener = driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', port=8900, pool=NttCisPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) assert listener.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert listener.name == 'test' def test_ex_create_virtual_listener_without_port(driver): listener = driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test', pool=NttCisPool( id='1234', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None )) assert listener.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert listener.name == 'test' def test_ex_create_virtual_listener_without_pool(driver): listener = driver.ex_create_virtual_listener( network_domain_id='12345', name='test', ex_description='test') assert listener.id == '8334f461-0df0-42d5-97eb-f4678eb26bea' assert listener.name == 'test' def test_get_balancer(driver): bal = driver.get_balancer('6115469d-a8bb-445b-bb23-d23b5283f2b9') assert bal.name == 'myProduction.Virtual.Listener' assert bal.id == '6115469d-a8bb-445b-bb23-d23b5283f2b9' assert bal.port == '8899' assert bal.ip == '165.180.12.22' assert bal.state == State.RUNNING def test_list_protocols(driver): protocols = driver.list_protocols() assert 0 < len(protocols) def test_ex_get_nodes(driver): nodes = driver.ex_get_nodes() assert 2 == len(nodes) assert nodes[0].name == 'ProductionNode.1' assert nodes[0].id == '34de6ed6-46a4-4dae-a753-2f8d3840c6f9' assert nodes[0].ip == '10.10.10.101' def test_ex_get_node(driver): node = driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') assert node.name == 'ProductionNode.2' assert node.id == '34de6ed6-46a4-4dae-a753-2f8d3840c6f9' assert node.ip == '10.10.10.101' def test_ex_update_node(driver): node = driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') node.connection_limit = '100' result = driver.ex_update_node(node) assert result.connection_limit == '100' def test_ex_destroy_node(driver): result = driver.ex_destroy_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') assert result is True def test_ex_set_node_state(driver): node = driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9') result = driver.ex_set_node_state(node, False) assert result.connection_limit == '10000' def test_ex_get_pools(driver): pools = driver.ex_get_pools() assert 0 != len(pools) assert pools[0].name == 'myDevelopmentPool.1' assert pools[0].id == '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' def test_ex_get_pool(driver): pool = driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') assert pool.name == 'myDevelopmentPool.1' assert pool.id == '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' def test_ex_update_pool(driver): pool = driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') pool.slow_ramp_time = '120' result = driver.ex_update_pool(pool) assert result is True def test_ex_destroy_pool(driver): response = driver.ex_destroy_pool( pool=NttCisPool( id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7', name='test', description='test', status=State.RUNNING, health_monitor_id=None, load_balance_method=None, service_down_action=None, slow_ramp_time=None)) assert response is True def test_get_pool_members(driver): members = driver.ex_get_pool_members('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7') assert 2 == len(members) assert members[0].id == '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0' assert members[0].name == '10.0.3.13' assert members[0].status == 'NORMAL' assert members[0].ip == '10.0.3.13' assert members[0].port == 9889 assert members[0].node_id == '3c207269-e75e-11e4-811f-005056806999' def test_get_pool_member(driver): member = driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') assert member.id == '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0' assert member.name == '10.0.3.13' assert member.status == 'NORMAL' assert member.ip == '10.0.3.13' assert member.port == 9889 def test_set_pool_member_state(driver): member = driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0') result = driver.ex_set_pool_member_state(member, True) assert result is True def test_ex_destroy_pool_member(driver): response = driver.ex_destroy_pool_member(member=NttCisPoolMember( id='', name='test', status=State.RUNNING, ip='1.2.3.4', port=80, node_id='3c207269-e75e-11e4-811f-005056806999'), destroy_node=False) assert response is True def test_ex_destroy_pool_member_with_node(driver): response = driver.ex_destroy_pool_member( member=NttCisPoolMember( id='', name='test', status=State.RUNNING, ip='1.2.3.4', port=80, node_id='34de6ed6-46a4-4dae-a753-2f8d3840c6f9'), destroy_node=True) assert response is True def test_ex_get_default_health_monitors(driver): monitors = driver.ex_get_default_health_monitors( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) assert len(monitors) == 6 assert monitors[0].id == '01683574-d487-11e4-811f-005056806999' assert monitors[0].name == 'CCDEFAULT.Http' assert monitors[0].node_compatible is False assert monitors[0].pool_compatible is True def test_ex_get_default_persistence_profiles(driver): profiles = driver.ex_get_default_persistence_profiles( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) assert len(profiles) == 4 assert profiles[0].id == 'a34ca024-f3db-11e4-b010-005056806999' assert profiles[0].name == 'CCDEFAULT.Cookie' assert profiles[0].fallback_compatible is False assert len(profiles[0].compatible_listeners) == 1 assert profiles[0].compatible_listeners[0].type == 'PERFORMANCE_LAYER_4' def test_ex_get_default_irules(driver): irules = driver.ex_get_default_irules( '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7' ) assert len(irules) == 4 assert irules[0].id == '2b20cb2c-ffdc-11e4-b010-005056806999' assert irules[0].name == 'CCDEFAULT.HttpsRedirect' assert len(irules[0].compatible_listeners) == 1 assert irules[0].compatible_listeners[0].type == 'PERFORMANCE_LAYER_4' def test_ex_insert_ssl_certificate(driver): net_dom_id = "6aafcf08-cb0b-432c-9c64-7371265db086 " cert = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/loadbalancer/fixtures/nttcis/alice.crt" key = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/loadbalancer/fixtures/nttcis/alice.key" result = driver.ex_import_ssl_domain_certificate(net_dom_id, "alice", cert, key, description="test cert") assert result is True def test_ex_insert_ssl_certificate_FAIL(driver): NttCisMockHttp.type = "FAIL" net_dom_id = "6aafcf08-cb0b-432c-9c64-7371265db086 " cert = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/loadbalancer/fixtures/nttcis/denis.crt" key = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/loadbalancer/fixtures/nttcis/denis.key" with pytest.raises(NttCisAPIException) as excinfo: result = driver.ex_import_ssl_domain_certificate(net_dom_id, "denis", cert, key, description="test cert") assert excinfo.value.msg == "Data Center EU6 requires key length must be one of 512, 1024, 2048." def test_ex_create_ssl_offload_profile(driver): net_domain_id = "6aafcf08-cb0b-432c-9c64-7371265db086" name = "ssl_offload" domain_cert = driver.ex_list_ssl_domain_certs(name="alice")[0] result = driver.ex_create_ssl_offload_profile(net_domain_id, name, domain_cert.id, ciphers="!ECDHE+AES-GCM:") assert result is True def test_ex_list_ssl_offload_profile(driver): NttCisMockHttp.type = "LIST" profiles = driver.ex_list_ssl_offload_profiles() assert profiles[0].sslDomainCertificate.name == "alice" def test_ex_get_ssl_offload_profile(driver): profile_id = "b1d3b5a7-75d7-4c44-a2b7-5bfa773dec63" profile = driver.ex_get_ssl_offload_profile(profile_id) assert profile.name == "ssl_offload" def test_edit_ssl_offload_profile(driver): profile_name = "ssl_offload" datacenter_id = "EU6" NttCisMockHttp.type = "LIST" profile = driver.ex_list_ssl_offload_profiles(name=profile_name, datacenter_id=datacenter_id)[0] NttCisMockHttp.type = None result = driver.ex_edit_ssl_offload_profile(profile.id, profile.name, profile.sslDomainCertificate.id, ciphers=profile.ciphers, description="A test edit of an offload profile") assert result is True def test_delete_ssl_offload_profile(driver): profile_name = "ssl_offload" NttCisMockHttp.type = "LIST" profile = driver.ex_list_ssl_offload_profiles(name=profile_name)[0] NttCisMockHttp.type = None result = driver.ex_delete_ssl_offload_profile(profile.id) assert result is True def test_delete_ssl_certificate_chain(driver): NttCisMockHttp.type = "LIST" chain_name = "ted_carol" cert_chain = driver.ex_list_ssl_certificate_chains(name=chain_name)[0] NttCisMockHttp.type = None result = driver.ex_delete_ssl_certificate_chain(cert_chain.id) assert result is True def test_delete_ssl_domain_certificate(driver): NttCisMockHttp.type = "LIST" cert_name = "alice" cert = driver.ex_list_ssl_domain_certs(name=cert_name)[0] NttCisMockHttp.type = None result = driver.ex_delete_ssl_domain_certificate(cert.id) assert result is True class NttCisMockHttp(MockHttp): fixtures = LoadBalancerFileFixtures('nttcis') def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED]) def _oec_0_9_myaccount(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_FAIL(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _oec_0_9_myaccount_LIST(self, method, url, body, headers): body = self.fixtures.load('oec_0_9_myaccount.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_virtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_pool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_poolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createPool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_addPoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_createVirtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_removePoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deleteVirtualListener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deletePool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_deleteNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_node.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editNode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editPool.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_editPoolMember.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultHealthMonitor.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultPersistenceProfile.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers): body = self.fixtures.load( 'networkDomainVip_defaultIrule.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_importSslDomainCertificate(self, method, url, body, headers): body = self.fixtures.load( "ssl_import_success.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_importSslDomainCertificate_FAIL(self, method, url, body, headers): body = self.fixtures.load( "ssl_import_fail.xml" ) return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_sslDomainCertificate_LIST(self, method, url, body, headers): body = self.fixtures.load( "ssl_cert_by_name.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_sslCertificateChain_LIST(self, method, url, body, headers): body = self.fixtures.load( "ssl_list_cert_chain_by_name.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_sslDomainCertificate(self, method, url, body, headers): body = self.fixtures.load( "ssl_cert_by_name.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createSslOffloadProfile(self, method, url, body, headers): body = self.fixtures.load( "create_ssl_offload_profile.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_sslOffloadProfile_LIST(self, method, url, body, headers): body = self.fixtures.load( "list_ssl_offload_profiles.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_sslOffloadProfile_b1d3b5a7_75d7_4c44_a2b7_5bfa773dec63(self, method, url, body, headers): body = self.fixtures.load( "get_ssl_offload_profile.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editSslOffloadProfile(self, method, url, body, headers): body = self.fixtures.load( "edit_ssl_offload_profile.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteSslOffloadProfile(self, method, url, body, headers): body = self.fixtures.load( "delete_ssl_offload_profile.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteSslCertificateChain(self, method, url, body, headers): body = self.fixtures.load( "delete_ssl_certificate_chain.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteSslDomainCertificate(self, method, url, body, headers): body = self.fixtures.load( "delete_ssl_domain_certificate.xml" ) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_rackspace.py0000664000175000017500000020320213535474530025163 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import datetime try: import simplejson as json except ImportError: import json from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlencode from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm from libcloud.loadbalancer.types import MemberCondition from libcloud.loadbalancer.drivers.rackspace import RackspaceLBDriver, \ RackspaceHealthMonitor, RackspaceHTTPHealthMonitor, \ RackspaceConnectionThrottle, RackspaceAccessRule from libcloud.loadbalancer.drivers.rackspace import RackspaceAccessRuleType from libcloud.common.types import LibcloudError from libcloud.test import unittest from libcloud.test import MockHttp from libcloud.test.file_fixtures import LoadBalancerFileFixtures from libcloud.test.file_fixtures import OpenStackFixtures class RackspaceLBTests(unittest.TestCase): def setUp(self): RackspaceLBDriver.connectionCls.conn_class = RackspaceLBMockHttp RackspaceLBMockHttp.type = None self.driver = RackspaceLBDriver('user', 'key') self.driver.connection.poll_interval = 0.0 # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() def test_force_auth_token_kwargs(self): base_url = 'https://ord.loadbalancer.api.rackspacecloud.com/v1.0/11111' kwargs = { 'ex_force_auth_token': 'some-auth-token', 'ex_force_base_url': base_url } driver = RackspaceLBDriver('user', 'key', **kwargs) driver.list_balancers() self.assertEqual(kwargs['ex_force_auth_token'], driver.connection.auth_token) self.assertEqual('/v1.0/11111', driver.connection.request_path) def test_force_auth_url_kwargs(self): kwargs = { 'ex_force_auth_version': '2.0', 'ex_force_auth_url': 'https://identity.api.rackspace.com' } driver = RackspaceLBDriver('user', 'key', **kwargs) self.assertEqual(kwargs['ex_force_auth_url'], driver.connection._ex_force_auth_url) self.assertEqual(kwargs['ex_force_auth_version'], driver.connection._auth_version) def test_gets_auth_2_0_endpoint_defaults_to_ord_region(self): driver = RackspaceLBDriver('user', 'key', ex_force_auth_version='2.0_password' ) driver.connection._populate_hosts_and_request_paths() self.assertEqual( 'https://ord.loadbalancers.api.rackspacecloud.com/v1.0/11111', driver.connection.get_endpoint()) def test_gets_auth_2_0_endpoint_for_dfw(self): driver = RackspaceLBDriver('user', 'key', ex_force_auth_version='2.0_password', ex_force_region='dfw' ) driver.connection._populate_hosts_and_request_paths() self.assertEqual( 'https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/11111', driver.connection.get_endpoint()) def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertEqual(len(protocols), 10) self.assertTrue('http' in protocols) def test_ex_list_protocols_with_default_ports(self): protocols = self.driver.ex_list_protocols_with_default_ports() self.assertEqual(len(protocols), 10) self.assertTrue(('http', 80) in protocols) def test_list_supported_algorithms(self): algorithms = self.driver.list_supported_algorithms() self.assertTrue(Algorithm.RANDOM in algorithms) self.assertTrue(Algorithm.ROUND_ROBIN in algorithms) self.assertTrue(Algorithm.LEAST_CONNECTIONS in algorithms) self.assertTrue(Algorithm.WEIGHTED_ROUND_ROBIN in algorithms) self.assertTrue(Algorithm.WEIGHTED_LEAST_CONNECTIONS in algorithms) def test_ex_list_algorithms(self): algorithms = self.driver.ex_list_algorithm_names() self.assertTrue("RANDOM" in algorithms) self.assertTrue("ROUND_ROBIN" in algorithms) self.assertTrue("LEAST_CONNECTIONS" in algorithms) self.assertTrue("WEIGHTED_ROUND_ROBIN" in algorithms) self.assertTrue("WEIGHTED_LEAST_CONNECTIONS" in algorithms) def test_list_balancers(self): balancers = self.driver.list_balancers() self.assertEqual(len(balancers), 2) self.assertEqual(balancers[0].name, "test0") self.assertEqual(balancers[0].id, "8155") self.assertEqual(balancers[0].port, 80) self.assertEqual(balancers[0].ip, "1.1.1.25") self.assertTrue(balancers[0].extra.get('service_name') is not None) self.assertTrue(balancers[0].extra.get('uri') is not None) self.assertEqual(balancers[1].name, "test1") self.assertEqual(balancers[1].id, "8156") def test_list_balancers_ex_member_address(self): RackspaceLBMockHttp.type = 'EX_MEMBER_ADDRESS' balancers = self.driver.list_balancers(ex_member_address='127.0.0.1') self.assertEqual(len(balancers), 3) self.assertEqual(balancers[0].name, "First Loadbalancer") self.assertEqual(balancers[0].id, "1") self.assertEqual(balancers[1].name, "Second Loadbalancer") self.assertEqual(balancers[1].id, "2") self.assertEqual(balancers[2].name, "Third Loadbalancer") self.assertEqual(balancers[2].id, "8") def test_create_balancer(self): balancer = self.driver.create_balancer(name='test2', port=80, algorithm=Algorithm.ROUND_ROBIN, members=( Member( None, '10.1.0.10', 80, extra={'condition': MemberCondition.DISABLED, 'weight': 10}), Member(None, '10.1.0.11', 80)) ) self.assertEqual(balancer.name, 'test2') self.assertEqual(balancer.id, '8290') def test_ex_create_balancer(self): RackspaceLBDriver.connectionCls.conn_class = RackspaceLBWithVIPMockHttp RackspaceLBMockHttp.type = None driver = RackspaceLBDriver('user', 'key') balancer = driver.ex_create_balancer(name='test2', port=80, algorithm=Algorithm.ROUND_ROBIN, members=( Member( None, '10.1.0.11', 80),), vip='12af' ) self.assertEqual(balancer.name, 'test2') self.assertEqual(balancer.id, '8290') def test_destroy_balancer(self): balancer = self.driver.list_balancers()[0] ret = self.driver.destroy_balancer(balancer) self.assertTrue(ret) def test_ex_destroy_balancers(self): balancers = self.driver.list_balancers() ret = self.driver.ex_destroy_balancers(balancers) self.assertTrue(ret) def test_get_balancer(self): balancer = self.driver.get_balancer(balancer_id='8290') self.assertEqual(balancer.name, 'test2') self.assertEqual(balancer.id, '8290') def test_get_balancer_extra_vips(self): balancer = self.driver.get_balancer(balancer_id='18940') self.assertEqual(balancer.extra["virtualIps"], [{"address": "50.56.49.149", "id": 2359, "type": "PUBLIC", "ipVersion": "IPV4"}]) def test_get_balancer_extra_public_source_ipv4(self): balancer = self.driver.get_balancer(balancer_id='18940') self.assertEqual(balancer.extra["ipv4PublicSource"], '184.106.100.25') def test_get_balancer_extra_public_source_ipv6(self): balancer = self.driver.get_balancer(balancer_id='18940') self.assertEqual(balancer.extra["ipv6PublicSource"], '2001:4801:7901::6/64') def test_get_balancer_extra_private_source_ipv4(self): balancer = self.driver.get_balancer(balancer_id='18940') self.assertEqual(balancer.extra["ipv4PrivateSource"], '10.183.252.25') def test_get_balancer_extra_members(self): balancer = self.driver.get_balancer(balancer_id='8290') members = balancer.extra['members'] self.assertEqual(3, len(members)) self.assertEqual('10.1.0.11', members[0].ip) self.assertEqual('10.1.0.10', members[1].ip) self.assertEqual('10.1.0.9', members[2].ip) def test_get_balancer_extra_created(self): balancer = self.driver.get_balancer(balancer_id='8290') created_8290 = datetime.datetime(2011, 4, 7, 16, 27, 50) self.assertEqual(created_8290, balancer.extra['created']) def test_get_balancer_extra_updated(self): balancer = self.driver.get_balancer(balancer_id='8290') updated_8290 = datetime.datetime(2011, 4, 7, 16, 28, 12) self.assertEqual(updated_8290, balancer.extra['updated']) def test_get_balancer_extra_access_list(self): balancer = self.driver.get_balancer(balancer_id='94698') access_list = balancer.extra['accessList'] self.assertEqual(3, len(access_list)) self.assertEqual(2883, access_list[0].id) self.assertEqual("0.0.0.0/0", access_list[0].address) self.assertEqual(RackspaceAccessRuleType.DENY, access_list[0].rule_type) self.assertEqual(2884, access_list[1].id) self.assertEqual("2001:4801:7901::6/64", access_list[1].address) self.assertEqual(RackspaceAccessRuleType.ALLOW, access_list[1].rule_type) self.assertEqual(3006, access_list[2].id) self.assertEqual("8.8.8.8/0", access_list[2].address) self.assertEqual(RackspaceAccessRuleType.DENY, access_list[2].rule_type) def test_get_balancer_algorithm(self): balancer = self.driver.get_balancer(balancer_id='8290') self.assertEqual(balancer.extra["algorithm"], Algorithm.RANDOM) def test_get_balancer_protocol(self): balancer = self.driver.get_balancer(balancer_id='94695') self.assertEqual(balancer.extra['protocol'], 'HTTP') def test_get_balancer_weighted_round_robin_algorithm(self): balancer = self.driver.get_balancer(balancer_id='94692') self.assertEqual(balancer.extra["algorithm"], Algorithm.WEIGHTED_ROUND_ROBIN) def test_get_balancer_weighted_least_connections_algorithm(self): balancer = self.driver.get_balancer(balancer_id='94693') self.assertEqual(balancer.extra["algorithm"], Algorithm.WEIGHTED_LEAST_CONNECTIONS) def test_get_balancer_unknown_algorithm(self): balancer = self.driver.get_balancer(balancer_id='94694') self.assertFalse('algorithm' in balancer.extra) def test_get_balancer_connect_health_monitor(self): balancer = self.driver.get_balancer(balancer_id='94695') balancer_health_monitor = balancer.extra["healthMonitor"] self.assertEqual(balancer_health_monitor.type, "CONNECT") self.assertEqual(balancer_health_monitor.delay, 10) self.assertEqual(balancer_health_monitor.timeout, 5) self.assertEqual(balancer_health_monitor.attempts_before_deactivation, 2) def test_get_balancer_http_health_monitor(self): balancer = self.driver.get_balancer(balancer_id='94696') balancer_health_monitor = balancer.extra["healthMonitor"] self.assertEqual(balancer_health_monitor.type, "HTTP") self.assertEqual(balancer_health_monitor.delay, 10) self.assertEqual(balancer_health_monitor.timeout, 5) self.assertEqual(balancer_health_monitor.attempts_before_deactivation, 2) self.assertEqual(balancer_health_monitor.path, "/") self.assertEqual(balancer_health_monitor.status_regex, "^[234][0-9][0-9]$") self.assertEqual(balancer_health_monitor.body_regex, "Hello World!") def test_get_balancer_https_health_monitor(self): balancer = self.driver.get_balancer(balancer_id='94697') balancer_health_monitor = balancer.extra["healthMonitor"] self.assertEqual(balancer_health_monitor.type, "HTTPS") self.assertEqual(balancer_health_monitor.delay, 15) self.assertEqual(balancer_health_monitor.timeout, 12) self.assertEqual(balancer_health_monitor.attempts_before_deactivation, 5) self.assertEqual(balancer_health_monitor.path, "/test") self.assertEqual(balancer_health_monitor.status_regex, "^[234][0-9][0-9]$") self.assertEqual(balancer_health_monitor.body_regex, "abcdef") def test_get_balancer_connection_throttle(self): balancer = self.driver.get_balancer(balancer_id='94695') balancer_connection_throttle = balancer.extra["connectionThrottle"] self.assertEqual(balancer_connection_throttle.min_connections, 50) self.assertEqual(balancer_connection_throttle.max_connections, 200) self.assertEqual(balancer_connection_throttle.max_connection_rate, 50) self.assertEqual(balancer_connection_throttle.rate_interval_seconds, 10) def test_get_session_persistence(self): balancer = self.driver.get_balancer(balancer_id='94695') self.assertEqual(balancer.extra["sessionPersistenceType"], "HTTP_COOKIE") def test_get_connection_logging(self): balancer = self.driver.get_balancer(balancer_id='94695') self.assertEqual(balancer.extra["connectionLoggingEnabled"], True) def test_get_error_page(self): balancer = self.driver.get_balancer(balancer_id='18940') error_page = self.driver.ex_get_balancer_error_page(balancer) self.assertTrue("The service is temporarily unavailable" in error_page) def test_get_access_list(self): balancer = self.driver.get_balancer(balancer_id='18940') deny_rule, allow_rule = self.driver.ex_balancer_access_list(balancer) self.assertEqual(deny_rule.id, 2883) self.assertEqual(deny_rule.rule_type, RackspaceAccessRuleType.DENY) self.assertEqual(deny_rule.address, "0.0.0.0/0") self.assertEqual(allow_rule.id, 2884) self.assertEqual(allow_rule.address, "2001:4801:7901::6/64") self.assertEqual(allow_rule.rule_type, RackspaceAccessRuleType.ALLOW) def test_ex_create_balancer_access_rule(self): balancer = self.driver.get_balancer(balancer_id='94698') rule = RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, address='0.0.0.0/0') rule = self.driver.ex_create_balancer_access_rule(balancer, rule) self.assertEqual(2883, rule.id) def test_ex_create_balancer_access_rule_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94698') rule = RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, address='0.0.0.0/0') resp = self.driver.ex_create_balancer_access_rule_no_poll(balancer, rule) self.assertTrue(resp) def test_ex_create_balancer_access_rules(self): balancer = self.driver.get_balancer(balancer_id='94699') rules = [RackspaceAccessRule(rule_type=RackspaceAccessRuleType.ALLOW, address='2001:4801:7901::6/64'), RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, address='8.8.8.8/0')] rules = self.driver.ex_create_balancer_access_rules(balancer, rules) self.assertEqual(2, len(rules)) self.assertEqual(2884, rules[0].id) self.assertEqual(3006, rules[1].id) def test_ex_create_balancer_access_rules_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94699') rules = [RackspaceAccessRule(rule_type=RackspaceAccessRuleType.ALLOW, address='2001:4801:7901::6/64'), RackspaceAccessRule(rule_type=RackspaceAccessRuleType.DENY, address='8.8.8.8/0')] resp = self.driver.ex_create_balancer_access_rules_no_poll(balancer, rules) self.assertTrue(resp) def test_ex_destroy_balancer_access_rule(self): balancer = self.driver.get_balancer(balancer_id='94698') rule = RackspaceAccessRule(id='1007', rule_type=RackspaceAccessRuleType.ALLOW, address="10.45.13.5/12" ) balancer = self.driver.ex_destroy_balancer_access_rule(balancer, rule) rule_ids = [r.id for r in balancer.extra['accessList']] self.assertTrue(1007 not in rule_ids) def test_ex_destroy_balancer_access_rule_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94698') rule = RackspaceAccessRule(id=1007, rule_type=RackspaceAccessRuleType.ALLOW, address="10.45.13.5/12" ) resp = self.driver.ex_destroy_balancer_access_rule_no_poll(balancer, rule) self.assertTrue(resp) def test_ex_destroy_balancer_access_rules(self): balancer = self.driver.get_balancer(balancer_id='94699') balancer = self.driver.ex_destroy_balancer_access_rules(balancer, balancer.extra['accessList']) self.assertEqual('94699', balancer.id) def test_ex_destroy_balancer_access_rules_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94699') resp = self.driver.ex_destroy_balancer_access_rules_no_poll(balancer, balancer.extra['accessList']) self.assertTrue(resp) def test_ex_update_balancer_health_monitor(self): balancer = self.driver.get_balancer(balancer_id='94695') monitor = RackspaceHealthMonitor(type='CONNECT', delay=10, timeout=5, attempts_before_deactivation=2) balancer = self.driver.ex_update_balancer_health_monitor( balancer, monitor) updated_monitor = balancer.extra['healthMonitor'] self.assertEqual('CONNECT', updated_monitor.type) self.assertEqual(10, updated_monitor.delay) self.assertEqual(5, updated_monitor.timeout) self.assertEqual(2, updated_monitor.attempts_before_deactivation) def test_ex_update_balancer_http_health_monitor(self): balancer = self.driver.get_balancer(balancer_id='94696') monitor = RackspaceHTTPHealthMonitor(type='HTTP', delay=10, timeout=5, attempts_before_deactivation=2, path='/', status_regex='^[234][0-9][0-9]$', body_regex='Hello World!') balancer = self.driver.ex_update_balancer_health_monitor( balancer, monitor) updated_monitor = balancer.extra['healthMonitor'] self.assertEqual('HTTP', updated_monitor.type) self.assertEqual(10, updated_monitor.delay) self.assertEqual(5, updated_monitor.timeout) self.assertEqual(2, updated_monitor.attempts_before_deactivation) self.assertEqual('/', updated_monitor.path) self.assertEqual('^[234][0-9][0-9]$', updated_monitor.status_regex) self.assertEqual('Hello World!', updated_monitor.body_regex) def test_ex_update_balancer_health_monitor_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94695') monitor = RackspaceHealthMonitor(type='CONNECT', delay=10, timeout=5, attempts_before_deactivation=2) resp = self.driver.ex_update_balancer_health_monitor_no_poll(balancer, monitor) self.assertTrue(resp) def test_ex_update_balancer_http_health_monitor_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94696') monitor = RackspaceHTTPHealthMonitor(type='HTTP', delay=10, timeout=5, attempts_before_deactivation=2, path='/', status_regex='^[234][0-9][0-9]$', body_regex='Hello World!') resp = self.driver.ex_update_balancer_health_monitor_no_poll(balancer, monitor) self.assertTrue(resp) def test_ex_update_balancer_http_health_monitor_with_no_option_body_regex(self): balancer = self.driver.get_balancer(balancer_id='94700') monitor = RackspaceHTTPHealthMonitor(type='HTTP', delay=10, timeout=5, attempts_before_deactivation=2, path='/', status_regex='^[234][0-9][0-9]$', body_regex='') balancer = self.driver.ex_update_balancer_health_monitor( balancer, monitor) updated_monitor = balancer.extra['healthMonitor'] self.assertEqual('HTTP', updated_monitor.type) self.assertEqual(10, updated_monitor.delay) self.assertEqual(5, updated_monitor.timeout) self.assertEqual(2, updated_monitor.attempts_before_deactivation) self.assertEqual('/', updated_monitor.path) self.assertEqual('^[234][0-9][0-9]$', updated_monitor.status_regex) self.assertEqual('', updated_monitor.body_regex) def test_ex_disable_balancer_health_monitor(self): balancer = self.driver.get_balancer(balancer_id='8290') balancer = self.driver.ex_disable_balancer_health_monitor(balancer) self.assertTrue('healthMonitor' not in balancer.extra) def test_ex_disable_balancer_health_monitor_no_poll(self): balancer = self.driver.get_balancer(balancer_id='8290') resp = self.driver.ex_disable_balancer_health_monitor_no_poll(balancer) self.assertTrue(resp) def test_ex_update_balancer_connection_throttle(self): balancer = self.driver.get_balancer(balancer_id='94695') connection_throttle = RackspaceConnectionThrottle(max_connections=200, min_connections=50, max_connection_rate=50, rate_interval_seconds=10) balancer = self.driver.ex_update_balancer_connection_throttle(balancer, connection_throttle) updated_throttle = balancer.extra['connectionThrottle'] self.assertEqual(200, updated_throttle.max_connections) self.assertEqual(50, updated_throttle.min_connections) self.assertEqual(50, updated_throttle.max_connection_rate) self.assertEqual(10, updated_throttle.rate_interval_seconds) def test_ex_update_balancer_connection_throttle_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94695') connection_throttle = RackspaceConnectionThrottle(max_connections=200, min_connections=50, max_connection_rate=50, rate_interval_seconds=10) resp = self.driver.ex_update_balancer_connection_throttle_no_poll( balancer, connection_throttle) self.assertTrue(resp) def test_ex_disable_balancer_connection_throttle(self): balancer = self.driver.get_balancer(balancer_id='8290') balancer = self.driver.ex_disable_balancer_connection_throttle( balancer) self.assertTrue('connectionThrottle' not in balancer.extra) def test_ex_disable_balancer_connection_throttle_no_poll(self): balancer = self.driver.get_balancer(balancer_id='8290') resp = self.driver.ex_disable_balancer_connection_throttle_no_poll( balancer) self.assertTrue(resp) def test_ex_enable_balancer_connection_logging(self): balancer = self.driver.get_balancer(balancer_id='94695') balancer = self.driver.ex_enable_balancer_connection_logging( balancer) self.assertTrue(balancer.extra["connectionLoggingEnabled"]) def test_ex_enable_balancer_connection_logging_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94695') resp = self.driver.ex_enable_balancer_connection_logging_no_poll( balancer) self.assertTrue(resp) def test_ex_disable_balancer_connection_logging(self): balancer = self.driver.get_balancer(balancer_id='8290') balancer = self.driver.ex_disable_balancer_connection_logging( balancer ) self.assertFalse(balancer.extra["connectionLoggingEnabled"]) def test_ex_disable_balancer_connection_logging_no_poll(self): balancer = self.driver.get_balancer(balancer_id='8290') resp = self.driver.ex_disable_balancer_connection_logging_no_poll( balancer ) self.assertTrue(resp) def test_ex_enable_balancer_session_persistence(self): balancer = self.driver.get_balancer(balancer_id='94695') balancer = self.driver.ex_enable_balancer_session_persistence(balancer) persistence_type = balancer.extra['sessionPersistenceType'] self.assertEqual('HTTP_COOKIE', persistence_type) def test_ex_enable_balancer_session_persistence_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94695') resp = self.driver.ex_enable_balancer_session_persistence_no_poll( balancer) self.assertTrue(resp) def test_disable_balancer_session_persistence(self): balancer = self.driver.get_balancer(balancer_id='8290') balancer = self.driver.ex_disable_balancer_session_persistence( balancer) self.assertTrue('sessionPersistenceType' not in balancer.extra) def test_disable_balancer_session_persistence_no_poll(self): balancer = self.driver.get_balancer(balancer_id='8290') resp = self.driver.ex_disable_balancer_session_persistence_no_poll( balancer) self.assertTrue(resp) def test_ex_update_balancer_error_page(self): balancer = self.driver.get_balancer(balancer_id='8290') content = "Generic Error Page" balancer = self.driver.ex_update_balancer_error_page( balancer, content) error_page_content = self.driver.ex_get_balancer_error_page(balancer) self.assertEqual(content, error_page_content) def test_ex_update_balancer_error_page_no_poll(self): balancer = self.driver.get_balancer(balancer_id='8290') content = "Generic Error Page" resp = self.driver.ex_update_balancer_error_page_no_poll( balancer, content) self.assertTrue(resp) def test_ex_disable_balancer_custom_error_page_no_poll(self): balancer = self.driver.get_balancer(balancer_id='94695') resp = self.driver.ex_disable_balancer_custom_error_page_no_poll( balancer) self.assertTrue(resp) def test_ex_disable_balancer_custom_error_page(self): fixtures = LoadBalancerFileFixtures('rackspace') error_page_fixture = json.loads( fixtures.load('error_page_default.json')) default_error_page = error_page_fixture['errorpage']['content'] balancer = self.driver.get_balancer(balancer_id='94695') balancer = self.driver.ex_disable_balancer_custom_error_page(balancer) error_page_content = self.driver.ex_get_balancer_error_page(balancer) self.assertEqual(default_error_page, error_page_content) def test_balancer_list_members(self): expected = {'10.1.0.10:80', '10.1.0.11:80', '10.1.0.9:8080'} balancer = self.driver.get_balancer(balancer_id='8290') members = balancer.list_members() self.assertEqual(len(members), 3) self.assertEqual(members[0].balancer, balancer) self.assertEqual(expected, set(["%s:%s" % (member.ip, member.port) for member in members])) def test_balancer_members_extra_weight(self): balancer = self.driver.get_balancer(balancer_id='8290') members = balancer.list_members() self.assertEqual(12, members[0].extra['weight']) self.assertEqual(8, members[1].extra['weight']) def test_balancer_members_extra_condition(self): balancer = self.driver.get_balancer(balancer_id='8290') members = balancer.list_members() self.assertEqual(MemberCondition.ENABLED, members[0].extra['condition']) self.assertEqual(MemberCondition.DISABLED, members[1].extra['condition']) self.assertEqual(MemberCondition.DRAINING, members[2].extra['condition']) def test_balancer_members_extra_status(self): balancer = self.driver.get_balancer(balancer_id='8290') members = balancer.list_members() self.assertEqual('ONLINE', members[0].extra['status']) self.assertEqual('OFFLINE', members[1].extra['status']) self.assertEqual('DRAINING', members[2].extra['status']) def test_balancer_attach_member(self): balancer = self.driver.get_balancer(balancer_id='8290') extra = {'condition': MemberCondition.DISABLED, 'weight': 10} member = balancer.attach_member(Member(None, ip='10.1.0.12', port='80', extra=extra)) self.assertEqual(member.ip, '10.1.0.12') self.assertEqual(member.port, 80) def test_balancer_attach_member_with_no_condition_specified(self): balancer = self.driver.get_balancer(balancer_id='8291') member = balancer.attach_member(Member(None, ip='10.1.0.12', port='80')) self.assertEqual(member.ip, '10.1.0.12') self.assertEqual(member.port, 80) def test_balancer_attach_members(self): balancer = self.driver.get_balancer(balancer_id='8292') members = [Member(None, ip='10.1.0.12', port='80'), Member(None, ip='10.1.0.13', port='80')] attached_members = self.driver.ex_balancer_attach_members(balancer, members) first_member = attached_members[0] second_member = attached_members[1] self.assertEqual(first_member.ip, '10.1.0.12') self.assertEqual(first_member.port, 80) self.assertEqual(second_member.ip, '10.1.0.13') self.assertEqual(second_member.port, 80) def test_balancer_detach_member(self): balancer = self.driver.get_balancer(balancer_id='8290') member = balancer.list_members()[0] ret = balancer.detach_member(member) self.assertTrue(ret) def test_ex_detach_members(self): balancer = self.driver.get_balancer(balancer_id='8290') members = balancer.list_members() balancer = self.driver.ex_balancer_detach_members(balancer, members) self.assertEqual('8290', balancer.id) def test_ex_detach_members_no_poll(self): balancer = self.driver.get_balancer(balancer_id='8290') members = balancer.list_members() ret = self.driver.ex_balancer_detach_members_no_poll(balancer, members) self.assertTrue(ret) def test_update_balancer_protocol(self): balancer = LoadBalancer(id='3130', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) updated_balancer = self.driver.update_balancer( balancer, protocol='HTTPS') self.assertEqual('HTTPS', updated_balancer.extra['protocol']) def test_update_balancer_protocol_to_imapv2(self): balancer = LoadBalancer(id='3135', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) updated_balancer = self.driver.update_balancer( balancer, protocol='imapv2') self.assertEqual('IMAPv2', updated_balancer.extra['protocol']) def test_update_balancer_protocol_to_imapv3(self): balancer = LoadBalancer(id='3136', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) updated_balancer = self.driver.update_balancer( balancer, protocol='IMAPV3') self.assertEqual('IMAPv3', updated_balancer.extra['protocol']) def test_update_balancer_protocol_to_imapv4(self): balancer = LoadBalancer(id='3137', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) updated_balancer = self.driver.update_balancer( balancer, protocol='IMAPv4') self.assertEqual('IMAPv4', updated_balancer.extra['protocol']) def test_update_balancer_port(self): balancer = LoadBalancer(id='3131', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) updated_balancer = self.driver.update_balancer(balancer, port=1337) self.assertEqual(1337, updated_balancer.port) def test_update_balancer_name(self): balancer = LoadBalancer(id='3132', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) updated_balancer = self.driver.update_balancer( balancer, name='new_lb_name') self.assertEqual('new_lb_name', updated_balancer.name) def test_update_balancer_algorithm(self): balancer = LoadBalancer(id='3133', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) updated_balancer = self.driver.update_balancer(balancer, algorithm=Algorithm.ROUND_ROBIN) self.assertEqual( Algorithm.ROUND_ROBIN, updated_balancer.extra['algorithm']) def test_update_balancer_bad_algorithm_exception(self): balancer = LoadBalancer(id='3134', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) try: self.driver.update_balancer(balancer, algorithm='HAVE_MERCY_ON_OUR_SERVERS') except LibcloudError: pass else: self.fail( 'Should have thrown an exception with bad algorithm value') def test_ex_update_balancer_no_poll_protocol(self): balancer = LoadBalancer(id='3130', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) action_succeeded = self.driver.ex_update_balancer_no_poll( balancer, protocol='HTTPS') self.assertTrue(action_succeeded) def test_ex_update_balancer_no_poll_port(self): balancer = LoadBalancer(id='3131', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) action_succeeded = self.driver.ex_update_balancer_no_poll( balancer, port=1337) self.assertTrue(action_succeeded) def test_ex_update_balancer_no_poll_name(self): balancer = LoadBalancer(id='3132', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) action_succeeded = self.driver.ex_update_balancer_no_poll( balancer, name='new_lb_name') self.assertTrue(action_succeeded) def test_ex_update_balancer_no_poll_algorithm(self): balancer = LoadBalancer(id='3133', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) action_succeeded = self.driver.ex_update_balancer_no_poll(balancer, algorithm=Algorithm.ROUND_ROBIN) self.assertTrue(action_succeeded) def test_ex_update_balancer_no_poll_bad_algorithm_exception(self): balancer = LoadBalancer(id='3134', name='LB_update', state='PENDING_UPDATE', ip='10.34.4.3', port=80, driver=self.driver) try: self.driver.update_balancer(balancer, algorithm='HAVE_MERCY_ON_OUR_SERVERS') except LibcloudError: pass else: self.fail('Should have thrown exception with bad algorithm value') def test_ex_update_balancer_member_extra_attributes(self): balancer = self.driver.get_balancer(balancer_id='8290') members = self.driver.balancer_list_members(balancer) first_member = members[0] member = self.driver.ex_balancer_update_member(balancer, first_member, condition=MemberCondition.ENABLED, weight=12) self.assertEqual(MemberCondition.ENABLED, member.extra['condition']) self.assertEqual(12, member.extra['weight']) def test_ex_update_balancer_member_no_poll_extra_attributes(self): balancer = self.driver.get_balancer(balancer_id='8290') members = self.driver.balancer_list_members(balancer) first_member = members[0] resp = self.driver.ex_balancer_update_member_no_poll( balancer, first_member, condition=MemberCondition.ENABLED, weight=12) self.assertTrue(resp) def test_ex_list_current_usage(self): balancer = self.driver.get_balancer(balancer_id='8290') usage = self.driver.ex_list_current_usage(balancer=balancer) self.assertEqual( usage['loadBalancerUsageRecords'][0]['incomingTransferSsl'], 6182163) class RackspaceUKLBTests(RackspaceLBTests): def setUp(self): RackspaceLBDriver.connectionCls.conn_class = RackspaceLBMockHttp RackspaceLBMockHttp.type = None self.driver = RackspaceLBDriver('user', 'key', region='lon') # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() class RackspaceLBMockHttp(MockHttp, unittest.TestCase): fixtures = LoadBalancerFileFixtures('rackspace') auth_fixtures = OpenStackFixtures() def _v2_0_tokens(self, method, url, body, headers): body = self.fixtures.load('_v2_0__auth.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _v1_0_11111_loadbalancers_protocols(self, method, url, body, headers): body = self.fixtures.load('v1_slug_loadbalancers_protocols.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) def _v1_0_11111_loadbalancers_algorithms(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('v1_slug_loadbalancers_algorithms.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('v1_slug_loadbalancers.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == "POST": json_body = json.loads(body) loadbalancer_json = json_body['loadBalancer'] member_1_json, member_2_json = loadbalancer_json['nodes'] self.assertEqual(loadbalancer_json['protocol'], 'HTTP') self.assertEqual(loadbalancer_json['algorithm'], 'ROUND_ROBIN') self.assertEqual(loadbalancer_json['virtualIps'][0]['type'], 'PUBLIC') self.assertEqual(member_1_json['condition'], 'DISABLED') self.assertEqual(member_1_json['weight'], 10) self.assertEqual(member_2_json['condition'], 'ENABLED') body = self.fixtures.load('v1_slug_loadbalancers_post.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) elif method == 'DELETE': balancers = self.fixtures.load('v1_slug_loadbalancers.json') balancers_json = json.loads(balancers) for balancer in balancers_json['loadBalancers']: id = balancer['id'] self.assertTrue(urlencode([('id', id)]) in url, msg='Did not delete balancer with id %d' % id) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_EX_MEMBER_ADDRESS(self, method, url, body, headers): body = self.fixtures.load('v1_slug_loadbalancers_nodeaddress.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _v1_0_11111_loadbalancers_8155(self, method, url, body, headers): if method == "DELETE": return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('v1_slug_loadbalancers_8290.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_nodes(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('v1_slug_loadbalancers_8290_nodes.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == "POST": json_body = json.loads(body) json_node = json_body['nodes'][0] self.assertEqual('DISABLED', json_node['condition']) self.assertEqual(10, json_node['weight']) response_body = self.fixtures.load( 'v1_slug_loadbalancers_8290_nodes_post.json') return (httplib.ACCEPTED, response_body, {}, httplib.responses[httplib.ACCEPTED]) elif method == "DELETE": nodes = self.fixtures.load('v1_slug_loadbalancers_8290_nodes.json') json_nodes = json.loads(nodes) for node in json_nodes['nodes']: id = node['id'] self.assertTrue(urlencode([('id', id)]) in url, msg='Did not delete member with id %d' % id) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8291(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('v1_slug_loadbalancers_8291.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_8291_nodes(self, method, url, body, headers): if method == "POST": json_body = json.loads(body) json_node = json_body['nodes'][0] self.assertEqual('ENABLED', json_node['condition']) response_body = self.fixtures.load( 'v1_slug_loadbalancers_8290_nodes_post.json') return (httplib.ACCEPTED, response_body, {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8292(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('v1_slug_loadbalancers_8292.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_8292_nodes(self, method, url, body, headers): if method == "POST": json_body = json.loads(body) json_node_1 = json_body['nodes'][0] json_node_2 = json_body['nodes'][1] self.assertEqual('10.1.0.12', json_node_1['address']) self.assertEqual('10.1.0.13', json_node_2['address']) response_body = self.fixtures.load( 'v1_slug_loadbalancers_8292_nodes_post.json') return (httplib.ACCEPTED, response_body, {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_nodes_30944(self, method, url, body, headers): if method == "PUT": json_body = json.loads(body) self.assertEqual('ENABLED', json_body['condition']) self.assertEqual(12, json_body['weight']) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) elif method == "DELETE": return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_healthmonitor(self, method, url, body, headers): if method == "DELETE": return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_connectionthrottle(self, method, url, body, headers): if method == 'DELETE': return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_connectionlogging(self, method, url, body, headers): # Connection Logging uses a PUT to disable connection logging if method == 'PUT': json_body = json.loads(body) self.assertFalse(json_body["connectionLogging"]["enabled"]) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_sessionpersistence(self, method, url, body, headers): if method == 'DELETE': return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_errorpage(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'v1_slug_loadbalancers_8290_errorpage.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'PUT': json_body = json.loads(body) self.assertEqual('Generic Error Page', json_body['errorpage']['content']) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_18940(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_18940_ex_public_ips.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_18945(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_18945_ex_public_ips.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_18940_errorpage(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_18940_errorpage.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_18940_accesslist(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'v1_slug_loadbalancers_18940_accesslist.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_18941(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_18941_ex_private_ips.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94692(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94692_weighted_round_robin.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94693(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94693_weighted_least_connections.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94694(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94694_unknown_algorithm.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94695(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94695_full_details.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94695_healthmonitor(self, method, url, body, headers): if method == 'PUT': json_body = json.loads(body) self.assertEqual('CONNECT', json_body['type']) self.assertEqual(10, json_body['delay']) self.assertEqual(5, json_body['timeout']) self.assertEqual(2, json_body['attemptsBeforeDeactivation']) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94695_connectionthrottle(self, method, url, body, headers): if method == 'PUT': json_body = json.loads(body) self.assertEqual(50, json_body['minConnections']) self.assertEqual(200, json_body['maxConnections']) self.assertEqual(50, json_body['maxConnectionRate']) self.assertEqual(10, json_body['rateInterval']) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94695_connectionlogging(self, method, url, body, headers): if method == 'PUT': json_body = json.loads(body) self.assertTrue(json_body["connectionLogging"]["enabled"]) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94695_sessionpersistence(self, method, url, body, headers): if method == 'PUT': json_body = json.loads(body) persistence_type = json_body[ 'sessionPersistence']['persistenceType'] self.assertEqual('HTTP_COOKIE', persistence_type) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94695_errorpage(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load("error_page_default.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'DELETE': return (httplib.OK, '', {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94696(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94696_http_health_monitor.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94696_healthmonitor(self, method, url, body, headers): if method == 'PUT': json_body = json.loads(body) self.assertEqual('HTTP', json_body['type']) self.assertEqual(10, json_body['delay']) self.assertEqual(5, json_body['timeout']) self.assertEqual(2, json_body['attemptsBeforeDeactivation']) self.assertEqual('/', json_body['path']) self.assertEqual('^[234][0-9][0-9]$', json_body['statusRegex']) self.assertEqual('Hello World!', json_body['bodyRegex']) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94697(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94697_https_health_monitor.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94698(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94698_with_access_list.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94698_accesslist(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'v1_slug_loadbalancers_94698_accesslist.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == 'POST': json_body = json.loads(body) self.assertEqual('0.0.0.0/0', json_body['networkItem']['address']) self.assertEqual('DENY', json_body['networkItem']['type']) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94699(self, method, url, body, headers): if method == 'GET': # Use the same fixture for batch deletes as for single deletes body = self.fixtures.load( 'v1_slug_loadbalancers_94698_with_access_list.json') json_body = json.loads(body) json_body['loadBalancer']['id'] = 94699 updated_body = json.dumps(json_body) return (httplib.OK, updated_body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94699_accesslist(self, method, url, body, headers): if method == 'DELETE': fixture = 'v1_slug_loadbalancers_94698_with_access_list.json' fixture_json = json.loads(self.fixtures.load(fixture)) access_list_json = fixture_json['loadBalancer']['accessList'] for access_rule in access_list_json: id = access_rule['id'] self.assertTrue(urlencode([('id', id)]) in url, msg='Did not delete access rule with id %d' % id) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) elif method == 'POST': json_body = json.loads(body) access_list = json_body['accessList'] self.assertEqual('ALLOW', access_list[0]['type']) self.assertEqual('2001:4801:7901::6/64', access_list[0]['address']) self.assertEqual('DENY', access_list[1]['type']) self.assertEqual('8.8.8.8/0', access_list[1]['address']) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94698_accesslist_1007(self, method, url, body, headers): if method == 'DELETE': return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_94700(self, method, url, body, headers): if method == "GET": body = self.fixtures.load( "v1_slug_loadbalancers_94700_http_health_monitor_no_body_regex.json") return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_94700_healthmonitor(self, method, url, body, headers): if method == 'PUT': json_body = json.loads(body) self.assertEqual('HTTP', json_body['type']) self.assertEqual(10, json_body['delay']) self.assertEqual(5, json_body['timeout']) self.assertEqual(2, json_body['attemptsBeforeDeactivation']) self.assertEqual('/', json_body['path']) self.assertEqual('^[234][0-9][0-9]$', json_body['statusRegex']) self.assertFalse('bodyRegex' in json_body) return (httplib.ACCEPTED, '', {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError def _v1_0_11111_loadbalancers_3130(self, method, url, body, headers): """ update_balancer(b, protocol='HTTPS'), then get_balancer('3130') """ if method == "PUT": json_body = json.loads(body) self.assertDictEqual(json_body, {'protocol': 'HTTPS'}) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) elif method == "GET": response_body = json.loads( self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) response_body['loadBalancer']['id'] = 3130 response_body['loadBalancer']['protocol'] = 'HTTPS' return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_3131(self, method, url, body, headers): """ update_balancer(b, port=443), then get_balancer('3131') """ if method == "PUT": json_body = json.loads(body) self.assertDictEqual(json_body, {'port': 1337}) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) elif method == "GET": response_body = json.loads( self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) response_body['loadBalancer']['id'] = 3131 response_body['loadBalancer']['port'] = 1337 return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_3132(self, method, url, body, headers): """ update_balancer(b, name='new_lb_name'), then get_balancer('3132') """ if method == "PUT": json_body = json.loads(body) self.assertDictEqual(json_body, {'name': 'new_lb_name'}) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) elif method == "GET": response_body = json.loads( self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) response_body['loadBalancer']['id'] = 3132 response_body['loadBalancer']['name'] = 'new_lb_name' return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_3133(self, method, url, body, headers): """ update_balancer(b, algorithm='ROUND_ROBIN'), then get_balancer('3133') """ if method == "PUT": json_body = json.loads(body) self.assertDictEqual(json_body, {'algorithm': 'ROUND_ROBIN'}) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) elif method == "GET": response_body = json.loads( self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) response_body['loadBalancer']['id'] = 3133 response_body['loadBalancer']['algorithm'] = 'ROUND_ROBIN' return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_3134(self, method, url, body, headers): """ update.balancer(b, algorithm='HAVE_MERCY_ON_OUR_SERVERS') """ if method == "PUT": return (httplib.BAD_REQUEST, "", {}, httplib.responses[httplib.BAD_REQUEST]) raise NotImplementedError def _v1_0_11111_loadbalancers_3135(self, method, url, body, headers): """ update_balancer(b, protocol='IMAPv3'), then get_balancer('3135') """ if method == "PUT": json_body = json.loads(body) self.assertDictEqual(json_body, {'protocol': 'IMAPv2'}) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) elif method == "GET": response_body = json.loads( self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) response_body['loadBalancer']['id'] = 3135 response_body['loadBalancer']['protocol'] = 'IMAPv2' return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_3136(self, method, url, body, headers): """ update_balancer(b, protocol='IMAPv3'), then get_balancer('3136') """ if method == "PUT": json_body = json.loads(body) self.assertDictEqual(json_body, {'protocol': 'IMAPv3'}) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) elif method == "GET": response_body = json.loads( self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) response_body['loadBalancer']['id'] = 3136 response_body['loadBalancer']['protocol'] = 'IMAPv3' return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_3137(self, method, url, body, headers): """ update_balancer(b, protocol='IMAPv3'), then get_balancer('3137') """ if method == "PUT": json_body = json.loads(body) self.assertDictEqual(json_body, {'protocol': 'IMAPv4'}) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) elif method == "GET": response_body = json.loads( self.fixtures.load("v1_slug_loadbalancers_3xxx.json")) response_body['loadBalancer']['id'] = 3137 response_body['loadBalancer']['protocol'] = 'IMAPv4' return (httplib.OK, json.dumps(response_body), {}, httplib.responses[httplib.OK]) raise NotImplementedError def _v1_0_11111_loadbalancers_8290_usage_current(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load( 'v1_0_slug_loadbalancers_8290_usage_current.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) raise NotImplementedError class RackspaceLBWithVIPMockHttp(MockHttp, unittest.TestCase): fixtures = LoadBalancerFileFixtures('rackspace') auth_fixtures = OpenStackFixtures() def _v2_0_tokens(self, method, url, body, headers): body = self.fixtures.load('_v2_0__auth.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _v1_0_11111_loadbalancers(self, method, url, body, headers): if method == "GET": body = self.fixtures.load('v1_slug_loadbalancers.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) elif method == "POST": json_body = json.loads(body) loadbalancer_json = json_body['loadBalancer'] self.assertEqual(loadbalancer_json['virtualIps'][0]['id'], '12af') body = self.fixtures.load('v1_slug_loadbalancers_post.json') return (httplib.ACCEPTED, body, {}, httplib.responses[httplib.ACCEPTED]) raise NotImplementedError if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_slb.py0000664000175000017500000006202013535474530024010 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.compute.base import Node from libcloud.compute.types import NodeState from libcloud.loadbalancer.base import Member, Algorithm from libcloud.loadbalancer.drivers.slb import SLBDriver, \ SLBLoadBalancerHttpListener, SLBLoadBalancerHttpsListener, \ SLBLoadBalancerTcpListener, SLBLoadBalancerUdpListener from libcloud.loadbalancer.types import State from libcloud.test.file_fixtures import LoadBalancerFileFixtures from libcloud.test import MockHttp from libcloud.test.secrets import LB_SLB_PARAMS from libcloud.utils.py3 import httplib class SLBDriverTestCases(unittest.TestCase): region = LB_SLB_PARAMS[2] def setUp(self): SLBMockHttp.test = self SLBDriver.connectionCls.conn_class = SLBMockHttp SLBMockHttp.type = None SLBMockHttp.use_param = 'Action' self.driver = SLBDriver(*LB_SLB_PARAMS) def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertEqual(4, len(protocols)) expected = ['tcp', 'udp', 'http', 'https'] diff = set(expected) - set(protocols) self.assertEqual(0, len(diff)) def test_list_balancers(self): balancers = self.driver.list_balancers() self.assertEqual(len(balancers), 1) balancer = balancers[0] self.assertEqual('15229f88562-cn-hangzhou-dg-a01', balancer.id) self.assertEqual('abc', balancer.name) self.assertEqual(State.RUNNING, balancer.state) self.assertEqual('120.27.186.149', balancer.ip) self.assertTrue(balancer.port is None) self.assertEqual(self.driver, balancer.driver) expected_extra = { 'create_timestamp': 1452403099000, 'address_type': 'internet', 'region_id': 'cn-hangzhou-dg-a01', 'region_id_alias': 'cn-hangzhou', 'create_time': '2016-01-10T13:18Z', 'master_zone_id': 'cn-hangzhou-d', 'slave_zone_id': 'cn-hangzhou-b', 'network_type': 'classic' } self._validate_extras(expected_extra, balancer.extra) def _validate_extras(self, expected, actual): self.assertTrue(actual is not None) for key, value in iter(expected.items()): self.assertTrue(key in actual) self.assertEqual(value, actual[key], ('extra %(key)s not equal, ' 'expected: "%(expected)s", ' 'actual: "%(actual)s"' % {'key': key, 'expected': value, 'actual': actual[key]})) def test_list_balancers_with_ids(self): SLBMockHttp.type = 'list_balancers_ids' self.balancer_ids = ['id1', 'id2'] balancers = self.driver.list_balancers( ex_balancer_ids=self.balancer_ids) self.assertTrue(balancers is not None) def test_list_balancers_with_ex_filters(self): SLBMockHttp.type = 'list_balancers_filters' self.ex_filters = {'AddressType': 'internet'} balancers = self.driver.list_balancers(ex_filters=self.ex_filters) self.assertTrue(balancers is not None) def test_get_balancer(self): SLBMockHttp.type = 'get_balancer' balancer = self.driver.get_balancer(balancer_id='tests') self.assertEqual(balancer.id, '15229f88562-cn-hangzhou-dg-a01') self.assertEqual(balancer.name, 'abc') self.assertEqual(balancer.state, State.RUNNING) def test_destroy_balancer(self): balancer = self.driver.get_balancer(balancer_id='tests') self.assertTrue(self.driver.destroy_balancer(balancer)) def test_create_balancer(self): self.name = 'balancer1' self.port = 80 self.protocol = 'http' self.algorithm = Algorithm.WEIGHTED_ROUND_ROBIN self.extra = { 'ex_address_type': 'internet', 'ex_internet_charge_type': 'paybytraffic', 'ex_bandwidth': 1, 'ex_master_zone_id': 'cn-hangzhou-d', 'ex_slave_zone_id': 'cn-hangzhou-b', 'StickySession': 'on', 'HealthCheck': 'on'} self.members = [Member('node1', None, None)] balancer = self.driver.create_balancer(name=self.name, port=self.port, protocol=self.protocol, algorithm=self.algorithm, members=self.members, **self.extra) self.assertEqual(balancer.name, self.name) self.assertEqual(balancer.port, self.port) self.assertEqual(balancer.state, State.UNKNOWN) def test_create_balancer_no_port_exception(self): self.assertRaises(AttributeError, self.driver.create_balancer, None, None, 'http', Algorithm.WEIGHTED_ROUND_ROBIN, None) def test_create_balancer_unsupport_protocol_exception(self): self.assertRaises(AttributeError, self.driver.create_balancer, None, 443, 'ssl', Algorithm.WEIGHTED_ROUND_ROBIN, None) def test_create_balancer_multiple_member_ports_exception(self): members = [Member('m1', '1.2.3.4', 80), Member('m2', '1.2.3.5', 81)] self.assertRaises(AttributeError, self.driver.create_balancer, None, 80, 'http', Algorithm.WEIGHTED_ROUND_ROBIN, members) def test_create_balancer_bandwidth_value_error(self): self.assertRaises(AttributeError, self.driver.create_balancer, None, 80, 'http', Algorithm.WEIGHTED_ROUND_ROBIN, None, ex_bandwidth='NAN') def test_create_balancer_paybybandwidth_without_bandwidth_exception(self): self.assertRaises(AttributeError, self.driver.create_balancer, None, 80, 'http', Algorithm.WEIGHTED_ROUND_ROBIN, None, ex_internet_charge_type='paybybandwidth') def test_balancer_list_members(self): balancer = self.driver.get_balancer(balancer_id='tests') members = balancer.list_members() self.assertEqual(len(members), 1) self.assertEqual(members[0].balancer, balancer) self.assertEqual('i-23tshnsdq', members[0].id) def test_balancer_list_listeners(self): balancer = self.driver.get_balancer(balancer_id='tests') listeners = self.driver.ex_list_listeners(balancer) self.assertEqual(1, len(listeners)) listener = listeners[0] self.assertEqual('80', listener.port) def test_balancer_detach_member(self): self.balancer = self.driver.get_balancer(balancer_id='tests') self.member = Member('i-23tshnsdq', None, None) self.assertTrue(self.balancer.detach_member(self.member)) def test_balancer_attach_compute_node(self): SLBMockHttp.type = 'attach_compute_node' self.balancer = self.driver.get_balancer(balancer_id='tests') self.node = Node(id='node1', name='node-name', state=NodeState.RUNNING, public_ips=['1.2.3.4'], private_ips=['4.3.2.1'], driver=self.driver) member = self.driver.balancer_attach_compute_node( self.balancer, self.node) self.assertEqual(self.node.id, member.id) self.assertEqual(self.node.public_ips[0], member.ip) self.assertEqual(self.balancer.port, member.port) def test_ex_create_listener(self): SLBMockHttp.type = 'create_listener' self.balancer = self.driver.get_balancer(balancer_id='tests') self.backend_port = 80 self.protocol = 'http' self.algorithm = Algorithm.WEIGHTED_ROUND_ROBIN self.bandwidth = 1 self.extra = {'StickySession': 'off', 'HealthCheck': 'off'} self.assertTrue(self.driver.ex_create_listener(self.balancer, self.backend_port, self.protocol, self.algorithm, self.bandwidth, **self.extra)) def test_ex_create_listener_override_port(self): SLBMockHttp.type = 'create_listener_override_port' self.balancer = self.driver.get_balancer(balancer_id='tests') self.backend_port = 80 self.protocol = 'http' self.algorithm = Algorithm.WEIGHTED_ROUND_ROBIN self.bandwidth = 1 self.extra = {'StickySession': 'off', 'HealthCheck': 'off', 'ListenerPort': 8080} self.assertTrue(self.driver.ex_create_listener(self.balancer, self.backend_port, self.protocol, self.algorithm, self.bandwidth, **self.extra)) def test_ex_start_listener(self): SLBMockHttp.type = 'start_listener' balancer = self.driver.get_balancer(balancer_id='tests') self.port = 80 self.assertTrue(self.driver.ex_start_listener(balancer, self.port)) def test_ex_stop_listener(self): SLBMockHttp.type = 'stop_listener' balancer = self.driver.get_balancer(balancer_id='tests') self.port = 80 self.assertTrue(self.driver.ex_stop_listener(balancer, self.port)) def test_ex_upload_certificate(self): self.name = 'cert1' self.cert = 'cert-data' self.key = 'key-data' certificate = self.driver.ex_upload_certificate(self.name, self.cert, self.key) self.assertEqual(self.name, certificate.name) self.assertEqual('01:DF:AB:CD', certificate.fingerprint) def test_ex_list_certificates(self): certs = self.driver.ex_list_certificates() self.assertEqual(2, len(certs)) cert = certs[0] self.assertEqual('139a00604ad-cn-east-hangzhou-01', cert.id) self.assertEqual('abe', cert.name) self.assertEqual('A:B:E', cert.fingerprint) def test_ex_list_certificates_ids(self): SLBMockHttp.type = 'list_certificates_ids' self.cert_ids = ['cert1', 'cert2'] certs = self.driver.ex_list_certificates(certificate_ids=self.cert_ids) self.assertTrue(certs is not None) def test_ex_delete_certificate(self): self.cert_id = 'cert1' self.assertTrue(self.driver.ex_delete_certificate(self.cert_id)) def test_ex_set_certificate_name(self): self.cert_id = 'cert1' self.cert_name = 'cert-name' self.assertTrue(self.driver.ex_set_certificate_name(self.cert_id, self.cert_name)) class SLBMockHttp(MockHttp, unittest.TestCase): fixtures = LoadBalancerFileFixtures('slb') def _DescribeLoadBalancers(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _list_balancers_ids_DescribeLoadBalancers(self, method, url, body, headers): params = {'LoadBalancerId': ','.join(self.test.balancer_ids)} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _list_balancers_filters_DescribeLoadBalancers(self, method, url, body, headers): params = {'AddressType': 'internet'} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _get_balancer_DescribeLoadBalancers(self, method, url, body, headers): params = {'LoadBalancerId': 'tests'} self.assertUrlContainsQueryParams(url, params) return self._DescribeLoadBalancers(method, url, body, headers) def _DeleteLoadBalancer(self, method, url, body, headers): params = {'LoadBalancerId': '15229f88562-cn-hangzhou-dg-a01'} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('delete_load_balancer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeLoadBalancerAttribute(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancer_attribute.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateLoadBalancer(self, method, url, body, headers): params = {'RegionId': self.test.region, 'LoadBalancerName': self.test.name} balancer_keys = { 'AddressType': 'ex_address_type', 'InternetChargeType': 'ex_internet_charge_type', 'Bandwidth': 'ex_bandwidth', 'MasterZoneId': 'ex_master_zone_id', 'SlaveZoneId': 'ex_slave_zone_id' } for key in balancer_keys: params[key] = str(self.test.extra[balancer_keys[key]]) self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('create_load_balancer.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _AddBackendServers(self, method, url, body, headers): _id = self.test.members[0].id self.assertTrue("ServerId" in url and _id in url) self.assertTrue("Weight" in url and "100" in url) body = self.fixtures.load('add_backend_servers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _CreateLoadBalancerHTTPListener(self, method, url, body, headers): body = self.fixtures.load('create_load_balancer_http_listener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _StartLoadBalancerListener(self, method, url, body, headers): body = self.fixtures.load('start_load_balancer_listener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _RemoveBackendServers(self, method, url, body, headers): _id = self.test.member.id servers_json = '["%s"]' % _id params = {'LoadBalancerId': self.test.balancer.id, 'BackendServers': servers_json} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('add_backend_servers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _attach_compute_node_DescribeLoadBalancers(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _attach_compute_node_AddBackendServers(self, method, url, body, headers): _id = self.test.node.id self.assertTrue("ServerId" in url and _id in url) self.assertTrue("Weight" in url and "100" in url) body = self.fixtures.load('add_backend_servers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _create_listener_CreateLoadBalancerHTTPListener(self, method, url, body, headers): params = {'LoadBalancerId': self.test.balancer.id, 'RegionId': self.test.region, 'ListenerPort': str(self.test.balancer.port), 'BackendServerPort': str(self.test.backend_port), 'Scheduler': 'wrr', 'Bandwidth': '1', 'StickySession': 'off', 'HealthCheck': 'off'} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('create_load_balancer_http_listener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _create_listener_DescribeLoadBalancers(self, method, url, body, headers): body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _create_listener_override_port_CreateLoadBalancerHTTPListener( self, method, url, body, headers): params = {'LoadBalancerId': self.test.balancer.id, 'RegionId': self.test.region, 'ListenerPort': str(self.test.extra['ListenerPort']), 'BackendServerPort': str(self.test.backend_port), 'Scheduler': 'wrr', 'Bandwidth': '1', 'StickySession': 'off', 'HealthCheck': 'off'} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('create_load_balancer_http_listener.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _create_listener_override_port_DescribeLoadBalancers( self, method, url, body, headers): body = self.fixtures.load('describe_load_balancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _start_listener_DescribeLoadBalancers(self, method, url, body, headers): return self._DescribeLoadBalancers(method, url, body, headers) def _start_listener_StartLoadBalancerListener(self, method, url, body, headers): params = {'ListenerPort': str(self.test.port)} self.assertUrlContainsQueryParams(url, params) return self._StartLoadBalancerListener(method, url, body, headers) def _stop_listener_DescribeLoadBalancers(self, method, url, body, headers): return self._DescribeLoadBalancers(method, url, body, headers) def _stop_listener_StopLoadBalancerListener(self, method, url, body, headers): params = {'ListenerPort': str(self.test.port)} self.assertUrlContainsQueryParams(url, params) return self._StartLoadBalancerListener(method, url, body, headers) def _UploadServerCertificate(self, method, url, body, headers): body = self.fixtures.load('upload_server_certificate.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DescribeServerCertificates(self, method, url, body, headers): body = self.fixtures.load('describe_server_certificates.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _list_certificates_ids_DescribeServerCertificates(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ServerCertificateId': ','.join(self.test.cert_ids)} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('describe_server_certificates.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _DeleteServerCertificate(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ServerCertificateId': self.test.cert_id} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('delete_server_certificate.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _SetServerCertificateName(self, method, url, body, headers): params = {'RegionId': self.test.region, 'ServerCertificateId': self.test.cert_id, 'ServerCertificateName': self.test.cert_name} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('set_server_certificate_name.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class AssertDictMixin(object): def assert_dict_equals(self, expected, actual): expected_keys = set(expected.keys()) actual_keys = set(actual.keys()) self.assertEqual(len(expected_keys), len(actual_keys)) self.assertEqual(0, len(expected_keys - actual_keys)) for key in expected: self.assertEqual(expected[key], actual[key]) class SLBLoadBalancerHttpListenerTestCase(unittest.TestCase, AssertDictMixin): def setUp(self): self.listener = SLBLoadBalancerHttpListener.create( 80, 8080, Algorithm.WEIGHTED_ROUND_ROBIN, 1, extra={'StickySession': 'on', 'StickySessionType': 'insert', 'HealthCheck': 'on'} ) def test_get_required_params(self): expected = {'Action': 'CreateLoadBalancerHTTPListener', 'ListenerPort': 80, 'BackendServerPort': 8080, 'Scheduler': 'wrr', 'Bandwidth': 1, 'StickySession': 'on', 'HealthCheck': 'on'} self.assert_dict_equals(expected, self.listener.get_required_params()) def test_get_optional_params(self): expected = {'StickySessionType': 'insert'} self.assert_dict_equals(expected, self.listener.get_optional_params()) def test_repr(self): self.assertTrue('SLBLoadBalancerHttpListener' in str(self.listener)) class SLBLoadBalancerHttpsListenerTestCase(unittest.TestCase, AssertDictMixin): def setUp(self): self.listener = SLBLoadBalancerHttpsListener.create( 80, 8080, Algorithm.WEIGHTED_ROUND_ROBIN, 1, extra={'StickySession': 'on', 'StickySessionType': 'insert', 'HealthCheck': 'on', 'ServerCertificateId': 'fake-cert1'} ) def test_get_required_params(self): expected = {'Action': 'CreateLoadBalancerHTTPSListener', 'ListenerPort': 80, 'BackendServerPort': 8080, 'Scheduler': 'wrr', 'Bandwidth': 1, 'StickySession': 'on', 'HealthCheck': 'on', 'ServerCertificateId': 'fake-cert1'} self.assert_dict_equals(expected, self.listener.get_required_params()) def test_get_optional_params(self): expected = {'StickySessionType': 'insert'} self.assert_dict_equals(expected, self.listener.get_optional_params()) class SLBLoadBalancerTcpListenerTestCase(unittest.TestCase, AssertDictMixin): def setUp(self): self.listener = SLBLoadBalancerTcpListener.create( 80, 8080, Algorithm.WEIGHTED_ROUND_ROBIN, 1, extra={'PersistenceTimeout': 0, 'HealthCheckDomain': ''} ) def test_get_required_params(self): expected = {'Action': 'CreateLoadBalancerTCPListener', 'ListenerPort': 80, 'BackendServerPort': 8080, 'Scheduler': 'wrr', 'Bandwidth': 1} self.assert_dict_equals(expected, self.listener.get_required_params()) def test_get_optional_params(self): expected = {'PersistenceTimeout': 0, 'HealthCheckDomain': ''} self.assert_dict_equals(expected, self.listener.get_optional_params()) class SLBLoadBalancerUdpListenerTestCase(unittest.TestCase, AssertDictMixin): def setUp(self): self.listener = SLBLoadBalancerUdpListener.create( 80, 8080, Algorithm.WEIGHTED_ROUND_ROBIN, 1, extra={'PersistenceTimeout': 0} ) def test_get_required_params(self): expected = {'Action': 'CreateLoadBalancerUDPListener', 'ListenerPort': 80, 'BackendServerPort': 8080, 'Scheduler': 'wrr', 'Bandwidth': 1} self.assert_dict_equals(expected, self.listener.get_required_params()) def test_get_optional_params(self): expected = {'PersistenceTimeout': 0} self.assert_dict_equals(expected, self.listener.get_optional_params()) if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/loadbalancer/test_softlayer.py0000664000175000017500000001775613535474530025260 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import xmlrpclib from libcloud.compute.base import NodeLocation from libcloud.loadbalancer.base import Member, Algorithm from libcloud.loadbalancer.drivers.softlayer import SoftlayerLBDriver from libcloud.loadbalancer.types import State from libcloud.test import MockHttp from libcloud.test.secrets import SOFTLAYER_PARAMS from libcloud.test.file_fixtures import LoadBalancerFileFixtures class SoftlayerLBTests(unittest.TestCase): def setUp(self): SoftlayerLBDriver.connectionCls.conn_class = SoftLayerMockHttp SoftLayerMockHttp.type = None self.driver = SoftlayerLBDriver(*SOFTLAYER_PARAMS) def test_list_protocols(self): protocols = self.driver.list_protocols() self.assertEqual(len(protocols), 6) self.assertTrue('tcp' in protocols) self.assertTrue('http' in protocols) def test_list_balancers(self): balancers = self.driver.list_balancers() self.assertEqual(len(balancers), 2) self.assertEqual(balancers[0].id, '76185') self.assertEqual(balancers[0].extra['datacenter'], 'dal05') self.assertEqual(balancers[0].extra['connection_limit'], 50) self.assertEqual(balancers[1].id, '76265') self.assertEqual(balancers[1].extra['datacenter'], 'par01') self.assertEqual(balancers[1].extra['connection_limit'], 50) def test_get_balancer(self): balancer = self.driver.get_balancer(balancer_id='76185') self.assertEqual(balancer.id, '76185') self.assertEqual(balancer.state, State.UNKNOWN) self.assertEqual(balancer.extra['datacenter'], 'dal05') self.assertEqual(balancer.extra['protocol'], 'http') self.assertEqual(balancer.extra['algorithm'], Algorithm.ROUND_ROBIN) def test_balancer_list_members(self): balancer = self.driver.get_balancer(balancer_id='76185') members = balancer.list_members() self.assertEqual(len(members), 3) self.assertEqual(members[0].balancer, balancer) self.assertEqual(members[0].id, '226227') self.assertEqual(members[0].ip, '10.126.5.34') self.assertEqual(members[1].balancer, balancer) self.assertEqual(members[1].id, '226229') self.assertEqual(members[1].ip, '10.126.5.35') def test_balancer_attach_member(self): balancer = self.driver.get_balancer(balancer_id='76185') member = balancer.attach_member(Member(None, ip='10.126.5.34', port=8000)) self.assertEqual(member.id, '226227') self.assertEqual(member.ip, '10.126.5.34') self.assertEqual(member.port, 8000) def test_balancer_detach_member(self): balancer = self.driver.get_balancer(balancer_id='76265') member = Member('226227', None, None) self.assertTrue(balancer.detach_member(member)) def test_destroy_balancer(self): balancer = self.driver.get_balancer(balancer_id='76185') self.assertTrue(self.driver.destroy_balancer(balancer)) def test_ex_list_balancer_packages(self): packages = self.driver.ex_list_balancer_packages() self.assertEqual(len(packages), 9) def test_ex_place_balancer_order(self): packages = self.driver.ex_list_balancer_packages() lb_package = [p for p in packages if p.capacity == 50][0] self.assertTrue(self.driver.ex_place_balancer_order( lb_package, NodeLocation('dal05', None, None, None))) class SoftLayerMockHttp(MockHttp): fixtures = LoadBalancerFileFixtures('softlayer') def _get_method_name(self, type, use_param, qs, path): return "_xmlrpc" def _xmlrpc(self, method, url, body, headers): params, meth_name = xmlrpclib.loads(body) url = url.replace("/", "_") meth_name = "%s_%s" % (url, meth_name) return getattr(self, meth_name)(method, url, body, headers) def _xmlrpc_v3_SoftLayer_Account_getAdcLoadBalancers( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Account_getAdcLoadBalancers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Billing_Item_cancelService(self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Billing_Item_cancelService.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Location_Datacenter_getDatacenters( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Location_Datacenter_getDatacenters.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_Service_deleteObject( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Network_Application_Delivery_Controller_' 'LoadBalancer_Service_deleteObject.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_editObject( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Network_Application_Delivery_Controller_' 'LoadBalancer_VirtualIpAddress_editObject.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_getBillingItem( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Network_Application_Delivery_Controller_' 'LoadBalancer_VirtualIpAddress_getBillingItem.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_VirtualIpAddress_getObject( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Network_Application_Delivery_Controller_' 'LoadBalancer_VirtualIpAddress_getObject.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Network_Subnet_IpAddress_getByIpAddress( self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Network_Subnet_IpAddress_getByIpAddress.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Product_Order_placeOrder(self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Product_Order_placeOrder.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _xmlrpc_v3_SoftLayer_Product_Package_getItems(self, method, url, body, headers): body = self.fixtures.load( 'v3__SoftLayer_Product_Package_getItems.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == "__main__": sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/pricing_test.json0000664000175000017500000000017713535474530022602 0ustar kamikami00000000000000{ "compute": { "foo": { "1": 1.00, "2": 2.00 } }, "updated": 1309019791 } apache-libcloud-2.8.0/libcloud/test/secrets.py-dist0000664000175000017500000001113713570310635022170 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Make a copy of this file named 'secrets.py' and add your credentials there. # Note you can run unit tests without setting your credentials. BLUEBOX_PARAMS = ('customer_id', 'api_key') BRIGHTBOX_PARAMS = ('client_id', 'client_secret') EC2_PARAMS = ('access_id', 'secret') ECP_PARAMS = ('user_name', 'password') GANDI_PARAMS = ('user',) GCE_PARAMS = ('email@developer.gserviceaccount.com', 'key') # Service Account Authentication # GCE_PARAMS = ('client_id', 'client_secret') # Installed App Authentication GCE_KEYWORD_PARAMS = {'project': 'project_name'} GKE_PARAMS = ('email@developer.gserviceaccount.com', 'key') # Service Account Authentication # GKE_PARAMS = ('client_id', 'client_secret') # Installed App Authentication GKE_KEYWORD_PARAMS = {'project': 'project_name'} HOSTINGCOM_PARAMS = ('user', 'secret') IBM_PARAMS = ('user', 'secret') ONAPP_PARAMS = ('key') ONEANDONE_PARAMS = ('token') # OPENSTACK_PARAMS = ('user_name', 'api_key', secure_bool, 'host', port_int) OPENSTACK_PARAMS = ('user_name', 'api_key', False, 'host', 8774) OPENNEBULA_PARAMS = ('user', 'key') DIMENSIONDATA_PARAMS = ('user', 'password') NTTCIS_PARAMS = ('user', 'password') OPSOURCE_PARAMS = ('user', 'password') OVH_PARAMS = ('application_key', 'application_secret', 'project_id', 'consumer_key') RACKSPACE_PARAMS = ('user', 'key') RACKSPACE_NOVA_PARAMS = ('user_name', 'api_key', False, 'host', 8774) SLICEHOST_PARAMS = ('key',) SCALEWAY_PARAMS = ('access_key', 'token') SOFTLAYER_PARAMS = ('user', 'api_key') VCLOUD_PARAMS = ('user', 'secret') VOXEL_PARAMS = ('key', 'secret') VPSNET_PARAMS = ('user', 'key') JOYENT_PARAMS = ('user', 'key') VCL_PARAMS = ('user', 'pass', True, 'foo.bar.com') GRIDSPOT_PARAMS = ('key',) HOSTVIRTUAL_PARAMS = ('key',) DIGITALOCEAN_v1_PARAMS = ('user', 'key') DIGITALOCEAN_v2_PARAMS = ('token',) CLOUDFRAMES_PARAMS = ('key', 'secret', False, 'host', 8888) PROFIT_BRICKS_PARAMS = ('user', 'key') VULTR_PARAMS = ('key') PACKET_PARAMS = ('api_key') ECS_PARAMS = ('access_key', 'access_secret') CLOUDSCALE_PARAMS = ('token',) UPCLOUD_PARAMS = ('user', 'secret') GRIDSCALE_PARAMS = ('user uuid', 'api token') # Storage STORAGE_S3_PARAMS = ('key', 'secret') STORAGE_OSS_PARAMS = ('key', 'secret') # Google key = 20 char alphanumeric string starting with GOOG STORAGE_GOOGLE_STORAGE_PARAMS = ('GOOG0123456789ABCXYZ', 'secret') # Azure key is b64 encoded and must be decoded before signing requests STORAGE_AZURE_BLOBS_PARAMS = ('account', 'cGFzc3dvcmQ=') STORAGE_AZURITE_BLOBS_PARAMS = ('account', 'cGFzc3dvcmQ=', False, 'localhost', 10000) # Loadbalancer LB_BRIGHTBOX_PARAMS = ('user', 'key') LB_ELB_PARAMS = ('access_id', 'secret', 'region') LB_ALB_PARAMS = ('access_id', 'secret', 'region') LB_SLB_PARAMS = ('access_id', 'secret', 'region') # DNS DNS_PARAMS_LINODE = ('key') DNS_PARAMS_ZERIGO = ('email', 'api token') DNS_PARAMS_RACKSPACE = ('user', 'key') DNS_PARAMS_HOSTVIRTUAL = ('key',) DNS_PARAMS_ROUTE53 = ('access_id', 'secret') DNS_GANDI = ('user', ) DNS_GANDI_LIVE = ('key', ) DNS_PARAMS_GOOGLE = ('email_address', 'key') DNS_KEYWORD_PARAMS_GOOGLE = {'project': 'project_name'} DNS_PARAMS_WORLDWIDEDNS = ('user', 'key') DNS_PARAMS_DNSIMPLE = ('user', 'key') DNS_PARAMS_POINTDNS = ('user', 'key') DNS_PARAMS_LIQUIDWEB = ('user', 'key') DNS_PARAMS_ZONOMI = ('key') DNS_PARAMS_DURABLEDNS = ('api_user', 'api_key') DNS_PARAMS_GODADDY = ('customer-id', 'api_user', 'api_key') DNS_PARAMS_CLOUDFLARE = ('user@example.com', 'key') DNS_PARAMS_AURORADNS = ('apikey', 'secretkey') DNS_PARAMS_NSONE = ('key', ) DNS_PARAMS_LUADNS = ('user', 'key') DNS_PARAMS_BUDDYNS = ('key', ) DNS_PARAMS_DNSPOD = ('key', ) DNS_PARAMS_ONAPP = ('key', 'secret') # Container CONTAINER_PARAMS_DOCKER = ('user', 'password') CONTAINER_PARAMS_ECS = ('user', 'password', 'region') CONTAINER_PARAMS_KUBERNETES = ('user', 'password') CONTAINER_PARAMS_RANCHER = ('user', 'password') CONTAINER_PARAMS_GKE = ('user', 'password') apache-libcloud-2.8.0/libcloud/test/storage/0000775000175000017500000000000013600223624020641 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/__init__.py0000664000175000017500000000000013535474530022753 0ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/0000775000175000017500000000000013600223624022512 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/atmos/0000775000175000017500000000000013600223624023635 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/atmos/already_exists.xml0000664000175000017500000000022513535474530027411 0ustar kamikami00000000000000 1016 The resource you are trying to create already exists. apache-libcloud-2.8.0/libcloud/test/storage/fixtures/atmos/empty_directory_listing.xml0000664000175000017500000000021213535474530031340 0ustar kamikami00000000000000 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/atmos/list_containers.xml0000664000175000017500000000301413535474530027570 0ustar kamikami00000000000000 b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9 directory container1 860855a4a445b5e45eeef4024371fd5c73ee3ada directory container2 651eae32634bf84529c74eabd555fda48c7cead6 regular not-a-container1 089293be672782a255498b0b05c4877acf23ef9e directory container3 bd804e9f356b51844f93273ec8c94b2e274711d0 directory container4 b40b0f3a17fad1d8c8b2085f668f8107bb400fa5 regular not-a-container-2 10bd74388b55a3c8c329ff5dd6d21bd55bfb7370 directory container5 c04fa4aa3d0adcdf104baa0cef7b6279680a23c3 directory container6 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/atmos/not_empty.xml0000664000175000017500000000022413535474530026406 0ustar kamikami00000000000000 1023 The directory you are trying to delete is not empty. apache-libcloud-2.8.0/libcloud/test/storage/fixtures/atmos/not_found.xml0000664000175000017500000000020313535474530026360 0ustar kamikami00000000000000 1003 The requested object was not found. apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azure_blobs/0000775000175000017500000000000013600223624025021 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azure_blobs/list_containers_1.xml0000664000175000017500000000177513570310635031202 0ustar kamikami00000000000000 2 container1 Mon, 07 Jan 2013 06:31:06 GMT "0x8CFBAB7B4F23346" unlocked available container2 Mon, 07 Jan 2013 06:31:07 GMT "0x8CFBAB7B5B82D8E" unlocked available /account/container3 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azure_blobs/list_containers_2.xml0000664000175000017500000000201013570310635031162 0ustar kamikami00000000000000 /account/container3 2 container3 Mon, 07 Jan 2013 06:31:08 GMT "0x8CFBAB7B6452A71" unlocked available container4 Fri, 04 Jan 2013 08:32:41 GMT "0x8CFB86D32305484" unlocked available apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azure_blobs/list_containers_empty.xml0000664000175000017500000000036213570310635032167 0ustar kamikami00000000000000 100 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azure_blobs/list_objects_1.xml0000664000175000017500000000416413570310635030461 0ustar kamikami00000000000000 2 object1.txt Fri, 04 Jan 2013 09:48:06 GMT 0x8CFB877BB56A6FB 0 application/octet-stream 1B2M2Y8AsgTpgAmY7PhCfg== BlockBlob unlocked available true value1 value2 object2.txt Sat, 05 Jan 2013 03:51:42 GMT 0x8CFB90F1BA8CD8F 1048576 application/octet-stream ttgbNgpWctgMJ0MPORU+LA== BlockBlob unlocked available true value1 value2 2!76!MDAwMDExIXNvbWUxMTcudHh0ITAwMDAyOCE5OTk5LTEyLTMxVDIzOjU5OjU5Ljk5OTk5OTlaIQ-- apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azure_blobs/list_objects_2.xml0000664000175000017500000000354413570310635030463 0ustar kamikami00000000000000 object3.txt 2 object3.txt Sat, 05 Jan 2013 03:52:08 GMT 0x8CFB90F2B6FC022 1048576 application/octet-stream ttgbNgpWctgMJ0MPORU+LA== BlockBlob unlocked available true object4.txt Fri, 04 Jan 2013 10:20:14 GMT 0x8CFB87C38717450 0 application/octet-stream 1B2M2Y8AsgTpgAmY7PhCfg== BlockBlob unlocked available true apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azure_blobs/list_objects_empty.xml0000664000175000017500000000035513570310635031455 0ustar kamikami00000000000000 2 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azurite_blobs/0000775000175000017500000000000013600223624025356 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azurite_blobs/list_containers_1.xml0000664000175000017500000000170313570310635031526 0ustar kamikami00000000000000 2 container1 Mon, 07 Jan 2013 06:31:06 GMT "0x8CFBAB7B4F23346" unlocked available container2 Mon, 07 Jan 2013 06:31:07 GMT "0x8CFBAB7B5B82D8E" unlocked available /account/container3 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azurite_blobs/list_containers_2.xml0000664000175000017500000000171613570310635031533 0ustar kamikami00000000000000 /account/container3 2 container3 Mon, 07 Jan 2013 06:31:08 GMT "0x8CFBAB7B6452A71" unlocked available container4 Fri, 04 Jan 2013 08:32:41 GMT "0x8CFB86D32305484" unlocked available apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azurite_blobs/list_containers_empty.xml0000664000175000017500000000035413570310635032525 0ustar kamikami00000000000000 100 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azurite_blobs/list_objects_1.xml0000664000175000017500000000344113570310635031013 0ustar kamikami00000000000000 2 object1.txt Fri, 04 Jan 2013 09:48:06 GMT 0x8CFB877BB56A6FB 0 application/octet-stream BlockBlob unlocked available value1 value2 object2.txt Sat, 05 Jan 2013 03:51:42 GMT 0x8CFB90F1BA8CD8F 1048576 application/octet-stream BlockBlob unlocked available value1 value2 2!76!MDAwMDExIXNvbWUxMTcudHh0ITAwMDAyOCE5OTk5LTEyLTMxVDIzOjU5OjU5Ljk5OTk5OTlaIQ-- apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azurite_blobs/list_objects_2.xml0000664000175000017500000000273713570310635031023 0ustar kamikami00000000000000 object3.txt 2 object3.txt Sat, 05 Jan 2013 03:52:08 GMT 0x8CFB90F2B6FC022 1048576 application/octet-stream BlockBlob unlocked available object4.txt Fri, 04 Jan 2013 10:20:14 GMT 0x8CFB87C38717450 0 application/octet-stream BlockBlob unlocked available apache-libcloud-2.8.0/libcloud/test/storage/fixtures/azurite_blobs/list_objects_empty.xml0000664000175000017500000000034213570310635032006 0ustar kamikami00000000000000 2 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/0000775000175000017500000000000013600223624025013 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_create_bucket.json0000664000175000017500000000020613535474530031102 0ustar kamikami00000000000000{ "accountId": "8c7eea3fe570", "bucketId": "681c87aebeaa530f5e250710", "bucketName": "test0005", "bucketType": "allPrivate" } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_delete_bucket.json0000664000175000017500000000020613535474530031101 0ustar kamikami00000000000000{ "accountId": "8c7eea3fe570", "bucketId": "681c87aebeaa530f5e250710", "bucketName": "test0005", "bucketType": "allPrivate" } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_delete_file_version.json0000664000175000017500000000020113535474530032303 0ustar kamikami00000000000000{ "fileId": "4_z481c37de2e1ab3bf5e150710_f1060bc60382f42a2_d20160111_m063042_c001_v0001012_t0008", "fileName": "test8.txt" } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_get_upload_url.json0000664000175000017500000000023613535474530031312 0ustar kamikami00000000000000{ "authorizationToken": "nope", "bucketId": "481c37de2e1ab3bf5e150710", "uploadUrl": "https://podxxx.backblaze.com/b2api/v1/b2_upload_file/abcd/defg" } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_hide_file.json0000664000175000017500000000030213535474530030207 0ustar kamikami00000000000000{ "action": "hide", "fileId": "4_z481c37de2e1ab3bf5e150710_f1089c2d0af334258_d20160118_m103421_c001_v0001015_t0019", "fileName": "2.txt", "size": 0, "uploadTimestamp": 1453113261000 } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_list_buckets.json0000664000175000017500000000076513535474530031007 0ustar kamikami00000000000000{ "buckets": [ { "accountId": "8c7eea3fe570", "bucketId": "481c37de2e1ab3bf5e150710", "bucketName": "test00001", "bucketType": "allPrivate" }, { "accountId": "8c7eea3fe570", "bucketId": "886c573e2e1ab3bf5e150710", "bucketName": "test00002", "bucketType": "allPublic" }, { "accountId": "8c7eea3fe570", "bucketId": "c85c97ee2eeab3bf5e150710", "bucketName": "test00003", "bucketType": "allPrivate" } ] } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_list_file_names.json0000664000175000017500000000156113535474530031444 0ustar kamikami00000000000000 { "files": [ { "action": "upload", "fileId": "abcd", "fileName": "2.txt", "size": 2, "uploadTimestamp": 1450545966000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f108012807a71d788_d20160110_m155541_c001_v0001001_t0016", "fileName": "test5.txt", "size": 24, "uploadTimestamp": 1452441341000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f1071961a62d3426d_d20160110_m155708_c001_v0001013_t0042", "fileName": "test6.txt", "size": 24, "uploadTimestamp": 1452441428000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f1060bc60382f42a2_d20160111_m063042_c001_v0001012_t0008", "fileName": "test8.txt", "size": 24, "uploadTimestamp": 1452493842000 } ], "nextFileName": null } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_list_file_versions.json0000664000175000017500000000411013535474530032202 0ustar kamikami00000000000000{ "files": [ { "action": "hide", "fileId": "4_z481c37de2e1ab3bf5e150710_f11356114bd70b633_d20151219_m171034_c001_v0001015_t0017", "fileName": "1.txt", "size": 0, "uploadTimestamp": 1450545034000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f114de3a6d4984677_d20151219_m165328_c001_v0001011_t0013", "fileName": "1.txt", "size": 4, "uploadTimestamp": 1450544008000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f112d803c648864bd_d20151219_m172606_c001_v0001013_t0006", "fileName": "2.txt", "size": 2, "uploadTimestamp": 1450545966000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f112d1d656ee3d11a_d20160117_m215631_c001_v0001017_t0020", "fileName": "test10.txt", "size": 24, "uploadTimestamp": 1453067791000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f108012807a71d788_d20160110_m155541_c001_v0001001_t0016", "fileName": "test5.txt", "size": 24, "uploadTimestamp": 1452441341000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f118ba13b3b4343ae_d20151220_m135857_c001_v0001003_t0007", "fileName": "test5.txt", "size": 24, "uploadTimestamp": 1450619937000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f1071961a62d3426d_d20160110_m155708_c001_v0001013_t0042", "fileName": "test6.txt", "size": 24, "uploadTimestamp": 1452441428000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f106af7e634b95e05_d20160117_m180806_c001_v0001017_t0017", "fileName": "test8.txt", "size": 24, "uploadTimestamp": 1453054086000 }, { "action": "upload", "fileId": "4_z481c37de2e1ab3bf5e150710_f114bdc6fc4c203d9_d20160117_m215616_c001_v0001017_t0006", "fileName": "test9.txt", "size": 24, "uploadTimestamp": 1453067776000 } ], "nextFileId": null, "nextFileName": null } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/backblaze_b2/b2_upload_file.json0000664000175000017500000000040413535474530030565 0ustar kamikami00000000000000{ "accountId": "8c7eea3fe570", "bucketId": "481c37de2e1ab3bf5e150710", "contentLength": 24, "contentSha1": "23d23d43d4ecad793c049c81c4bc436ba1e8531e", "contentType": "text/plain", "fileId": "abcde", "fileInfo": {}, "fileName": "test0007.txt" } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/0000775000175000017500000000000013600223624024643 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/_v2_0__auth.json0000664000175000017500000001213413535474530027637 0ustar kamikami00000000000000{ "access": { "token": { "id": "aaaaaaaaaaaa-bbb-cccccccccccccc", "expires": "2999-11-23T21:00:14.000-06:00" }, "serviceCatalog": [ { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", "version": { "versionInfo": "https://cdn2.clouddrive.com/v1/", "versionList": "https://cdn2.clouddrive.com/", "versionId": "1" } }, { "region": "LON", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://cdn.clouddrive.com/v1/MossoCloudFS", "version": { "versionInfo": "https://cdn2.clouddrive.com/v1/", "versionList": "https://cdn2.clouddrive.com/", "versionId": "1" } } ], "name": "cloudFilesCDN", "type": "rax:object-cdn" }, { "endpoints": [ { "region": "ORD", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://storage4.ord1.clouddrive.com/v1/MossoCloudFS", "internalURL": "https://snet-storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" }, { "region": "LON", "tenantId": "MossoCloudFS_11111-111111111-1111111111-1111111", "publicURL": "https://storage4.lon1.clouddrive.com/v1/MossoCloudFS", "internalURL": "https://snet-storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111" } ], "name": "cloudFiles", "type": "object-store" }, { "endpoints": [ { "tenantId": "1337", "publicURL": "https://servers.api.rackspacecloud.com/v1.0/1337", "version": { "versionInfo": "https://servers.api.rackspacecloud.com/v1.0/", "versionList": "https://servers.api.rackspacecloud.com/", "versionId": "1.0" } } ], "name": "cloudServers", "type": "compute" }, { "endpoints": [ { "region": "RegionOne", "tenantId": "1337", "publicURL": "https://127.0.0.1/v2/1337", "versionInfo": "https://127.0.0.1/v2/", "versionList": "https://127.0.0.1/", "versionId": "2" } ], "name": "nova", "type": "compute" }, { "endpoints": [ { "region": "DFW", "tenantId": "613469", "publicURL": "https://dfw.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://dfw.servers.api.rackspacecloud.com/v2/", "versionList": "https://dfw.servers.api.rackspacecloud.com/", "versionId": "2" }, { "region": "ORD", "tenantId": "613469", "publicURL": "https://ord.servers.api.rackspacecloud.com/v2/1337", "versionInfo": "https://ord.servers.api.rackspacecloud.com/v2/", "versionList": "https://ord.servers.api.rackspacecloud.com/", "versionId": "2" } ], "name": "cloudServersOpenStack", "type": "compute" }, { "endpoints": [ { "region": "DFW", "tenantId": "1337", "publicURL": "https://preprod.dfw.servers.api.rackspacecloud.com/v2/1337" } ], "name": "cloudServersPreprod", "type": "compute" } ], "user": { "id": "7", "roles": [ { "id": "identity:default", "description": "Default Role.", "name": "identity:default" } ], "name": "testuser" } } } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_container_objects.json0000664000175000017500000000130213535474530032273 0ustar kamikami00000000000000[ {"name":"foo test 1","hash":"16265549b5bda64ecdaa5156de4c97cc", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:50.351810"}, {"name":"foo test 2","hash":"16265549b5bda64ecdaa5156de4c97bb", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:50.351810"}, {"name":"foo tes 3","hash":"16265549b5bda64ecdaa5156de4c97ee", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:46.549890"}, {"name":"foo test 3","hash":"16265549b5bda64ecdaa5156de4c97ff", "bytes":1160520,"content_type":"application/text", "last_modified":"2011-01-25T22:01:50.351810"} ] apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_empty.json0000664000175000017500000000000313535474530033506 0ustar kamikami00000000000000{} ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted1.jsonapache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted0000664000175000017500000000102313535474530034255 0ustar kamikami00000000000000[ {"name":"foo-test-1","hash":"16265549b5bda64ecdaa5156de4c97cc", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:50.351810"}, {"name":"foo-test-2","hash":"16265549b5bda64ecdaa5156de4c97bb", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:50.351810"}, {"name":"foo-test-3","hash":"16265549b5bda64ecdaa5156de4c97ee", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:46.549890"} ] ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted2.jsonapache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_container_objects_not_exhausted0000664000175000017500000000054213535474530034262 0ustar kamikami00000000000000[ {"name":"foo-test-4","hash":"16265549b5bda64ecdaa5156de4c97cc", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:50.351810"}, {"name":"foo-test-5","hash":"16265549b5bda64ecdaa5156de4c97bb", "bytes":1160520,"content_type":"application/zip", "last_modified":"2011-01-25T22:01:50.351810"} ] apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_containers.json0000664000175000017500000000024013535474530030745 0ustar kamikami00000000000000[ {"name":"container1","count":4,"bytes":3484450}, {"name":"container2","count":120,"bytes":340084450}, {"name":"container3","count":0,"bytes":0} ] apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/list_containers_empty.json0000664000175000017500000000000313535474530032160 0ustar kamikami00000000000000{} apache-libcloud-2.8.0/libcloud/test/storage/fixtures/cloudfiles/meta_data.json0000664000175000017500000000010413535474530027463 0ustar kamikami00000000000000{"bytes_used": 1234567, "container_count": 10, "object_count": 400} apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/0000775000175000017500000000000013600223624025512 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/get_container.json0000664000175000017500000000057113535474530031244 0ustar kamikami00000000000000{ "kind": "storage#bucket", "id": "test-bucket", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket", "projectNumber": "123", "name": "test-bucket", "timeCreated": "2015-12-17T21:38:31.413Z", "updated": "2015-12-17T21:38:31.413Z", "metageneration": "123", "location": "US", "storageClass": "STANDARD", "etag": "etag" } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/get_object.json0000664000175000017500000000122513535474530030525 0ustar kamikami00000000000000{ "kind": "storage#object", "id": "test-bucket/test-object/12345", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object ", "name": "test-object", "bucket": "test-bucket", "generation": "12345", "metageneration": "67890", "contentType": "text/plain", "timeCreated": "2016-09-14T01:19:33.850Z", "updated": "2016-09-14T01:19:33.850Z", "storageClass": "STANDARD", "size": "123", "md5Hash": "wVenkDHhxA+FkxgpvF/FUg==", "mediaLink": "https://www.googleapis.com/download/storage/v1/b/test-bucket/o/test-object?generation=12345&alt=media", "crc32": "+x0GyA==", "etag": "etag" } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_container_acl.json0000664000175000017500000000530313535474530032255 0ustar kamikami00000000000000{ "kind": "storage#bucketAccessControls", "items": [ { "kind": "storage#bucketAccessControl", "id": "test-bucket/project-owners-123", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/acl/project-owners-123 ", "bucket": "test-bucket", "entity": "project-owners-123", "role": "OWNER", "projectTeam": { "projectNumber": "123", "team": "owners" }, "etag": "etag" }, { "kind": "storage#bucketAccessControl", "id": "test-bucket/project-editors-123", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/acl/project-editors-123 ", "bucket": "test-bucket", "entity": "project-editors-123", "role": "WRITER", "projectTeam": { "projectNumber": "123", "team": "editors" }, "etag": "etag" }, { "kind": "storage#bucketAccessControl", "id": "test-bucket/project-viewers-123", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/acl/project-viewers-123 ", "bucket": "test-bucket", "entity": "project-viewers-123", "role": "READER", "projectTeam": { "projectNumber": "123", "team": "viewers" }, "etag": "etag" }, { "kind": "storage#bucketAccessControl", "id": "test-bucket/user-test@test.com", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/acl/user-test@test.com ", "bucket": "test-bucket", "entity": "user-test@test.com", "role": "OWNER", "email": "test@test.com", "etag": "etag" }, { "kind": "storage#bucketAccessControl", "id": "test-bucket/domain-test.com", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/acl/domain-test.com ", "bucket": "test-bucket", "entity": "domain-test.com", "role": "OWNER", "domain": "test.com", "etag": "etag" }, { "kind": "storage#bucketAccessControl", "id": "test-bucket/group-test-group@google.com", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/acl/group-test-group@google.com ", "bucket": "test-bucket", "entity": "group-test-group@google.com", "role": "OWNER", "email": "test-group@google.com", "etag": "etag" } ] } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_container_objects.xml0000664000175000017500000000114213535474530032773 0ustar kamikami00000000000000 test_container 1000 false 1.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_container_objects_empty.xml0000664000175000017500000000041213535474530034210 0ustar kamikami00000000000000 test_container 1000 false ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted1.xmlapache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhau0000664000175000017500000000241113535474530034246 0ustar kamikami00000000000000 test_container 1000 true 1.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD 2.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD 3.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhausted2.xmlapache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_container_objects_not_exhau0000664000175000017500000000166313535474530034256 0ustar kamikami00000000000000 test_container 3 false 4.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD 5.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_containers.xml0000664000175000017500000000103413535474530031445 0ustar kamikami00000000000000 af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 foobar test1 2011-04-09T12:34:49.000Z test2 2011-02-09T12:34:49.000Z apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_containers_empty.xml0000664000175000017500000000047313535474530032671 0ustar kamikami00000000000000 af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 foobar apache-libcloud-2.8.0/libcloud/test/storage/fixtures/google_storage/list_object_acl.json0000664000175000017500000000646213535474530031550 0ustar kamikami00000000000000{ "kind": "storage#objectAccessControls", "items": [ { "kind": "storage#objectAccessControl", "id": "test-bucket/test-object/12345/project-owners-123", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object/acl/project-owners-123 ", "bucket": "test-bucket", "object": "test-object", "generation": "12345", "entity": "project-owners-123", "role": "OWNER", "projectTeam": { "projectNumber": "123", "team": "owners" }, "etag": "etag" }, { "kind": "storage#objectAccessControl", "id": "test-bucket/test-object/12345/project-editors-123", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object/acl/project-editors-123 ", "bucket": "test-bucket", "object": "test-object", "generation": "12345", "entity": "project-editors-123", "role": "OWNER", "projectTeam": { "projectNumber": "123", "team": "editors" }, "etag": "etag" }, { "kind": "storage#objectAccessControl", "id": "test-bucket/test-object/12345/project-viewers-123", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object/acl/project-viewers-123 ", "bucket": "test-bucket", "object": "test-object", "generation": "12345", "entity": "project-viewers-123", "role": "READER", "projectTeam": { "projectNumber": "123", "team": "viewers" }, "etag": "etag" }, { "kind": "storage#objectAccessControl", "id": "test-bucket/test-object/12345/user-test@test.com", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object/acl/user-test@test.com ", "bucket": "test-bucket", "object": "test-object", "generation": "12345", "entity": "user-test@test.com", "role": "OWNER", "email": "test@test.com", "etag": "etag" }, { "kind": "storage#objectAccessControl", "id": "test-bucket/test-object/12345/domain-test.com", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object/acl/domain-test.com ", "bucket": "test-bucket", "object": "test-object", "generation": "12345", "entity": "domain-test.com", "role": "OWNER", "domain": "test.com", "etag": "etag" }, { "kind": "storage#objectAccessControl", "id": "test-bucket/test-object/12345/group-test-group@google.com", "selfLink": "https://www.googleapis.com/storage/v1/b/test-bucket/o/test-object/acl/group-test-group@google.com ", "bucket": "test-bucket", "object": "test-object", "generation": "12345", "entity": "group-test-group@google.com", "role": "OWNER", "email": "test-group@google.com", "etag": "etag" } ] } apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/0000775000175000017500000000000013600223624023316 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/complete_multipart_upload.xml0000664000175000017500000000046313535474530031333 0ustar kamikami00000000000000 http://oss-example.oss-cn-hangzhou.aliyuncs.com/multipart.data oss-example multipart.data B864DB6A936D376F9F8D3ED3BBE540DD-3 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/ex_iterate_multipart_uploads_p1.xml0000664000175000017500000000142213535474530032433 0ustar kamikami00000000000000 oss-example oss.avi 0004B99B8E707874FC2D692FA5D77D3F 2 true multipart.data 0004B999EF518A1FE585B0C9360DC4C8 2012-02-23T04:18:23.000Z oss.avi 0004B99B8E707874FC2D692FA5D77D3F 2012-02-23T06:14:27.000Z apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/ex_iterate_multipart_uploads_p2.xml0000664000175000017500000000110013535474530032425 0ustar kamikami00000000000000 oss-example 2 false multipart.data 0004B999EF5A239BB9138C6227D69F95 2012-02-23T04:18:23.000Z apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/initiate_multipart_upload.xml0000664000175000017500000000034613535474530031331 0ustar kamikami00000000000000 multipart_upload multipart.data 0004B9894A22E5B1888A1E29F8236E2D apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/list_container_objects.xml0000664000175000017500000000164113535474530030603 0ustar kamikami00000000000000 20150624 100 false en/ 2016-01-15T14:43:15.000Z "D41D8CD98F00B204E9800998ECF8427E" Normal 0 Standard 1751306716098727 1751306716098727 test.txt 2016-01-15T14:42:46.000Z "26AB0DB90D72E28AD0BA1E22EE510510" Normal 2 Standard 1751306716098727 1751306716098727 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/list_container_objects_chinese.xml0000664000175000017500000000176413535474530032307 0ustar kamikami00000000000000 test_container 100 false WEB\xe6\x8e\xa7\xe5\x88\xb6\xe5\x8f\xb0.odp 2016-01-15T14:43:06.000Z "281371EA1618CF0E645D6BB90A158276" Normal 1234567 Standard 1751306716098727 \xe4\xb8\xad\xe6\x96\x87/ 2016-01-15T14:43:34.000Z "D41D8CD98F00B204E9800998ECF8427E" Normal 0 Standard 1751306716098727 1751306716098727 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/list_container_objects_empty.xml0000664000175000017500000000034413535474530032020 0ustar kamikami00000000000000 20160116 100 false apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/list_container_objects_prefix.xml0000664000175000017500000000164613535474530032165 0ustar kamikami00000000000000 20150624 en 100 false en/ 2016-01-15T14:43:15.000Z "D41D8CD98F00B204E9800998ECF8427E" Normal 0 Standard 1751306716098727 1751306716098727 en/test.txt 2016-01-15T14:42:46.000Z "26AB0DB90D72E28AD0BA1E22EE510510" Normal 2 Standard 1751306716098727 1751306716098727 apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/list_containers.xml0000664000175000017500000000105413535474530027253 0ustar kamikami00000000000000 ut_test_put_bucket ut_test_put_bucket oss-cn-hangzhou-a xz02tphky6fjfiuc0 2014-05-15T11:18:32.000Z oss-cn-hangzhou-a xz02tphky6fjfiuc1 2014-05-15T11:18:32.000Z apache-libcloud-2.8.0/libcloud/test/storage/fixtures/oss/list_containers_empty.xml0000664000175000017500000000041413535474530030470 0ustar kamikami00000000000000 af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 foobar apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/0000775000175000017500000000000013600223624023037 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/complete_multipart.xml0000664000175000017500000000052713535474530027511 0ustar kamikami00000000000000 http://Example-Bucket.s3.amazonaws.com/Example-Object Example-Bucket Example-Object "3858f62230ac3c915f300c664312c11f-9" apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/initiate_multipart.xml0000664000175000017500000000045013535474530027502 0ustar kamikami00000000000000 example-bucket example-object VXBsb2FkIElEIGZvciA2aWWpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_container_objects.xml0000664000175000017500000000114313535474530030321 0ustar kamikami00000000000000 test_container 1000 false 1.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_container_objects_empty.xml0000664000175000017500000000041313535474530031536 0ustar kamikami00000000000000 test_container 1000 false apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted1.xml0000664000175000017500000000241213535474530033334 0ustar kamikami00000000000000 test_container 1000 true 1.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD 2.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD 3.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_container_objects_not_exhausted2.xml0000664000175000017500000000166413535474530033345 0ustar kamikami00000000000000 test_container 3 false 4.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD 5.zip 2011-04-09T19:05:18.000Z "4397da7a7649e8085de9916c240e8166" 1234567 65a011niqo39cdf8ec533ec3d1ccaafsa932 STANDARD apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_containers.xml0000664000175000017500000000103513535474530026773 0ustar kamikami00000000000000 af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 foobar test1 2011-04-09T12:34:49.000Z test2 2011-02-09T12:34:49.000Z apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_containers_empty.xml0000664000175000017500000000047413535474530030217 0ustar kamikami00000000000000 af4rf45db0927637c66fb848dfc972b8b5126e1237bde6fe02862b11481fdfd9 foobar apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_multipart_1.xml0000664000175000017500000000377713535474530027106 0ustar kamikami00000000000000 foo_bar_container my-movie.m2ts YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ 3 true my-divisor XMgbGlrZSBlbHZpbmcncyBub3QgaGF2aW5nIG11Y2ggbHVjaw arn:aws:iam::111122223333:user/user1-11111a31-17b5-4fb7-9df5-b111111f13de user1-11111a31-17b5-4fb7-9df5-b111111f13de 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a OwnerDisplayName STANDARD 2010-11-10T20:48:33.000Z my-movie.m2ts VXBsb2FkIElEIGZvciBlbHZpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA b1d16700c70b0b05597d7acd6a3f92be InitiatorDisplayName b1d16700c70b0b05597d7acd6a3f92be OwnerDisplayName STANDARD 2010-11-10T20:48:33.000Z my-movie.m2ts YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ arn:aws:iam::444455556666:user/user1-22222a31-17b5-4fb7-9df5-b222222f13de user1-22222a31-17b5-4fb7-9df5-b222222f13de b1d16700c70b0b05597d7acd6a3f92be OwnerDisplayName STANDARD 2010-11-10T20:49:33.000Z apache-libcloud-2.8.0/libcloud/test/storage/fixtures/s3/list_multipart_2.xml0000664000175000017500000000370413535474530027075 0ustar kamikami00000000000000 foo_bar_container 3 false my-divisor XMgbGlrZSBlbHZpbmcncyBub3QgaGF2aW5nIG11Y2ggbHVjaw arn:aws:iam::111122223333:user/user1-11111a31-17b5-4fb7-9df5-b111111f13de user1-11111a31-17b5-4fb7-9df5-b111111f13de 75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a OwnerDisplayName STANDARD 2010-11-10T20:48:33.000Z my-movie.m2ts VXBsb2FkIElEIGZvciBlbHZpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA b1d16700c70b0b05597d7acd6a3f92be InitiatorDisplayName b1d16700c70b0b05597d7acd6a3f92be OwnerDisplayName STANDARD 2010-11-10T20:48:33.000Z my-movie.m2ts YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ arn:aws:iam::444455556666:user/user1-22222a31-17b5-4fb7-9df5-b222222f13de user1-22222a31-17b5-4fb7-9df5-b222222f13de b1d16700c70b0b05597d7acd6a3f92be OwnerDisplayName STANDARD 2010-11-10T20:49:33.000Z apache-libcloud-2.8.0/libcloud/test/storage/test_atmos.py0000664000175000017500000007672413535474530023430 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import os.path import sys import unittest from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import b import libcloud.utils.files from libcloud.common.types import LibcloudError from libcloud.storage.base import Container, Object from libcloud.storage.types import ContainerAlreadyExistsError, \ ContainerDoesNotExistError, \ ContainerIsNotEmptyError, \ ObjectDoesNotExistError from libcloud.storage.drivers.atmos import AtmosConnection, AtmosDriver from libcloud.storage.drivers.dummy import DummyIterator from libcloud.test import MockHttp, generate_random_data, make_response from libcloud.test.file_fixtures import StorageFileFixtures class AtmosTests(unittest.TestCase): def setUp(self): AtmosDriver.connectionCls.conn_class = AtmosMockHttp AtmosDriver.path = '' AtmosMockHttp.type = None AtmosMockHttp.upload_created = False self.driver = AtmosDriver('dummy', base64.b64encode(b('dummy'))) self._remove_test_file() def tearDown(self): self._remove_test_file() def _remove_test_file(self): file_path = os.path.abspath(__file__) + '.temp' try: os.unlink(file_path) except OSError: pass def test_list_containers(self): AtmosMockHttp.type = 'EMPTY' containers = self.driver.list_containers() self.assertEqual(len(containers), 0) AtmosMockHttp.type = None containers = self.driver.list_containers() self.assertEqual(len(containers), 6) def test_list_container_objects(self): container = Container(name='test_container', extra={}, driver=self.driver) AtmosMockHttp.type = 'EMPTY' objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 0) AtmosMockHttp.type = None objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 2) obj = [o for o in objects if o.name == 'not-a-container1'][0] self.assertEqual(obj.meta_data['object_id'], '651eae32634bf84529c74eabd555fda48c7cead6') self.assertEqual(obj.container.name, 'test_container') def test_get_container(self): container = self.driver.get_container(container_name='test_container') self.assertEqual(container.name, 'test_container') self.assertEqual(container.extra['object_id'], 'b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9') def test_get_container_escaped(self): container = self.driver.get_container( container_name='test & container') self.assertEqual(container.name, 'test & container') self.assertEqual(container.extra['object_id'], 'b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9') def test_get_container_not_found(self): try: self.driver.get_container(container_name='not_found') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_create_container_success(self): container = self.driver.create_container( container_name='test_create_container') self.assertTrue(isinstance(container, Container)) self.assertEqual(container.name, 'test_create_container') self.assertEqual(container.extra['object_id'], '31a27b593629a3fe59f887fd973fd953e80062ce') def test_create_container_already_exists(self): AtmosMockHttp.type = 'ALREADY_EXISTS' try: self.driver.create_container( container_name='test_create_container') except ContainerAlreadyExistsError: pass else: self.fail( 'Container already exists but an exception was not thrown') def test_delete_container_success(self): container = Container(name='foo_bar_container', extra={}, driver=self) result = self.driver.delete_container(container=container) self.assertTrue(result) def test_delete_container_not_found(self): AtmosMockHttp.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self) try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail( 'Container does not exist but an exception was not thrown') def test_delete_container_not_empty(self): AtmosMockHttp.type = 'NOT_EMPTY' container = Container(name='foo_bar_container', extra={}, driver=self) try: self.driver.delete_container(container=container) except ContainerIsNotEmptyError: pass else: self.fail('Container is not empty but an exception was not thrown') def test_get_object_success(self): obj = self.driver.get_object(container_name='test_container', object_name='test_object') self.assertEqual(obj.container.name, 'test_container') self.assertEqual(obj.size, 555) self.assertEqual(obj.hash, '6b21c4a111ac178feacf9ec9d0c71f17') self.assertEqual(obj.extra['object_id'], '322dce3763aadc41acc55ef47867b8d74e45c31d6643') self.assertEqual( obj.extra['last_modified'], 'Tue, 25 Jan 2011 22:01:49 GMT') self.assertEqual(obj.meta_data['foo-bar'], 'test 1') self.assertEqual(obj.meta_data['bar-foo'], 'test 2') def test_get_object_escaped(self): obj = self.driver.get_object(container_name='test & container', object_name='test & object') self.assertEqual(obj.container.name, 'test & container') self.assertEqual(obj.size, 555) self.assertEqual(obj.hash, '6b21c4a111ac178feacf9ec9d0c71f17') self.assertEqual(obj.extra['object_id'], '322dce3763aadc41acc55ef47867b8d74e45c31d6643') self.assertEqual( obj.extra['last_modified'], 'Tue, 25 Jan 2011 22:01:49 GMT') self.assertEqual(obj.meta_data['foo-bar'], 'test 1') self.assertEqual(obj.meta_data['bar-foo'], 'test 2') def test_get_object_not_found(self): try: self.driver.get_object(container_name='test_container', object_name='not_found') except ObjectDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_delete_object_success(self): AtmosMockHttp.type = 'DELETE' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) status = self.driver.delete_object(obj=obj) self.assertTrue(status) def test_delete_object_escaped_success(self): AtmosMockHttp.type = 'DELETE' container = Container(name='foo & bar_container', extra={}, driver=self.driver) obj = Object(name='foo & bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) status = self.driver.delete_object(obj=obj) self.assertTrue(status) def test_delete_object_not_found(self): AtmosMockHttp.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) try: self.driver.delete_object(obj=obj) except ObjectDoesNotExistError: pass else: self.fail('Object does not exist but an exception was not thrown') def test_download_object_success(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) def test_download_object_escaped_success(self): container = Container(name='foo & bar_container', extra={}, driver=self.driver) obj = Object(name='foo & bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) def test_download_object_success_not_found(self): AtmosMockHttp.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) destination_path = os.path.abspath(__file__) + '.temp' try: self.driver.download_object( obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) except ObjectDoesNotExistError: pass else: self.fail('Object does not exist but an exception was not thrown') def test_download_object_as_stream(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) stream = self.driver.download_object_as_stream( obj=obj, chunk_size=None) self.assertTrue(hasattr(stream, '__iter__')) def test_download_object_as_stream_escaped(self): container = Container(name='foo & bar_container', extra={}, driver=self.driver) obj = Object(name='foo & bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) stream = self.driver.download_object_as_stream( obj=obj, chunk_size=None) self.assertTrue(hasattr(stream, '__iter__')) def test_upload_object_success(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(200, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} old_func = AtmosDriver._upload_object AtmosDriver._upload_object = upload_file path = os.path.abspath(__file__) container = Container(name='fbc', extra={}, driver=self) object_name = 'ftu' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=path, container=container, extra=extra, object_name=object_name) self.assertEqual(obj.name, 'ftu') self.assertEqual(obj.size, 1000) self.assertTrue('some-value' in obj.meta_data) AtmosDriver._upload_object = old_func def test_upload_object_no_content_type(self): def no_content_type(name): return None, None old_func = libcloud.utils.files.guess_file_mime_type libcloud.utils.files.guess_file_mime_type = no_content_type file_path = os.path.abspath(__file__) container = Container(name='fbc', extra={}, driver=self) object_name = 'ftu' obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name) # Just check that the file was uploaded OK, as the fallback # Content-Type header should be set (application/octet-stream). self.assertEqual(obj.name, object_name) libcloud.utils.files.guess_file_mime_type = old_func def test_upload_object_error(self): def dummy_content_type(name): return 'application/zip', None def send(self, method, **kwargs): raise LibcloudError('') old_func1 = libcloud.utils.files.guess_file_mime_type libcloud.utils.files.guess_file_mime_type = dummy_content_type old_func2 = AtmosMockHttp.request AtmosMockHttp.request = send file_path = os.path.abspath(__file__) container = Container(name='fbc', extra={}, driver=self) object_name = 'ftu' try: self.driver.upload_object( file_path=file_path, container=container, object_name=object_name) except LibcloudError: pass else: self.fail( 'Timeout while uploading but an exception was not thrown') finally: libcloud.utils.files.guess_file_mime_type = old_func1 AtmosMockHttp.request = old_func2 def test_upload_object_nonexistent_file(self): def dummy_content_type(name): return 'application/zip', None old_func = libcloud.utils.files.guess_file_mime_type libcloud.utils.files.guess_file_mime_type = dummy_content_type file_path = os.path.abspath(__file__ + '.inexistent') container = Container(name='fbc', extra={}, driver=self) object_name = 'ftu' try: self.driver.upload_object( file_path=file_path, container=container, object_name=object_name) except OSError: pass else: self.fail('Inesitent but an exception was not thrown') finally: libcloud.utils.files.guess_file_mime_type = old_func def test_upload_object_via_stream_new_object(self): def dummy_content_type(name): return 'application/zip', None old_func = libcloud.storage.drivers.atmos.guess_file_mime_type libcloud.storage.drivers.atmos.guess_file_mime_type = dummy_content_type container = Container(name='fbc', extra={}, driver=self) object_name = 'ftsdn' iterator = DummyIterator(data=['2', '3', '5']) try: self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator) finally: libcloud.storage.drivers.atmos.guess_file_mime_type = old_func def test_upload_object_via_stream_existing_object(self): def dummy_content_type(name): return 'application/zip', None old_func = libcloud.storage.drivers.atmos.guess_file_mime_type libcloud.storage.drivers.atmos.guess_file_mime_type = dummy_content_type container = Container(name='fbc', extra={}, driver=self) object_name = 'ftsde' iterator = DummyIterator(data=['2', '3', '5']) try: self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator) finally: libcloud.storage.drivers.atmos.guess_file_mime_type = old_func def test_upload_object_via_stream_no_content_type(self): def no_content_type(name): return None, None old_func = libcloud.storage.drivers.atmos.guess_file_mime_type libcloud.storage.drivers.atmos.guess_file_mime_type = no_content_type container = Container(name='fbc', extra={}, driver=self) object_name = 'ftsdct' iterator = DummyIterator(data=['2', '3', '5']) try: self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator) except AttributeError: pass else: self.fail( 'File content type not provided' ' but an exception was not thrown') finally: libcloud.storage.drivers.atmos.guess_file_mime_type = old_func def test_signature_algorithm(self): test_uid = 'fredsmagicuid' test_key = base64.b64encode(b('ssssshhhhhmysecretkey')) test_date = 'Mon, 04 Jul 2011 07:39:19 GMT' test_values = [ ('GET', '/rest/namespace/foo', '', {}, 'WfSASIA25TuqO2n0aO9k/dtg6S0='), ('GET', '/rest/namespace/foo%20%26%20bar', '', {}, 'vmlqXqcInxxoP4YX5mR09BonjX4='), ('POST', '/rest/namespace/foo', '', {}, 'oYKdsF+1DOuUT7iX5CJCDym2EQk='), ('PUT', '/rest/namespace/foo', '', {}, 'JleF9dpSWhaT3B2swZI3s41qqs4='), ('DELETE', '/rest/namespace/foo', '', {}, '2IX+Bd5XZF5YY+g4P59qXV1uLpo='), ('GET', '/rest/namespace/foo?metata/system', '', {}, 'zuHDEAgKM1winGnWn3WBsqnz4ks='), ('POST', '/rest/namespace/foo?metadata/user', '', { 'x-emc-meta': 'fakemeta=fake, othermeta=faketoo' }, '7sLx1nxPIRAtocfv02jz9h1BjbU='), ] class FakeDriver(object): path = '' for method, action, api_path, headers, expected in test_values: c = AtmosConnection(test_uid, test_key) c.method = method c.action = action d = FakeDriver() d.path = api_path c.driver = d headers = c.add_default_headers(headers) headers['Date'] = headers['x-emc-date'] = test_date self.assertEqual(c._calculate_signature({}, headers), b(expected).decode('utf-8')) class AtmosMockHttp(MockHttp, unittest.TestCase): fixtures = StorageFileFixtures('atmos') upload_created = False upload_stream_created = False def __init__(self, *args, **kwargs): unittest.TestCase.__init__(self) if kwargs.get('host', None) and kwargs.get('port', None): MockHttp.__init__(self, *args, **kwargs) self._upload_object_via_stream_first_request = True def runTest(self): pass def request(self, method, url, body=None, headers=None, raw=False, stream=False): headers = headers or {} parsed = urlparse.urlparse(url) if parsed.query.startswith('metadata/'): parsed = list(parsed) parsed[2] = parsed[2] + '/' + parsed[4] parsed[4] = '' url = urlparse.urlunparse(parsed) return super(AtmosMockHttp, self).request(method, url, body, headers, raw) def _rest_namespace_EMPTY(self, method, url, body, headers): body = self.fixtures.load('empty_directory_listing.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_namespace(self, method, url, body, headers): body = self.fixtures.load('list_containers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_namespace_test_container_EMPTY(self, method, url, body, headers): body = self.fixtures.load('empty_directory_listing.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_namespace_test_container(self, method, url, body, headers): body = self.fixtures.load('list_containers.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_namespace_test_container__metadata_system( self, method, url, body, headers): headers = { 'x-emc-meta': 'objectid=b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9' } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_test_20_26_20container__metadata_system( self, method, url, body, headers): headers = { 'x-emc-meta': 'objectid=b21cb59a2ba339d1afdd4810010b0a5aba2ab6b9' } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_not_found__metadata_system(self, method, url, body, headers): body = self.fixtures.load('not_found.xml') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) def _rest_namespace_test_create_container(self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_test_create_container__metadata_system(self, method, url, body, headers): headers = { 'x-emc-meta': 'objectid=31a27b593629a3fe59f887fd973fd953e80062ce' } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_test_create_container_ALREADY_EXISTS(self, method, url, body, headers): body = self.fixtures.load('already_exists.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.BAD_REQUEST]) def _rest_namespace_foo_bar_container(self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_foo_bar_container_NOT_FOUND(self, method, url, body, headers): body = self.fixtures.load('not_found.xml') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) def _rest_namespace_foo_bar_container_NOT_EMPTY(self, method, url, body, headers): body = self.fixtures.load('not_empty.xml') return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.BAD_REQUEST]) def _rest_namespace_test_container_test_object_metadata_system( self, method, url, body, headers): meta = { 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', 'size': '555', 'mtime': '2011-01-25T22:01:49Z' } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_test_20_26_20container_test_20_26_20object_metadata_system( self, method, url, body, headers): meta = { 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', 'size': '555', 'mtime': '2011-01-25T22:01:49Z' } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_test_container_test_object_metadata_user(self, method, url, body, headers): meta = { 'md5': '6b21c4a111ac178feacf9ec9d0c71f17', 'foo-bar': 'test 1', 'bar-foo': 'test 2', } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_test_20_26_20container_test_20_26_20object_metadata_user( self, method, url, body, headers): meta = { 'md5': '6b21c4a111ac178feacf9ec9d0c71f17', 'foo-bar': 'test 1', 'bar-foo': 'test 2', } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_test_container_not_found_metadata_system(self, method, url, body, headers): body = self.fixtures.load('not_found.xml') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) def _rest_namespace_foo_bar_container_foo_bar_object_DELETE(self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_foo_20_26_20bar_container_foo_20_26_20bar_object_DELETE( self, method, url, body, headers): return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_foo_bar_container_foo_bar_object_NOT_FOUND( self, method, url, body, headers): body = self.fixtures.load('not_found.xml') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) def _rest_namespace_fbc_ftu_metadata_system(self, method, url, body, headers): if not self.upload_created: self.__class__.upload_created = True body = self.fixtures.load('not_found.xml') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) self.__class__.upload_created = False meta = { 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', 'size': '555', 'mtime': '2011-01-25T22:01:49Z' } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftu_metadata_user(self, method, url, body, headers): self.assertTrue('x-emc-meta' in headers) return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftsdn_metadata_system(self, method, url, body, headers): if not self.upload_stream_created: self.__class__.upload_stream_created = True body = self.fixtures.load('not_found.xml') return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND]) self.__class__.upload_stream_created = False meta = { 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', 'size': '555', 'mtime': '2011-01-25T22:01:49Z' } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftsdn(self, method, url, body, headers): if self._upload_object_via_stream_first_request: self.assertTrue('Range' not in headers) self.assertEqual(method, 'POST') self._upload_object_via_stream_first_request = False else: self.assertTrue('Range' in headers) self.assertEqual(method, 'PUT') return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftsdn_metadata_user(self, method, url, body, headers): self.assertTrue('x-emc-meta' in headers) return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftsde_metadata_system(self, method, url, body, headers): meta = { 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', 'size': '555', 'mtime': '2011-01-25T22:01:49Z' } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftsde(self, method, url, body, headers): if self._upload_object_via_stream_first_request: self.assertTrue('Range' not in headers) self._upload_object_via_stream_first_request = False else: self.assertTrue('Range' in headers) self.assertEqual(method, 'PUT') return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftsde_metadata_user(self, method, url, body, headers): self.assertTrue('x-emc-meta' in headers) return (httplib.OK, '', {}, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftsd_metadata_system(self, method, url, body, headers): meta = { 'objectid': '322dce3763aadc41acc55ef47867b8d74e45c31d6643', 'size': '555', 'mtime': '2011-01-25T22:01:49Z' } headers = { 'x-emc-meta': ', '.join([k + '=' + v for k, v in list(meta.items())]) } return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _rest_namespace_foo_bar_container_foo_bar_object(self, method, url, body, headers): body = generate_random_data(1000) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_namespace_foo_20_26_20bar_container_foo_20_26_20bar_object( self, method, url, body, headers): body = generate_random_data(1000) return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _rest_namespace_fbc_ftu(self, method, url, body, headers): return (httplib.CREATED, '', {}, httplib.responses[httplib.CREATED]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_aurora.py0000664000175000017500000000246013535474530023560 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.storage.drivers.auroraobjects import AuroraObjectsStorageDriver from libcloud.test.storage.test_s3 import S3MockHttp, S3Tests class AuroraObjectsTests(S3Tests, unittest.TestCase): driver_type = AuroraObjectsStorageDriver def setUp(self): super(AuroraObjectsTests, self).setUp() AuroraObjectsStorageDriver.connectionCls.conn_class = S3MockHttp S3MockHttp.type = None self.driver = self.create_driver() if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_azure_blobs.py0000664000175000017500000011754713570310635024605 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import os import sys import tempfile from io import BytesIO from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qs from libcloud.utils.py3 import b from libcloud.utils.py3 import basestring from libcloud.common.types import InvalidCredsError from libcloud.common.types import LibcloudError from libcloud.storage.base import Container, Object from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import ContainerAlreadyExistsError from libcloud.storage.types import InvalidContainerNameError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError from libcloud.storage.drivers.azure_blobs import AzureBlobsStorageDriver from libcloud.storage.drivers.azure_blobs import AZURE_BLOCK_MAX_SIZE from libcloud.storage.drivers.azure_blobs import AZURE_PAGE_CHUNK_SIZE from libcloud.test import unittest from libcloud.test import MockHttp, generate_random_data # pylint: disable-msg=E0611 from libcloud.test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611 from libcloud.test.secrets import STORAGE_AZURE_BLOBS_PARAMS from libcloud.test.secrets import STORAGE_AZURITE_BLOBS_PARAMS class AzureBlobsMockHttp(MockHttp, unittest.TestCase): fixtures = StorageFileFixtures('azure_blobs') base_headers = {} def _UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, '', self.base_headers, httplib.responses[httplib.UNAUTHORIZED]) def _list_containers_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_containers_empty.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_containers(self, method, url, body, headers): query_string = urlparse.urlsplit(url).query query = parse_qs(query_string) if 'marker' not in query: body = self.fixtures.load('list_containers_1.xml') else: body = self.fixtures.load('list_containers_2.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _test_container_EMPTY(self, method, url, body, headers): if method == 'DELETE': body = u'' return (httplib.ACCEPTED, body, self.base_headers, httplib.responses[httplib.ACCEPTED]) else: body = self.fixtures.load('list_objects_empty.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _new__container_INVALID_NAME(self, method, url, body, headers): return (httplib.BAD_REQUEST, body, self.base_headers, httplib.responses[httplib.BAD_REQUEST]) def _test_container(self, method, url, body, headers): query_string = urlparse.urlsplit(url).query query = parse_qs(query_string) if 'marker' not in query: body = self.fixtures.load('list_objects_1.xml') else: body = self.fixtures.load('list_objects_2.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _test_container100(self, method, url, body, headers): body = '' if method != 'HEAD': return (httplib.BAD_REQUEST, body, self.base_headers, httplib.responses[httplib.BAD_REQUEST]) return (httplib.NOT_FOUND, body, self.base_headers, httplib.responses[httplib.NOT_FOUND]) def _test_container200(self, method, url, body, headers): body = '' if method != 'HEAD': return (httplib.BAD_REQUEST, body, self.base_headers, httplib.responses[httplib.BAD_REQUEST]) headers = {} headers['etag'] = '0x8CFB877BB56A6FB' headers['last-modified'] = 'Fri, 04 Jan 2013 09:48:06 GMT' headers['x-ms-lease-status'] = 'unlocked' headers['x-ms-lease-state'] = 'available' headers['x-ms-meta-meta1'] = 'value1' return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _test_container200_test(self, method, url, body, headers): body = '' if method != 'HEAD': return (httplib.BAD_REQUEST, body, self.base_headers, httplib.responses[httplib.BAD_REQUEST]) headers = {} headers['etag'] = '0x8CFB877BB56A6FB' headers['last-modified'] = 'Fri, 04 Jan 2013 09:48:06 GMT' headers['content-length'] = '12345' headers['content-type'] = 'application/zip' headers['x-ms-blob-type'] = 'Block' headers['x-ms-lease-status'] = 'unlocked' headers['x-ms-lease-state'] = 'available' headers['x-ms-meta-rabbits'] = 'monkeys' return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _test2_test_list_containers(self, method, url, body, headers): # test_get_object body = self.fixtures.load('list_containers.xml') headers = {'content-type': 'application/zip', 'etag': '"e31208wqsdoj329jd"', 'x-amz-meta-rabbits': 'monkeys', 'content-length': '12345', 'last-modified': 'Thu, 13 Sep 2012 07:13:22 GMT' } return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _new_container_ALREADY_EXISTS(self, method, url, body, headers): # test_create_container return (httplib.CONFLICT, body, headers, httplib.responses[httplib.CONFLICT]) def _new_container(self, method, url, body, headers): # test_create_container, test_delete_container headers = {} if method == 'PUT': status = httplib.CREATED headers['etag'] = '0x8CFB877BB56A6FB' headers['last-modified'] = 'Fri, 04 Jan 2013 09:48:06 GMT' headers['x-ms-lease-status'] = 'unlocked' headers['x-ms-lease-state'] = 'available' headers['x-ms-meta-meta1'] = 'value1' elif method == 'DELETE': status = httplib.NO_CONTENT return (status, body, headers, httplib.responses[status]) def _new_container_DOESNT_EXIST(self, method, url, body, headers): # test_delete_container return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _foo_bar_container_NOT_FOUND(self, method, url, body, headers): # test_delete_container_not_found return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _foo_bar_container_foo_bar_object_NOT_FOUND(self, method, url, body, headers): # test_delete_object_not_found return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.NOT_FOUND]) def _foo_bar_container_foo_bar_object_DELETE(self, method, url, body, headers): # test_delete_object return (httplib.ACCEPTED, body, headers, httplib.responses[httplib.ACCEPTED]) def _foo_bar_container_foo_test_upload(self, method, url, body, headers): # test_upload_object_success self._assert_content_length_header_is_string(headers=headers) body = '' headers = {} headers['etag'] = '0x8CFB877BB56A6FB' headers['content-md5'] = 'd4fe4c9829f7ca1cc89db7ad670d2bbd' return (httplib.CREATED, body, headers, httplib.responses[httplib.CREATED]) def _foo_bar_container_foo_test_upload_block(self, method, url, body, headers): # test_upload_object_success self._assert_content_length_header_is_string(headers=headers) body = '' headers = {} headers['etag'] = '0x8CFB877BB56A6FB' return (httplib.CREATED, body, headers, httplib.responses[httplib.CREATED]) def _foo_bar_container_foo_test_upload_page(self, method, url, body, headers): # test_upload_object_success body = '' headers = {} headers['etag'] = '0x8CFB877BB56A6FB' return (httplib.CREATED, body, headers, httplib.responses[httplib.CREATED]) def _foo_bar_container_foo_test_upload_blocklist(self, method, url, body, headers): # test_upload_object_success self._assert_content_length_header_is_string(headers=headers) body = '' headers = {} headers['etag'] = '0x8CFB877BB56A6FB' headers['content-md5'] = 'd4fe4c9829f7ca1cc89db7ad670d2bbd' return (httplib.CREATED, body, headers, httplib.responses[httplib.CREATED]) def _foo_bar_container_foo_test_upload_lease(self, method, url, body, headers): # test_upload_object_success self._assert_content_length_header_is_string(headers=headers) action = headers['x-ms-lease-action'] rheaders = {'x-ms-lease-id': 'someleaseid'} body = '' if action == 'acquire': return (httplib.CREATED, body, rheaders, httplib.responses[httplib.CREATED]) else: if headers.get('x-ms-lease-id', None) != 'someleaseid': return (httplib.BAD_REQUEST, body, rheaders, httplib.responses[httplib.BAD_REQUEST]) return (httplib.OK, body, headers, httplib.responses[httplib.CREATED]) def _foo_bar_container_foo_test_upload_INVALID_HASH(self, method, url, body, headers): # test_upload_object_invalid_hash1 self._assert_content_length_header_is_string(headers=headers) body = '' headers = {} headers['etag'] = '0x8CFB877BB56A6FB' headers['content-md5'] = 'd4fe4c9829f7ca1cc89db7ad670d2bbd' return (httplib.CREATED, body, headers, httplib.responses[httplib.CREATED]) def _foo_bar_container_foo_bar_object(self, method, url, body, headers): # test_upload_object_invalid_file_size self._assert_content_length_header_is_string(headers=headers) body = generate_random_data(1000) return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_bar_object_INVALID_SIZE(self, method, url, body, headers): # test_upload_object_invalid_file_size self._assert_content_length_header_is_string(headers=headers) body = '' return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _assert_content_length_header_is_string(self, headers): if 'Content-Length' in headers: self.assertTrue(isinstance(headers['Content-Length'], basestring)) class AzuriteBlobsMockHttp(AzureBlobsMockHttp): fixtures = StorageFileFixtures('azurite_blobs') def _get_method_name(self, *args, **kwargs): method_name = super(AzuriteBlobsMockHttp, self).\ _get_method_name(*args, **kwargs) if method_name.startswith('_account'): method_name = method_name[8:] return method_name class AzureBlobsTests(unittest.TestCase): driver_type = AzureBlobsStorageDriver driver_args = STORAGE_AZURE_BLOBS_PARAMS mock_response_klass = AzureBlobsMockHttp @classmethod def create_driver(self): return self.driver_type(*self.driver_args) def setUp(self): self.driver_type.connectionCls.conn_class = self.mock_response_klass self.mock_response_klass.type = None self.driver = self.create_driver() def tearDown(self): self._remove_test_file() def _remove_test_file(self): file_path = os.path.abspath(__file__) + '.temp' try: os.unlink(file_path) except OSError: pass def test_invalid_credentials(self): self.mock_response_klass.type = 'UNAUTHORIZED' try: self.driver.list_containers() except InvalidCredsError as e: self.assertEqual(True, isinstance(e, InvalidCredsError)) else: self.fail('Exception was not thrown') def test_list_containers_empty(self): self.mock_response_klass.type = 'list_containers_EMPTY' containers = self.driver.list_containers() self.assertEqual(len(containers), 0) def test_list_containers_success(self): self.mock_response_klass.type = 'list_containers' AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 containers = self.driver.list_containers() self.assertEqual(len(containers), 4) self.assertTrue('last_modified' in containers[1].extra) self.assertTrue('url' in containers[1].extra) self.assertTrue('etag' in containers[1].extra) self.assertTrue('lease' in containers[1].extra) self.assertTrue('meta_data' in containers[1].extra) def test_list_container_objects_empty(self): self.mock_response_klass.type = 'EMPTY' container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 0) def test_list_container_objects_success(self): self.mock_response_klass.type = None AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 4) obj = objects[1] self.assertEqual(obj.name, 'object2.txt') self.assertEqual(obj.hash, '0x8CFB90F1BA8CD8F') self.assertEqual(obj.size, 1048576) self.assertEqual(obj.container.name, 'test_container') self.assertTrue('meta1' in obj.meta_data) self.assertTrue('meta2' in obj.meta_data) self.assertTrue('last_modified' in obj.extra) self.assertTrue('content_type' in obj.extra) self.assertTrue('content_encoding' in obj.extra) self.assertTrue('content_language' in obj.extra) def test_list_container_objects_with_prefix(self): self.mock_response_klass.type = None AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container, ex_prefix='test_prefix') self.assertEqual(len(objects), 4) obj = objects[1] self.assertEqual(obj.name, 'object2.txt') self.assertEqual(obj.hash, '0x8CFB90F1BA8CD8F') self.assertEqual(obj.size, 1048576) self.assertEqual(obj.container.name, 'test_container') self.assertTrue('meta1' in obj.meta_data) self.assertTrue('meta2' in obj.meta_data) self.assertTrue('last_modified' in obj.extra) self.assertTrue('content_type' in obj.extra) self.assertTrue('content_encoding' in obj.extra) self.assertTrue('content_language' in obj.extra) def test_get_container_doesnt_exist(self): self.mock_response_klass.type = None try: self.driver.get_container(container_name='test_container100') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_get_container_success(self): self.mock_response_klass.type = None container = self.driver.get_container( container_name='test_container200') self.assertTrue(container.name, 'test_container200') self.assertTrue(container.extra['etag'], '0x8CFB877BB56A6FB') self.assertTrue(container.extra['last_modified'], 'Fri, 04 Jan 2013 09:48:06 GMT') self.assertTrue(container.extra['lease']['status'], 'unlocked') self.assertTrue(container.extra['lease']['state'], 'available') self.assertTrue(container.extra['meta_data']['meta1'], 'value1') def test_get_object_container_doesnt_exist(self): # This method makes two requests which makes mocking the response a bit # trickier self.mock_response_klass.type = None try: self.driver.get_object(container_name='test_container100', object_name='test') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_get_object_success(self): # This method makes two requests which makes mocking the response a bit # trickier self.mock_response_klass.type = None obj = self.driver.get_object(container_name='test_container200', object_name='test') self.assertEqual(obj.name, 'test') self.assertEqual(obj.container.name, 'test_container200') self.assertEqual(obj.size, 12345) self.assertEqual(obj.hash, '0x8CFB877BB56A6FB') self.assertEqual(obj.extra['last_modified'], 'Fri, 04 Jan 2013 09:48:06 GMT') self.assertEqual(obj.extra['content_type'], 'application/zip') self.assertEqual(obj.meta_data['rabbits'], 'monkeys') def test_create_container_invalid_name(self): # invalid container name self.mock_response_klass.type = 'INVALID_NAME' try: self.driver.create_container(container_name='new--container') except InvalidContainerNameError: pass else: self.fail('Exception was not thrown') def test_create_container_already_exists(self): # container with this name already exists self.mock_response_klass.type = 'ALREADY_EXISTS' try: self.driver.create_container(container_name='new-container') except ContainerAlreadyExistsError: pass else: self.fail('Exception was not thrown') def test_create_container_success(self): # success self.mock_response_klass.type = None name = 'new-container' container = self.driver.create_container(container_name=name) self.assertEqual(container.name, name) def test_delete_container_doesnt_exist(self): container = Container(name='new_container', extra=None, driver=self.driver) self.mock_response_klass.type = 'DOESNT_EXIST' try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_delete_container_not_empty(self): self.mock_response_klass.type = None AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 container = Container(name='test_container', extra={}, driver=self.driver) try: self.driver.delete_container(container=container) except ContainerIsNotEmptyError: pass else: self.fail('Exception was not thrown') def test_delete_container_success(self): self.mock_response_klass.type = 'EMPTY' AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2 container = Container(name='test_container', extra={}, driver=self.driver) self.assertTrue(self.driver.delete_container(container=container)) def test_delete_container_not_found(self): self.mock_response_klass.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self.driver) try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail('Container does not exist but an exception was not' + 'thrown') def test_download_object_success(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) def test_download_object_invalid_file_size(self): self.mock_response_klass.type = 'INVALID_SIZE' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertFalse(result) def test_download_object_invalid_file_already_exists(self): self.mock_response_klass.type = 'INVALID_SIZE' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = os.path.abspath(__file__) try: self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) except LibcloudError: pass else: self.fail('Exception was not thrown') def test_download_object_as_stream_success(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) stream = self.driver.download_object_as_stream(obj=obj, chunk_size=None) consumed_stream = ''.join(chunk.decode('utf-8') for chunk in stream) self.assertEqual(len(consumed_stream), obj.size) def test_upload_object_invalid_ex_blob_type(self): # Invalid hash is detected on the amazon side and BAD_REQUEST is # returned file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, verify_hash=True, ex_blob_type='invalid-blob') except LibcloudError as e: self.assertTrue(str(e).lower().find('invalid blob type') != -1) else: self.fail('Exception was not thrown') def test_upload_object_invalid_md5(self): # Invalid md5 is returned by azure self.mock_response_klass.type = 'INVALID_HASH' container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' file_path = os.path.abspath(__file__) try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, verify_hash=True) except ObjectHashMismatchError: pass else: self.fail( 'Invalid hash was returned but an exception was not thrown') def test_upload_small_block_object_success(self): file_path = os.path.abspath(__file__) file_size = os.stat(file_path).st_size container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=False, ex_blob_type='BlockBlob') self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, file_size) self.assertTrue('some-value' in obj.meta_data) def test_upload_big_block_object_success(self): file_path = tempfile.mktemp(suffix='.jpg') file_size = AZURE_BLOCK_MAX_SIZE + 1 with open(file_path, 'w') as file_hdl: file_hdl.write('0' * file_size) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=False, ex_blob_type='BlockBlob') self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, file_size) self.assertTrue('some-value' in obj.meta_data) os.remove(file_path) def test_upload_page_object_success(self): self.mock_response_klass.use_param = None file_path = tempfile.mktemp(suffix='.jpg') file_size = AZURE_PAGE_CHUNK_SIZE * 4 with open(file_path, 'w') as file_hdl: file_hdl.write('0' * file_size) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=False, ex_blob_type='PageBlob') self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, file_size) self.assertTrue('some-value' in obj.meta_data) os.remove(file_path) def test_upload_page_object_failure(self): file_path = tempfile.mktemp(suffix='.jpg') file_size = AZURE_PAGE_CHUNK_SIZE * 2 + 1 with open(file_path, 'w') as file_hdl: file_hdl.write('0' * file_size) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=False, ex_blob_type='PageBlob') except LibcloudError as e: self.assertTrue(str(e).lower().find('not aligned') != -1) os.remove(file_path) def test_upload_small_block_object_success_with_lease(self): self.mock_response_klass.use_param = 'comp' file_path = os.path.abspath(__file__) file_size = os.stat(file_path).st_size container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=False, ex_blob_type='BlockBlob', ex_use_lease=True) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, file_size) self.assertTrue('some-value' in obj.meta_data) self.mock_response_klass.use_param = None def test_upload_big_block_object_success_with_lease(self): self.mock_response_klass.use_param = 'comp' file_path = tempfile.mktemp(suffix='.jpg') file_size = AZURE_BLOCK_MAX_SIZE * 2 with open(file_path, 'w') as file_hdl: file_hdl.write('0' * file_size) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=False, ex_blob_type='BlockBlob', ex_use_lease=False) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, file_size) self.assertTrue('some-value' in obj.meta_data) os.remove(file_path) self.mock_response_klass.use_param = None def test_upload_page_object_success_with_lease(self): self.mock_response_klass.use_param = 'comp' file_path = tempfile.mktemp(suffix='.jpg') file_size = AZURE_PAGE_CHUNK_SIZE * 4 with open(file_path, 'w') as file_hdl: file_hdl.write('0' * file_size) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=False, ex_blob_type='PageBlob', ex_use_lease=True) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, file_size) self.assertTrue('some-value' in obj.meta_data) os.remove(file_path) self.mock_response_klass.use_param = None def test_upload_blob_object_via_stream(self): self.mock_response_klass.use_param = 'comp' container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' iterator = BytesIO(b('345')) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra, ex_blob_type='BlockBlob') self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, 3) self.mock_response_klass.use_param = None def test_upload_blob_object_via_stream_from_iterable(self): self.mock_response_klass.use_param = 'comp' container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' iterator = iter([b('34'), b('5')]) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra, ex_blob_type='BlockBlob') self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, 3) self.mock_response_klass.use_param = None def test_upload_blob_object_via_stream_with_lease(self): self.mock_response_klass.use_param = 'comp' container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' iterator = BytesIO(b('345')) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra, ex_blob_type='BlockBlob', ex_use_lease=True) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, 3) self.mock_response_klass.use_param = None def test_upload_page_object_via_stream(self): self.mock_response_klass.use_param = 'comp' container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' blob_size = AZURE_PAGE_CHUNK_SIZE iterator = BytesIO(b('1' * blob_size)) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra, ex_blob_type='PageBlob', ex_page_blob_size=blob_size) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, blob_size) self.mock_response_klass.use_param = None def test_upload_page_object_via_stream_with_lease(self): self.mock_response_klass.use_param = 'comp' container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' blob_size = AZURE_PAGE_CHUNK_SIZE iterator = BytesIO(b('1' * blob_size)) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra, ex_blob_type='PageBlob', ex_page_blob_size=blob_size, ex_use_lease=True) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, blob_size) def test_delete_object_not_found(self): self.mock_response_klass.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, meta_data=None, container=container, driver=self.driver) try: self.driver.delete_object(obj=obj) except ObjectDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_delete_object_success(self): self.mock_response_klass.type = 'DELETE' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, meta_data=None, container=container, driver=self.driver) result = self.driver.delete_object(obj=obj) self.assertTrue(result) def test_storage_driver_host(self): # Non regression tests for issue LIBCLOUD-399 dealing with the bad # management of the connectionCls.host class attribute driver1 = self.driver_type('fakeaccount1', 'deadbeafcafebabe==') driver2 = self.driver_type('fakeaccount2', 'deadbeafcafebabe==') driver3 = self.driver_type('fakeaccount3', 'deadbeafcafebabe==', host='test.foo.bar.com') host1 = driver1.connection.host host2 = driver2.connection.host host3 = driver3.connection.host self.assertEqual(host1, 'fakeaccount1.blob.core.windows.net') self.assertEqual(host2, 'fakeaccount2.blob.core.windows.net') self.assertEqual(host3, 'test.foo.bar.com') class AzuriteBlobsTests(AzureBlobsTests): driver_args = STORAGE_AZURITE_BLOBS_PARAMS mock_response_klass = AzuriteBlobsMockHttp if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_backblaze_b2.py0000664000175000017500000002461313570310635024566 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import tempfile import mock import json from libcloud.storage.drivers.backblaze_b2 import BackblazeB2StorageDriver from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.utils.files import exhaust_iterator from libcloud.test import unittest from libcloud.test import MockHttp from libcloud.test.file_fixtures import StorageFileFixtures class MockAuthConn(mock.Mock): account_id = 'abcdefgh' class BackblazeB2StorageDriverTestCase(unittest.TestCase): driver_klass = BackblazeB2StorageDriver driver_args = ('a', 'b') def setUp(self): self.driver_klass.connectionCls.authCls.conn_class = BackblazeB2MockHttp self.driver_klass.connectionCls.conn_class = \ BackblazeB2MockHttp BackblazeB2MockHttp.type = None self.driver = self.driver_klass(*self.driver_args) def test_list_containers(self): containers = self.driver.list_containers() self.assertEqual(len(containers), 3) self.assertEqual(containers[0].name, 'test00001') self.assertEqual(containers[0].extra['id'], '481c37de2e1ab3bf5e150710') self.assertEqual(containers[0].extra['bucketType'], 'allPrivate') def test_list_container_objects(self): container = self.driver.list_containers()[0] objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 4) self.assertEqual(objects[0].name, '2.txt') self.assertEqual(objects[0].size, 2) self.assertEqual(objects[0].extra['fileId'], 'abcd') self.assertEqual(objects[0].extra['uploadTimestamp'], 1450545966000) def test_get_container(self): container = self.driver.get_container('test00001') self.assertEqual(container.name, 'test00001') self.assertEqual(container.extra['id'], '481c37de2e1ab3bf5e150710') self.assertEqual(container.extra['bucketType'], 'allPrivate') def test_get_object(self): obj = self.driver.get_object('test00001', '2.txt') self.assertEqual(obj.name, '2.txt') self.assertEqual(obj.size, 2) self.assertEqual(obj.extra['fileId'], 'abcd') self.assertEqual(obj.extra['uploadTimestamp'], 1450545966000) def test_create_container(self): container = self.driver.create_container(container_name='test0005') self.assertEqual(container.name, 'test0005') self.assertEqual(container.extra['id'], '681c87aebeaa530f5e250710') self.assertEqual(container.extra['bucketType'], 'allPrivate') def test_delete_container(self): container = self.driver.list_containers()[0] result = self.driver.delete_container(container=container) self.assertTrue(result) def test_download_object(self): container = self.driver.list_containers()[0] obj = self.driver.list_container_objects(container=container)[0] _, destination_path = tempfile.mkstemp() result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=True) self.assertTrue(result) def test_download_object_as_stream(self): container = self.driver.list_containers()[0] obj = self.driver.list_container_objects(container=container)[0] stream = self.driver.download_object_as_stream(obj=obj, chunk_size=1024) self.assertTrue(hasattr(stream, '__iter__')) self.assertEqual(exhaust_iterator(stream), b('ab')) def test_upload_object(self): file_path = os.path.abspath(__file__) container = self.driver.list_containers()[0] obj = self.driver.upload_object(file_path=file_path, container=container, object_name='test0007.txt') self.assertEqual(obj.name, 'test0007.txt') self.assertEqual(obj.size, 24) self.assertEqual(obj.extra['fileId'], 'abcde') def test_upload_object_via_stream(self): container = self.driver.list_containers()[0] file_path = os.path.abspath(__file__) with open(file_path, 'rb') as fp: iterator = iter(fp) obj = self.driver.upload_object_via_stream(iterator=iterator, container=container, object_name='test0007.txt') self.assertEqual(obj.name, 'test0007.txt') self.assertEqual(obj.size, 24) self.assertEqual(obj.extra['fileId'], 'abcde') def test_delete_object(self): container = self.driver.list_containers()[0] obj = self.driver.list_container_objects(container=container)[0] result = self.driver.delete_object(obj=obj) self.assertTrue(result) def test_ex_hide_object(self): container = self.driver.list_containers()[0] container_id = container.extra['id'] obj = self.driver.ex_hide_object(container_id=container_id, object_name='2.txt') self.assertEqual(obj.name, '2.txt') def test_ex_list_object_versions(self): container = self.driver.list_containers()[0] container_id = container.extra['id'] objects = self.driver.ex_list_object_versions(container_id=container_id) self.assertEqual(len(objects), 9) def test_ex_get_upload_data(self): container = self.driver.list_containers()[0] container_id = container.extra['id'] data = self.driver.ex_get_upload_data(container_id=container_id) self.assertEqual(data['authorizationToken'], 'nope') self.assertEqual(data['bucketId'], '481c37de2e1ab3bf5e150710') self.assertEqual(data['uploadUrl'], 'https://podxxx.backblaze.com/b2api/v1/b2_upload_file/abcd/defg') def test_ex_get_upload_url(self): container = self.driver.list_containers()[0] container_id = container.extra['id'] url = self.driver.ex_get_upload_url(container_id=container_id) self.assertEqual(url, 'https://podxxx.backblaze.com/b2api/v1/b2_upload_file/abcd/defg') class BackblazeB2MockHttp(MockHttp): fixtures = StorageFileFixtures('backblaze_b2') def _b2api_v1_b2_authorize_account(self, method, url, body, headers): if method == 'GET': body = json.dumps({ 'accountId': 'test', 'apiUrl': 'https://apiNNN.backblazeb2.com', 'downloadUrl': 'https://f002.backblazeb2.com', 'authorizationToken': 'test' }) else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_list_buckets(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('b2_list_buckets.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_list_file_names(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('b2_list_file_names.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_create_bucket(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('b2_create_bucket.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_delete_bucket(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('b2_delete_bucket.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_delete_file_version(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('b2_delete_file_version.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_get_upload_url(self, method, url, body, headers): # test_upload_object if method == 'GET': body = self.fixtures.load('b2_get_upload_url.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_upload_file_abcd_defg(self, method, url, body, headers): # test_upload_object if method == 'POST': body = self.fixtures.load('b2_upload_file.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_list_file_versions(self, method, url, body, headers): if method == 'GET': body = self.fixtures.load('b2_list_file_versions.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _b2api_v1_b2_hide_file(self, method, url, body, headers): if method == 'POST': body = self.fixtures.load('b2_hide_file.json') else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _file_test00001_2_txt(self, method, url, body, headers): # test_download_object if method == 'GET': body = 'ab' else: raise AssertionError('Unsupported method') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_base.py0000664000175000017500000002114713576514553023211 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import hashlib from libcloud.utils.py3 import httplib from io import BytesIO import mock from mock import Mock from libcloud.utils.py3 import StringIO from libcloud.utils.py3 import b from libcloud.utils.py3 import PY2 from libcloud.utils.py3 import assertRaisesRegex from libcloud.storage.base import StorageDriver from libcloud.storage.base import DEFAULT_CONTENT_TYPE from libcloud.test import unittest from libcloud.test import MockHttp from libcloud.test import BodyStream class BaseMockRawResponse(MockHttp): def _(self, method, url, body, headers): body = 'ab' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def root(self, method, url, body, headers): body = 'ab' return (httplib.OK, body, {}, httplib.responses[httplib.OK]) class BaseStorageTests(unittest.TestCase): def setUp(self): self.send_called = 0 StorageDriver.connectionCls.conn_class = BaseMockRawResponse self.driver1 = StorageDriver('username', 'key', host='localhost') self.driver1.supports_chunked_encoding = True self.driver2 = StorageDriver('username', 'key', host='localhost') self.driver2.supports_chunked_encoding = False self.driver1.strict_mode = False self.driver1.strict_mode = False def test__upload_object_iterator_must_have_next_method(self): valid_iterators = [BytesIO(b('134')), StringIO('bar')] invalid_iterators = ['foobar', '', False, True, 1, object()] def upload_func(*args, **kwargs): return True, 'barfoo', 100 kwargs = {'object_name': 'foo', 'content_type': 'foo/bar', 'upload_func': upload_func, 'upload_func_kwargs': {}, 'request_path': '/', 'headers': {}} for value in valid_iterators: kwargs['stream'] = value self.driver1._upload_object(**kwargs) for value in invalid_iterators: kwargs['stream'] = value try: self.driver1._upload_object(**kwargs) except AttributeError: pass else: self.fail('Exception was not thrown') def test__upload_object_does_not_stream_response(self): resp = self.driver1._upload_object( object_name='foo', content_type='foo/bar', request_path='/', stream=iter(b'foo')) mock_response = resp["response"].response._response response_streamed = mock_response.request.stream assert response_streamed is False def test__get_hash_function(self): self.driver1.hash_type = 'md5' func = self.driver1._get_hash_function() self.assertTrue(func) self.driver1.hash_type = 'sha1' func = self.driver1._get_hash_function() self.assertTrue(func) try: self.driver1.hash_type = 'invalid-hash-function' func = self.driver1._get_hash_function() except RuntimeError: pass else: self.fail('Invalid hash type but exception was not thrown') def test_upload_no_content_type_supplied_or_detected(self): iterator = StringIO() upload_func = Mock() upload_func.return_value = True, '', 0 # strict_mode is disabled, default content type should be used self.driver1.connection = Mock() self.driver1._upload_object(object_name='test', content_type=None, upload_func=upload_func, upload_func_kwargs={}, request_path='/', stream=iterator) headers = self.driver1.connection.request.call_args[-1]['headers'] self.assertEqual(headers['Content-Type'], DEFAULT_CONTENT_TYPE) # strict_mode is enabled, exception should be thrown self.driver1.strict_mode = True expected_msg = ('File content-type could not be guessed and no' ' content_type value is provided') assertRaisesRegex(self, AttributeError, expected_msg, self.driver1._upload_object, object_name='test', content_type=None, upload_func=upload_func, upload_func_kwargs={}, request_path='/', stream=iterator) @mock.patch('libcloud.utils.files.exhaust_iterator') @mock.patch('libcloud.utils.files.read_in_chunks') def test_upload_object_hash_calculation_is_efficient(self, mock_read_in_chunks, mock_exhaust_iterator): # Verify that we don't buffer whole file in memory when calculating # object has when iterator has __next__ method, but instead read and calculate hash in chunks size = 100 self.driver1.connection = Mock() # stream has __next__ method and next() method mock_read_in_chunks.return_value = 'a' * size iterator = BodyStream('a' * size) self.assertTrue(hasattr(iterator, '__next__')) self.assertTrue(hasattr(iterator, 'next')) upload_func = Mock() upload_func.return_value = True, '', size self.assertEqual(mock_read_in_chunks.call_count, 0) self.assertEqual(mock_exhaust_iterator.call_count, 0) result = self.driver1._upload_object(object_name='test1', content_type=None, upload_func=upload_func, upload_func_kwargs={}, request_path='/', stream=iterator) hasher = hashlib.md5() hasher.update(b('a') * size) expected_hash = hasher.hexdigest() self.assertEqual(result['data_hash'], expected_hash) self.assertEqual(result['bytes_transferred'], size) headers = self.driver1.connection.request.call_args[-1]['headers'] self.assertEqual(headers['Content-Type'], DEFAULT_CONTENT_TYPE) self.assertEqual(mock_read_in_chunks.call_count, 1) self.assertEqual(mock_exhaust_iterator.call_count, 0) # stream has only has next() method mock_read_in_chunks.return_value = 'b' * size iterator = iter([str(v) for v in ['b' * size]]) if PY2: self.assertFalse(hasattr(iterator, '__next__')) self.assertTrue(hasattr(iterator, 'next')) else: self.assertTrue(hasattr(iterator, '__next__')) self.assertFalse(hasattr(iterator, 'next')) self.assertEqual(mock_read_in_chunks.call_count, 1) self.assertEqual(mock_exhaust_iterator.call_count, 0) self.assertEqual(mock_read_in_chunks.call_count, 1) self.assertEqual(mock_exhaust_iterator.call_count, 0) result = self.driver1._upload_object(object_name='test2', content_type=None, upload_func=upload_func, upload_func_kwargs={}, request_path='/', stream=iterator) hasher = hashlib.md5() hasher.update(b('b') * size) expected_hash = hasher.hexdigest() self.assertEqual(result['data_hash'], expected_hash) self.assertEqual(result['bytes_transferred'], size) headers = self.driver1.connection.request.call_args[-1]['headers'] self.assertEqual(headers['Content-Type'], DEFAULT_CONTENT_TYPE) self.assertEqual(mock_read_in_chunks.call_count, 2) self.assertEqual(mock_exhaust_iterator.call_count, 0) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_cloudfiles.py0000664000175000017500000015172313570310635024421 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import hmac import os import os.path # pylint: disable-msg=W0404 import math import sys import copy from io import BytesIO import hashlib from hashlib import sha1 import mock from mock import Mock from mock import PropertyMock import libcloud.utils.files from libcloud.utils.py3 import b from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlquote from libcloud.utils.py3 import StringIO from libcloud.utils.py3 import PY3 from libcloud.utils.files import exhaust_iterator from libcloud.common.types import MalformedResponseError from libcloud.storage.base import CHUNK_SIZE, Container, Object from libcloud.storage.types import ContainerAlreadyExistsError from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError from libcloud.storage.types import InvalidContainerNameError from libcloud.storage.drivers.cloudfiles import CloudFilesStorageDriver from libcloud.test import MockHttp # pylint: disable-msg=E0611 from libcloud.test import unittest, generate_random_data, make_response from libcloud.test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611 class CloudFilesTests(unittest.TestCase): driver_klass = CloudFilesStorageDriver driver_args = ('dummy', 'dummy') driver_kwargs = {} region = 'ord' def setUp(self): self.driver_klass.connectionCls.conn_class = CloudFilesMockHttp CloudFilesMockHttp.type = None driver_kwargs = self.driver_kwargs.copy() driver_kwargs['region'] = self.region self.driver = self.driver_klass(*self.driver_args, **driver_kwargs) # normally authentication happens lazily, but we force it here self.driver.connection._populate_hosts_and_request_paths() self._remove_test_file() def tearDown(self): self._remove_test_file() def test_invalid_ex_force_service_region(self): driver = CloudFilesStorageDriver('driver', 'dummy', ex_force_service_region='invalid') try: driver.list_containers() except Exception as e: self.assertEqual(e.value, 'Could not find specified endpoint') else: self.fail('Exception was not thrown') def test_ex_force_service_region(self): driver = CloudFilesStorageDriver('driver', 'dummy', ex_force_service_region='ORD') driver.list_containers() def test_force_auth_token_kwargs(self): base_url = 'https://cdn2.clouddrive.com/v1/MossoCloudFS' kwargs = { 'ex_force_auth_token': 'some-auth-token', 'ex_force_base_url': base_url } driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs) driver.list_containers() self.assertEqual(kwargs['ex_force_auth_token'], driver.connection.auth_token) self.assertEqual('cdn2.clouddrive.com', driver.connection.host) self.assertEqual('/v1/MossoCloudFS', driver.connection.request_path) def test_force_auth_url_kwargs(self): kwargs = { 'ex_force_auth_version': '2.0', 'ex_force_auth_url': 'https://identity.api.rackspace.com' } driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs) self.assertEqual(kwargs['ex_force_auth_url'], driver.connection._ex_force_auth_url) self.assertEqual(kwargs['ex_force_auth_version'], driver.connection._auth_version) def test_invalid_json_throws_exception(self): CloudFilesMockHttp.type = 'MALFORMED_JSON' try: self.driver.list_containers() except MalformedResponseError: pass else: self.fail('Exception was not thrown') def test_service_catalog(self): url = 'https://storage4.%s1.clouddrive.com/v1/MossoCloudFS' % \ (self.region) self.assertEqual( url, self.driver.connection.get_endpoint()) self.driver.connection.cdn_request = True self.assertEqual( 'https://cdn.clouddrive.com/v1/MossoCloudFS', self.driver.connection.get_endpoint()) self.driver.connection.cdn_request = False def test_list_containers(self): CloudFilesMockHttp.type = 'EMPTY' containers = self.driver.list_containers() self.assertEqual(len(containers), 0) CloudFilesMockHttp.type = None containers = self.driver.list_containers() self.assertEqual(len(containers), 3) container = [c for c in containers if c.name == 'container2'][0] self.assertEqual(container.extra['object_count'], 120) self.assertEqual(container.extra['size'], 340084450) def test_list_container_objects(self): CloudFilesMockHttp.type = 'EMPTY' container = Container( name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 0) CloudFilesMockHttp.type = None objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 4) obj = [o for o in objects if o.name == 'foo test 1'][0] self.assertEqual(obj.hash, '16265549b5bda64ecdaa5156de4c97cc') self.assertEqual(obj.size, 1160520) self.assertEqual(obj.container.name, 'test_container') def test_list_container_object_name_encoding(self): CloudFilesMockHttp.type = 'EMPTY' container = Container(name='test container 1', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 0) def test_list_container_objects_with_prefix(self): CloudFilesMockHttp.type = 'EMPTY' container = Container( name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container, ex_prefix='test_prefix1') self.assertEqual(len(objects), 0) CloudFilesMockHttp.type = None objects = self.driver.list_container_objects(container=container, ex_prefix='test_prefix2') self.assertEqual(len(objects), 4) obj = [o for o in objects if o.name == 'foo test 1'][0] self.assertEqual(obj.hash, '16265549b5bda64ecdaa5156de4c97cc') self.assertEqual(obj.size, 1160520) self.assertEqual(obj.container.name, 'test_container') def test_list_container_objects_iterator(self): CloudFilesMockHttp.type = 'ITERATOR' container = Container( name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 5) obj = [o for o in objects if o.name == 'foo-test-1'][0] self.assertEqual(obj.hash, '16265549b5bda64ecdaa5156de4c97cc') self.assertEqual(obj.size, 1160520) self.assertEqual(obj.container.name, 'test_container') def test_get_container(self): container = self.driver.get_container(container_name='test_container') self.assertEqual(container.name, 'test_container') self.assertEqual(container.extra['object_count'], 800) self.assertEqual(container.extra['size'], 1234568) def test_get_container_not_found(self): try: self.driver.get_container(container_name='not_found') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_get_object_success(self): obj = self.driver.get_object(container_name='test_container', object_name='test_object') self.assertEqual(obj.container.name, 'test_container') self.assertEqual(obj.size, 555) self.assertEqual(obj.hash, '6b21c4a111ac178feacf9ec9d0c71f17') self.assertEqual(obj.extra['content_type'], 'application/zip') self.assertEqual( obj.extra['last_modified'], 'Tue, 25 Jan 2011 22:01:49 GMT') self.assertEqual(obj.meta_data['foo-bar'], 'test 1') self.assertEqual(obj.meta_data['bar-foo'], 'test 2') def test_get_object_object_name_encoding(self): obj = self.driver.get_object(container_name='test_container', object_name='~/test_object/') self.assertEqual(obj.name, '~/test_object/') def test_get_object_not_found(self): try: self.driver.get_object(container_name='test_container', object_name='not_found') except ObjectDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_create_container_success(self): container = self.driver.create_container( container_name='test_create_container') self.assertTrue(isinstance(container, Container)) self.assertEqual(container.name, 'test_create_container') self.assertEqual(container.extra['object_count'], 0) def test_create_container_already_exists(self): CloudFilesMockHttp.type = 'ALREADY_EXISTS' try: self.driver.create_container( container_name='test_create_container') except ContainerAlreadyExistsError: pass else: self.fail( 'Container already exists but an exception was not thrown') def test_create_container_invalid_name_too_long(self): name = ''.join(['x' for x in range(0, 257)]) try: self.driver.create_container(container_name=name) except InvalidContainerNameError: pass else: self.fail( 'Invalid name was provided (name is too long)' ', but exception was not thrown') def test_create_container_invalid_name_slashes_in_name(self): try: self.driver.create_container(container_name='test/slashes/') except InvalidContainerNameError: pass else: self.fail( 'Invalid name was provided (name contains slashes)' ', but exception was not thrown') def test_delete_container_success(self): container = Container(name='foo_bar_container', extra={}, driver=self) result = self.driver.delete_container(container=container) self.assertTrue(result) def test_delete_container_not_found(self): CloudFilesMockHttp.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self) try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail( 'Container does not exist but an exception was not thrown') def test_delete_container_not_empty(self): CloudFilesMockHttp.type = 'NOT_EMPTY' container = Container(name='foo_bar_container', extra={}, driver=self) try: self.driver.delete_container(container=container) except ContainerIsNotEmptyError: pass else: self.fail('Container is not empty but an exception was not thrown') def test_download_object_success(self): container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=CloudFilesStorageDriver) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) def test_download_object_invalid_file_size(self): CloudFilesMockHttp.type = 'INVALID_SIZE' container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=CloudFilesStorageDriver) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertFalse(result) def test_download_object_success_not_found(self): CloudFilesMockHttp.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=CloudFilesStorageDriver) destination_path = os.path.abspath(__file__) + '.temp' try: self.driver.download_object( obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) except ObjectDoesNotExistError: pass else: self.fail('Object does not exist but an exception was not thrown') def test_download_object_as_stream(self): container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=CloudFilesStorageDriver) stream = self.driver.download_object_as_stream( obj=obj, chunk_size=None) self.assertTrue(hasattr(stream, '__iter__')) def test_download_object_as_stream_data_is_not_buffered_in_memory(self): # Test case which verifies that response.response attribute is not accessed # and as such, whole body response is not buffered into RAM # If content is consumed and response.content attribute accessed exception # will be thrown and test will fail mock_response = Mock(name='mock response') mock_response.headers = {} mock_response.status = 200 msg1 = '"response" attribute was accessed but it shouldn\'t have been' msg2 = '"content" attribute was accessed but it shouldn\'t have been' type(mock_response).response = PropertyMock(name='mock response attribute', side_effect=Exception(msg1)) type(mock_response).content = PropertyMock(name='mock content attribute', side_effect=Exception(msg2)) mock_response.iter_content.return_value = StringIO('a' * 1000) self.driver.connection.request = Mock() self.driver.connection.request.return_value = mock_response container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object_NO_BUFFER', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver) result = self.driver.download_object_as_stream(obj=obj) result = exhaust_iterator(result) if PY3: result = result.decode('utf-8') self.assertEqual(result, 'a' * 1000) def test_upload_object_success(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(201, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} old_func = CloudFilesStorageDriver._upload_object CloudFilesStorageDriver._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object( file_path=file_path, container=container, extra=extra, object_name=object_name) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, 1000) self.assertTrue('some-value' in obj.meta_data) CloudFilesStorageDriver._upload_object = old_func def test_upload_object_zero_size_object(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(201, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 0, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} old_func = CloudFilesStorageDriver._upload_object CloudFilesStorageDriver._upload_object = upload_file old_request = self.driver.connection.request file_path = os.path.join(os.path.dirname(__file__), '__init__.py') container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'empty' extra = {} def func(*args, **kwargs): self.assertEqual(kwargs['headers']['Content-Length'], 0) func.called = True return old_request(*args, **kwargs) self.driver.connection.request = func func.called = False obj = self.driver.upload_object( file_path=file_path, container=container, extra=extra, object_name=object_name) self.assertEqual(obj.name, 'empty') self.assertEqual(obj.size, 0) CloudFilesStorageDriver._upload_object = old_func self.driver.connection.request = old_request def test_upload_object_invalid_hash(self): CloudFilesMockHttp.type = 'INVALID_HASH' def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(201, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 1000, 'data_hash': 'blah blah'} old_func = CloudFilesStorageDriver._upload_object CloudFilesStorageDriver._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_upload' try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, verify_hash=True) except ObjectHashMismatchError: pass else: self.fail( 'Invalid hash was returned but an exception was not thrown') finally: CloudFilesStorageDriver._upload_object = old_func def test_upload_object_no_content_type(self): def no_content_type(name): return None, None old_func = libcloud.utils.files.guess_file_mime_type libcloud.utils.files.guess_file_mime_type = no_content_type file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_upload' obj = self.driver.upload_object(file_path=file_path, verify_hash=False, container=container, object_name=object_name) self.assertEqual(obj.name, object_name) libcloud.utils.files.guess_file_mime_type = old_func def test_upload_object_inexistent_file(self): def dummy_content_type(name): return 'application/zip', None old_func = libcloud.utils.files.guess_file_mime_type libcloud.utils.files.guess_file_mime_type = dummy_content_type file_path = os.path.abspath(__file__ + '.inexistent') container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_upload' try: self.driver.upload_object( file_path=file_path, container=container, object_name=object_name) except OSError: pass else: self.fail('Inexistent but an exception was not thrown') finally: libcloud.utils.files.guess_file_mime_type = old_func def test_upload_object_via_stream(self): def dummy_content_type(name): return 'application/zip', None old_func = libcloud.utils.files.guess_file_mime_type libcloud.utils.files.guess_file_mime_type = dummy_content_type container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_stream_data' iterator = BytesIO(b('235')) try: self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator) finally: libcloud.utils.files.guess_file_mime_type = old_func def test_upload_object_via_stream_stream_seek_at_end(self): def dummy_content_type(name): return 'application/zip', None old_func = libcloud.utils.files.guess_file_mime_type libcloud.utils.files.guess_file_mime_type = dummy_content_type container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_stream_data_seek' iterator = BytesIO(b('123456789')) iterator.seek(10) self.assertEqual(iterator.tell(), 10) try: self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator) finally: libcloud.utils.files.guess_file_mime_type = old_func def test_delete_object_success(self): container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=CloudFilesStorageDriver) status = self.driver.delete_object(obj=obj) self.assertTrue(status) def test_delete_object_not_found(self): CloudFilesMockHttp.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=CloudFilesStorageDriver) try: self.driver.delete_object(obj=obj) except ObjectDoesNotExistError: pass else: self.fail('Object does not exist but an exception was not thrown') def test_ex_get_meta_data(self): meta_data = self.driver.ex_get_meta_data() self.assertTrue(isinstance(meta_data, dict)) self.assertTrue('object_count' in meta_data) self.assertTrue('container_count' in meta_data) self.assertTrue('bytes_used' in meta_data) self.assertTrue('temp_url_key' in meta_data) def test_ex_purge_object_from_cdn(self): CloudFilesMockHttp.type = 'PURGE_SUCCESS' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self) self.assertTrue(self.driver.ex_purge_object_from_cdn(obj=obj)) def test_ex_purge_object_from_cdn_with_email(self): CloudFilesMockHttp.type = 'PURGE_SUCCESS_EMAIL' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self) self.assertTrue(self.driver.ex_purge_object_from_cdn(obj=obj, email='test@test.com')) @mock.patch('os.path.getsize') def test_ex_multipart_upload_object_for_small_files(self, getsize_mock): getsize_mock.return_value = 0 old_func = CloudFilesStorageDriver.upload_object mocked_upload_object = mock.Mock(return_value="test") CloudFilesStorageDriver.upload_object = mocked_upload_object file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_upload' obj = self.driver.ex_multipart_upload_object( file_path=file_path, container=container, object_name=object_name) CloudFilesStorageDriver.upload_object = old_func self.assertTrue(mocked_upload_object.called) self.assertEqual(obj, "test") def test_ex_multipart_upload_object_success(self): _upload_object_part = CloudFilesStorageDriver._upload_object_part _upload_object_manifest = CloudFilesStorageDriver._upload_object_manifest mocked__upload_object_part = mock.Mock(return_value="test_part") mocked__upload_object_manifest = mock.Mock( return_value="test_manifest") CloudFilesStorageDriver._upload_object_part = mocked__upload_object_part CloudFilesStorageDriver._upload_object_manifest = mocked__upload_object_manifest parts = 5 file_path = os.path.abspath(__file__) chunk_size = int(math.ceil(float(os.path.getsize(file_path)) / parts)) container = Container(name='foo_bar_container', extra={}, driver=self) object_name = 'foo_test_upload' self.driver.ex_multipart_upload_object( file_path=file_path, container=container, object_name=object_name, chunk_size=chunk_size) CloudFilesStorageDriver._upload_object_part = _upload_object_part CloudFilesStorageDriver._upload_object_manifest = _upload_object_manifest self.assertEqual(mocked__upload_object_part.call_count, parts) self.assertTrue(mocked__upload_object_manifest.call_count, 1) def test__upload_object_part(self): _put_object = CloudFilesStorageDriver._put_object mocked__put_object = mock.Mock(return_value="test") CloudFilesStorageDriver._put_object = mocked__put_object part_number = 7 object_name = "test_object" expected_name = object_name + '/%08d' % part_number container = Container(name='foo_bar_container', extra={}, driver=self) self.driver._upload_object_part(container, object_name, part_number, None) CloudFilesStorageDriver._put_object = _put_object func_kwargs = tuple(mocked__put_object.call_args)[1] self.assertEqual(func_kwargs['object_name'], expected_name) self.assertEqual(func_kwargs['container'], container) def test_upload_object_via_stream_with_cors_headers(self): """ Test we can add some ``Cross-origin resource sharing`` headers to the request about to be sent. """ cors_headers = { 'Access-Control-Allow-Origin': 'http://mozilla.com', 'Origin': 'http://storage.clouddrive.com', } expected_headers = { # Automatically added headers 'Content-Type': 'application/octet-stream' } expected_headers.update(cors_headers) def intercept_request(request_path, method=None, data=None, headers=None, raw=True): # What we're actually testing self.assertDictEqual(expected_headers, headers) raise NotImplementedError('oops') self.driver.connection.request = intercept_request container = Container(name='CORS', extra={}, driver=self.driver) try: self.driver.upload_object_via_stream( iterator=iter(b'blob data like an image or video'), container=container, object_name="test_object", headers=cors_headers, ) except NotImplementedError: # Don't care about the response we'd have to mock anyway # as long as we intercepted the request and checked its headers pass else: self.fail('Expected NotImplementedError to be thrown to ' 'verify we actually checked the expected headers') def test_upload_object_via_stream_python3_bytes_error(self): container = Container(name='py3', extra={}, driver=self.driver) bytes_blob = b'blob data like an image or video' # This is mostly to check we didn't discover other errors along the way mocked_response = container.upload_object_via_stream( iterator=iter(bytes_blob), object_name="img_or_vid", ) self.assertEqual(len(bytes_blob), mocked_response.size) @unittest.skip("Skipping as chunking is disabled in 2.0rc1") def test_upload_object_via_stream_chunked_encoding(self): # Create enough bytes it should get split into two chunks bytes_blob = ''.join(['\0' for _ in range(CHUNK_SIZE + 1)]) hex_chunk_size = ('%X' % CHUNK_SIZE).encode('utf8') expected = [ # Chunk 1 hex_chunk_size + b'\r\n', bytes(bytes_blob[:CHUNK_SIZE].encode('utf8')), b'\r\n', # Chunk 2 b'1\r\n', bytes(bytes_blob[CHUNK_SIZE:].encode('utf8')), b'\r\n', # If chunked, also send a final message b'0\r\n\r\n', ] logged_data = [] class InterceptResponse(MockHttp): def __init__(self, connection, response=None): super(InterceptResponse, self).__init__(connection=connection, response=response) old_send = self.connection.connection.send def intercept_send(data): old_send(data) logged_data.append(data) self.connection.connection.send = intercept_send def _v1_MossoCloudFS_py3_img_or_vid2(self, method, url, body, headers): headers = {'etag': 'd79fb00c27b50494a463e680d459c90c'} headers.update(self.base_headers) _201 = httplib.CREATED return _201, '', headers, httplib.responses[_201] self.driver_klass.connectionCls.rawResponseCls = InterceptResponse container = Container(name='py3', extra={}, driver=self.driver) container.upload_object_via_stream( iterator=iter(bytes_blob), object_name="img_or_vid2", ) self.assertListEqual(expected, logged_data) def test__upload_object_manifest(self): hash_function = self.driver._get_hash_function() hash_function.update(b('')) data_hash = hash_function.hexdigest() fake_response = type('CloudFilesResponse', (), {'headers': {'etag': data_hash} }) _request = self.driver.connection.request mocked_request = mock.Mock(return_value=fake_response) self.driver.connection.request = mocked_request container = Container(name='foo_bar_container', extra={}, driver=self) object_name = "test_object" self.driver._upload_object_manifest(container, object_name) func_args, func_kwargs = tuple(mocked_request.call_args) self.driver.connection.request = _request self.assertEqual( func_args[0], "/" + container.name + "/" + object_name) self.assertEqual(func_kwargs["headers"]["X-Object-Manifest"], container.name + "/" + object_name + "/") self.assertEqual(func_kwargs["method"], "PUT") def test__upload_object_manifest_wrong_hash(self): fake_response = type('CloudFilesResponse', (), {'headers': {'etag': '0000000'}}) _request = self.driver.connection.request mocked_request = mock.Mock(return_value=fake_response) self.driver.connection.request = mocked_request container = Container(name='foo_bar_container', extra={}, driver=self) object_name = "test_object" try: self.driver._upload_object_manifest(container, object_name) except ObjectHashMismatchError: pass else: self.fail('Exception was not thrown') finally: self.driver.connection.request = _request def test_create_container_put_object_name_encoding(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(201, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} old_func = CloudFilesStorageDriver._upload_object CloudFilesStorageDriver._upload_object = upload_file container_name = 'speci@l_name' object_name = 'm@obj€ct' file_path = os.path.abspath(__file__) container = self.driver.create_container(container_name=container_name) self.assertEqual(container.name, container_name) obj = self.driver.upload_object( file_path=file_path, container=container, object_name=object_name) self.assertEqual(obj.name, object_name) CloudFilesStorageDriver._upload_object = old_func def test_ex_enable_static_website(self): container = Container(name='foo_bar_container', extra={}, driver=self) result = self.driver.ex_enable_static_website(container=container, index_file='index.html') self.assertTrue(result) def test_ex_set_error_page(self): container = Container(name='foo_bar_container', extra={}, driver=self) result = self.driver.ex_set_error_page(container=container, file_name='error.html') self.assertTrue(result) def test_ex_set_account_metadata_temp_url_key(self): result = self.driver.ex_set_account_metadata_temp_url_key("a key") self.assertTrue(result) @mock.patch("libcloud.storage.drivers.cloudfiles.time") def test_ex_get_object_temp_url(self, time): time.return_value = 0 self.driver.ex_get_meta_data = mock.Mock() self.driver.ex_get_meta_data.return_value = {'container_count': 1, 'object_count': 1, 'bytes_used': 1, 'temp_url_key': 'foo'} container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self) hmac_body = "%s\n%s\n%s" % ('GET', 60, "/v1/MossoCloudFS/foo_bar_container/foo_bar_object") sig = hmac.new(b('foo'), b(hmac_body), sha1).hexdigest() ret = self.driver.ex_get_object_temp_url(obj, 'GET') temp_url = ('https://storage4.%s1.clouddrive.com/v1/MossoCloudFS/' 'foo_bar_container/foo_bar_object?temp_url_expires=60&temp_url_sig=%s' % (self.region, sig)) self.assertEqual(''.join(sorted(ret)), ''.join(sorted(temp_url))) def test_ex_get_object_temp_url_no_key_raises_key_error(self): self.driver.ex_get_meta_data = mock.Mock() self.driver.ex_get_meta_data.return_value = {'container_count': 1, 'object_count': 1, 'bytes_used': 1, 'temp_url_key': None} container = Container(name='foo_bar_container', extra={}, driver=self) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self) self.assertRaises( KeyError, self.driver.ex_get_object_temp_url, obj, 'GET') def _remove_test_file(self): file_path = os.path.abspath(__file__) + '.temp' try: os.unlink(file_path) except OSError: pass class CloudFilesDeprecatedUSTests(CloudFilesTests): driver_klass = CloudFilesStorageDriver region = 'ord' class CloudFilesDeprecatedUKTests(CloudFilesTests): driver_klass = CloudFilesStorageDriver region = 'lon' class CloudFilesMockHttp(MockHttp, unittest.TestCase): fixtures = StorageFileFixtures('cloudfiles') base_headers = {'content-type': 'application/json; charset=UTF-8'} # fake auth token response def _v2_0_tokens(self, method, url, body, headers): headers = copy.deepcopy(self.base_headers) body = self.fixtures.load('_v2_0__auth.json') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_MALFORMED_JSON(self, method, url, body, headers): # test_invalid_json_throws_exception body = 'broken: json /*"' return (httplib.NO_CONTENT, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_EMPTY(self, method, url, body, headers): return (httplib.NO_CONTENT, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS(self, method, url, body, headers): headers = copy.deepcopy(self.base_headers) if method == 'GET': # list_containers body = self.fixtures.load('list_containers.json') status_code = httplib.OK elif method == 'HEAD': # get_meta_data body = self.fixtures.load('meta_data.json') status_code = httplib.NO_CONTENT headers.update({'x-account-container-count': '10', 'x-account-object-count': '400', 'x-account-bytes-used': '1234567' }) elif method == 'POST': body = '' status_code = httplib.NO_CONTENT return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_not_found(self, method, url, body, headers): # test_get_object_not_found if method == 'HEAD': body = '' else: raise ValueError('Invalid method') return (httplib.NOT_FOUND, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_container_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_container_objects_empty.json') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_20container_201_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_container_objects_empty.json') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_container(self, method, url, body, headers): headers = copy.deepcopy(self.base_headers) if method == 'GET': # list_container_objects if url.find('marker') == -1: body = self.fixtures.load('list_container_objects.json') status_code = httplib.OK else: body = '' status_code = httplib.NO_CONTENT elif method == 'HEAD': # get_container body = self.fixtures.load('list_container_objects_empty.json') status_code = httplib.NO_CONTENT headers.update({'x-container-object-count': '800', 'x-container-bytes-used': '1234568' }) return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_container_ITERATOR(self, method, url, body, headers): headers = copy.deepcopy(self.base_headers) # list_container_objects if url.find('foo-test-3') != -1: body = self.fixtures.load( 'list_container_objects_not_exhausted2.json') status_code = httplib.OK elif url.find('foo-test-5') != -1: body = '' status_code = httplib.NO_CONTENT else: # First request body = self.fixtures.load( 'list_container_objects_not_exhausted1.json') status_code = httplib.OK return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_container_not_found( self, method, url, body, headers): # test_get_container_not_found if method == 'HEAD': body = '' else: raise ValueError('Invalid method') return (httplib.NOT_FOUND, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_container_test_object( self, method, url, body, headers): headers = copy.deepcopy(self.base_headers) if method == 'HEAD': # get_object body = self.fixtures.load('list_container_objects_empty.json') status_code = httplib.NO_CONTENT headers.update({'content-length': '555', 'last-modified': 'Tue, 25 Jan 2011 22:01:49 GMT', 'etag': '6b21c4a111ac178feacf9ec9d0c71f17', 'x-object-meta-foo-bar': 'test 1', 'x-object-meta-bar-foo': 'test 2', 'content-type': 'application/zip'}) return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_container__7E_test_object( self, method, url, body, headers): headers = copy.deepcopy(self.base_headers) if method == 'HEAD': # get_object_name_encoding body = self.fixtures.load('list_container_objects_empty.json') status_code = httplib.NO_CONTENT headers.update({'content-length': '555', 'last-modified': 'Tue, 25 Jan 2011 22:01:49 GMT', 'etag': '6b21c4a111ac178feacf9ec9d0c71f17', 'x-object-meta-foo-bar': 'test 1', 'x-object-meta-bar-foo': 'test 2', 'content-type': 'application/zip'}) return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_create_container( self, method, url, body, headers): # test_create_container_success headers = copy.deepcopy(self.base_headers) body = self.fixtures.load('list_container_objects_empty.json') headers = copy.deepcopy(self.base_headers) headers.update({'content-length': '18', 'date': 'Mon, 28 Feb 2011 07:52:57 GMT' }) status_code = httplib.CREATED return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_speci_40l_name(self, method, url, body, headers): # test_create_container_put_object_name_encoding # Verify that the name is properly url encoded container_name = 'speci@l_name' encoded_container_name = urlquote(container_name) self.assertTrue(encoded_container_name in url) headers = copy.deepcopy(self.base_headers) body = self.fixtures.load('list_container_objects_empty.json') headers = copy.deepcopy(self.base_headers) headers.update({'content-length': '18', 'date': 'Mon, 28 Feb 2011 07:52:57 GMT' }) status_code = httplib.CREATED return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_test_create_container_ALREADY_EXISTS( self, method, url, body, headers): # test_create_container_already_exists headers = copy.deepcopy(self.base_headers) body = self.fixtures.load('list_container_objects_empty.json') headers.update({'content-type': 'text/plain'}) status_code = httplib.ACCEPTED return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container(self, method, url, body, headers): if method == 'DELETE': # test_delete_container_success body = self.fixtures.load('list_container_objects_empty.json') headers = self.base_headers status_code = httplib.NO_CONTENT elif method == 'POST': # test_ex_enable_static_website body = '' headers = self.base_headers status_code = httplib.ACCEPTED return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_object_PURGE_SUCCESS( self, method, url, body, headers): if method == 'DELETE': # test_ex_purge_from_cdn headers = self.base_headers status_code = httplib.NO_CONTENT return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_object_PURGE_SUCCESS_EMAIL( self, method, url, body, headers): if method == 'DELETE': # test_ex_purge_from_cdn_with_email self.assertEqual(headers['X-Purge-Email'], 'test@test.com') headers = self.base_headers status_code = httplib.NO_CONTENT return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_NOT_FOUND( self, method, url, body, headers): if method == 'DELETE': # test_delete_container_not_found body = self.fixtures.load('list_container_objects_empty.json') headers = self.base_headers status_code = httplib.NOT_FOUND return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_NOT_EMPTY( self, method, url, body, headers): if method == 'DELETE': # test_delete_container_not_empty body = self.fixtures.load('list_container_objects_empty.json') headers = self.base_headers status_code = httplib.CONFLICT return (status_code, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_foo_bar_object( self, method, url, body, headers): if method == 'DELETE': # test_delete_object_success body = self.fixtures.load('list_container_objects_empty.json') headers = self.base_headers status_code = httplib.NO_CONTENT return (status_code, body, headers, httplib.responses[httplib.OK]) elif method == 'GET': body = generate_random_data(1000) return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_py3_img_or_vid(self, method, url, body, headers): headers = {'etag': 'e2378cace8712661ce7beec3d9362ef6'} headers.update(self.base_headers) return httplib.CREATED, '', headers, httplib.responses[httplib.CREATED] def _v1_MossoCloudFS_foo_bar_container_foo_test_upload( self, method, url, body, headers): # test_object_upload_success body = '' headers = {} headers.update(self.base_headers) headers['etag'] = 'hash343hhash89h932439jsaa89' return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_speci_40l_name_m_40obj_E2_82_ACct(self, method, url, body, headers): # test_create_container_put_object_name_encoding # Verify that the name is properly url encoded object_name = 'm@obj€ct' urlquote(object_name) headers = copy.deepcopy(self.base_headers) body = '' headers['etag'] = 'hash343hhash89h932439jsaa89' return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_empty(self, method, url, body, headers): # test_upload_object_zero_size_object body = '' headers = {} headers.update(self.base_headers) headers['etag'] = 'hash343hhash89h932439jsaa89' return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_foo_test_upload_INVALID_HASH( self, method, url, body, headers): # test_object_upload_invalid_hash body = '' headers = {} headers.update(self.base_headers) headers['etag'] = 'foobar' return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_foo_bar_object_INVALID_SIZE( self, method, url, body, headers): # test_download_object_invalid_file_size body = generate_random_data(100) return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_foo_bar_object_NOT_FOUND( self, method, url, body, headers): body = '' return (httplib.NOT_FOUND, body, self.base_headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_foo_test_stream_data( self, method, url, body, headers): # test_upload_object_via_stream_success hasher = hashlib.md5() hasher.update(b'235') hash_value = hasher.hexdigest() headers = {} headers.update(self.base_headers) headers['etag'] = hash_value body = 'test' return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_foo_test_stream_data_seek( self, method, url, body, headers): # test_upload_object_via_stream_stream_seek_at_end hasher = hashlib.md5() hasher.update(b'123456789') hash_value = hasher.hexdigest() headers = {} headers.update(self.base_headers) headers['etag'] = hash_value body = 'test' return (httplib.CREATED, body, headers, httplib.responses[httplib.OK]) def _v1_MossoCloudFS_foo_bar_container_foo_bar_object_NO_BUFFER( self, method, url, body, headers): # test_download_object_data_is_not_buffered_in_memory headers = {} headers.update(self.base_headers) headers['etag'] = '577ef1154f3240ad5b9b413aa7346a1e' body = generate_random_data(1000) return (httplib.OK, body, headers, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_digitalocean_spaces.py0000664000175000017500000001231413535474530026247 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.common.types import LibcloudError from libcloud.storage.base import Container, Object from libcloud.storage.drivers.digitalocean_spaces import ( DigitalOceanSpacesStorageDriver, DOSpacesConnectionAWS4, DOSpacesConnectionAWS2) from libcloud.test import LibcloudTestCase from libcloud.test.secrets import STORAGE_S3_PARAMS class DigitalOceanSpacesTests(LibcloudTestCase): driver_type = DigitalOceanSpacesStorageDriver driver_args = STORAGE_S3_PARAMS default_host = 'nyc3.digitaloceanspaces.com' @classmethod def create_driver(self): return self.driver_type(*self.driver_args, signature_version='2', host=self.default_host) def setUp(self): self.driver = self.create_driver() self.container = Container('test-container', {}, self.driver) self.object = Object('test-object', 1, 'hash', {}, 'meta_data', self.container, self.driver) def test_connection_class_type(self): res = self.driver.connectionCls is DOSpacesConnectionAWS2 self.assertTrue(res, 'driver.connectionCls does not match!') def test_connection_class_host(self): host = self.driver.connectionCls.host self.assertEqual(host, self.default_host) def test_container_enable_cdn_not_implemented(self): with self.assertRaises(NotImplementedError): self.container.enable_cdn() def test_container_get_cdn_url_not_implemented(self): with self.assertRaises(NotImplementedError): self.container.get_cdn_url() def test_object_enable_cdn_not_implemented(self): with self.assertRaises(NotImplementedError): self.object.enable_cdn() def test_object_get_cdn_url_not_implemented(self): with self.assertRaises(NotImplementedError): self.object.get_cdn_url() def test_invalid_signature_version(self): with self.assertRaises(ValueError): self.driver_type(*self.driver_args, signature_version='3', host=self.default_host) def test_invalid_region(self): with self.assertRaises(LibcloudError): self.driver_type(*self.driver_args, region='atlantis', host=self.default_host) class DigitalOceanSpacesTests_v4(DigitalOceanSpacesTests): driver_type = DigitalOceanSpacesStorageDriver driver_args = STORAGE_S3_PARAMS default_host = 'nyc3.digitaloceanspaces.com' @classmethod def create_driver(self): return self.driver_type(*self.driver_args, signature_version='4') def test_connection_class_type(self): res = self.driver.connectionCls is DOSpacesConnectionAWS4 self.assertTrue(res, 'driver.connectionCls does not match!') def test_connection_class_host(self): host = self.driver.connectionCls.host self.assertEqual(host, self.default_host) class DigitalOceanSpacesDoubleInstanceTests(LibcloudTestCase): driver_type = DigitalOceanSpacesStorageDriver driver_args = STORAGE_S3_PARAMS default_host = 'nyc3.digitaloceanspaces.com' alt_host = 'ams3.digitaloceanspaces.com' def setUp(self): self.driver_v2 = self.driver_type(*self.driver_args, signature_version='2') self.driver_v4 = self.driver_type(*self.driver_args, signature_version='4', region='ams3') def test_connection_class_type(self): res = self.driver_v2.connectionCls is DOSpacesConnectionAWS2 self.assertTrue(res, 'driver.connectionCls does not match!') res = self.driver_v4.connectionCls is DOSpacesConnectionAWS4 self.assertTrue(res, 'driver.connectionCls does not match!') # Verify again that connection class hasn't been overriden when # instantiating a second driver class res = self.driver_v2.connectionCls is DOSpacesConnectionAWS2 self.assertTrue(res, 'driver.connectionCls does not match!') def test_connection_class_host(self): host = self.driver_v2.connectionCls.host self.assertEqual(host, self.default_host) host = self.driver_v4.connectionCls.host self.assertEqual(host, self.alt_host) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_dummy.py0000664000175000017500000000401513570310635023412 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import pytest from libcloud.storage.drivers.dummy import DummyStorageDriver @pytest.fixture def driver(): return DummyStorageDriver('key', 'id') @pytest.fixture def container_with_contents(driver): container_name = 'test' object_name = 'test.dat' container = driver.create_container(container_name=container_name) driver.upload_object( __file__, container=container, object_name=object_name ) return container_name, object_name def test_list_container_objects(driver, container_with_contents): container_name, object_name = container_with_contents container = driver.get_container(container_name) objects = driver.list_container_objects(container=container) assert any(o for o in objects if o.name == object_name) def test_list_container_objects_filter_by_prefix( driver, container_with_contents ): container_name, object_name = container_with_contents container = driver.get_container(container_name) objects = driver.list_container_objects( container=container, ex_prefix=object_name[:3] ) assert any(o for o in objects if o.name == object_name) objects = driver.list_container_objects( container=container, ex_prefix='does-not-exist.dat' ) assert not objects apache-libcloud-2.8.0/libcloud/test/storage/test_google_storage.py0000664000175000017500000005172013535474530025272 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import copy import json import mock import re import sys import unittest from io import BytesIO import email.utils import pytest from mock import Mock from mock import PropertyMock from libcloud.common.google import GoogleAuthType from libcloud.common.types import InvalidCredsError from libcloud.storage.base import Container from libcloud.storage.base import Object from libcloud.storage.drivers import google_storage from libcloud.test import StorageMockHttp from libcloud.test.common.test_google import GoogleTestCase from libcloud.test.file_fixtures import StorageFileFixtures from libcloud.test.secrets import STORAGE_GOOGLE_STORAGE_PARAMS from libcloud.test.storage.test_s3 import S3Tests, S3MockHttp from libcloud.utils.py3 import httplib from libcloud.utils.py3 import StringIO CONN_CLS = google_storage.GoogleStorageConnection JSON_CONN_CLS = google_storage.GoogleStorageJSONConnection TODAY = email.utils.formatdate(usegmt=True) def _error_helper(code, headers): message = httplib.responses[code] body = { 'error': { 'errors': [ { 'code': code, 'message': message, 'reason': message, }, ], }, } return code, json.dumps(body), headers, httplib.responses[code] class GoogleStorageMockHttp(S3MockHttp): fixtures = StorageFileFixtures('google_storage') def _test2_test_get_object(self, method, url, body, headers): # test_get_object # Google uses a different HTTP header prefix for meta data body = self.fixtures.load('list_containers.xml') headers = { 'content-type': 'application/zip', 'etag': '"e31208wqsdoj329jd"', 'x-goog-meta-rabbits': 'monkeys', 'content-length': '12345', 'last-modified': 'Thu, 13 Sep 2012 07:13:22 GMT' } return httplib.OK, body, headers, httplib.responses[httplib.OK] def _container_path_UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, '', self.base_headers, httplib.responses[httplib.OK]) class GoogleStorageJSONMockHttp(StorageMockHttp): """ Extracts bucket and object out of requests and routes to methods of the forms (bucket, object, entity, and type are sanitized values {'-', '.', '/' are replaced with '_'}): _[_] __acl[_entity][_] __defaultObjectAcl[_][_] __[_] ___acl[_][_] Ugly example: /storage/v1/b/test-bucket/o/test-object/acl/test-entity with type='FOO' yields _test_bucket_test_object_acl_test_entity_FOO """ fixtures = StorageFileFixtures('google_storage') base_headers = {} # Path regex captures bucket, object, defaultObjectAcl, and acl values. path_rgx = re.compile( r'/storage/[^/]+/b/([^/]+)' r'(?:/(defaultObjectAcl(?:/[^/]+)?$)|' r'(?:/o/(.+?))?(?:/(acl(?:/[^/]+)?))?$)') # Permissions to use when handling requests. bucket_perms = google_storage.ContainerPermissions.NONE object_perms = google_storage.ObjectPermissions.NONE _FORBIDDEN = _error_helper(httplib.FORBIDDEN, base_headers) _NOT_FOUND = _error_helper(httplib.NOT_FOUND, base_headers) _PRECONDITION_FAILED = _error_helper( httplib.PRECONDITION_FAILED, base_headers) def _get_method_name(self, type, use_param, qs, path): match = self.path_rgx.match(path) if not match: raise ValueError('%s is not a valid path.' % path) joined_groups = '_'.join([g for g in match.groups() if g]) if type: meth_name = '_%s_%s' % (joined_groups, type) else: meth_name = '_%s' % joined_groups # Return sanitized method name. return meth_name.replace('/', '_').replace('.', '_').replace('-', '_') def _response_helper(self, fixture): body = self.fixtures.load(fixture) return httplib.OK, body, {}, httplib.responses[httplib.OK] #################### # Request handlers # #################### def _test_bucket(self, method, url, body, headers): """Bucket request.""" if method != 'GET': raise NotImplementedError('%s is not implemented.' % method) if self.bucket_perms < google_storage.ContainerPermissions.READER: return self._FORBIDDEN else: return self._response_helper('get_container.json') def _test_bucket_acl(self, method, url, body, headers): """Bucket list ACL request.""" if method != 'GET': raise NotImplementedError('%s is not implemented.' % method) if self.bucket_perms < google_storage.ContainerPermissions.OWNER: return self._FORBIDDEN else: return self._response_helper('list_container_acl.json') def _test_bucket_test_object(self, method, url, body, headers): """Object request.""" if method != 'GET': raise NotImplementedError('%s is not implemented.' % method) if self.object_perms < google_storage.ObjectPermissions.READER: return self._FORBIDDEN else: return self._response_helper('get_object.json') def _test_bucket_test_object_acl(self, method, url, body, headers): """Object list ACL request.""" if method != 'GET': raise NotImplementedError('%s is not implemented.' % method) if self.object_perms < google_storage.ObjectPermissions.OWNER: return self._FORBIDDEN else: return self._response_helper('list_object_acl.json') def _test_bucket_writecheck(self, method, url, body, headers): gen_match = headers.get('x-goog-if-generation-match') if method != 'DELETE' or gen_match != '0': msg = ('Improper write check delete strategy. method: %s, ' 'headers: %s' % (method, headers)) raise ValueError(msg) if self.bucket_perms < google_storage.ContainerPermissions.WRITER: return self._FORBIDDEN else: return self._PRECONDITION_FAILED class GoogleStorageConnectionTest(GoogleTestCase): @mock.patch('email.utils.formatdate') def test_add_default_headers(self, mock_formatdate): mock_formatdate.return_value = TODAY starting_headers = {'starting': 'headers'} project = 'foo-project' # Modify headers when there is no project. conn = CONN_CLS( 'foo_user', 'bar_key', secure=True, auth_type=GoogleAuthType.GCS_S3) conn.get_project = mock.Mock(return_value=None) headers = dict(starting_headers) headers['Date'] = TODAY self.assertEqual( conn.add_default_headers(dict(starting_headers)), headers) # Modify headers when there is a project. conn = CONN_CLS( 'foo_user', 'bar_key', secure=True, auth_type=GoogleAuthType.GCS_S3) conn.get_project = mock.Mock(return_value=project) headers = dict(starting_headers) headers['Date'] = TODAY headers[CONN_CLS.PROJECT_ID_HEADER] = project self.assertEqual( conn.add_default_headers(dict(starting_headers)), headers) @mock.patch('libcloud.storage.drivers.s3.' 'BaseS3Connection.get_auth_signature') def test_get_s3_auth_signature(self, mock_s3_auth_sig_method): # Check that the S3 HMAC signature method is used. # Check that headers are copied and modified properly before calling # the signature method. mock_s3_auth_sig_method.return_value = 'mock signature!' starting_params = {} starting_headers = { 'Date': TODAY, 'x-goog-foo': 'X-GOOG: MAINTAIN UPPERCASE!', 'x-Goog-bar': 'Header key should be lowered', 'Other': 'LOWER THIS!' } modified_headers = { 'date': TODAY, 'x-goog-foo': 'X-GOOG: MAINTAIN UPPERCASE!', 'x-goog-bar': 'Header key should be lowered', 'other': 'lower this!' } conn = CONN_CLS( 'foo_user', 'bar_key', secure=True, auth_type=GoogleAuthType.GCS_S3) conn.method = 'GET' conn.action = '/path' result = conn._get_s3_auth_signature(starting_params, starting_headers) self.assertNotEqual(starting_headers, modified_headers) self.assertEqual(result, 'mock signature!') mock_s3_auth_sig_method.assert_called_once_with( method='GET', headers=modified_headers, params=starting_params, expires=None, secret_key='bar_key', path='/path', vendor_prefix='x-goog' ) @mock.patch('libcloud.common.google.GoogleOAuth2Credential') def test_pre_connect_hook_oauth2(self, mock_oauth2_credential_init): # Check that we get the Authorization header from the OAuth2 token, # not from the HMAC signature method. # Check that the headers and pa mock_oauth2_credential_init.return_value = mock.Mock() starting_params = {'starting': 'params'} starting_headers = {'starting': 'headers'} conn = CONN_CLS( 'foo_user', 'bar_key', secure=True, auth_type=GoogleAuthType.GCE) conn._get_s3_auth_signature = mock.Mock() conn.oauth2_credential = mock.Mock() conn.oauth2_credential.access_token = 'Access_Token!' expected_headers = dict(starting_headers) expected_headers['Authorization'] = 'Bearer Access_Token!' result = conn.pre_connect_hook( dict(starting_params), dict(starting_headers)) self.assertEqual(result, (starting_params, expected_headers)) def test_pre_connect_hook_hmac(self): # Check that we call for a HMAC signature, passing params and headers # Check that we properly apply the HMAC signature. # Check that we don't use OAuth2 credentials. starting_params = {'starting': 'params'} starting_headers = {'starting': 'headers'} def fake_hmac_method(params, headers): # snapshot the params and headers passed (they are modified later) fake_hmac_method.params_passed = copy.deepcopy(params) fake_hmac_method.headers_passed = copy.deepcopy(headers) return 'fake signature!' conn = CONN_CLS( 'foo_user', 'bar_key', secure=True, auth_type=GoogleAuthType.GCS_S3) conn._get_s3_auth_signature = fake_hmac_method conn.action = 'GET' conn.method = '/foo' expected_headers = dict(starting_headers) expected_headers['Authorization'] = ( '%s %s:%s' % (google_storage.SIGNATURE_IDENTIFIER, 'foo_user', 'fake signature!') ) result = conn.pre_connect_hook( dict(starting_params), dict(starting_headers)) self.assertEqual(result, (dict(starting_params), expected_headers)) self.assertEqual(fake_hmac_method.params_passed, starting_params) self.assertEqual(fake_hmac_method.headers_passed, starting_headers) self.assertIsNone(conn.oauth2_credential) class GoogleStorageTests(S3Tests, GoogleTestCase): driver_type = google_storage.GoogleStorageDriver driver_args = STORAGE_GOOGLE_STORAGE_PARAMS mock_response_klass = GoogleStorageMockHttp def setUp(self): super(GoogleStorageTests, self).setUp() self.driver_type.jsonConnectionCls.conn_class = GoogleStorageJSONMockHttp def tearDown(self): self._remove_test_file() def test_billing_not_enabled(self): # TODO pass def test_token(self): # Not supported on Google Storage pass def test_delete_permissions(self): mock_request = mock.Mock() self.driver.json_connection.request = mock_request # Test deleting object permissions. self.driver.ex_delete_permissions( 'bucket', 'object', entity='user-foo') url = '/storage/v1/b/bucket/o/object/acl/user-foo' mock_request.assert_called_once_with(url, method='DELETE') # Test deleting bucket permissions. mock_request.reset_mock() self.driver.ex_delete_permissions('bucket', entity='user-foo') url = '/storage/v1/b/bucket/acl/user-foo' mock_request.assert_called_once_with(url, method='DELETE') def test_delete_permissions_no_entity(self): mock_request = mock.Mock() mock_get_user = mock.Mock(return_value=None) self.driver._get_user = mock_get_user self.driver.json_connection.request = mock_request # Test deleting permissions on an object with no entity. self.assertRaises( ValueError, self.driver.ex_delete_permissions, 'bucket', 'object') # Test deleting permissions on an bucket with no entity. self.assertRaises( ValueError, self.driver.ex_delete_permissions, 'bucket') mock_request.assert_not_called() # Test deleting permissions on an object with a default entity. mock_get_user.return_value = 'foo@foo.com' self.driver.ex_delete_permissions('bucket', 'object') url = '/storage/v1/b/bucket/o/object/acl/user-foo@foo.com' mock_request.assert_called_once_with(url, method='DELETE') # Test deleting permissions on an bucket with a default entity. mock_request.reset_mock() mock_get_user.return_value = 'foo@foo.com' self.driver.ex_delete_permissions('bucket') url = '/storage/v1/b/bucket/acl/user-foo@foo.com' mock_request.assert_called_once_with(url, method='DELETE') def test_get_permissions(self): def test_permission_config(bucket_perms, object_perms): GoogleStorageJSONMockHttp.bucket_perms = bucket_perms GoogleStorageJSONMockHttp.object_perms = object_perms perms = self.driver.ex_get_permissions( 'test-bucket', 'test-object') self.assertEqual(perms, (bucket_perms, object_perms)) bucket_levels = range(len(google_storage.ContainerPermissions.values)) object_levels = range(len(google_storage.ObjectPermissions.values)) for bucket_perms in bucket_levels: for object_perms in object_levels: test_permission_config(bucket_perms, object_perms) def test_set_permissions(self): mock_request = mock.Mock() self.driver.json_connection.request = mock_request # Test setting object permissions. self.driver.ex_set_permissions( 'bucket', 'object', entity='user-foo', role='OWNER') url = '/storage/v1/b/bucket/o/object/acl' mock_request.assert_called_once_with( url, method='POST', data=json.dumps({'role': 'OWNER', 'entity': 'user-foo'})) # Test setting object permissions with an ObjectPermissions value. mock_request.reset_mock() self.driver.ex_set_permissions( 'bucket', 'object', entity='user-foo', role=google_storage.ObjectPermissions.OWNER) url = '/storage/v1/b/bucket/o/object/acl' mock_request.assert_called_once_with( url, method='POST', data=json.dumps({'role': 'OWNER', 'entity': 'user-foo'})) # Test setting bucket permissions. mock_request.reset_mock() self.driver.ex_set_permissions( 'bucket', entity='user-foo', role='OWNER') url = '/storage/v1/b/bucket/acl' mock_request.assert_called_once_with( url, method='POST', data=json.dumps({'role': 'OWNER', 'entity': 'user-foo'})) # Test setting bucket permissions with a ContainerPermissions value. mock_request.reset_mock() self.driver.ex_set_permissions( 'bucket', entity='user-foo', role=google_storage.ContainerPermissions.OWNER) url = '/storage/v1/b/bucket/acl' mock_request.assert_called_once_with( url, method='POST', data=json.dumps({'role': 'OWNER', 'entity': 'user-foo'})) def test_set_permissions_bad_roles(self): mock_request = mock.Mock() self.driver.json_connection.request = mock_request # Test forgetting a role. self.assertRaises( ValueError, self.driver.ex_set_permissions, 'bucket', 'object') self.assertRaises( ValueError, self.driver.ex_set_permissions, 'bucket') mock_request.assert_not_called() # Test container permissions on an object. self.assertRaises( ValueError, self.driver.ex_set_permissions, 'bucket', 'object', role=google_storage.ContainerPermissions.OWNER) mock_request.assert_not_called() # Test object permissions on a container. self.assertRaises( ValueError, self.driver.ex_set_permissions, 'bucket', role=google_storage.ObjectPermissions.OWNER) mock_request.assert_not_called() def test_set_permissions_no_entity(self): mock_request = mock.Mock() mock_get_user = mock.Mock(return_value=None) self.driver._get_user = mock_get_user self.driver.json_connection.request = mock_request # Test for setting object permissions with no entity. self.assertRaises( ValueError, self.driver.ex_set_permissions, 'bucket', 'object', role='OWNER') # Test for setting bucket permissions with no entity. self.assertRaises( ValueError, self.driver.ex_set_permissions, 'bucket', role='OWNER') mock_request.assert_not_called() # Test for setting object permissions with a default entity. mock_get_user.return_value = 'foo@foo.com' self.driver.ex_set_permissions('bucket', 'object', role='OWNER') url = '/storage/v1/b/bucket/o/object/acl' mock_request.assert_called_once_with( url, method='POST', data=json.dumps({'role': 'OWNER', 'entity': 'user-foo@foo.com'})) # Test for setting bucket permissions with a default entity. mock_request.reset_mock() mock_get_user.return_value = 'foo@foo.com' self.driver.ex_set_permissions('bucket', role='OWNER') url = '/storage/v1/b/bucket/acl' mock_request.assert_called_once_with( url, method='POST', data=json.dumps({'role': 'OWNER', 'entity': 'user-foo@foo.com'})) def test_invalid_credentials_on_upload(self): self.mock_response_klass.type = 'UNAUTHORIZED' container = Container(name='container', driver=self.driver, extra={}) with pytest.raises(InvalidCredsError): self.driver.upload_object_via_stream( BytesIO(b' '), container, 'path') def test_download_object_data_is_not_buffered_in_memory(self): # Test case which verifies that response.body attribute is not accessed # and as such, whole body response is not buffered into RAM # If content is consumed and response.content attribute accessed execption # will be thrown and test will fail mock_response = Mock(name='mock response') mock_response.headers = {} mock_response.status_code = 200 msg = '"content" attribute was accessed but it shouldn\'t have been' type(mock_response).content = PropertyMock(name='mock content attribute', side_effect=Exception(msg)) mock_response.iter_content.return_value = StringIO('a' * 1000) self.driver.connection.connection.getresponse = Mock() self.driver.connection.connection.getresponse.return_value = mock_response container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object_NO_BUFFER', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = self._file_path result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=True, delete_on_failure=True) self.assertTrue(result) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_local.py0000664000175000017500000002645513535474530023373 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import with_statement import os import sys import shutil import unittest import tempfile import mock from libcloud.common.types import LibcloudError from libcloud.storage.base import Container from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerAlreadyExistsError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import InvalidContainerNameError try: from libcloud.storage.drivers.local import LocalStorageDriver from libcloud.storage.drivers.local import LockLocalStorage from lockfile import LockTimeout except ImportError: print('lockfile library is not available, skipping local_storage tests...') LocalStorageDriver = None LockTimeout = None class LocalTests(unittest.TestCase): driver_type = LocalStorageDriver @classmethod def create_driver(self): self.key = tempfile.mkdtemp() return self.driver_type(self.key, None) def setUp(self): self.driver = self.create_driver() def tearDown(self): shutil.rmtree(self.key) self.key = None def make_tmp_file(self): _, tmppath = tempfile.mkstemp() with open(tmppath, 'wb') as fp: fp.write(b'blah' * 1024) return tmppath def remove_tmp_file(self, tmppath): os.unlink(tmppath) def test_list_containers_empty(self): containers = self.driver.list_containers() self.assertEqual(len(containers), 0) def test_containers_success(self): self.driver.create_container('test1') self.driver.create_container('test2') containers = self.driver.list_containers() self.assertEqual(len(containers), 2) container = containers[1] self.assertTrue('creation_time' in container.extra) self.assertTrue('modify_time' in container.extra) self.assertTrue('access_time' in container.extra) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 0) objects = container.list_objects() self.assertEqual(len(objects), 0) for container in containers: self.driver.delete_container(container) def test_objects_success(self): tmppath = self.make_tmp_file() container = self.driver.create_container('test3') obj1 = container.upload_object(tmppath, 'object1') obj2 = container.upload_object(tmppath, 'path/object2') obj3 = container.upload_object(tmppath, 'path/to/object3') obj4 = container.upload_object(tmppath, 'path/to/object4.ext') with open(tmppath, 'rb') as tmpfile: obj5 = container.upload_object_via_stream(tmpfile, 'object5') objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 5) for obj in objects: self.assertNotEqual(obj.hash, None) self.assertEqual(obj.size, 4096) self.assertEqual(obj.container.name, 'test3') self.assertTrue('creation_time' in obj.extra) self.assertTrue('modify_time' in obj.extra) self.assertTrue('access_time' in obj.extra) obj1.delete() obj2.delete() objects = container.list_objects() self.assertEqual(len(objects), 3) container.delete_object(obj3) container.delete_object(obj4) container.delete_object(obj5) objects = container.list_objects() self.assertEqual(len(objects), 0) container.delete() self.remove_tmp_file(tmppath) def test_get_container_doesnt_exist(self): try: self.driver.get_container(container_name='container1') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_get_container_success(self): self.driver.create_container('test4') container = self.driver.get_container(container_name='test4') self.assertTrue(container.name, 'test4') container.delete() def test_get_object_container_doesnt_exist(self): try: self.driver.get_object(container_name='test-inexistent', object_name='test') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_get_object_success(self): tmppath = self.make_tmp_file() container = self.driver.create_container('test5') container.upload_object(tmppath, 'test') obj = self.driver.get_object(container_name='test5', object_name='test') self.assertEqual(obj.name, 'test') self.assertEqual(obj.container.name, 'test5') self.assertEqual(obj.size, 4096) self.assertNotEqual(obj.hash, None) self.assertTrue('creation_time' in obj.extra) self.assertTrue('modify_time' in obj.extra) self.assertTrue('access_time' in obj.extra) obj.delete() container.delete() self.remove_tmp_file(tmppath) def test_create_container_invalid_name(self): try: self.driver.create_container(container_name='new/container') except InvalidContainerNameError: pass else: self.fail('Exception was not thrown') def test_create_container_already_exists(self): container = self.driver.create_container( container_name='new-container') try: self.driver.create_container(container_name='new-container') except ContainerAlreadyExistsError: pass else: self.fail('Exception was not thrown') # success self.driver.delete_container(container) def test_create_container_success(self): name = 'new_container' container = self.driver.create_container(container_name=name) self.assertEqual(container.name, name) self.driver.delete_container(container) def test_delete_container_doesnt_exist(self): container = Container(name='new_container', extra=None, driver=self.driver) try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_delete_container_not_empty(self): tmppath = self.make_tmp_file() container = self.driver.create_container('test6') obj = container.upload_object(tmppath, 'test') try: self.driver.delete_container(container=container) except ContainerIsNotEmptyError: pass else: self.fail('Exception was not thrown') # success obj.delete() self.remove_tmp_file(tmppath) self.assertTrue(self.driver.delete_container(container=container)) def test_delete_container_not_found(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail('Container does not exist but an exception was not' + 'thrown') def test_delete_container_success(self): container = self.driver.create_container('test7') self.assertTrue(self.driver.delete_container(container=container)) def test_download_object_success(self): tmppath = self.make_tmp_file() container = self.driver.create_container('test6') obj = container.upload_object(tmppath, 'test') destination_path = tmppath + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) obj.delete() container.delete() self.remove_tmp_file(tmppath) os.unlink(destination_path) def test_download_object_and_overwrite(self): tmppath = self.make_tmp_file() container = self.driver.create_container('test6') obj = container.upload_object(tmppath, 'test') destination_path = tmppath + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) try: self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) except LibcloudError: pass else: self.fail('Exception was not thrown') result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=True, delete_on_failure=True) self.assertTrue(result) # success obj.delete() container.delete() self.remove_tmp_file(tmppath) os.unlink(destination_path) def test_download_object_as_stream_success(self): tmppath = self.make_tmp_file() container = self.driver.create_container('test6') obj = container.upload_object(tmppath, 'test') stream = self.driver.download_object_as_stream(obj=obj, chunk_size=1024) self.assertTrue(hasattr(stream, '__iter__')) data = b''.join(stream) self.assertTrue(len(data), 4096) obj.delete() container.delete() self.remove_tmp_file(tmppath) @mock.patch("lockfile.mkdirlockfile.MkdirLockFile.acquire", mock.MagicMock(side_effect=LockTimeout)) def test_proper_lockfile_imports(self): # LockLocalStorage was previously using an un-imported exception # in its __enter__ method, so the following would raise a NameError. lls = LockLocalStorage("blah") self.assertRaises(LibcloudError, lls.__enter__) if not LocalStorageDriver: class LocalTests(unittest.TestCase): # NOQA pass if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_ninefold.py0000664000175000017500000000252713535474530024071 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import base64 from libcloud.utils.py3 import b from libcloud.storage.drivers.ninefold import NinefoldStorageDriver from libcloud.test.storage.test_atmos import AtmosMockHttp, AtmosTests class NinefoldTests(AtmosTests, unittest.TestCase): def setUp(self): NinefoldStorageDriver.connectionCls.conn_class = AtmosMockHttp NinefoldStorageDriver.path = '' AtmosMockHttp.type = None AtmosMockHttp.upload_created = False self.driver = NinefoldStorageDriver('dummy', base64.b64encode(b('dummy'))) self._remove_test_file() apache-libcloud-2.8.0/libcloud/test/storage/test_oss.py0000664000175000017500000007574613535474530023114 0ustar kamikami00000000000000# -*- coding=utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import unicode_literals import os import sys import unittest try: import mock except ImportError: from unittest import mock from libcloud.utils.py3 import b from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qs from libcloud.common.types import InvalidCredsError from libcloud.storage.base import Container, Object from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import InvalidContainerNameError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError from libcloud.storage.drivers.oss import OSSConnection from libcloud.storage.drivers.oss import OSSStorageDriver from libcloud.storage.drivers.oss import CHUNK_SIZE from libcloud.storage.drivers.dummy import DummyIterator from libcloud.test import MockHttp, generate_random_data, make_response # pylint: disable-msg=E0611 from libcloud.test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611 from libcloud.test.secrets import STORAGE_OSS_PARAMS class OSSConnectionTestCase(unittest.TestCase): def setUp(self): self.conn = OSSConnection('44CF9590006BF252F707', 'OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV') def test_signature(self): expected = b('26NBxoKdsyly4EDv6inkoDft/yA=') headers = { 'Content-MD5': 'ODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=', 'Content-Type': 'text/html', 'Expires': 'Thu, 17 Nov 2005 18:49:58 GMT', 'X-OSS-Meta-Author': 'foo@bar.com', 'X-OSS-Magic': 'abracadabra', 'Host': 'oss-example.oss-cn-hangzhou.aliyuncs.com' } action = '/oss-example/nelson' actual = OSSConnection._get_auth_signature('PUT', headers, {}, headers['Expires'], self.conn.key, action, 'x-oss-') self.assertEqual(expected, actual) class ObjectTestCase(unittest.TestCase): def test_object_with_chinese_name(self): driver = OSSStorageDriver(*STORAGE_OSS_PARAMS) obj = Object(name='中文', size=0, hash=None, extra=None, meta_data=None, container=None, driver=driver) self.assertTrue(obj.__repr__() is not None) class OSSMockHttp(MockHttp, unittest.TestCase): fixtures = StorageFileFixtures('oss') base_headers = {} def _unauthorized(self, method, url, body, headers): return (httplib.UNAUTHORIZED, '', self.base_headers, httplib.responses[httplib.OK]) def _list_containers_empty(self, method, url, body, headers): body = self.fixtures.load('list_containers_empty.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_containers(self, method, url, body, headers): body = self.fixtures.load('list_containers.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_container_objects_empty(self, method, url, body, headers): body = self.fixtures.load('list_container_objects_empty.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_container_objects(self, method, url, body, headers): body = self.fixtures.load('list_container_objects.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_container_objects_chinese(self, method, url, body, headers): body = self.fixtures.load('list_container_objects_chinese.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_container_objects_prefix(self, method, url, body, headers): params = {'prefix': self.test.prefix} self.assertUrlContainsQueryParams(url, params) body = self.fixtures.load('list_container_objects_prefix.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _get_container(self, method, url, body, headers): return self._list_containers(method, url, body, headers) def _get_object(self, method, url, body, headers): return self._list_containers(method, url, body, headers) def _notexisted_get_object(self, method, url, body, headers): return (httplib.NOT_FOUND, body, self.base_headers, httplib.responses[httplib.NOT_FOUND]) def _test_get_object(self, method, url, body, headers): self.base_headers.update( {'accept-ranges': 'bytes', 'connection': 'keep-alive', 'content-length': '0', 'content-type': 'application/octet-stream', 'date': 'Sat, 16 Jan 2016 15:38:14 GMT', 'etag': '"D41D8CD98F00B204E9800998ECF8427E"', 'last-modified': 'Fri, 15 Jan 2016 14:43:15 GMT', 'server': 'AliyunOSS', 'x-oss-object-type': 'Normal', 'x-oss-request-id': '569A63E6257784731E3D877F', 'x-oss-meta-rabbits': 'monkeys'}) return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _invalid_name(self, method, url, body, headers): # test_create_container_bad_request return (httplib.BAD_REQUEST, body, headers, httplib.responses[httplib.OK]) def _already_exists(self, method, url, body, headers): # test_create_container_already_existed return (httplib.CONFLICT, body, headers, httplib.responses[httplib.OK]) def _create_container(self, method, url, body, headers): # test_create_container_success self.assertEqual('PUT', method) self.assertEqual('', body) return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _create_container_location(self, method, url, body, headers): # test_create_container_success self.assertEqual('PUT', method) location_constraint = ('' '%s' '' % self.test.ex_location) self.assertEqual(location_constraint, body) return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _delete_container_doesnt_exist(self, method, url, body, headers): # test_delete_container_doesnt_exist return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.OK]) def _delete_container_not_empty(self, method, url, body, headers): # test_delete_container_not_empty return (httplib.CONFLICT, body, headers, httplib.responses[httplib.OK]) def _delete_container(self, method, url, body, headers): return (httplib.NO_CONTENT, body, self.base_headers, httplib.responses[httplib.NO_CONTENT]) def _foo_bar_object_not_found(self, method, url, body, headers): # test_delete_object_not_found return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.OK]) def _foo_bar_object_delete(self, method, url, body, headers): # test_delete_object return (httplib.NO_CONTENT, body, headers, httplib.responses[httplib.OK]) def _list_multipart(self, method, url, body, headers): query_string = urlparse.urlsplit(url).query query = parse_qs(query_string) if 'key-marker' not in query: body = self.fixtures.load('ex_iterate_multipart_uploads_p1.xml') else: body = self.fixtures.load('ex_iterate_multipart_uploads_p2.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_object(self, method, url, body, headers): # test_download_object_success body = generate_random_data(1000) return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_object_invalid_size(self, method, url, body, headers): # test_upload_object_invalid_file_size body = '' return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_test_stream_data_multipart(self, method, url, body, headers): headers = {} body = '' headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} return (httplib.OK, body, headers, httplib.responses[httplib.OK]) class OSSStorageDriverTestCase(unittest.TestCase): driver_type = OSSStorageDriver driver_args = STORAGE_OSS_PARAMS mock_response_klass = OSSMockHttp @classmethod def create_driver(self): return self.driver_type(*self.driver_args) def setUp(self): self.driver_type.connectionCls.conn_class = self.mock_response_klass self.mock_response_klass.type = None self.mock_response_klass.test = self self.driver = self.create_driver() def tearDown(self): self._remove_test_file() def _remove_test_file(self): file_path = os.path.abspath(__file__) + '.temp' try: os.unlink(file_path) except OSError: pass def test_invalid_credentials(self): self.mock_response_klass.type = 'unauthorized' self.assertRaises(InvalidCredsError, self.driver.list_containers) def test_list_containers_empty(self): self.mock_response_klass.type = 'list_containers_empty' containers = self.driver.list_containers() self.assertEqual(len(containers), 0) def test_list_containers_success(self): self.mock_response_klass.type = 'list_containers' containers = self.driver.list_containers() self.assertEqual(len(containers), 2) container = containers[0] self.assertEqual('xz02tphky6fjfiuc0', container.name) self.assertTrue('creation_date' in container.extra) self.assertEqual('2014-05-15T11:18:32.000Z', container.extra['creation_date']) self.assertTrue('location' in container.extra) self.assertEqual('oss-cn-hangzhou-a', container.extra['location']) self.assertEqual(self.driver, container.driver) def test_list_container_objects_empty(self): self.mock_response_klass.type = 'list_container_objects_empty' container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 0) def test_list_container_objects_success(self): self.mock_response_klass.type = 'list_container_objects' container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 2) obj = objects[0] self.assertEqual(obj.name, 'en/') self.assertEqual(obj.hash, 'D41D8CD98F00B204E9800998ECF8427E') self.assertEqual(obj.size, 0) self.assertEqual(obj.container.name, 'test_container') self.assertEqual( obj.extra['last_modified'], '2016-01-15T14:43:15.000Z') self.assertTrue('owner' in obj.meta_data) def test_list_container_objects_with_chinese(self): self.mock_response_klass.type = 'list_container_objects_chinese' container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 2) obj = [o for o in objects if o.name == 'WEB控制台.odp'][0] self.assertEqual(obj.hash, '281371EA1618CF0E645D6BB90A158276') self.assertEqual(obj.size, 1234567) self.assertEqual(obj.container.name, 'test_container') self.assertEqual( obj.extra['last_modified'], '2016-01-15T14:43:06.000Z') self.assertTrue('owner' in obj.meta_data) def test_list_container_objects_with_prefix(self): self.mock_response_klass.type = 'list_container_objects_prefix' container = Container(name='test_container', extra={}, driver=self.driver) self.prefix = 'test_prefix' objects = self.driver.list_container_objects(container=container, ex_prefix=self.prefix) self.assertEqual(len(objects), 2) def test_get_container_doesnt_exist(self): self.mock_response_klass.type = 'get_container' self.assertRaises(ContainerDoesNotExistError, self.driver.get_container, container_name='not-existed') def test_get_container_success(self): self.mock_response_klass.type = 'get_container' container = self.driver.get_container( container_name='xz02tphky6fjfiuc0') self.assertTrue(container.name, 'xz02tphky6fjfiuc0') def test_get_object_container_doesnt_exist(self): self.mock_response_klass.type = 'get_object' self.assertRaises(ObjectDoesNotExistError, self.driver.get_object, container_name='xz02tphky6fjfiuc0', object_name='notexisted') def test_get_object_success(self): self.mock_response_klass.type = 'get_object' obj = self.driver.get_object(container_name='xz02tphky6fjfiuc0', object_name='test') self.assertEqual(obj.name, 'test') self.assertEqual(obj.container.name, 'xz02tphky6fjfiuc0') self.assertEqual(obj.size, 0) self.assertEqual(obj.hash, 'D41D8CD98F00B204E9800998ECF8427E') self.assertEqual(obj.extra['last_modified'], 'Fri, 15 Jan 2016 14:43:15 GMT') self.assertEqual(obj.extra['content_type'], 'application/octet-stream') self.assertEqual(obj.meta_data['rabbits'], 'monkeys') def test_create_container_bad_request(self): # invalid container name, returns a 400 bad request self.mock_response_klass.type = 'invalid_name' self.assertRaises(ContainerError, self.driver.create_container, container_name='invalid_name') def test_create_container_already_exists(self): # container with this name already exists self.mock_response_klass.type = 'already_exists' self.assertRaises(InvalidContainerNameError, self.driver.create_container, container_name='new-container') def test_create_container_success(self): # success self.mock_response_klass.type = 'create_container' name = 'new_container' container = self.driver.create_container(container_name=name) self.assertEqual(container.name, name) def test_create_container_with_ex_location(self): self.mock_response_klass.type = 'create_container_location' name = 'new_container' self.ex_location = 'oss-cn-beijing' container = self.driver.create_container(container_name=name, ex_location=self.ex_location) self.assertEqual(container.name, name) self.assertTrue(container.extra['location'], self.ex_location) def test_delete_container_doesnt_exist(self): container = Container(name='new_container', extra=None, driver=self.driver) self.mock_response_klass.type = 'delete_container_doesnt_exist' self.assertRaises(ContainerDoesNotExistError, self.driver.delete_container, container=container) def test_delete_container_not_empty(self): container = Container(name='new_container', extra=None, driver=self.driver) self.mock_response_klass.type = 'delete_container_not_empty' self.assertRaises(ContainerIsNotEmptyError, self.driver.delete_container, container=container) def test_delete_container_success(self): self.mock_response_klass.type = 'delete_container' container = Container(name='new_container', extra=None, driver=self.driver) self.assertTrue(self.driver.delete_container(container=container)) def test_download_object_success(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) def test_download_object_invalid_file_size(self): self.mock_response_klass.type = 'invalid_size' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = os.path.abspath(__file__) + '.temp' result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertFalse(result) def test_download_object_not_found(self): self.mock_response_klass.type = 'not_found' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = os.path.abspath(__file__) + '.temp' self.assertRaises(ObjectDoesNotExistError, self.driver.download_object, obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) def test_download_object_as_stream_success(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) stream = self.driver.download_object_as_stream(obj=obj, chunk_size=None) self.assertTrue(hasattr(stream, '__iter__')) def test_upload_object_invalid_hash1(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(200, headers={'etag': '2345'}), 'bytes_transferred': 1000, 'data_hash': 'hash343hhash89h932439jsaa89'} self.mock_response_klass.type = 'INVALID_HASH1' old_func = self.driver_type._upload_object self.driver_type._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, verify_hash=True) except ObjectHashMismatchError: pass else: self.fail( 'Invalid hash was returned but an exception was not thrown') finally: self.driver_type._upload_object = old_func def test_upload_object_success(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(200, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} self.mock_response_klass.type = None old_func = self.driver_type._upload_object self.driver_type._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=True) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, 1000) self.assertTrue('some-value' in obj.meta_data) self.driver_type._upload_object = old_func def test_upload_object_with_acl(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(200, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} self.mock_response_klass.type = None old_func = self.driver_type._upload_object self.driver_type._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'acl': 'public-read'} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=True) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, 1000) self.assertEqual(obj.extra['acl'], 'public-read') self.driver_type._upload_object = old_func def test_upload_object_with_invalid_acl(self): file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'acl': 'invalid-acl'} self.assertRaises(AttributeError, self.driver.upload_object, file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=True) def test_upload_empty_object_via_stream(self): if self.driver.supports_multipart_upload: self.mock_response_klass.type = 'multipart' else: self.mock_response_klass.type = None container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = DummyIterator(data=['']) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, 0) def test_upload_small_object_via_stream(self): if self.driver.supports_multipart_upload: self.mock_response_klass.type = 'multipart' else: self.mock_response_klass.type = None container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = DummyIterator(data=['2', '3', '5']) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, 3) def test_upload_big_object_via_stream(self): if self.driver.supports_multipart_upload: self.mock_response_klass.type = 'multipart' else: self.mock_response_klass.type = None container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = DummyIterator( data=['2' * CHUNK_SIZE, '3' * CHUNK_SIZE, '5']) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, CHUNK_SIZE * 2 + 1) def test_upload_object_via_stream_abort(self): if not self.driver.supports_multipart_upload: return self.mock_response_klass.type = 'MULTIPART' def _faulty_iterator(): for i in range(0, 5): yield str(i) raise RuntimeError('Error in fetching data') container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = _faulty_iterator() extra = {'content_type': 'text/plain'} try: self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) except Exception: pass return def test_ex_iterate_multipart_uploads(self): if not self.driver.supports_multipart_upload: return self.mock_response_klass.type = 'list_multipart' container = Container(name='foo_bar_container', extra={}, driver=self.driver) for upload in self.driver.ex_iterate_multipart_uploads(container, max_uploads=2): self.assertTrue(upload.key is not None) self.assertTrue(upload.id is not None) self.assertTrue(upload.initiated is not None) def test_ex_abort_all_multipart_uploads(self): if not self.driver.supports_multipart_upload: return self.mock_response_klass.type = 'list_multipart' container = Container(name='foo_bar_container', extra={}, driver=self.driver) with mock.patch('libcloud.storage.drivers.oss.OSSStorageDriver' '._abort_multipart', autospec=True) as mock_abort: self.driver.ex_abort_all_multipart_uploads(container) self.assertEqual(3, mock_abort.call_count) def test_delete_object_not_found(self): self.mock_response_klass.type = 'not_found' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, meta_data=None, container=container, driver=self.driver) self.assertRaises(ObjectDoesNotExistError, self.driver.delete_object, obj=obj) def test_delete_object_success(self): self.mock_response_klass.type = 'delete' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, meta_data=None, container=container, driver=self.driver) result = self.driver.delete_object(obj=obj) self.assertTrue(result) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_rgw.py0000664000175000017500000000722613535474530023073 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.storage.drivers.rgw import S3RGWStorageDriver from libcloud.storage.drivers.rgw import S3RGWOutscaleStorageDriver from libcloud.storage.drivers.rgw import S3RGWConnectionAWS4 from libcloud.storage.drivers.rgw import S3RGWConnectionAWS2 from libcloud.test.secrets import STORAGE_S3_PARAMS class S3RGWTests(unittest.TestCase): driver_type = S3RGWStorageDriver driver_args = STORAGE_S3_PARAMS default_host = 'localhost' @classmethod def create_driver(self): return self.driver_type(*self.driver_args, signature_version='2', host=self.default_host) def setUp(self): self.driver = self.create_driver() def test_connection_class_type(self): res = self.driver.connectionCls is S3RGWConnectionAWS2 self.assertTrue(res, 'driver.connectionCls does not match!') def test_connection_class_host(self): host = self.driver.connectionCls.host self.assertEqual(host, self.default_host) class S3RGWOutscaleTests(S3RGWTests): driver_type = S3RGWOutscaleStorageDriver default_host = 'osu.eu-west-2.outscale.com' @classmethod def create_driver(self): return self.driver_type(*self.driver_args, signature_version='4') def test_connection_class_type(self): res = self.driver.connectionCls is S3RGWConnectionAWS4 self.assertTrue(res, 'driver.connectionCls does not match!') def test_connection_class_host(self): host = self.driver.connectionCls.host self.assertEqual(host, self.default_host) class S3RGWOutscaleDoubleInstanceTests(S3RGWTests): driver_type = S3RGWOutscaleStorageDriver default_host = 'osu.eu-west-2.outscale.com' def setUp(self): self.driver_v2 = self.driver_type(*self.driver_args, signature_version='2') self.driver_v4 = self.driver_type(*self.driver_args, signature_version='4') def test_connection_class_type(self): res = self.driver_v2.connectionCls is S3RGWConnectionAWS2 self.assertTrue(res, 'driver.connectionCls does not match!') res = self.driver_v4.connectionCls is S3RGWConnectionAWS4 self.assertTrue(res, 'driver.connectionCls does not match!') # Verify again that connection class hasn't been overriden when # instantiating a second driver class res = self.driver_v2.connectionCls is S3RGWConnectionAWS2 self.assertTrue(res, 'driver.connectionCls does not match!') def test_connection_class_host(self): host = self.driver_v2.connectionCls.host self.assertEqual(host, self.default_host) host = self.driver_v4.connectionCls.host self.assertEqual(host, self.default_host) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/storage/test_s3.py0000664000175000017500000012756113577507766022644 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import hmac import os import sys from io import BytesIO from hashlib import sha1 import mock from mock import Mock from mock import PropertyMock import libcloud.utils.files # NOQA: F401 from libcloud.utils.py3 import ET from libcloud.utils.py3 import httplib from libcloud.utils.py3 import urlparse from libcloud.utils.py3 import parse_qs from libcloud.utils.py3 import StringIO from libcloud.utils.py3 import PY3 from libcloud.utils.files import exhaust_iterator from libcloud.common.types import InvalidCredsError from libcloud.common.types import LibcloudError, MalformedResponseError from libcloud.storage.base import Container, Object from libcloud.storage.types import ContainerDoesNotExistError from libcloud.storage.types import ContainerError from libcloud.storage.types import ContainerIsNotEmptyError from libcloud.storage.types import InvalidContainerNameError from libcloud.storage.types import ObjectDoesNotExistError from libcloud.storage.types import ObjectHashMismatchError from libcloud.storage.drivers.s3 import BaseS3Connection from libcloud.storage.drivers.s3 import S3StorageDriver, S3USWestStorageDriver from libcloud.storage.drivers.s3 import CHUNK_SIZE from libcloud.utils.py3 import b from libcloud.test import MockHttp # pylint: disable-msg=E0611 from libcloud.test import unittest, make_response, generate_random_data from libcloud.test.file_fixtures import StorageFileFixtures # pylint: disable-msg=E0611 from libcloud.test.secrets import STORAGE_S3_PARAMS class S3MockHttp(MockHttp): fixtures = StorageFileFixtures('s3') base_headers = {} def _UNAUTHORIZED(self, method, url, body, headers): return (httplib.UNAUTHORIZED, '', self.base_headers, httplib.responses[httplib.OK]) def _DIFFERENT_REGION(self, method, url, body, headers): return (httplib.MOVED_PERMANENTLY, '', self.base_headers, httplib.responses[httplib.OK]) def _list_containers_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_containers_empty.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_containers_TOKEN(self, method, url, body, headers): if 'x-amz-security-token' in headers: assert headers['x-amz-security-token'] == 'asdf' body = self.fixtures.load('list_containers_empty.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _list_containers(self, method, url, body, headers): body = self.fixtures.load('list_containers.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _test_container_EMPTY(self, method, url, body, headers): body = self.fixtures.load('list_container_objects_empty.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _test_container(self, method, url, body, headers): body = self.fixtures.load('list_container_objects.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _test_container_ITERATOR(self, method, url, body, headers): if url.find('3.zip') == -1: # First part of the response (first 3 objects) file_name = 'list_container_objects_not_exhausted1.xml' else: file_name = 'list_container_objects_not_exhausted2.xml' body = self.fixtures.load(file_name) return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _test2_get_object(self, method, url, body, headers): body = self.fixtures.load('list_container_objects.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _test2_test_get_object(self, method, url, body, headers): # test_get_object body = self.fixtures.load('list_containers.xml') headers = {'content-type': 'application/zip', 'etag': '"e31208wqsdoj329jd"', 'x-amz-meta-rabbits': 'monkeys', 'content-length': '12345', 'last-modified': 'Thu, 13 Sep 2012 07:13:22 GMT' } return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _new_container_INVALID_NAME(self, method, url, body, headers): # test_create_container return (httplib.BAD_REQUEST, body, headers, httplib.responses[httplib.OK]) def _new_container_ALREADY_EXISTS(self, method, url, body, headers): # test_create_container return (httplib.CONFLICT, body, headers, httplib.responses[httplib.OK]) def _new_container(self, method, url, body, headers): # test_create_container, test_delete_container if method == 'PUT': status = httplib.OK elif method == 'DELETE': status = httplib.NO_CONTENT return (status, body, headers, httplib.responses[httplib.OK]) def _new_container_DOESNT_EXIST(self, method, url, body, headers): # test_delete_container return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.OK]) def _new_container_NOT_EMPTY(self, method, url, body, headers): # test_delete_container return (httplib.CONFLICT, body, headers, httplib.responses[httplib.OK]) def _test1_get_container(self, method, url, body, headers): body = self.fixtures.load('list_container_objects.xml') return (httplib.OK, body, self.base_headers, httplib.responses[httplib.OK]) def _container1_get_container(self, method, url, body, headers): return (httplib.NOT_FOUND, '', self.base_headers, httplib.responses[httplib.NOT_FOUND]) def _test_inexistent_get_object(self, method, url, body, headers): return (httplib.NOT_FOUND, '', self.base_headers, httplib.responses[httplib.NOT_FOUND]) def _foo_bar_container(self, method, url, body, headers): # test_delete_container return (httplib.NO_CONTENT, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_NOT_FOUND(self, method, url, body, headers): # test_delete_container_not_found return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_bar_object_NOT_FOUND(self, method, url, body, headers): # test_delete_object_not_found return (httplib.NOT_FOUND, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_bar_object_DELETE(self, method, url, body, headers): # test_delete_object return (httplib.NO_CONTENT, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_test_stream_data(self, method, url, body, headers): # test_upload_object_via_stream body = '' headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_test_stream_data_MULTIPART(self, method, url, body, headers): if method == 'POST': if 'uploadId' in url: # Complete multipart request body = self.fixtures.load('complete_multipart.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) else: # Initiate multipart request body = self.fixtures.load('initiate_multipart.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) elif method == 'DELETE': # Abort multipart request return (httplib.NO_CONTENT, '', headers, httplib.responses[httplib.NO_CONTENT]) else: # Upload chunk multipart request headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} return (httplib.OK, '', headers, httplib.responses[httplib.OK]) def _foo_bar_container_LIST_MULTIPART(self, method, url, body, headers): query_string = urlparse.urlsplit(url).query query = parse_qs(query_string) if 'key-marker' not in query: body = self.fixtures.load('list_multipart_1.xml') else: body = self.fixtures.load('list_multipart_2.xml') return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_my_divisor_LIST_MULTIPART(self, method, url, body, headers): body = '' return (httplib.NO_CONTENT, body, headers, httplib.responses[httplib.NO_CONTENT]) def _foo_bar_container_my_movie_m2ts_LIST_MULTIPART(self, method, url, body, headers): body = '' return (httplib.NO_CONTENT, body, headers, httplib.responses[httplib.NO_CONTENT]) def parse_body(self): if len(self.body) == 0 and not self.parse_zero_length_body: return self.body try: try: body = ET.XML(self.body) except ValueError: # lxml wants a bytes and tests are basically hard-coded to str body = ET.XML(self.body.encode('utf-8')) except Exception: raise MalformedResponseError("Failed to parse XML", body=self.body, driver=self.connection.driver) return body def _foo_bar_container_foo_bar_object(self, method, url, body, headers): # test_download_object_success body = generate_random_data(1000) return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_bar_object_NO_BUFFER(self, method, url, body, headers): # test_download_object_data_is_not_buffered_in_memory body = generate_random_data(1000) return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_test_upload_INVALID_HASH1(self, method, url, body, headers): body = '' headers = {} headers['etag'] = '"foobar"' # test_upload_object_invalid_hash1 return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_test_upload_INVALID_HASH2(self, method, url, body, headers): # test_upload_object_invalid_hash2 body = '' headers = {'etag': '"hash343hhash89h932439jsaa89"'} return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_test_upload(self, method, url, body, headers): # test_upload_object_success body = '' headers = {'etag': '"0cc175b9c0f1b6a831c399e269772661"'} return (httplib.OK, body, headers, httplib.responses[httplib.OK]) def _foo_bar_container_foo_bar_object_INVALID_SIZE(self, method, url, body, headers): # test_upload_object_invalid_file_size body = '' return (httplib.OK, body, headers, httplib.responses[httplib.OK]) class S3Tests(unittest.TestCase): driver_type = S3StorageDriver driver_args = STORAGE_S3_PARAMS mock_response_klass = S3MockHttp @classmethod def create_driver(self): return self.driver_type(*self.driver_args) def setUp(self): self.driver_type.connectionCls.conn_class = self.mock_response_klass self.mock_response_klass.type = None self.driver = self.create_driver() self._file_path = os.path.abspath(__file__) + '.temp' def tearDown(self): self._remove_test_file() def _remove_test_file(self): try: os.unlink(self._file_path) except OSError: pass def test_invalid_credentials(self): self.mock_response_klass.type = 'UNAUTHORIZED' try: self.driver.list_containers() except InvalidCredsError as e: self.assertEqual(True, isinstance(e, InvalidCredsError)) else: self.fail('Exception was not thrown') def test_token(self): self.mock_response_klass.type = 'list_containers_TOKEN' self.driver = self.driver_type(*self.driver_args, token='asdf') self.driver.list_containers() def test_signature(self): secret_key = 'ssssh!' sig = BaseS3Connection.get_auth_signature( method='GET', headers={'foo': 'bar', 'content-type': 'TYPE!', 'x-aws-test': 'test_value'}, params={'hello': 'world'}, expires=None, secret_key=secret_key, path='/', vendor_prefix='x-aws' ) string_to_sign = 'GET\n\nTYPE!\n\nx-aws-test:test_value\n/' b64_hmac = base64.b64encode( hmac.new(b(secret_key), b(string_to_sign), digestmod=sha1).digest() ) expected_sig = b64_hmac.decode('utf-8') self.assertEqual(sig, expected_sig) def test_bucket_is_located_in_different_region(self): self.mock_response_klass.type = 'DIFFERENT_REGION' try: self.driver.list_containers() except LibcloudError: pass else: self.fail('Exception was not thrown') def test_list_containers_empty(self): self.mock_response_klass.type = 'list_containers_EMPTY' containers = self.driver.list_containers() self.assertEqual(len(containers), 0) def test_list_containers_success(self): self.mock_response_klass.type = 'list_containers' containers = self.driver.list_containers() self.assertEqual(len(containers), 2) self.assertTrue('creation_date' in containers[1].extra) def test_list_container_objects_empty(self): self.mock_response_klass.type = 'EMPTY' container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 0) def test_list_container_objects_success(self): self.mock_response_klass.type = None container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) self.assertEqual(len(objects), 1) obj = [o for o in objects if o.name == '1.zip'][0] self.assertEqual(obj.hash, '4397da7a7649e8085de9916c240e8166') self.assertEqual(obj.size, 1234567) self.assertEqual(obj.container.name, 'test_container') self.assertEqual( obj.extra['last_modified'], '2011-04-09T19:05:18.000Z') self.assertTrue('owner' in obj.meta_data) def test_list_container_objects_iterator_has_more(self): self.mock_response_klass.type = 'ITERATOR' container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container) obj = [o for o in objects if o.name == '1.zip'][0] self.assertEqual(obj.hash, '4397da7a7649e8085de9916c240e8166') self.assertEqual(obj.size, 1234567) self.assertEqual(obj.container.name, 'test_container') self.assertTrue(obj in objects) self.assertEqual(len(objects), 5) def test_list_container_objects_with_prefix(self): self.mock_response_klass.type = None container = Container(name='test_container', extra={}, driver=self.driver) objects = self.driver.list_container_objects(container=container, ex_prefix='test_prefix') self.assertEqual(len(objects), 1) obj = [o for o in objects if o.name == '1.zip'][0] self.assertEqual(obj.hash, '4397da7a7649e8085de9916c240e8166') self.assertEqual(obj.size, 1234567) self.assertEqual(obj.container.name, 'test_container') self.assertTrue('owner' in obj.meta_data) def test_get_container_doesnt_exist(self): self.mock_response_klass.type = 'get_container' try: self.driver.get_container(container_name='container1') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_get_container_success(self): self.mock_response_klass.type = 'get_container' container = self.driver.get_container(container_name='test1') self.assertTrue(container.name, 'test1') def test_get_object_container_doesnt_exist(self): # This method makes two requests which makes mocking the response a bit # trickier self.mock_response_klass.type = 'get_object' try: self.driver.get_object(container_name='test-inexistent', object_name='test') except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_get_object_success(self): # This method makes two requests which makes mocking the response a bit # trickier self.mock_response_klass.type = 'get_object' obj = self.driver.get_object(container_name='test2', object_name='test') self.assertEqual(obj.name, 'test') self.assertEqual(obj.container.name, 'test2') self.assertEqual(obj.size, '12345') self.assertEqual(obj.hash, 'e31208wqsdoj329jd') self.assertEqual(obj.extra['last_modified'], 'Thu, 13 Sep 2012 07:13:22 GMT') self.assertEqual(obj.extra['content_type'], 'application/zip') self.assertEqual(obj.meta_data['rabbits'], 'monkeys') def test_create_container_bad_request(self): # invalid container name, returns a 400 bad request self.mock_response_klass.type = 'INVALID_NAME' try: self.driver.create_container(container_name='new_container') except ContainerError: pass else: self.fail('Exception was not thrown') def test_create_container_already_exists(self): # container with this name already exists self.mock_response_klass.type = 'ALREADY_EXISTS' try: self.driver.create_container(container_name='new-container') except InvalidContainerNameError: pass else: self.fail('Exception was not thrown') def test_create_container_success(self): # success self.mock_response_klass.type = None name = 'new_container' container = self.driver.create_container(container_name=name) self.assertEqual(container.name, name) def test_delete_container_doesnt_exist(self): container = Container(name='new_container', extra=None, driver=self.driver) self.mock_response_klass.type = 'DOESNT_EXIST' try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_delete_container_not_empty(self): container = Container(name='new_container', extra=None, driver=self.driver) self.mock_response_klass.type = 'NOT_EMPTY' try: self.driver.delete_container(container=container) except ContainerIsNotEmptyError: pass else: self.fail('Exception was not thrown') # success self.mock_response_klass.type = None self.assertTrue(self.driver.delete_container(container=container)) def test_delete_container_not_found(self): self.mock_response_klass.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self.driver) try: self.driver.delete_container(container=container) except ContainerDoesNotExistError: pass else: self.fail('Container does not exist but an exception was not' + 'thrown') def test_delete_container_success(self): self.mock_response_klass.type = None container = Container(name='new_container', extra=None, driver=self.driver) self.assertTrue(self.driver.delete_container(container=container)) def test_download_object_success(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = self._file_path result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=True, delete_on_failure=True) self.assertTrue(result) def test_download_object_data_is_not_buffered_in_memory(self): # Test case which verifies that response.body attribute is not accessed # and as such, whole body response is not buffered into RAM # If content is consumed and response.content attribute accessed execption # will be thrown and test will fail mock_response = Mock(name='mock response') mock_response.headers = {} mock_response.status_code = 200 msg = '"content" attribute was accessed but it shouldn\'t have been' type(mock_response).content = PropertyMock(name='mock content attribute', side_effect=Exception(msg)) mock_response.iter_content.return_value = StringIO('a' * 1000) self.driver.connection.connection.getresponse = Mock() self.driver.connection.connection.getresponse.return_value = mock_response container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object_NO_BUFFER', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = self._file_path result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertTrue(result) def test_download_object_as_stream_data_is_not_buffered_in_memory(self): # Test case which verifies that response.response attribute is not accessed # and as such, whole body response is not buffered into RAM # If content is consumed and response.content attribute accessed exception # will be thrown and test will fail mock_response = Mock(name='mock response') mock_response.headers = {} mock_response.status = 200 msg1 = '"response" attribute was accessed but it shouldn\'t have been' msg2 = '"content" attribute was accessed but it shouldn\'t have been' type(mock_response).response = PropertyMock(name='mock response attribute', side_effect=Exception(msg1)) type(mock_response).content = PropertyMock(name='mock content attribute', side_effect=Exception(msg2)) mock_response.iter_content.return_value = StringIO('a' * 1000) self.driver.connection.request = Mock() self.driver.connection.request.return_value = mock_response container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object_NO_BUFFER', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) result = self.driver.download_object_as_stream(obj=obj) result = exhaust_iterator(result) if PY3: result = result.decode('utf-8') self.assertEqual(result, 'a' * 1000) def test_download_object_invalid_file_size(self): self.mock_response_klass.type = 'INVALID_SIZE' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = self._file_path result = self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) self.assertFalse(result) def test_download_object_invalid_file_already_exists(self): self.mock_response_klass.type = 'INVALID_SIZE' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) destination_path = os.path.abspath(__file__) try: self.driver.download_object(obj=obj, destination_path=destination_path, overwrite_existing=False, delete_on_failure=True) except LibcloudError: pass else: self.fail('Exception was not thrown') @unittest.skip("The MockHttp classes cannot support this test at present") def test_download_object_as_stream_success(self): container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1000, hash=None, extra={}, container=container, meta_data=None, driver=self.driver_type) def mock_get_object(self, obj, callback, callback_kwargs, response, success_status_code=None): return response._response.iter_content(1024) old_func = self.driver_type._get_object self.driver_type._get_object = mock_get_object try: stream = self.driver.download_object_as_stream(obj=obj, chunk_size=1024) self.assertTrue(hasattr(stream, '__iter__')) finally: self.driver_type._get_object = old_func def test_upload_object_invalid_ex_storage_class(self): # Invalid hash is detected on the amazon side and BAD_REQUEST is # returned file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, verify_hash=True, ex_storage_class='invalid-class') except ValueError as e: self.assertTrue(str(e).lower().find('invalid storage class') != -1) else: self.fail('Exception was not thrown') def test_upload_object_invalid_hash1(self): # Invalid hash is detected on the amazon side and BAD_REQUEST is # returned def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(200), 'bytes_transferred': 1000, 'data_hash': 'hash343hhash89h932439jsaa89'} self.mock_response_klass.type = 'INVALID_HASH1' old_func = self.driver_type._upload_object self.driver_type._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, verify_hash=True) except ObjectHashMismatchError: pass else: self.fail( 'Invalid hash was returned but an exception was not thrown') finally: self.driver_type._upload_object = old_func def test_upload_object_invalid_hash2(self): # Invalid hash is detected when comparing hash provided in the response # ETag header def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(200, headers={'etag': 'woopwoopwoop'}), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} self.mock_response_klass.type = 'INVALID_HASH2' old_func = self.driver_type._upload_object self.driver_type._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' try: self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, verify_hash=True) except ObjectHashMismatchError: pass else: self.fail( 'Invalid hash was returned but an exception was not thrown') finally: self.driver_type._upload_object = old_func def test_upload_object_success(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): return {'response': make_response(200, headers={'etag': '0cc175b9c0f1b6a831c399e269772661'}), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} self.mock_response_klass.type = None old_func = self.driver_type._upload_object self.driver_type._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'meta_data': {'some-value': 'foobar'}} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=True) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, 1000) self.assertTrue('some-value' in obj.meta_data) self.driver_type._upload_object = old_func def test_upload_object_with_acl(self): def upload_file(self, object_name=None, content_type=None, request_path=None, request_method=None, headers=None, file_path=None, stream=None): headers = {'etag': '0cc175b9c0f1b6a831c399e269772661'} return {'response': make_response(200, headers=headers), 'bytes_transferred': 1000, 'data_hash': '0cc175b9c0f1b6a831c399e269772661'} self.mock_response_klass.type = None old_func = self.driver_type._upload_object self.driver_type._upload_object = upload_file file_path = os.path.abspath(__file__) container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_upload' extra = {'acl': 'public-read'} obj = self.driver.upload_object(file_path=file_path, container=container, object_name=object_name, extra=extra, verify_hash=True) self.assertEqual(obj.name, 'foo_test_upload') self.assertEqual(obj.size, 1000) self.assertEqual(obj.extra['acl'], 'public-read') self.driver_type._upload_object = old_func def test_upload_empty_object_via_stream(self): if self.driver.supports_s3_multipart_upload: self.mock_response_klass.type = 'MULTIPART' else: self.mock_response_klass.type = None container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = BytesIO(b('')) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, 0) def test_upload_small_object_via_stream(self): if self.driver.supports_s3_multipart_upload: self.mock_response_klass.type = 'MULTIPART' else: self.mock_response_klass.type = None container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = BytesIO(b('234')) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, 3) def test_upload_big_object_via_stream(self): if self.driver.supports_s3_multipart_upload: self.mock_response_klass.type = 'MULTIPART' else: self.mock_response_klass.type = None container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = BytesIO(b('234' * CHUNK_SIZE)) extra = {'content_type': 'text/plain'} obj = self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) self.assertEqual(obj.name, object_name) self.assertEqual(obj.size, CHUNK_SIZE * 3) def test_upload_object_via_stream_guess_file_mime_type(self): if self.driver.supports_s3_multipart_upload: self.mock_response_klass.type = 'MULTIPART' else: self.mock_response_klass.type = None container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = BytesIO(b('234')) with mock.patch( 'libcloud.utils.files.guess_file_mime_type', autospec=True) as mock_guess_file_mime_type: mock_guess_file_mime_type.return_value = ('application/zip', None) self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator) mock_guess_file_mime_type.assert_called_with(object_name) def test_upload_object_via_stream_abort(self): if not self.driver.supports_s3_multipart_upload: return self.mock_response_klass.type = 'MULTIPART' def _faulty_iterator(): for i in range(0, 5): yield str(i) raise RuntimeError('Error in fetching data') container = Container(name='foo_bar_container', extra={}, driver=self.driver) object_name = 'foo_test_stream_data' iterator = _faulty_iterator() extra = {'content_type': 'text/plain'} try: self.driver.upload_object_via_stream(container=container, object_name=object_name, iterator=iterator, extra=extra) except Exception: pass return def test_s3_list_multipart_uploads(self): if not self.driver.supports_s3_multipart_upload: return self.mock_response_klass.type = 'LIST_MULTIPART' S3StorageDriver.RESPONSES_PER_REQUEST = 2 container = Container(name='foo_bar_container', extra={}, driver=self.driver) for upload in self.driver.ex_iterate_multipart_uploads(container): self.assertNotEqual(upload.key, None) self.assertNotEqual(upload.id, None) self.assertNotEqual(upload.created_at, None) self.assertNotEqual(upload.owner, None) self.assertNotEqual(upload.initiator, None) def test_s3_abort_multipart_uploads(self): if not self.driver.supports_s3_multipart_upload: return self.mock_response_klass.type = 'LIST_MULTIPART' S3StorageDriver.RESPONSES_PER_REQUEST = 2 container = Container(name='foo_bar_container', extra={}, driver=self.driver) self.driver.ex_cleanup_all_multipart_uploads(container) def test_delete_object_not_found(self): self.mock_response_klass.type = 'NOT_FOUND' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, meta_data=None, container=container, driver=self.driver) try: self.driver.delete_object(obj=obj) except ObjectDoesNotExistError: pass else: self.fail('Exception was not thrown') def test_delete_object_success(self): self.mock_response_klass.type = 'DELETE' container = Container(name='foo_bar_container', extra={}, driver=self.driver) obj = Object(name='foo_bar_object', size=1234, hash=None, extra=None, meta_data=None, container=container, driver=self.driver) result = self.driver.delete_object(obj=obj) self.assertTrue(result) def test_region_keyword_argument(self): # Default region driver = S3StorageDriver(*self.driver_args) self.assertEqual(driver.region, 'us-east-1') self.assertEqual(driver.connection.host, 's3.amazonaws.com') # Custom region driver = S3StorageDriver(*self.driver_args, region='us-west-2') self.assertEqual(driver.region, 'us-west-2') self.assertEqual(driver.connection.host, 's3-us-west-2.amazonaws.com') # Verify class instance and class variables don't get mixed up driver1 = S3StorageDriver(*self.driver_args, region='us-west-2') self.assertEqual(driver1.region, 'us-west-2') self.assertEqual(driver1.connection.host, 's3-us-west-2.amazonaws.com') driver2 = S3StorageDriver(*self.driver_args, region='ap-south-1') self.assertEqual(driver2.region, 'ap-south-1') self.assertEqual(driver2.connection.host, 's3-ap-south-1.amazonaws.com') self.assertEqual(driver1.region, 'us-west-2') self.assertEqual(driver1.connection.host, 's3-us-west-2.amazonaws.com') # Test all supported regions for region in S3StorageDriver.list_regions(): driver = S3StorageDriver(*self.driver_args, region=region) self.assertEqual(driver.region, region) # Invalid region expected_msg = 'Invalid or unsupported region: foo' self.assertRaisesRegexp(ValueError, expected_msg, S3StorageDriver, *self.driver_args, region='foo') # host argument still has precedence over reguin driver3 = S3StorageDriver(*self.driver_args, region='ap-south-1', host='host1.bar.com') self.assertEqual(driver3.region, 'ap-south-1') self.assertEqual(driver3.connection.host, 'host1.bar.com') driver4 = S3StorageDriver(*self.driver_args, host='host2.bar.com') self.assertEqual(driver4.connection.host, 'host2.bar.com') def test_deprecated_driver_class_per_region(self): driver = S3USWestStorageDriver(*self.driver_args) self.assertEqual(driver.region, 'us-west-1') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_connection.py0000664000175000017500000003772613570310635022771 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more§ # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import socket import sys import ssl from mock import Mock, patch import requests_mock from libcloud.test import unittest from libcloud.common.base import Connection, CertificateConnection from libcloud.http import LibcloudBaseConnection from libcloud.http import LibcloudConnection from libcloud.http import SignedHTTPSAdapter from libcloud.utils.misc import retry from libcloud.utils.py3 import assertRaisesRegex class BaseConnectionClassTestCase(unittest.TestCase): def setUp(self): self.orig_proxy = os.environ.pop('http_proxy', None) def tearDown(self): if self.orig_proxy: os.environ['http_proxy'] = self.orig_proxy def test_parse_proxy_url(self): conn = LibcloudBaseConnection() proxy_url = 'http://127.0.0.1:3128' result = conn._parse_proxy_url(proxy_url=proxy_url) self.assertEqual(result[0], 'http') self.assertEqual(result[1], '127.0.0.1') self.assertEqual(result[2], 3128) self.assertIsNone(result[3]) self.assertIsNone(result[4]) proxy_url = 'https://127.0.0.2:3129' result = conn._parse_proxy_url(proxy_url=proxy_url) self.assertEqual(result[0], 'https') self.assertEqual(result[1], '127.0.0.2') self.assertEqual(result[2], 3129) self.assertIsNone(result[3]) self.assertIsNone(result[4]) proxy_url = 'http://user1:pass1@127.0.0.1:3128' result = conn._parse_proxy_url(proxy_url=proxy_url) self.assertEqual(result[0], 'http') self.assertEqual(result[1], '127.0.0.1') self.assertEqual(result[2], 3128) self.assertEqual(result[3], 'user1') self.assertEqual(result[4], 'pass1') proxy_url = 'https://user1:pass1@127.0.0.2:3129' result = conn._parse_proxy_url(proxy_url=proxy_url) self.assertEqual(result[0], 'https') self.assertEqual(result[1], '127.0.0.2') self.assertEqual(result[2], 3129) self.assertEqual(result[3], 'user1') self.assertEqual(result[4], 'pass1') proxy_url = 'http://127.0.0.1' expected_msg = 'proxy_url must be in the following format' assertRaisesRegex(self, ValueError, expected_msg, conn._parse_proxy_url, proxy_url=proxy_url) proxy_url = 'http://@127.0.0.1:3128' expected_msg = 'URL is in an invalid format' assertRaisesRegex(self, ValueError, expected_msg, conn._parse_proxy_url, proxy_url=proxy_url) proxy_url = 'http://user@127.0.0.1:3128' expected_msg = 'URL is in an invalid format' assertRaisesRegex(self, ValueError, expected_msg, conn._parse_proxy_url, proxy_url=proxy_url) def test_constructor(self): proxy_url = 'http://127.0.0.2:3128' os.environ['http_proxy'] = proxy_url conn = LibcloudConnection(host='localhost', port=80) self.assertEqual(conn.proxy_scheme, 'http') self.assertEqual(conn.proxy_host, '127.0.0.2') self.assertEqual(conn.proxy_port, 3128) self.assertEqual(conn.session.proxies, { 'http': 'http://127.0.0.2:3128', 'https': 'http://127.0.0.2:3128', }) _ = os.environ.pop('http_proxy', None) conn = LibcloudConnection(host='localhost', port=80) self.assertIsNone(conn.proxy_scheme) self.assertIsNone(conn.proxy_host) self.assertIsNone(conn.proxy_port) proxy_url = 'http://127.0.0.3:3128' conn.set_http_proxy(proxy_url=proxy_url) self.assertEqual(conn.proxy_scheme, 'http') self.assertEqual(conn.proxy_host, '127.0.0.3') self.assertEqual(conn.proxy_port, 3128) self.assertEqual(conn.session.proxies, { 'http': 'http://127.0.0.3:3128', 'https': 'http://127.0.0.3:3128', }) proxy_url = 'http://127.0.0.4:3128' conn = LibcloudConnection(host='localhost', port=80, proxy_url=proxy_url) self.assertEqual(conn.proxy_scheme, 'http') self.assertEqual(conn.proxy_host, '127.0.0.4') self.assertEqual(conn.proxy_port, 3128) self.assertEqual(conn.session.proxies, { 'http': 'http://127.0.0.4:3128', 'https': 'http://127.0.0.4:3128', }) os.environ['http_proxy'] = proxy_url proxy_url = 'http://127.0.0.5:3128' conn = LibcloudConnection(host='localhost', port=80, proxy_url=proxy_url) self.assertEqual(conn.proxy_scheme, 'http') self.assertEqual(conn.proxy_host, '127.0.0.5') self.assertEqual(conn.proxy_port, 3128) self.assertEqual(conn.session.proxies, { 'http': 'http://127.0.0.5:3128', 'https': 'http://127.0.0.5:3128', }) os.environ['http_proxy'] = proxy_url proxy_url = 'https://127.0.0.6:3129' conn = LibcloudConnection(host='localhost', port=80, proxy_url=proxy_url) self.assertEqual(conn.proxy_scheme, 'https') self.assertEqual(conn.proxy_host, '127.0.0.6') self.assertEqual(conn.proxy_port, 3129) self.assertEqual(conn.session.proxies, { 'http': 'https://127.0.0.6:3129', 'https': 'https://127.0.0.6:3129', }) def test_connection_to_unusual_port(self): conn = LibcloudConnection(host='localhost', port=8080) self.assertIsNone(conn.proxy_scheme) self.assertIsNone(conn.proxy_host) self.assertIsNone(conn.proxy_port) self.assertEqual(conn.host, 'http://localhost:8080') conn = LibcloudConnection(host='localhost', port=80) self.assertEqual(conn.host, 'http://localhost') def test_connection_url_merging(self): """ Test that the connection class will parse URLs correctly """ conn = Connection(url='http://test.com/') conn.connect() self.assertEqual(conn.connection.host, 'http://test.com') with requests_mock.mock() as m: m.get('http://test.com/test', text='data') response = conn.request('/test') self.assertEqual(response.body, 'data') def test_morph_action_hook(self): conn = Connection(url="http://test.com") conn.request_path = '' self.assertEqual(conn.morph_action_hook('/test'), '/test') self.assertEqual(conn.morph_action_hook('test'), '/test') conn.request_path = '/v1' self.assertEqual(conn.morph_action_hook('/test'), '/v1/test') self.assertEqual(conn.morph_action_hook('test'), '/v1/test') conn.request_path = '/v1' self.assertEqual(conn.morph_action_hook('/test'), '/v1/test') self.assertEqual(conn.morph_action_hook('test'), '/v1/test') conn.request_path = 'v1' self.assertEqual(conn.morph_action_hook('/test'), '/v1/test') self.assertEqual(conn.morph_action_hook('test'), '/v1/test') conn.request_path = 'v1/' self.assertEqual(conn.morph_action_hook('/test'), '/v1/test') self.assertEqual(conn.morph_action_hook('test'), '/v1/test') def test_connect_with_prefix(self): """ Test that a connection with a base path (e.g. /v1/) will add the base path to requests """ conn = Connection(url='http://test.com/') conn.connect() conn.request_path = '/v1' self.assertEqual(conn.connection.host, 'http://test.com') with requests_mock.mock() as m: m.get('http://test.com/v1/test', text='data') response = conn.request('/test') self.assertEqual(response.body, 'data') def test_secure_connection_unusual_port(self): """ Test that the connection class will default to secure (https) even when the port is an unusual (non 443, 80) number """ conn = Connection(secure=True, host='localhost', port=8081) conn.connect() self.assertEqual(conn.connection.host, 'https://localhost:8081') conn2 = Connection(url='https://localhost:8081') conn2.connect() self.assertEqual(conn2.connection.host, 'https://localhost:8081') def test_secure_by_default(self): """ Test that the connection class will default to secure (https) """ conn = Connection(host='localhost', port=8081) conn.connect() self.assertEqual(conn.connection.host, 'https://localhost:8081') def test_implicit_port(self): """ Test that the port is not included in the URL if the protocol implies the port, e.g. http implies 80 """ conn = Connection(secure=True, host='localhost', port=443) conn.connect() self.assertEqual(conn.connection.host, 'https://localhost') conn2 = Connection(secure=False, host='localhost', port=80) conn2.connect() self.assertEqual(conn2.connection.host, 'http://localhost') def test_insecure_connection_unusual_port(self): """ Test that the connection will allow unusual ports and insecure schemes """ conn = Connection(secure=False, host='localhost', port=8081) conn.connect() self.assertEqual(conn.connection.host, 'http://localhost:8081') conn2 = Connection(url='http://localhost:8081') conn2.connect() self.assertEqual(conn2.connection.host, 'http://localhost:8081') class ConnectionClassTestCase(unittest.TestCase): def setUp(self): self.originalConnect = Connection.connect self.originalResponseCls = Connection.responseCls Connection.connect = Mock() Connection.responseCls = Mock() Connection.allow_insecure = True def tearDown(self): Connection.connect = self.originalConnect Connection.responseCls = Connection.responseCls Connection.allow_insecure = True def test_dont_allow_insecure(self): Connection.allow_insecure = True Connection(secure=False) Connection.allow_insecure = False expected_msg = (r'Non https connections are not allowed \(use ' r'secure=True\)') assertRaisesRegex(self, ValueError, expected_msg, Connection, secure=False) def test_cache_busting(self): params1 = {'foo1': 'bar1', 'foo2': 'bar2'} params2 = [('foo1', 'bar1'), ('foo2', 'bar2')] con = Connection() con.connection = Mock() con.pre_connect_hook = Mock() con.pre_connect_hook.return_value = {}, {} con.cache_busting = False con.request(action='/path', params=params1) args, kwargs = con.pre_connect_hook.call_args self.assertFalse('cache-busting' in args[0]) self.assertEqual(args[0], params1) con.request(action='/path', params=params2) args, kwargs = con.pre_connect_hook.call_args self.assertFalse('cache-busting' in args[0]) self.assertEqual(args[0], params2) con.cache_busting = True con.request(action='/path', params=params1) args, kwargs = con.pre_connect_hook.call_args self.assertTrue('cache-busting' in args[0]) con.request(action='/path', params=params2) args, kwargs = con.pre_connect_hook.call_args self.assertTrue('cache-busting' in args[0][len(params2)]) def test_context_is_reset_after_request_has_finished(self): context = {'foo': 'bar'} def responseCls(connection, response): connection.called = True self.assertEqual(connection.context, context) con = Connection() con.called = False con.connection = Mock() con.responseCls = responseCls con.set_context(context) self.assertEqual(con.context, context) con.request('/') # Context should have been reset self.assertTrue(con.called) self.assertEqual(con.context, {}) # Context should also be reset if a method inside request throws con = Connection(timeout=1, retry_delay=0.1) con.connection = Mock() con.set_context(context) self.assertEqual(con.context, context) con.connection.request = Mock(side_effect=ssl.SSLError()) try: con.request('/') except ssl.SSLError: pass self.assertEqual(con.context, {}) con.connection = Mock() con.set_context(context) self.assertEqual(con.context, context) con.responseCls = Mock(side_effect=ValueError()) try: con.request('/') except ValueError: pass self.assertEqual(con.context, {}) def _raise_socket_error(self): raise socket.gaierror('') def test_retry_with_sleep(self): con = Connection() con.connection = Mock() connect_method = 'libcloud.common.base.Connection.request' with patch(connect_method) as mock_connect: mock_connect.__name__ = 'mock_connect' with self.assertRaises(socket.gaierror): mock_connect.side_effect = socket.gaierror('') retry_request = retry(timeout=0.2, retry_delay=0.1, backoff=1) retry_request(con.request)(action='/') self.assertGreater(mock_connect.call_count, 1, 'Retry logic failed') def test_retry_with_timeout(self): con = Connection() con.connection = Mock() connect_method = 'libcloud.common.base.Connection.request' with patch(connect_method) as mock_connect: mock_connect.__name__ = 'mock_connect' with self.assertRaises(socket.gaierror): mock_connect.side_effect = socket.gaierror('') retry_request = retry(timeout=0.2, retry_delay=0.1, backoff=1) retry_request(con.request)(action='/') self.assertGreater(mock_connect.call_count, 1, 'Retry logic failed') def test_retry_with_backoff(self): con = Connection() con.connection = Mock() connect_method = 'libcloud.common.base.Connection.request' with patch(connect_method) as mock_connect: mock_connect.__name__ = 'mock_connect' with self.assertRaises(socket.gaierror): mock_connect.side_effect = socket.gaierror('') retry_request = retry(timeout=0.2, retry_delay=0.1, backoff=1) retry_request(con.request)(action='/') self.assertGreater(mock_connect.call_count, 1, 'Retry logic failed') class CertificateConnectionClassTestCase(unittest.TestCase): def setUp(self): self.connection = CertificateConnection(cert_file='test.pem', url='https://test.com/test') self.connection.connect() def test_adapter_internals(self): adapter = self.connection.connection.session.adapters['https://'] self.assertTrue(isinstance(adapter, SignedHTTPSAdapter)) self.assertEqual(adapter.cert_file, 'test.pem') if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_file_fixtures.py0000664000175000017500000000602513535474530023474 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.utils.py3 import httplib from libcloud.test.file_fixtures import ComputeFileFixtures from libcloud.common.base import Connection, Response, JsonResponse, XmlResponse from libcloud.test import MockHttp class FileFixturesTests(unittest.TestCase): def test_success(self): f = ComputeFileFixtures('meta') self.assertEqual("Hello, World!", f.load('helloworld.txt')) def test_failure(self): f = ComputeFileFixtures('meta') self.assertRaises(IOError, f.load, 'nil') def test_unicode(self): f = ComputeFileFixtures('meta') self.assertEqual(u"Ś", f.load('unicode.txt')) class MockHttpFileFixturesTests(unittest.TestCase): """ Test the behaviour of MockHttp """ def setUp(self): Connection.conn_class = TestMockHttp Connection.responseCls = Response self.connection = Connection() def test_unicode_response(self): r = self.connection.request("/unicode") self.assertEqual(r.parse_body(), u"Ś") def test_json_unicode_response(self): self.connection.responseCls = JsonResponse r = self.connection.request("/unicode/json") self.assertEqual(r.object, {'test': u"Ś"}) def test_xml_unicode_response(self): self.connection.responseCls = XmlResponse response = self.connection.request("/unicode/xml") self.assertEqual(response.object.text, u"Ś") class TestMockHttp(MockHttp): fixtures = ComputeFileFixtures('meta') def _unicode(self, method, url, body, headers): body = self.fixtures.load('unicode.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _unicode_json(self, method, url, body, headers): body = self.fixtures.load('unicode.json') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _unicode_xml(self, method, url, body, headers): body = self.fixtures.load('unicode.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) def _ascii(self, method, url, body, headers): body = self.fixtures.load('helloworld.txt') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_http.py0000664000175000017500000000671113570310635021577 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import os.path import warnings import libcloud.security from libcloud.utils.py3 import reload from libcloud.utils.py3 import assertRaisesRegex from libcloud.http import LibcloudConnection from libcloud.test import unittest ORIGINAL_CA_CERTS_PATH = libcloud.security.CA_CERTS_PATH class TestHttpLibSSLTests(unittest.TestCase): def setUp(self): libcloud.security.VERIFY_SSL_CERT = False libcloud.security.CA_CERTS_PATH = ORIGINAL_CA_CERTS_PATH self.httplib_object = LibcloudConnection('foo.bar', port=80) def test_custom_ca_path_using_env_var_doesnt_exist(self): os.environ['SSL_CERT_FILE'] = '/foo/doesnt/exist' try: reload(libcloud.security) except ValueError as e: msg = 'Certificate file /foo/doesnt/exist doesn\'t exist' self.assertEqual(str(e), msg) else: self.fail('Exception was not thrown') def test_custom_ca_path_using_env_var_is_directory(self): file_path = os.path.dirname(os.path.abspath(__file__)) os.environ['SSL_CERT_FILE'] = file_path expected_msg = 'Certificate file can\'t be a directory' assertRaisesRegex(self, ValueError, expected_msg, reload, libcloud.security) def test_custom_ca_path_using_env_var_exist(self): # When setting a path we don't actually check that a valid CA file is # provided. # This happens later in the code in http.connect method file_path = os.path.abspath(__file__) os.environ['SSL_CERT_FILE'] = file_path reload(libcloud.security) self.assertEqual(libcloud.security.CA_CERTS_PATH, file_path) def test_ca_cert_list_warning(self): with warnings.catch_warnings(record=True) as w: self.httplib_object.verify = True self.httplib_object._setup_ca_cert( ca_cert=[ORIGINAL_CA_CERTS_PATH]) self.assertEqual(self.httplib_object.ca_cert, ORIGINAL_CA_CERTS_PATH) self.assertEqual(w[0].category, DeprecationWarning) def test_setup_ca_cert(self): # verify = False, _setup_ca_cert should be a no-op self.httplib_object.verify = False self.httplib_object._setup_ca_cert() self.assertIsNone(self.httplib_object.ca_cert) # verify = True, a valid path is provided, self.ca_cert should be set to # a valid path self.httplib_object.verify = True libcloud.security.CA_CERTS_PATH = os.path.abspath(__file__) self.httplib_object._setup_ca_cert() self.assertTrue(self.httplib_object.ca_cert is not None) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_init.py0000664000175000017500000000560113570310635021560 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more§ # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import logging try: import paramiko have_paramiko = True except ImportError: have_paramiko = False from mock import patch import libcloud from libcloud import _init_once from libcloud.utils.loggingconnection import LoggingConnection from libcloud.base import DriverTypeNotFoundError from libcloud.test import unittest class TestUtils(unittest.TestCase): def test_init_once_and_debug_mode(self): if have_paramiko: paramiko_logger = logging.getLogger('paramiko') paramiko_logger.setLevel(logging.INFO) # Debug mode is disabled _init_once() self.assertIsNone(LoggingConnection.log) if have_paramiko: paramiko_log_level = paramiko_logger.getEffectiveLevel() self.assertEqual(paramiko_log_level, logging.INFO) # Enable debug mode os.environ['LIBCLOUD_DEBUG'] = '/dev/null' _init_once() self.assertTrue(LoggingConnection.log is not None) if have_paramiko: paramiko_log_level = paramiko_logger.getEffectiveLevel() self.assertEqual(paramiko_log_level, logging.DEBUG) def test_factory(self): driver = libcloud.get_driver(libcloud.DriverType.COMPUTE, libcloud.DriverType.COMPUTE.EC2) self.assertEqual(driver.__name__, 'EC2NodeDriver') def test_raises_error(self): with self.assertRaises(DriverTypeNotFoundError): libcloud.get_driver('potato', 'potato') @patch.object(libcloud.requests, '__version__', '2.6.0') @patch.object(libcloud.requests.packages.chardet, '__version__', '2.2.1') def test_init_once_detects_bad_yum_install_requests(self, *args): expected_msg = 'Known bad version of requests detected' with self.assertRaisesRegexp(AssertionError, expected_msg): _init_once() @patch.object(libcloud.requests, '__version__', '2.6.0') @patch.object(libcloud.requests.packages.chardet, '__version__', '2.3.0') def test_init_once_correct_chardet_version(self, *args): _init_once() if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_logging_connection.py0000664000175000017500000000532113535474530024467 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from io import StringIO import zlib import requests_mock import libcloud from libcloud.test import unittest from libcloud.common.base import Connection from libcloud.http import LibcloudConnection from libcloud.utils.loggingconnection import LoggingConnection class TestLoggingConnection(unittest.TestCase): def tearDown(self): Connection.conn_class = LibcloudConnection def test_debug_method_uses_log_class(self): with StringIO() as fh: libcloud.enable_debug(fh) conn = Connection(timeout=10) conn.connect() self.assertTrue(isinstance(conn.connection, LoggingConnection)) def test_debug_log_class_handles_request(self): with StringIO() as fh: libcloud.enable_debug(fh) conn = Connection(url='http://test.com/') conn.connect() self.assertEqual(conn.connection.host, 'http://test.com') with requests_mock.mock() as m: m.get('http://test.com/test', text='data') conn.request('/test') log = fh.getvalue() self.assertTrue(isinstance(conn.connection, LoggingConnection)) self.assertIn('-i -X GET', log) self.assertIn('data', log) def test_debug_log_class_handles_request_with_compression(self): request = zlib.compress(b'data') with StringIO() as fh: libcloud.enable_debug(fh) conn = Connection(url='http://test.com/') conn.connect() self.assertEqual(conn.connection.host, 'http://test.com') with requests_mock.mock() as m: m.get('http://test.com/test', content=request, headers={'content-encoding': 'zlib'}) conn.request('/test') log = fh.getvalue() self.assertTrue(isinstance(conn.connection, LoggingConnection)) self.assertIn('-i -X GET', log) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_pricing.py0000664000175000017500000001101313535474530022250 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os.path import sys import unittest import libcloud.pricing PRICING_FILE_PATH = os.path.join(os.path.dirname(__file__), 'pricing_test.json') class PricingTestCase(unittest.TestCase): def test_get_pricing_success(self): self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) pricing = libcloud.pricing.get_pricing(driver_type='compute', driver_name='foo', pricing_file_path=PRICING_FILE_PATH) self.assertEqual(pricing['1'], 1.0) self.assertEqual(pricing['2'], 2.0) self.assertEqual(libcloud.pricing.PRICING_DATA['compute']['foo']['1'], 1.0) self.assertEqual(libcloud.pricing.PRICING_DATA['compute']['foo']['2'], 2.0) def test_get_pricing_invalid_file_path(self): try: libcloud.pricing.get_pricing(driver_type='compute', driver_name='bar', pricing_file_path='inexistent.json') except IOError: pass else: self.fail('Invalid pricing file path provided, but an exception was not' ' thrown') def test_get_pricing_invalid_driver_type(self): try: libcloud.pricing.get_pricing(driver_type='invalid_type', driver_name='bar', pricing_file_path='inexistent.json') except AttributeError: pass else: self.fail('Invalid driver_type provided, but an exception was not' ' thrown') def test_get_pricing_not_in_cache(self): try: libcloud.pricing.get_pricing(driver_type='compute', driver_name='inexistent', pricing_file_path=PRICING_FILE_PATH) except KeyError: pass else: self.fail('Invalid driver provided, but an exception was not' ' thrown') def test_get_size_price(self): libcloud.pricing.PRICING_DATA['compute']['foo'] = {2: 2, '3': 3} price1 = libcloud.pricing.get_size_price(driver_type='compute', driver_name='foo', size_id=2) price2 = libcloud.pricing.get_size_price(driver_type='compute', driver_name='foo', size_id='3') self.assertEqual(price1, 2) self.assertEqual(price2, 3) def test_invalid_pricing_cache(self): libcloud.pricing.PRICING_DATA['compute']['foo'] = {2: 2} self.assertTrue('foo' in libcloud.pricing.PRICING_DATA['compute']) libcloud.pricing.invalidate_pricing_cache() self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) def test_invalid_module_pricing_cache(self): libcloud.pricing.PRICING_DATA['compute']['foo'] = {1: 1} self.assertTrue('foo' in libcloud.pricing.PRICING_DATA['compute']) libcloud.pricing.invalidate_module_pricing_cache(driver_type='compute', driver_name='foo') self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) libcloud.pricing.invalidate_module_pricing_cache(driver_type='compute', driver_name='foo1') def test_set_pricing(self): self.assertFalse('foo' in libcloud.pricing.PRICING_DATA['compute']) libcloud.pricing.set_pricing(driver_type='compute', driver_name='foo', pricing={'foo': 1}) self.assertTrue('foo' in libcloud.pricing.PRICING_DATA['compute']) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_response_classes.py0000664000175000017500000001161213535474530024175 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest import requests import requests_mock from libcloud.common.base import XmlResponse, JsonResponse, Connection from libcloud.common.types import MalformedResponseError from libcloud.http import LibcloudConnection class ResponseClassesTests(unittest.TestCase): def setUp(self): self.mock_connection = LibcloudConnection(host='mock.com', port=80) self.mock_connection.driver = None def test_XmlResponse_class(self): with requests_mock.mock() as m: m.register_uri('GET', 'mock://test.com/2', text='bar') response_obj = requests.get('mock://test.com/2') response = XmlResponse(response=response_obj, connection=self.mock_connection) parsed = response.parse_body() self.assertEqual(parsed.tag, 'foo') self.assertEqual(parsed.text, 'bar') def test_XmlResponse_class_malformed_response(self): with requests_mock.mock() as m: m.register_uri('GET', 'mock://test.com/', text='') response_obj = requests.get('mock://test.com/') try: XmlResponse(response=response_obj, connection=self.mock_connection) except MalformedResponseError: pass else: self.fail('Exception was not thrown') def test_XmlResponse_class_zero_length_body_strip(self): with requests_mock.mock() as m: m.register_uri('GET', 'mock://test.com/', text=' ') response_obj = requests.get('mock://test.com/') response = XmlResponse(response=response_obj, connection=self.mock_connection) parsed = response.parse_body() self.assertEqual(parsed, '') def test_JsonResponse_class_success(self): with requests_mock.mock() as m: m.register_uri('GET', 'mock://test.com/', text='{"foo": "bar"}') response_obj = requests.get('mock://test.com/') response = JsonResponse(response=response_obj, connection=self.mock_connection) parsed = response.parse_body() self.assertEqual(parsed, {'foo': 'bar'}) def test_JsonResponse_class_malformed_response(self): with requests_mock.mock() as m: m.register_uri('GET', 'mock://test.com/', text='{"foo": "bar"') response_obj = requests.get('mock://test.com/') try: JsonResponse(response=response_obj, connection=self.mock_connection) except MalformedResponseError: pass else: self.fail('Exception was not thrown') def test_JsonResponse_class_zero_length_body_strip(self): with requests_mock.mock() as m: m.register_uri('GET', 'mock://test.com/', text=' ') response_obj = requests.get('mock://test.com/') response = JsonResponse(response=response_obj, connection=self.mock_connection) parsed = response.parse_body() self.assertEqual(parsed, '') def test_RawResponse_class_read_method(self): """ Test that the RawResponse class includes a response property which exhibits the same properties and methods as httplib.HTTPResponse for backward compat <1.5.0 """ TEST_DATA = '1234abcd' conn = Connection(host='mock.com', port=80, secure=False) conn.connect() with requests_mock.Mocker() as m: m.register_uri('GET', 'http://mock.com/raw_data', text=TEST_DATA, headers={'test': 'value'}) response = conn.request('/raw_data', raw=True) data = response.response.read() self.assertEqual(data, TEST_DATA) header_value = response.response.getheader('test') self.assertEqual(header_value, 'value') headers = response.response.getheaders() self.assertEqual(headers, [('test', 'value')]) self.assertEqual(response.response.status, 200) if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_types.py0000664000175000017500000000714113535474530021770 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import unittest from libcloud.common.types import LazyList class TestLazyList(unittest.TestCase): def setUp(self): super(TestLazyList, self).setUp self._get_more_counter = 0 def tearDown(self): super(TestLazyList, self).tearDown def test_init(self): data = [1, 2, 3, 4, 5] ll = LazyList(get_more=self._get_more_exhausted) ll_list = list(ll) self.assertEqual(ll_list, data) def test_iterator(self): data = [1, 2, 3, 4, 5] ll = LazyList(get_more=self._get_more_exhausted) for i, d in enumerate(ll): self.assertEqual(d, data[i]) def test_empty_list(self): ll = LazyList(get_more=self._get_more_empty) self.assertEqual(list(ll), []) self.assertEqual(len(ll), 0) self.assertTrue(10 not in ll) def test_iterator_not_exhausted(self): data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ll = LazyList(get_more=self._get_more_not_exhausted) number_of_iterations = 0 for i, d in enumerate(ll): self.assertEqual(d, data[i]) number_of_iterations += 1 self.assertEqual(number_of_iterations, 10) def test_len(self): ll = LazyList(get_more=self._get_more_not_exhausted) ll = LazyList(get_more=self._get_more_not_exhausted) self.assertEqual(len(ll), 10) def test_contains(self): ll = LazyList(get_more=self._get_more_not_exhausted) self.assertTrue(40 not in ll) self.assertTrue(1 in ll) self.assertTrue(5 in ll) self.assertTrue(10 in ll) def test_indexing(self): ll = LazyList(get_more=self._get_more_not_exhausted) self.assertEqual(ll[0], 1) self.assertEqual(ll[9], 10) self.assertEqual(ll[-1], 10) try: ll[11] except IndexError: pass else: self.fail('Exception was not thrown') def test_repr(self): ll1 = LazyList(get_more=self._get_more_empty) ll2 = LazyList(get_more=self._get_more_exhausted) ll3 = LazyList(get_more=self._get_more_not_exhausted) self.assertEqual(repr(ll1), '[]') self.assertEqual(repr(ll2), '[1, 2, 3, 4, 5]') self.assertEqual(repr(ll3), '[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]') def _get_more_empty(self, last_key, value_dict): return [], None, True def _get_more_exhausted(self, last_key, value_dict): data = [1, 2, 3, 4, 5] return data, 5, True def _get_more_not_exhausted(self, last_key, value_dict): self._get_more_counter += 1 if not last_key: data, last_key, exhausted = [1, 2, 3, 4, 5], 5, False else: data, last_key, exhausted = [6, 7, 8, 9, 10], 10, True return data, last_key, exhausted if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/test/test_utils.py0000664000175000017500000003535013577507766022005 0ustar kamikami00000000000000# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one or more§ # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import pytest import socket import codecs import unittest import warnings import os.path import requests_mock from itertools import chain # In Python > 2.7 DeprecationWarnings are disabled by default warnings.simplefilter('default') import libcloud.utils.files from libcloud.utils.misc import get_driver, set_driver from libcloud.utils.py3 import PY3 from libcloud.utils.py3 import StringIO from libcloud.utils.py3 import b from libcloud.utils.py3 import bchr from libcloud.utils.py3 import hexadigits from libcloud.utils.py3 import urlquote from libcloud.compute.types import Provider from libcloud.compute.providers import DRIVERS from libcloud.compute.drivers.dummy import DummyNodeDriver from libcloud.utils.misc import get_secure_random_string from libcloud.utils.networking import is_public_subnet from libcloud.utils.networking import is_private_subnet from libcloud.utils.networking import is_valid_ip_address from libcloud.utils.networking import join_ipv4_segments from libcloud.utils.networking import increment_ipv4_segments from libcloud.utils.decorators import wrap_non_libcloud_exceptions from libcloud.utils.connection import get_response_object from libcloud.utils.publickey import ( get_pubkey_openssh_fingerprint, get_pubkey_ssh2_fingerprint, ) from libcloud.common.types import LibcloudError from libcloud.storage.drivers.dummy import DummyIterator WARNINGS_BUFFER = [] if PY3: from io import FileIO as file def show_warning(msg, cat, fname, lno, file=None, line=None): WARNINGS_BUFFER.append((msg, cat, fname, lno)) original_func = warnings.showwarning class TestUtils(unittest.TestCase): def setUp(self): global WARNINGS_BUFFER WARNINGS_BUFFER = [] def tearDown(self): global WARNINGS_BUFFER WARNINGS_BUFFER = [] warnings.showwarning = original_func def test_guess_file_mime_type(self): file_path = os.path.abspath(__file__) mimetype, encoding = libcloud.utils.files.guess_file_mime_type( file_path=file_path) self.assertTrue(mimetype.find('python') != -1) def test_get_driver(self): driver = get_driver(drivers=DRIVERS, provider=Provider.DUMMY) self.assertTrue(driver is not None) try: driver = get_driver(drivers=DRIVERS, provider='fooba') except AttributeError: pass else: self.fail('Invalid provider, but an exception was not thrown') def test_get_driver_string_and_enum_notation(self): driver = get_driver(drivers=DRIVERS, provider=Provider.DUMMY) self.assertEqual(driver, DummyNodeDriver) driver = get_driver(drivers=DRIVERS, provider='dummy') self.assertEqual(driver, DummyNodeDriver) driver = get_driver(drivers=DRIVERS, provider='DUMMY') self.assertEqual(driver, DummyNodeDriver) def test_set_driver(self): # Set an existing driver try: driver = set_driver(DRIVERS, Provider.DUMMY, 'libcloud.storage.drivers.dummy', 'DummyStorageDriver') except AttributeError: pass # Register a new driver driver = set_driver(DRIVERS, 'testingset', 'libcloud.storage.drivers.dummy', 'DummyStorageDriver') self.assertTrue(driver is not None) # Register it again try: set_driver(DRIVERS, 'testingset', 'libcloud.storage.drivers.dummy', 'DummyStorageDriver') except AttributeError: pass # Register an invalid module try: set_driver(DRIVERS, 'testingnew', 'libcloud.storage.drivers.dummy1', 'DummyStorageDriver') except ImportError: pass # Register an invalid class try: set_driver(DRIVERS, 'testingnew', 'libcloud.storage.drivers.dummy', 'DummyStorageDriver1') except AttributeError: pass def test_deprecated_warning(self): warnings.showwarning = show_warning libcloud.utils.SHOW_DEPRECATION_WARNING = False self.assertEqual(len(WARNINGS_BUFFER), 0) libcloud.utils.deprecated_warning('test_module') self.assertEqual(len(WARNINGS_BUFFER), 0) libcloud.utils.SHOW_DEPRECATION_WARNING = True self.assertEqual(len(WARNINGS_BUFFER), 0) libcloud.utils.deprecated_warning('test_module') self.assertEqual(len(WARNINGS_BUFFER), 1) def test_in_development_warning(self): warnings.showwarning = show_warning libcloud.utils.SHOW_IN_DEVELOPMENT_WARNING = False self.assertEqual(len(WARNINGS_BUFFER), 0) libcloud.utils.in_development_warning('test_module') self.assertEqual(len(WARNINGS_BUFFER), 0) libcloud.utils.SHOW_IN_DEVELOPMENT_WARNING = True self.assertEqual(len(WARNINGS_BUFFER), 0) libcloud.utils.in_development_warning('test_module') self.assertEqual(len(WARNINGS_BUFFER), 1) def test_read_in_chunks_iterator_no_data(self): iterator = DummyIterator() generator1 = libcloud.utils.files.read_in_chunks(iterator=iterator, yield_empty=False) generator2 = libcloud.utils.files.read_in_chunks(iterator=iterator, yield_empty=True) # yield_empty=False count = 0 for data in generator1: count += 1 self.assertEqual(data, b('')) self.assertEqual(count, 0) # yield_empty=True count = 0 for data in generator2: count += 1 self.assertEqual(data, b('')) self.assertEqual(count, 1) def test_read_in_chunks_iterator(self): def iterator(): for x in range(0, 1000): yield 'aa' for result in libcloud.utils.files.read_in_chunks(iterator(), chunk_size=10, fill_size=False): self.assertEqual(result, b('aa')) for result in libcloud.utils.files.read_in_chunks(iterator(), chunk_size=10, fill_size=True): self.assertEqual(result, b('aaaaaaaaaa')) def test_read_in_chunks_filelike(self): class FakeFile(file): def __init__(self): self.remaining = 500 def read(self, size): self.remaining -= 1 if self.remaining == 0: return '' return 'b' * (size + 1) for index, result in enumerate(libcloud.utils.files.read_in_chunks( FakeFile(), chunk_size=10, fill_size=False)): self.assertEqual(result, b('b' * 11)) self.assertEqual(index, 498) for index, result in enumerate(libcloud.utils.files.read_in_chunks( FakeFile(), chunk_size=10, fill_size=True)): if index != 548: self.assertEqual(result, b('b' * 10)) else: self.assertEqual(result, b('b' * 9)) self.assertEqual(index, 548) def test_exhaust_iterator(self): def iterator_func(): for x in range(0, 1000): yield 'aa' data = b('aa' * 1000) iterator = libcloud.utils.files.read_in_chunks(iterator=iterator_func()) result = libcloud.utils.files.exhaust_iterator(iterator=iterator) self.assertEqual(result, data) result = libcloud.utils.files.exhaust_iterator(iterator=iterator_func()) self.assertEqual(result, data) data = '12345678990' iterator = StringIO(data) result = libcloud.utils.files.exhaust_iterator(iterator=iterator) self.assertEqual(result, b(data)) def test_exhaust_iterator_empty_iterator(self): data = '' iterator = StringIO(data) result = libcloud.utils.files.exhaust_iterator(iterator=iterator) self.assertEqual(result, b(data)) def test_unicode_urlquote(self): # Regression tests for LIBCLOUD-429 if PY3: # Note: this is a unicode literal val = '\xe9' else: val = codecs.unicode_escape_decode('\xe9')[0] uri = urlquote(val) self.assertEqual(b(uri), b('%C3%A9')) # Unicode without unicode characters uri = urlquote('v=1') self.assertEqual(b(uri), b('v%3D1')) # Already-encoded bytestring without unicode characters uri = urlquote(b('v=1')) self.assertEqual(b(uri), b('v%3D1')) def test_get_secure_random_string(self): for i in range(1, 500): value = get_secure_random_string(size=i) self.assertEqual(len(value), i) def test_hexadigits(self): self.assertEqual(hexadigits(b('')), []) self.assertEqual(hexadigits(b('a')), ['61']) self.assertEqual(hexadigits(b('AZaz09-')), ['41', '5a', '61', '7a', '30', '39', '2d']) def test_bchr(self): if PY3: self.assertEqual(bchr(0), b'\x00') self.assertEqual(bchr(97), b'a') else: self.assertEqual(bchr(0), '\x00') self.assertEqual(bchr(97), 'a') class NetworkingUtilsTestCase(unittest.TestCase): def test_is_public_and_is_private_subnet(self): public_ips = [ '213.151.0.8', '86.87.86.1', '8.8.8.8', '8.8.4.4' ] private_ips = [ '192.168.1.100', '10.0.0.1', '172.16.0.0' ] for address in public_ips: is_public = is_public_subnet(ip=address) is_private = is_private_subnet(ip=address) self.assertTrue(is_public) self.assertFalse(is_private) for address in private_ips: is_public = is_public_subnet(ip=address) is_private = is_private_subnet(ip=address) self.assertFalse(is_public) self.assertTrue(is_private) def test_is_valid_ip_address(self): valid_ipv4_addresses = [ '192.168.1.100', '10.0.0.1', '213.151.0.8', '77.77.77.77' ] invalid_ipv4_addresses = [ '10.1', '256.256.256.256', '0.567.567.567', '192.168.0.257' ] valid_ipv6_addresses = [ 'fe80::200:5aee:feaa:20a2', '2607:f0d0:1002:51::4', '2607:f0d0:1002:0051:0000:0000:0000:0004', '::1' ] invalid_ipv6_addresses = [ '2607:f0d', '2607:f0d0:0004', ] for address in valid_ipv4_addresses: status = is_valid_ip_address(address=address, family=socket.AF_INET) self.assertTrue(status) for address in valid_ipv6_addresses: status = is_valid_ip_address(address=address, family=socket.AF_INET6) self.assertTrue(status) for address in chain(invalid_ipv4_addresses, invalid_ipv6_addresses): status = is_valid_ip_address(address=address, family=socket.AF_INET) self.assertFalse(status) for address in chain(invalid_ipv4_addresses, invalid_ipv6_addresses): status = is_valid_ip_address(address=address, family=socket.AF_INET6) self.assertFalse(status) def test_join_ipv4_segments(self): values = [ (('127', '0', '0', '1'), '127.0.0.1'), (('255', '255', '255', '0'), '255.255.255.0'), ] for segments, joined_ip in values: result = join_ipv4_segments(segments=segments) self.assertEqual(result, joined_ip) def test_increment_ipv4_segments(self): values = [ (('127', '0', '0', '1'), '127.0.0.2'), (('255', '255', '255', '0'), '255.255.255.1'), (('254', '255', '255', '255'), '255.0.0.0'), (('100', '1', '0', '255'), '100.1.1.0'), ] for segments, incremented_ip in values: result = increment_ipv4_segments(segments=segments) result = join_ipv4_segments(segments=result) self.assertEqual(result, incremented_ip) class TestPublicKeyUtils(unittest.TestCase): PUBKEY = ( 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOfbWSXOlqvYjZmRO84/lIoV4gvuX+' 'P1lLg50MMg6jZjLZIlYY081XPRmuom0xY0+BO++J2KgLl7gxJ6xMsKK2VQ+TakdfAH20' 'XfMcTohd/zVCeWsbqZQvEhVXBo4hPIktcfNz0u9Ez3EtInO+kb7raLcRhOVi9QmOkOrC' 'WtQU9mS71AWJuqI9H0YAnTiI8Hs5bn2tpMIqmTXT3g2bwywC25x1Nx9Hy0/FP+KUL6Ag' 'vDXv47l+TgSDfTBEkvq+IF1ITrnaOG+nRE02oZC6cwHYTifM/IOollkujxIQmi2Z+j66' 'OHSrjnEQugr0FqGJF2ygKfIh/i2u3fVLM60qE2NN user@example' ) def test_pubkey_openssh_fingerprint(self): fp = get_pubkey_openssh_fingerprint(self.PUBKEY) self.assertEqual(fp, '35:22:13:5b:82:e2:5d:e1:90:8c:73:74:9f:ef:3b:d8') def test_pubkey_ssh2_fingerprint(self): fp = get_pubkey_ssh2_fingerprint(self.PUBKEY) self.assertEqual(fp, '11:ad:5d:4c:5b:99:c9:80:7e:81:03:76:5a:25:9d:8c') def test_decorator(): @wrap_non_libcloud_exceptions def foo(): raise Exception("bork") with pytest.raises(LibcloudError): foo() def test_get_response_object(): with requests_mock.mock() as m: m.get('http://test.com/test', text='data') response = get_response_object('http://test.com/test') assert response.body == 'data' if __name__ == '__main__': sys.exit(unittest.main()) apache-libcloud-2.8.0/libcloud/utils/0000775000175000017500000000000013600223624017356 5ustar kamikami00000000000000apache-libcloud-2.8.0/libcloud/utils/__init__.py0000664000175000017500000000326713535474530021512 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import warnings __all__ = [ 'SHOW_DEPRECATION_WARNING', 'SHOW_IN_DEVELOPMENT_WARNING', 'OLD_API_REMOVE_VERSION', 'deprecated_warning', 'in_development_warning' ] SHOW_DEPRECATION_WARNING = True SHOW_IN_DEVELOPMENT_WARNING = True OLD_API_REMOVE_VERSION = '0.7.0' def deprecated_warning(module): if SHOW_DEPRECATION_WARNING: warnings.warn('This path has been deprecated and the module' ' is now available at "libcloud.compute.%s".' ' This path will be fully removed in libcloud %s.' % (module, OLD_API_REMOVE_VERSION), category=DeprecationWarning) def in_development_warning(module): if SHOW_IN_DEVELOPMENT_WARNING: warnings.warn('The module %s is in development and your are advised ' 'against using it in production.' % (module), category=FutureWarning) apache-libcloud-2.8.0/libcloud/utils/connection.py0000664000175000017500000000331213535474530022101 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from libcloud.utils.py3 import urlparse, parse_qs from libcloud.common.base import Connection __all__ = [ 'get_response_object' ] def get_response_object(url, method='GET', headers=None): """ Utility function which uses libcloud's connection class to issue an HTTP request. :param url: URL to send the request to. :type url: ``str`` :param method: HTTP method. :type method: ``str`` :param headers: Optional request headers. :type headers: ``dict`` :return: Response object. :rtype: :class:`Response`. """ parsed_url = urlparse.urlparse(url) parsed_qs = parse_qs(parsed_url.query) secure = parsed_url.scheme == 'https' headers = headers or {} method = method.upper() con = Connection(secure=secure, host=parsed_url.netloc) response = con.request(action=parsed_url.path, params=parsed_qs, headers=headers, method=method) return response apache-libcloud-2.8.0/libcloud/utils/decorators.py0000664000175000017500000000343013570310635022102 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from functools import wraps from libcloud.common.types import LibcloudError __all__ = [ 'wrap_non_libcloud_exceptions' ] def wrap_non_libcloud_exceptions(func): """ Decorators function which catches non LibcloudError exceptions, wraps them in LibcloudError class and re-throws the wrapped exception. Note: This function should only be used to wrap methods on the driver classes. """ @wraps(func) def decorated_function(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: if isinstance(e, LibcloudError): raise e if len(args) >= 1: driver = args[0] else: driver = None fault = getattr(e, 'fault', None) if fault and getattr(fault, 'string', None): message = fault.string else: message = str(e) raise LibcloudError(value=message, driver=driver) return decorated_function apache-libcloud-2.8.0/libcloud/utils/dist.py0000664000175000017500000001155513535474530020715 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Taken From Twisted Python which licensed under MIT license # https://github.com/powdahound/twisted/blob/master/twisted/python/dist.py # https://github.com/powdahound/twisted/blob/master/LICENSE import os import fnmatch # Names that are excluded from globbing results: EXCLUDE_NAMES = ['{arch}', 'CVS', '.cvsignore', '_darcs', 'RCS', 'SCCS', '.svn'] EXCLUDE_PATTERNS = ['*.py[cdo]', '*.s[ol]', '.#*', '*~', '*.py'] def _filter_names(names): """ Given a list of file names, return those names that should be copied. """ names = [n for n in names if n not in EXCLUDE_NAMES] # This is needed when building a distro from a working # copy (likely a checkout) rather than a pristine export: for pattern in EXCLUDE_PATTERNS: names = [n for n in names if not fnmatch.fnmatch(n, pattern) and not n.endswith('.py')] return names def relative_to(base, relativee): """ Gets 'relativee' relative to 'basepath'. i.e., >>> relative_to('/home/', '/home/radix/') 'radix' >>> relative_to('.', '/home/radix/Projects/Twisted') 'Projects/Twisted' The 'relativee' must be a child of 'basepath'. """ basepath = os.path.abspath(base) relativee = os.path.abspath(relativee) if relativee.startswith(basepath): relative = relativee[len(basepath):] if relative.startswith(os.sep): relative = relative[1:] return os.path.join(base, relative) raise ValueError("%s is not a subpath of %s" % (relativee, basepath)) def get_packages(dname, pkgname=None, results=None, ignore=None, parent=None): """ Get all packages which are under dname. This is necessary for Python 2.2's distutils. Pretty similar arguments to getDataFiles, including 'parent'. """ parent = parent or "" prefix = [] if parent: prefix = [parent] bname = os.path.basename(dname) ignore = ignore or [] if bname in ignore: return [] if results is None: results = [] if pkgname is None: pkgname = [] subfiles = os.listdir(dname) abssubfiles = [os.path.join(dname, x) for x in subfiles] if '__init__.py' in subfiles: results.append(prefix + pkgname + [bname]) for subdir in filter(os.path.isdir, abssubfiles): get_packages(subdir, pkgname=pkgname + [bname], results=results, ignore=ignore, parent=parent) res = ['.'.join(result) for result in results] return res def get_data_files(dname, ignore=None, parent=None): """ Get all the data files that should be included in this distutils Project. 'dname' should be the path to the package that you're distributing. 'ignore' is a list of sub-packages to ignore. This facilitates disparate package hierarchies. That's a fancy way of saying that the 'twisted' package doesn't want to include the 'twisted.conch' package, so it will pass ['conch'] as the value. 'parent' is necessary if you're distributing a subpackage like twisted.conch. 'dname' should point to 'twisted/conch' and 'parent' should point to 'twisted'. This ensures that your data_files are generated correctly, only using relative paths for the first element of the tuple ('twisted/conch/*'). The default 'parent' is the current working directory. """ parent = parent or "." ignore = ignore or [] result = [] for directory, subdirectories, filenames in os.walk(dname): resultfiles = [] for exname in EXCLUDE_NAMES: if exname in subdirectories: subdirectories.remove(exname) for ig in ignore: if ig in subdirectories: subdirectories.remove(ig) for filename in _filter_names(filenames): resultfiles.append(filename) if resultfiles: for filename in resultfiles: file_path = os.path.join(directory, filename) if parent: file_path = file_path.replace(parent + os.sep, '') result.append(file_path) return result apache-libcloud-2.8.0/libcloud/utils/escape.py0000664000175000017500000000161313535474530021204 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'sanitize_object_name', ] def sanitize_object_name(object_name): return object_name.replace('\\', '/') apache-libcloud-2.8.0/libcloud/utils/files.py0000664000175000017500000000727713535474530021062 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import mimetypes from libcloud.utils.py3 import PY3 from libcloud.utils.py3 import httplib from libcloud.utils.py3 import next from libcloud.utils.py3 import b if PY3: from io import FileIO as file CHUNK_SIZE = 8096 __all__ = [ 'read_in_chunks', 'exhaust_iterator', 'guess_file_mime_type' ] def read_in_chunks(iterator, chunk_size=None, fill_size=False, yield_empty=False): """ Return a generator which yields data in chunks. :param iterator: An object which implements an iterator interface or a File like object with read method. :type iterator: :class:`object` which implements iterator interface. :param chunk_size: Optional chunk size (defaults to CHUNK_SIZE) :type chunk_size: ``int`` :param fill_size: If True, make sure chunks are exactly chunk_size in length (except for last chunk). :type fill_size: ``bool`` :param yield_empty: If true and iterator returned no data, only yield empty bytes object :type yield_empty: ``bool`` TODO: At some point in the future we could use byte arrays here if version >= Python 3. This should speed things up a bit and reduce memory usage. """ chunk_size = chunk_size or CHUNK_SIZE if isinstance(iterator, (file, httplib.HTTPResponse)): get_data = iterator.read args = (chunk_size, ) else: get_data = next args = (iterator, ) data = b('') empty = False while not empty or len(data) > 0: if not empty: try: chunk = b(get_data(*args)) if len(chunk) > 0: data += chunk else: empty = True except StopIteration: empty = True if len(data) == 0: if empty and yield_empty: yield b('') return if fill_size: if empty or len(data) >= chunk_size: yield data[:chunk_size] data = data[chunk_size:] else: yield data data = b('') def exhaust_iterator(iterator): """ Exhaust an iterator and return all data returned by it. :type iterator: :class:`object` which implements iterator interface. :param iterator: An object which implements an iterator interface or a File like object with read method. :rtype ``str`` :return Data returned by the iterator. """ data = b('') try: chunk = b(next(iterator)) except StopIteration: chunk = b('') while len(chunk) > 0: data += chunk try: chunk = b(next(iterator)) except StopIteration: chunk = b('') return data def guess_file_mime_type(file_path): filename = os.path.basename(file_path) (mimetype, encoding) = mimetypes.guess_type(filename) return mimetype, encoding apache-libcloud-2.8.0/libcloud/utils/iso8601.py0000664000175000017500000001046713535474530021064 0ustar kamikami00000000000000""" Copyright (c) 2007 Michael Twomey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ISO 8601 date time string parsing Basic usage: >>> import iso8601 >>> iso8601.parse_date("2007-01-25T12:00:00Z") datetime.datetime(2007, 1, 25, 12, 0, tzinfo=) >>> """ # Taken from pyiso8601 which is licensed under the MIT license. from datetime import datetime, timedelta, tzinfo import re __all__ = ["parse_date", "ParseError"] # Adapted from http://delete.me.uk/2005/03/iso8601.html ISO8601_REGEX = re.compile( r"(?P[0-9]{4})(-(?P[0-9]{1,2})(-(?P[0-9]{1,2})" r"((?P.)(?P[0-9]{2}):(?P[0-9]{2})(:(?P[0-9]{2})(\.(?P[0-9]+))?)?" # NOQA r"(?PZ|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?") TIMEZONE_REGEX = re.compile("(?P[+-])(?P[0-9]{2}).(?P[0-9]{2})") # NOQA class ParseError(Exception): """Raised when there is a problem parsing a date string""" # Yoinked from python docs ZERO = timedelta(0) class Utc(tzinfo): """UTC """ def utcoffset(self, dt): return ZERO def tzname(self, dt): return "UTC" def dst(self, dt): return ZERO UTC = Utc() class FixedOffset(tzinfo): """Fixed offset in hours and minutes from UTC """ def __init__(self, offset_hours, offset_minutes, name): self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) self.__name = name def utcoffset(self, dt): return self.__offset def tzname(self, dt): return self.__name def dst(self, dt): return ZERO def __repr__(self): return "" % self.__name def parse_timezone(tzstring, default_timezone=UTC): """Parses ISO 8601 time zone specs into tzinfo offsets """ if tzstring == "Z": return default_timezone # This isn't strictly correct, but it's common to encounter dates without # timezones so I'll assume the default (which defaults to UTC). # Addresses issue 4. if tzstring is None: return default_timezone m = TIMEZONE_REGEX.match(tzstring) prefix, hours, minutes = m.groups() hours, minutes = int(hours), int(minutes) if prefix == "-": hours = -hours minutes = -minutes return FixedOffset(hours, minutes, tzstring) def parse_date(datestring, default_timezone=UTC): """Parses ISO 8601 dates into datetime objects The timezone is parsed from the date string. However it is quite common to have dates without a timezone (not strictly correct). In this case the default timezone specified in default_timezone is used. This is UTC by default. """ if not datestring: raise ValueError('datestring must be valid date string and not None') m = ISO8601_REGEX.match(datestring) if not m: raise ParseError("Unable to parse date string %r" % datestring) groups = m.groupdict() tz = parse_timezone(groups["timezone"], default_timezone=default_timezone) if groups["fraction"] is None: groups["fraction"] = 0 else: groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6) return datetime(int(groups["year"]), int(groups["month"]), int(groups["day"]), int(groups["hour"]), int(groups["minute"]), int(groups["second"]), int(groups["fraction"]), tz) apache-libcloud-2.8.0/libcloud/utils/logging.py0000664000175000017500000000332613535474530021375 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Taken from https://github.com/Kami/python-extra-log-formatters from __future__ import absolute_import import logging __all__ = [ 'ExtraLogFormatter' ] class ExtraLogFormatter(logging.Formatter): """ Custom log formatter which attaches all the attributes from the "extra" dictionary which start with an underscore to the end of the log message. For example: extra={'_id': 'user-1', '_path': '/foo/bar'} """ def format(self, record): custom_attributes = dict([(k, v) for k, v in record.__dict__.items() if k.startswith('_')]) custom_attributes = self._dict_to_str(custom_attributes) msg = logging.Formatter.format(self, record) msg = '%s (%s)' % (msg, custom_attributes) return msg def _dict_to_str(self, dictionary): result = ['%s=%s' % (k[1:], str(v)) for k, v in dictionary.items()] result = ','.join(result) return result apache-libcloud-2.8.0/libcloud/utils/loggingconnection.py0000664000175000017500000001242313576514553023460 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import absolute_import try: import simplejson as json # type: ignore except Exception: import json # type: ignore from pipes import quote as pquote from xml.dom.minidom import parseString import os from libcloud.common.base import (LibcloudConnection, HttpLibResponseProxy) from libcloud.utils.py3 import _real_unicode as u from libcloud.utils.misc import lowercase_keys class LoggingConnection(LibcloudConnection): """ Debug class to log all HTTP(s) requests as they could be made with the curl command. :cvar log: file-like object that logs entries are written to. """ protocol = 'https' log = None http_proxy_used = False def _log_response(self, r): rv = "# -------- begin %d:%d response ----------\n" % (id(self), id(r)) ht = "" v = r.version if r.version == 10: v = "HTTP/1.0" if r.version == 11: v = "HTTP/1.1" ht += "%s %s %s\r\n" % (v, r.status, r.reason) body = r.read() for h in r.getheaders(): ht += "%s: %s\r\n" % (h[0].title(), h[1]) ht += "\r\n" headers = lowercase_keys(dict(r.getheaders())) content_type = headers.get('content-type', None) pretty_print = os.environ.get('LIBCLOUD_DEBUG_PRETTY_PRINT_RESPONSE', False) if pretty_print and content_type == 'application/json': try: body = json.loads(body.decode('utf-8')) body = json.dumps(body, sort_keys=True, indent=4) except Exception: # Invalid JSON or server is lying about content-type pass elif pretty_print and content_type == 'text/xml': try: elem = parseString(body.decode('utf-8')) body = elem.toprettyxml() except Exception: # Invalid XML pass ht += u(body) rv += ht rv += ("\n# -------- end %d:%d response ----------\n" % (id(self), id(r))) return rv def _log_curl(self, method, url, body, headers): cmd = ["curl"] if self.http_proxy_used: if self.proxy_username and self.proxy_password: proxy_url = '%s://%s:%s@%s:%s' % (self.proxy_scheme, self.proxy_username, self.proxy_password, self.proxy_host, self.proxy_port) else: proxy_url = '%s://%s:%s' % (self.proxy_scheme, self.proxy_host, self.proxy_port) proxy_url = pquote(proxy_url) cmd.extend(['--proxy', proxy_url]) cmd.extend(['-i']) if method.lower() == 'head': # HEAD method need special handling cmd.extend(["--head"]) else: cmd.extend(["-X", pquote(method)]) for h in headers: cmd.extend(["-H", pquote("%s: %s" % (h, headers[h]))]) cert_file = getattr(self, 'cert_file', None) if cert_file: cmd.extend(["--cert", pquote(cert_file)]) # TODO: in python 2.6, body can be a file-like object. if body is not None and len(body) > 0: if isinstance(body, (bytearray, bytes)): body = body.decode('utf-8') cmd.extend(["--data-binary", pquote(body)]) cmd.extend(["--compress"]) cmd.extend([pquote("%s%s" % (self.host, url))]) return " ".join(cmd) def getresponse(self): original_response = LibcloudConnection.getresponse(self) if self.log is not None: rv = self._log_response(HttpLibResponseProxy(original_response)) self.log.write(u(rv + "\n")) self.log.flush() return original_response def request(self, method, url, body=None, headers=None, **kwargs): headers.update({'X-LC-Request-ID': str(id(self))}) if self.log is not None: pre = "# -------- begin %d request ----------\n" % id(self) self.log.write(u(pre + self._log_curl(method, url, body, headers) + "\n")) self.log.flush() return LibcloudConnection.request(self, method, url, body, headers) apache-libcloud-2.8.0/libcloud/utils/misc.py0000664000175000017500000002142413576514553020706 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import List import os import binascii import socket import time import ssl from datetime import datetime, timedelta from functools import wraps from libcloud.utils.py3 import httplib from libcloud.common.exceptions import RateLimitReachedError from libcloud.common.providers import get_driver as _get_driver from libcloud.common.providers import set_driver as _set_driver __all__ = [ 'find', 'get_driver', 'set_driver', 'merge_valid_keys', 'get_new_obj', 'str2dicts', 'dict2str', 'reverse_dict', 'lowercase_keys', 'get_secure_random_string', 'retry', 'ReprMixin' ] # Error message which indicates a transient SSL error upon which request # can be retried TRANSIENT_SSL_ERROR = 'The read operation timed out' class TransientSSLError(ssl.SSLError): """Represent transient SSL errors, e.g. timeouts""" pass # Constants used by the ``retry`` decorator DEFAULT_TIMEOUT = 30 # default retry timeout DEFAULT_DELAY = 1 # default sleep delay used in each iterator DEFAULT_BACKOFF = 1 # retry backup multiplier RETRY_EXCEPTIONS = (RateLimitReachedError, socket.error, socket.gaierror, httplib.NotConnected, httplib.ImproperConnectionState, TransientSSLError) def find(l, predicate): results = [x for x in l if predicate(x)] return results[0] if len(results) > 0 else None # Note: Those are aliases for backward-compatibility for functions which have # been moved to "libcloud.common.providers" module get_driver = _get_driver set_driver = _set_driver def merge_valid_keys(params, valid_keys, extra): """ Merge valid keys from extra into params dictionary and return dictionary with keys which have been merged. Note: params is modified in place. """ merged = {} if not extra: return merged for key in valid_keys: if key in extra: params[key] = extra[key] merged[key] = extra[key] return merged def get_new_obj(obj, klass, attributes): """ Pass attributes from the existing object 'obj' and attributes dictionary to a 'klass' constructor. Attributes from 'attributes' dictionary are only passed to the constructor if they are not None. """ kwargs = {} for key, value in list(obj.__dict__.items()): if isinstance(value, dict): kwargs[key] = value.copy() elif isinstance(value, (tuple, list)): kwargs[key] = value[:] else: kwargs[key] = value for key, value in list(attributes.items()): if value is None: continue if isinstance(value, dict): kwargs_value = kwargs.get(key, {}) for key1, value2 in list(value.items()): if value2 is None: continue kwargs_value[key1] = value2 kwargs[key] = kwargs_value else: kwargs[key] = value return klass(**kwargs) def str2dicts(data): """ Create a list of dictionaries from a whitespace and newline delimited text. For example, this: cpu 1100 ram 640 cpu 2200 ram 1024 becomes: [{'cpu': '1100', 'ram': '640'}, {'cpu': '2200', 'ram': '1024'}] """ list_data = [] list_data.append({}) d = list_data[-1] lines = data.split('\n') for line in lines: line = line.strip() if not line: d = {} list_data.append(d) d = list_data[-1] continue whitespace = line.find(' ') if not whitespace: continue key = line[0:whitespace] value = line[whitespace + 1:] d.update({key: value}) list_data = [val for val in list_data if val != {}] return list_data def str2list(data): """ Create a list of values from a whitespace and newline delimited text (keys are ignored). For example, this: ip 1.2.3.4 ip 1.2.3.5 ip 1.2.3.6 becomes: ['1.2.3.4', '1.2.3.5', '1.2.3.6'] """ list_data = [] for line in data.split('\n'): line = line.strip() if not line: continue try: splitted = line.split(' ') # key = splitted[0] value = splitted[1] except Exception: continue list_data.append(value) return list_data def dict2str(data): """ Create a string with a whitespace and newline delimited text from a dictionary. For example, this: {'cpu': '1100', 'ram': '640', 'smp': 'auto'} becomes: cpu 1100 ram 640 smp auto cpu 2200 ram 1024 """ result = '' for k in data: if data[k] is not None: result += '%s %s\n' % (str(k), str(data[k])) else: result += '%s\n' % str(k) return result def reverse_dict(dictionary): return dict([(value, key) for key, value in list(dictionary.items())]) def lowercase_keys(dictionary): return dict(((k.lower(), v) for k, v in dictionary.items())) def get_secure_random_string(size): """ Return a string of ``size`` random bytes. Returned string is suitable for cryptographic use. :param size: Size of the generated string. :type size: ``int`` :return: Random string. :rtype: ``str`` """ value = os.urandom(size) value = binascii.hexlify(value) value = value.decode('utf-8')[:size] return value class ReprMixin(object): """ Mixin class which adds __repr__ and __str__ methods for the attributes specified on the class. """ _repr_attributes = [] # type: List[str] def __repr__(self): attributes = [] for attribute in self._repr_attributes: value = getattr(self, attribute, None) attributes.append('%s=%s' % (attribute, value)) values = (self.__class__.__name__, ', '.join(attributes)) result = '<%s %s>' % values return result def __str__(self): return str(self.__repr__()) def retry(retry_exceptions=RETRY_EXCEPTIONS, retry_delay=DEFAULT_DELAY, timeout=DEFAULT_TIMEOUT, backoff=DEFAULT_BACKOFF): """ Retry decorator that helps to handle common transient exceptions. :param retry_exceptions: types of exceptions to retry on. :param retry_delay: retry delay between the attempts. :param timeout: maximum time to wait. :param backoff: multiplier added to delay between attempts. :Example: retry_request = retry(timeout=1, retry_delay=1, backoff=1) retry_request(self.connection.request)() """ if retry_exceptions is None: retry_exceptions = RETRY_EXCEPTIONS if retry_delay is None: retry_delay = DEFAULT_DELAY if timeout is None: timeout = DEFAULT_TIMEOUT if backoff is None: backoff = DEFAULT_BACKOFF timeout = max(timeout, 0) def transform_ssl_error(func, *args, **kwargs): try: return func(*args, **kwargs) except ssl.SSLError as exc: if TRANSIENT_SSL_ERROR in str(exc): raise TransientSSLError(*exc.args) raise exc def decorator(func): @wraps(func) def retry_loop(*args, **kwargs): current_delay = retry_delay end = datetime.now() + timedelta(seconds=timeout) while True: try: return transform_ssl_error(func, *args, **kwargs) except retry_exceptions as exc: if isinstance(exc, RateLimitReachedError): time.sleep(exc.retry_after) # Reset retries if we're told to wait due to rate # limiting current_delay = retry_delay end = datetime.now() + timedelta( seconds=exc.retry_after + timeout) elif datetime.now() >= end: raise else: time.sleep(current_delay) current_delay *= backoff return retry_loop return decorator apache-libcloud-2.8.0/libcloud/utils/networking.py0000664000175000017500000000721613535474530022140 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import socket import struct import platform __all__ = [ 'is_private_subnet', 'is_public_subnet', 'is_valid_ip_address', 'join_ipv4_segments', 'increment_ipv4_segments' ] def is_private_subnet(ip): """ Utility function to check if an IP address is inside a private subnet. :type ip: ``str`` :param ip: IP address to check :return: ``bool`` if the specified IP address is private. """ priv_subnets = [{'subnet': '10.0.0.0', 'mask': '255.0.0.0'}, {'subnet': '172.16.0.0', 'mask': '255.240.0.0'}, {'subnet': '192.168.0.0', 'mask': '255.255.0.0'}] ip = struct.unpack('I', socket.inet_aton(ip))[0] for network in priv_subnets: subnet = struct.unpack('I', socket.inet_aton(network['subnet']))[0] mask = struct.unpack('I', socket.inet_aton(network['mask']))[0] if (ip & mask) == (subnet & mask): return True return False def is_public_subnet(ip): """ Utility function to check if an IP address is inside a public subnet. :type ip: ``str`` :param ip: IP address to check :return: ``bool`` if the specified IP address is public. """ return not is_private_subnet(ip=ip) def is_valid_ip_address(address, family=socket.AF_INET): """ Check if the provided address is valid IPv4 or IPv6 address. :param address: IPv4 or IPv6 address to check. :type address: ``str`` :param family: Address family (socket.AF_INTET / socket.AF_INET6). :type family: ``int`` :return: ``bool`` True if the provided address is valid. """ is_windows = platform.system() == 'Windows' if is_windows and family == socket.AF_INET6: raise ValueError('Checking IPv6 addresses is not supported on Windows') try: if is_windows: socket.inet_aton(address) else: socket.inet_pton(family, address) except socket.error: return False return True def join_ipv4_segments(segments): """ Helper method to join ip numeric segment pieces back into a full ip address. :param segments: IPv4 segments to join. :type segments: ``list`` or ``tuple`` :return: IPv4 address. :rtype: ``str`` """ return '.'.join([str(s) for s in segments]) def increment_ipv4_segments(segments): """ Increment an ip address given in quad segments based on ipv4 rules :param segments: IPv4 segments to increment. :type segments: ``list`` or ``tuple`` :return: Incremented segments. :rtype: ``list`` """ segments = [int(segment) for segment in segments] segments[3] += 1 if segments[3] == 256: segments[3] = 0 segments[2] += 1 if segments[2] == 256: segments[2] = 0 segments[1] += 1 if segments[1] == 256: segments[1] = 0 segments[0] += 1 return segments apache-libcloud-2.8.0/libcloud/utils/publickey.py0000664000175000017500000000527613535474530021744 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import hashlib from libcloud.utils.py3 import hexadigits from libcloud.utils.py3 import b from libcloud.utils.py3 import base64_decode_string __all__ = [ 'get_pubkey_openssh_fingerprint', 'get_pubkey_ssh2_fingerprint', 'get_pubkey_comment' ] try: from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization cryptography_available = True except ImportError: cryptography_available = False def _to_md5_fingerprint(data): hashed = hashlib.md5(data).digest() return ":".join(hexadigits(hashed)) def get_pubkey_openssh_fingerprint(pubkey): # We import and export the key to make sure it is in OpenSSH format if not cryptography_available: raise RuntimeError('cryptography is not available') public_key = serialization.load_ssh_public_key( b(pubkey), backend=default_backend() ) pub_openssh = public_key.public_bytes( encoding=serialization.Encoding.OpenSSH, format=serialization.PublicFormat.OpenSSH, )[7:] # strip ssh-rsa prefix return _to_md5_fingerprint(base64_decode_string(pub_openssh)) def get_pubkey_ssh2_fingerprint(pubkey): # This is the format that EC2 shows for public key fingerprints in its # KeyPair mgmt API if not cryptography_available: raise RuntimeError('cryptography is not available') public_key = serialization.load_ssh_public_key( b(pubkey), backend=default_backend() ) pub_der = public_key.public_bytes( encoding=serialization.Encoding.DER, format=serialization.PublicFormat.SubjectPublicKeyInfo, ) return _to_md5_fingerprint(pub_der) def get_pubkey_comment(pubkey, default=None): if pubkey.startswith("ssh-"): # This is probably an OpenSSH key return pubkey.strip().split(' ', 3)[2] if default: return default raise ValueError('Public key is not in a supported format') apache-libcloud-2.8.0/libcloud/utils/py3.py0000664000175000017500000001630113600144066020446 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Libcloud Python 2.x and 3.x compatibility layer # Some methods below are taken from Django PYK3 port which is licensed under 3 # clause BSD license # https://bitbucket.org/loewis/django-3k # pylint: disable=import-error,no-member from __future__ import absolute_import import sys import types import unittest DEFAULT_LXML = False try: if DEFAULT_LXML: from lxml import etree as ET else: from xml.etree import ElementTree as ET except ImportError: from xml.etree import ElementTree as ET PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 PY2_pre_279 = PY2 and sys.version_info < (2, 7, 9) PY2 = False PY27 = False PY3 = False if (2, 0) <= sys.version_info < (3, 0): PY2 = True if (2, 7) <= sys.version_info < (2, 8): PY27 = True if sys.version_info >= (3, 0): PY3 = True if PY2_pre_279: try: from backports.ssl_match_hostname import match_hostname, CertificateError # NOQA except ImportError: import warnings warnings.warn("Missing backports.ssl_match_hostname package") else: # ssl module in Python >= 3.2 includes match hostname function from ssl import match_hostname, CertificateError # NOQA if PY3: import http.client as httplib from io import StringIO import urllib import urllib as urllib2 import base64 # pylint: disable=no-name-in-module import urllib.parse as urlparse import xmlrpc.client as xmlrpclib from urllib.parse import quote as urlquote from urllib.parse import unquote as urlunquote from urllib.parse import urlencode as urlencode from os.path import relpath if sys.version_info >= (3, 5, 0): from importlib import reload else: from imp import reload from builtins import bytes from builtins import next parse_qs = urlparse.parse_qs parse_qsl = urlparse.parse_qsl basestring = str def method_type(callable, instance, klass): return types.MethodType(callable, instance or klass()) def b(s): if isinstance(s, str): return s.encode('utf-8') elif isinstance(s, bytes): return s elif isinstance(s, int): return bytes([s]) else: raise TypeError("Invalid argument %r for b()" % (s,)) def ensure_string(s): if isinstance(s, str): return s elif isinstance(s, bytes): return s.decode('utf-8') else: raise TypeError("Invalid argument %r for ensure_string()" % (s,)) def byte(n): # assume n is a Latin-1 string of length 1 return ord(n) _real_unicode = str u = str def bchr(s): """Take an integer and make a 1-character byte string.""" return bytes([s]) def dictvalues(d): return list(d.values()) def tostring(node): return ET.tostring(node, encoding='unicode') def hexadigits(s): # s needs to be a byte string. return [format(x, "02x") for x in s] if sys.version_info >= (3, 1, 0): # encodestring and decodestring has been deprecated since 3.1.0 def base64_encode_string(*args, **kwargs): return base64.encodebytes(*args, **kwargs) # NOQA def base64_decode_string(*args, **kwargs): return base64.decodebytes(*args, **kwargs) # NOQA else: def base64_encode_string(*args, **kwargs): return base64.encodestring(*args, **kwargs) def base64_decode_string(*args, **kwargs): return base64.decodestring(*args, **kwargs) def assertRaisesRegex(self, *args, **kwargs): if not isinstance(self, unittest.TestCase): raise ValueError('First argument "self" needs to be an instance ' 'of unittest.TestCase') return getattr(self, 'assertRaisesRegex')(*args, **kwargs) def assertRegex(self, *args, **kwargs): if not isinstance(self, unittest.TestCase): raise ValueError('First argument "self" needs to be an instance ' 'of unittest.TestCase') return getattr(self, 'assertRegex')(*args, **kwargs) else: import httplib # NOQA from StringIO import StringIO # NOQA import urllib # NOQA import urllib2 # NOQA import urlparse # NOQA import xmlrpclib # NOQA import base64 # NOQA from urllib import quote as _urlquote # NOQA from urllib import unquote as urlunquote # NOQA from urllib import urlencode as urlencode # NOQA from __builtin__ import reload # NOQA parse_qs = urlparse.parse_qs parse_qsl = urlparse.parse_qsl from os.path import relpath # NOQA # Save the real value of unicode because urlquote needs it to tell the # difference between a unicode string and a byte string. _real_unicode = unicode basestring = unicode = str method_type = types.MethodType b = bytes = ensure_string = str def byte(n): return n u = unicode def bchr(s): """Take an integer and make a 1-character byte string.""" return chr(s) _default_value_next = object() def next(iterator, default=_default_value_next): try: return iterator.next() except StopIteration: if default is _default_value_next: raise return default def dictvalues(d): return d.values() tostring = ET.tostring def urlquote(s, safe='/'): if isinstance(s, _real_unicode): # Pretend to be py3 by encoding the URI automatically. s = s.encode('utf8') return _urlquote(s, safe) def hexadigits(s): # s needs to be a string. return [x.encode("hex") for x in s] def base64_encode_string(*args, **kwargs): return base64.encodestring(*args, **kwargs) def base64_decode_string(*args, **kwargs): return base64.decodestring(*args, **kwargs) def assertRaisesRegex(self, *args, **kwargs): if not isinstance(self, unittest.TestCase): raise ValueError('First argument "self" needs to be an instance ' 'of unittest.TestCase') return getattr(self, 'assertRaisesRegexp')(*args, **kwargs) def assertRegex(self, *args, **kwargs): if not isinstance(self, unittest.TestCase): raise ValueError('First argument "self" needs to be an instance ' 'of unittest.TestCase') return getattr(self, 'assertRegexpMatches')(*args, **kwargs) apache-libcloud-2.8.0/libcloud/utils/xml.py0000664000175000017500000000323513535474530020546 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'fixxpath', 'findtext', 'findattr', 'findall' ] def fixxpath(xpath, namespace=None): # ElementTree wants namespaces in its xpaths, so here we add them. if not namespace: return xpath return '/'.join(['{%s}%s' % (namespace, e) for e in xpath.split('/')]) def findtext(element, xpath, namespace=None, no_text_value=''): """ :param no_text_value: Value to return if the provided element has no text value. :type no_text_value: ``object`` """ value = element.findtext(fixxpath(xpath=xpath, namespace=namespace)) if value == '': return no_text_value return value def findattr(element, xpath, namespace=None): return element.findtext(fixxpath(xpath=xpath, namespace=namespace)) def findall(element, xpath, namespace=None): return element.findall(fixxpath(xpath=xpath, namespace=namespace)) apache-libcloud-2.8.0/requirements-tests.txt0000664000175000017500000000032213600144066021044 0ustar kamikami00000000000000pep8>=1.7.0,<1.8 flake8==3.7.9 astroid==1.6.6 pylint==1.9.4 mock==3.0.5 codecov coverage<4.0 requests requests_mock pytest==4.6.5 cryptography==2.6.1 # NOTE: Only needed by nttcis loadbalancer driver pyopenssl apache-libcloud-2.8.0/scripts/0000775000175000017500000000000013600223624016110 5ustar kamikami00000000000000apache-libcloud-2.8.0/scripts/check_file_names.sh0000775000175000017500000000242613535474530021725 0ustar kamikami00000000000000#!/usr/bin/env bash # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Script which checks there are no files which name is longer # than the allowed limit # ext4 support file name up to 255 characters long, but layering # ecrypt on top of it drops the limit to 143 characters FILE_NAME_LENGTH_LIMIT=143 FILES=$(find libcloud/ -regextype posix-egrep -regex ".*[^/]{${FILE_NAME_LENGTH_LIMIT},}") if [ "${FILES}" ]; then echo "Found files which name is longer than ${FILE_NAME_LENGTH_LIMIT} characters" echo "${FILES}" exit 1 fi exit 0 apache-libcloud-2.8.0/setup.cfg0000664000175000017500000000047213600223624016245 0ustar kamikami00000000000000[wheel] universal = 1 [nosetests] exclude = TestCaseMixin [aliases] test = pytest [tool:pytest] python_classes = *Test testpaths = libcloud/test filterwarnings = ignore::UserWarning [flake8] exclude = libcloud/compute/constants.py,libcloud/test ignore = E402,W503,W504 [egg_info] tag_build = tag_date = 0 apache-libcloud-2.8.0/setup.py0000664000175000017500000002675513600144066016154 0ustar kamikami00000000000000# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import re import fnmatch import setuptools from setuptools import setup from distutils.core import Command try: import epydoc # NOQA has_epydoc = True except ImportError: has_epydoc = False # NOTE: Those functions are intentionally moved in-line to prevent setup.py dependening on any # Libcloud code which depends on libraries such as typing, enum, requests, etc. # START: Taken From Twisted Python which licensed under MIT license # https://github.com/powdahound/twisted/blob/master/twisted/python/dist.py # https://github.com/powdahound/twisted/blob/master/LICENSE # Names that are excluded from globbing results: EXCLUDE_NAMES = ['{arch}', 'CVS', '.cvsignore', '_darcs', 'RCS', 'SCCS', '.svn'] EXCLUDE_PATTERNS = ['*.py[cdo]', '*.s[ol]', '.#*', '*~', '*.py'] def _filter_names(names): """ Given a list of file names, return those names that should be copied. """ names = [n for n in names if n not in EXCLUDE_NAMES] # This is needed when building a distro from a working # copy (likely a checkout) rather than a pristine export: for pattern in EXCLUDE_PATTERNS: names = [n for n in names if not fnmatch.fnmatch(n, pattern) and not n.endswith('.py')] return names def relative_to(base, relativee): """ Gets 'relativee' relative to 'basepath'. i.e., >>> relative_to('/home/', '/home/radix/') 'radix' >>> relative_to('.', '/home/radix/Projects/Twisted') 'Projects/Twisted' The 'relativee' must be a child of 'basepath'. """ basepath = os.path.abspath(base) relativee = os.path.abspath(relativee) if relativee.startswith(basepath): relative = relativee[len(basepath):] if relative.startswith(os.sep): relative = relative[1:] return os.path.join(base, relative) raise ValueError("%s is not a subpath of %s" % (relativee, basepath)) def get_packages(dname, pkgname=None, results=None, ignore=None, parent=None): """ Get all packages which are under dname. This is necessary for Python 2.2's distutils. Pretty similar arguments to getDataFiles, including 'parent'. """ parent = parent or "" prefix = [] if parent: prefix = [parent] bname = os.path.basename(dname) ignore = ignore or [] if bname in ignore: return [] if results is None: results = [] if pkgname is None: pkgname = [] subfiles = os.listdir(dname) abssubfiles = [os.path.join(dname, x) for x in subfiles] if '__init__.py' in subfiles: results.append(prefix + pkgname + [bname]) for subdir in filter(os.path.isdir, abssubfiles): get_packages(subdir, pkgname=pkgname + [bname], results=results, ignore=ignore, parent=parent) res = ['.'.join(result) for result in results] return res def get_data_files(dname, ignore=None, parent=None): """ Get all the data files that should be included in this distutils Project. 'dname' should be the path to the package that you're distributing. 'ignore' is a list of sub-packages to ignore. This facilitates disparate package hierarchies. That's a fancy way of saying that the 'twisted' package doesn't want to include the 'twisted.conch' package, so it will pass ['conch'] as the value. 'parent' is necessary if you're distributing a subpackage like twisted.conch. 'dname' should point to 'twisted/conch' and 'parent' should point to 'twisted'. This ensures that your data_files are generated correctly, only using relative paths for the first element of the tuple ('twisted/conch/*'). The default 'parent' is the current working directory. """ parent = parent or "." ignore = ignore or [] result = [] for directory, subdirectories, filenames in os.walk(dname): resultfiles = [] for exname in EXCLUDE_NAMES: if exname in subdirectories: subdirectories.remove(exname) for ig in ignore: if ig in subdirectories: subdirectories.remove(ig) for filename in _filter_names(filenames): resultfiles.append(filename) if resultfiles: for filename in resultfiles: file_path = os.path.join(directory, filename) if parent: file_path = file_path.replace(parent + os.sep, '') result.append(file_path) return result # END: Taken from Twisted # Different versions of python have different requirements. We can't use # libcloud.utils.py3 here because it relies on backports dependency being # installed / available PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 PY3_pre_34 = PY3 and sys.version_info < (3, 4) PY2_pre_27 = PY2 and sys.version_info < (2, 7) PY2_pre_279 = PY2 and sys.version_info < (2, 7, 9) PY2_or_3_pre_34 = sys.version_info < (3, 4, 0) HTML_VIEWSOURCE_BASE = 'https://svn.apache.org/viewvc/libcloud/trunk' PROJECT_BASE_DIR = 'http://libcloud.apache.org' TEST_PATHS = ['libcloud/test', 'libcloud/test/common', 'libcloud/test/compute', 'libcloud/test/storage', 'libcloud/test/loadbalancer', 'libcloud/test/dns', 'libcloud/test/container', 'libcloud/test/backup'] DOC_TEST_MODULES = ['libcloud.compute.drivers.dummy', 'libcloud.storage.drivers.dummy', 'libcloud.dns.drivers.dummy', 'libcloud.container.drivers.dummy', 'libcloud.backup.drivers.dummy'] SUPPORTED_VERSIONS = ['2.7', 'PyPy', '3.3+'] # NOTE: python_version syntax is only supported when build system has # setuptools >= 36.2 # For installation, minimum required pip version is 1.4 # Reference: https://hynek.me/articles/conditional-python-dependencies/ INSTALL_REQUIREMENTS = [ 'requests>=2.5.0', 'backports.ssl_match_hostname ; python_version<"2.7.9"', 'typing ; python_version<"3.4.0"', 'enum34 ; python_version<"3.4.0"', ] EXTRAS_REQUIRE = {} setuptools_version = tuple(setuptools.__version__.split(".")[0:2]) setuptools_version = tuple([int(c) for c in setuptools_version]) if setuptools_version < (36, 2): if 'bdist_wheel' in sys.argv: # NOTE: We need to do that because we use universal wheel msg = ('Need to use latest version of setuptools when building wheels to ensure included ' 'metadata is correct. Current version: %s' % (setuptools.__version__)) raise RuntimeError(msg) if setuptools_version < (18, 0): if PY2_pre_279: INSTALL_REQUIREMENTS.append('backports.ssl_match_hostname') if PY2_or_3_pre_34: INSTALL_REQUIREMENTS.append('typing') INSTALL_REQUIREMENTS.append('enum34') else: EXTRAS_REQUIRE[":python_version<'2.7.9'"] = ['backports.ssl_match_hostname'] EXTRAS_REQUIRE[":python_version<'3.4.0'"] = ['typing', 'enum34'] TEST_REQUIREMENTS = [ 'mock', 'requests_mock', 'pytest', 'pytest-runner' ] + INSTALL_REQUIREMENTS if PY2_pre_279: TEST_REQUIREMENTS.append('backports.ssl_match_hostname') if PY2_pre_27 or PY3_pre_34: version = '.'.join([str(x) for x in sys.version_info[:3]]) print('Version ' + version + ' is not supported. Supported versions are ' + ', '.join(SUPPORTED_VERSIONS)) sys.exit(1) def read_version_string(): version = None cwd = os.path.dirname(os.path.abspath(__file__)) version_file = os.path.join(cwd, 'libcloud/__init__.py') with open(version_file) as fp: content = fp.read() match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", content, re.M) if match: version = match.group(1) return version raise Exception('Cannot find version in libcloud/__init__.py') def forbid_publish(): argv = sys.argv if 'upload'in argv: print('You shouldn\'t use upload command to upload a release to PyPi. ' 'You need to manually upload files generated using release.sh ' 'script.\n' 'For more information, see "Making a release section" in the ' 'documentation') sys.exit(1) class ApiDocsCommand(Command): description = "generate API documentation" user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): if not has_epydoc: raise RuntimeError('Missing "epydoc" package!') os.system( 'pydoctor' ' --add-package=libcloud' ' --project-name=libcloud' ' --make-html' ' --html-viewsource-base="%s"' ' --project-base-dir=`pwd`' ' --project-url="%s"' % (HTML_VIEWSOURCE_BASE, PROJECT_BASE_DIR)) forbid_publish() needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv) pytest_runner = ['pytest-runner'] if needs_pytest else [] setup( name='apache-libcloud', version=read_version_string(), description='A standard Python library that abstracts away differences' + ' among multiple cloud provider APIs. For more information' + ' and documentation, please see http://libcloud.apache.org', long_description=open('README.rst').read(), author='Apache Software Foundation', author_email='dev@libcloud.apache.org', install_requires=INSTALL_REQUIREMENTS, extras_requires=EXTRAS_REQUIRE, python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4", packages=get_packages('libcloud'), package_dir={ 'libcloud': 'libcloud', }, package_data={ 'libcloud': get_data_files('libcloud', parent='libcloud') + ['py.typed'], }, license='Apache License (2.0)', url='http://libcloud.apache.org/', setup_requires=pytest_runner, tests_require=TEST_REQUIREMENTS, cmdclass={ 'apidocs': ApiDocsCommand, }, zip_safe=False, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: Apache Software License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Topic :: Software Development :: Libraries :: Python Modules', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy' ] ) apache-libcloud-2.8.0/tox.ini0000664000175000017500000002210413600144066015735 0ustar kamikami00000000000000[tox] envlist = py{2.7,pypy,pypy3,3.4,3.5,3.6,3.7,3.8},checks,lint,pylint,mypy,integration,coverage skipsdist = true [testenv] passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH deps = -r{toxinidir}/requirements-tests.txt lockfile libvirt-python==5.9.0 py2.7: paramiko==2.7.1 py3.7: setuptools==42.0.1 py3.8: setuptools==42.0.1 commands = cp libcloud/test/secrets.py-dist libcloud/test/secrets.py python setup.py test basepython = {py2.7,checks,lint,pylint,coverage,py2.7-dist,py2.7-wheel}: python2.7 docs: python3.5 pypypy: pypy pypypy3: pypy3 py3.4: python3.4 py3.5: python3.5 py3.6: python3.6 {py3.7,py3.7-dist,py3.7-dist-wheel}: python3.7 py3.8: python3.8 mypy: python3.7 whitelist_externals = cp bash scripts/*.sh [testenv:py2.7-dist] # Verify library installs without any dependencies when using python setup.py # install skipdist = True recreate = True # NOTE: We intentionally set empty deps to ensure it works on a clean # environment without any dependencies deps = # Ensure those packages are not installed. If they are, it indicates unclean # environment so those checks won't work correctly commands = bash -c "pip show requests && exit 1 || exit 0" bash -c "pip show typing && exit 1 || exit 0" bash -c "pip show enum34 && exit 1 || exit 0" bash -c "pip show apache-libcloud || exit 0" python setup.py install pip show apache-libcloud # Verify all dependencies were installed pip show requests pip show typing pip show enum34 [testenv:py2.7-dist-wheel] # Verify library installs without any dependencies when using built wheel skipdist = True recreate = True # NOTE: We intentionally set empty deps to ensure it works on a clean # environment without any dependencies deps = # Ensure those packages are not installed. If they are, it indicates unclean # environment so those checks won't work correctly commands = bash -c "pip show requests && exit 1 || exit 0" bash -c "pip show typing && exit 1 || exit 0" bash -c "pip show enum34 && exit 1 || exit 0" bash -c "pip show apache-libcloud || exit 0" bash -c "rm -rf dist/apache_libcloud-*.whl" pip install wheel python setup.py bdist_wheel bash -c "pip install dist/apache_libcloud-*.whl" pip show apache-libcloud # Verify all dependencies were installed pip show requests pip show typing pip show enum34 [testenv:py3.7-dist] # Verify library installs without any dependencies when using python setup.py # install skipdist = True recreate = True # NOTE: We intentionally set empty deps to ensure it works on a clean # environment without any dependencies deps = # Ensure those packages are not installed. If they are, it indicates unclean # environment so those checks won't work correctly commands = bash -c "pip show requests && exit 1 || exit 0" bash -c "pip show typing && exit 1 || exit 0" bash -c "pip show enum34 && exit 1 || exit 0" bash -c "pip show apache-libcloud || exit 0" python setup.py install pip show apache-libcloud # Verify all dependencies were installed pip show requests bash -c "pip show typing && exit 1 || exit 0" bash -c "pip show enum34 && exit 1 || exit 0" [testenv:py3.7-dist-wheel] # Verify library installs without any dependencies when using built wheel skipdist = True recreate = True # NOTE: We intentionally set empty deps to ensure it works on a clean # environment without any dependencies deps = # Ensure those packages are not installed. If they are, it indicates unclean # environment so those checks won't work correctly commands = bash -c "pip show requests && exit 1 || exit 0" bash -c "pip show typing && exit 1 || exit 0" bash -c "pip show enum34 && exit 1 || exit 0" bash -c "pip show apache-libcloud || exit 0" bash -c "rm -rf dist/apache_libcloud-*.whl" pip install wheel python setup.py bdist_wheel bash -c "pip install dist/apache_libcloud-*.whl" # Verify all dependencies were installed pip show requests bash -c "pip show typing && exit 1 || exit 0" bash -c "pip show enum34 && exit 1 || exit 0" [testenv:docs] deps = pysphere pyopenssl backports.ssl_match_hostname lockfile rstcheck changedir = docs commands = pip install sphinx~=1.6.0 rstcheck --report warning ../CHANGES.rst python ../contrib/generate_provider_feature_matrix_table.py sphinx-apidoc -d 4 ../libcloud/ -o apidocs/ /bin/bash -c "ls apidocs/modules.rst && (grep orphan apidocs/modules.rst || sed -i '1i :orphan:\n' apidocs/modules.rst) || (exit 0)" sphinx-build -W -b html -d {envtmpdir}/doctrees . _build/html [testenv:docs-travis] # Note: We don't build API docs on Travis since it causes build failures because # those API docs files are not included anywhere. deps = pysphere pyopenssl backports.ssl_match_hostname lockfile rstcheck changedir = docs commands = pip install sphinx~=1.6.0 rstcheck --report warning ../README.rst rstcheck --report warning ../CHANGES.rst rstcheck --report warning ../CONTRIBUTING.rst python ../contrib/generate_provider_feature_matrix_table.py /bin/bash -c "ls apidocs/modules.rst && (grep orphan apidocs/modules.rst || sed -i '1i :orphan:\n' apidocs/modules.rst) || (exit 0)" sphinx-build -W -b html -d {envtmpdir}/doctrees . _build/html [testenv:provider-tables] basepython: python2.7 deps = typing pysphere pyopenssl backports.ssl_match_hostname lockfile rstcheck requests commands = python ./contrib/generate_provider_feature_matrix_table.py [testenv:scrape-ec2-prices] basepython: python2.7 deps = requests demjson commands = python contrib/scrape-ec2-prices.py [testenv:scrape-ec2-sizes] basepython: python2.7 deps = requests ijson commands = bash -c 'python contrib/scrape-ec2-sizes.py > libcloud/compute/constants.py' [testenv:pylint] deps = -r{toxinidir}/requirements-tests.txt backports.ssl_match_hostname bottle lockfile paramiko==2.7.1 pysphere setenv = PYTHONPATH={toxinidir} commands = pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/common/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/compute/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/container/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/backup/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/dns/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/storage/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/utils/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc demos/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc contrib/ pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc pylint_plugins/ [testenv:lint] deps = -r{toxinidir}/requirements-tests.txt backports.ssl_match_hostname lockfile rstcheck commands = flake8 libcloud/ flake8 --max-line-length=160 libcloud/test/ flake8 demos/ flake8 integration/ flake8 scripts/ flake8 --ignore=E402,E902,W503,W504 docs/examples/ flake8 --ignore=E402,E902,W503,W504 --max-line-length=160 contrib/ python -mjson.tool libcloud/data/pricing.json /dev/null rstcheck --report warning README.rst rstcheck --report warning CHANGES.rst rstcheck --report warning CONTRIBUTING.rst [testenv:checks] commands = bash ./scripts/check_file_names.sh python ./scripts/check_asf_license_headers.py . [testenv:integration] deps = -r{toxinidir}/integration/requirements.txt commands = python -m integration [testenv:coverage] deps = -r{toxinidir}/requirements-tests.txt paramiko==2.7.1 pyopenssl python-dateutil libvirt-python==5.9.0 lockfile set-env = commands = cp libcloud/test/secrets.py-dist libcloud/test/secrets.py coverage run --source=libcloud setup.py test [testenv:coverage-travis] passenv = TOXENV CI TRAVIS TRAVIS_* deps = -r{toxinidir}/requirements-tests.txt paramiko==2.7.1 pyopenssl libvirt-python==5.9.0 lockfile set-env = commands = cp libcloud/test/secrets.py-dist libcloud/test/secrets.py coverage run --source=libcloud setup.py test codecov [testenv:mypy] deps = setuptools==42.0.1 typing mypy==0.740 commands = mypy --no-incremental libcloud/common/ mypy --no-incremental libcloud/compute/ mypy --no-incremental example_compute.py